diff --git a/include/swift/AST/Attr.h b/include/swift/AST/Attr.h index 0c4de231462ab..d64610ead6617 100644 --- a/include/swift/AST/Attr.h +++ b/include/swift/AST/Attr.h @@ -380,21 +380,14 @@ class DeclAttribute : public AttributeBase { /// valid if they match. EquivalentInABIAttr = 1ull << 18, - /// Attribute can be used in an \c \@abi attribute, but must match - /// equivalent on API decl; if omitted, API decl's attribute will be - /// cloned. Use where you would want to use \c EquivalentInABIAttr but - /// repeating the attribute is judged too burdensome. - InferredInABIAttr = 1ull << 19, - /// Use for attributes which are \em only valid on declarations that cannot /// have an \c @abi attribute, such as \c ImportDecl . - UnreachableInABIAttr = 1ull << 20, + UnreachableInABIAttr = 1ull << 19, }; enum : uint64_t { InABIAttrMask = ForbiddenInABIAttr | UnconstrainedInABIAttr - | EquivalentInABIAttr | InferredInABIAttr - | UnreachableInABIAttr + | EquivalentInABIAttr | UnreachableInABIAttr }; LLVM_READNONE diff --git a/include/swift/AST/DeclAttr.def b/include/swift/AST/DeclAttr.def index 38e758448c8b7..401a8460f4b05 100644 --- a/include/swift/AST/DeclAttr.def +++ b/include/swift/AST/DeclAttr.def @@ -143,7 +143,7 @@ SIMPLE_DECL_ATTR(NSManaged, NSManaged, CONTEXTUAL_SIMPLE_DECL_ATTR(lazy, Lazy, OnVar, - DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, + DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr, 16) SIMPLE_DECL_ATTR(LLDBDebuggerFunction, LLDBDebuggerFunction, @@ -163,7 +163,7 @@ SIMPLE_DECL_ATTR(unsafe_no_objc_tagged_pointer, UnsafeNoObjCTaggedPointer, DECL_ATTR(inline, Inline, OnVar | OnSubscript | OnAbstractFunction, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 20) DECL_ATTR(_semantics, Semantics, @@ -193,7 +193,7 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(postfix, Postfix, SIMPLE_DECL_ATTR(_transparent, Transparent, OnFunc | OnAccessor | OnConstructor | OnVar | OnDestructor, - UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, + UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 26) SIMPLE_DECL_ATTR(requires_stored_property_inits, RequiresStoredPropertyInits, @@ -216,7 +216,7 @@ SIMPLE_DECL_ATTR(_fixed_layout, FixedLayout, SIMPLE_DECL_ATTR(inlinable, Inlinable, OnVar | OnSubscript | OnAbstractFunction, - ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, + ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 32) DECL_ATTR(_specialize, Specialize, @@ -455,7 +455,7 @@ DECL_ATTR(_dynamicReplacement, DynamicReplacement, SIMPLE_DECL_ATTR(_borrowed, Borrowed, OnVar | OnSubscript, - UserInaccessible | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, + UserInaccessible | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 81) DECL_ATTR(_private, PrivateImport, @@ -465,7 +465,7 @@ DECL_ATTR(_private, PrivateImport, SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient, OnVar | OnSubscript | OnAbstractFunction, - UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr, + UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr, 83) SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly, diff --git a/include/swift/AST/DiagnosticsParse.def b/include/swift/AST/DiagnosticsParse.def index 06c64b5177e93..4e2d140d82412 100644 --- a/include/swift/AST/DiagnosticsParse.def +++ b/include/swift/AST/DiagnosticsParse.def @@ -1571,6 +1571,11 @@ ERROR(attr_unsupported_on_target, none, ERROR(attr_name_unsupported_on_target, none, "attribute '%0' is unsupported on target '%1'", (StringRef, StringRef)) +// abi attribute +ERROR(attr_abi_incompatible_kind,none, + "cannot use %0 in '@abi'", + (DescriptiveDeclKind)) + // availability ERROR(attr_availability_platform,none, "expected platform name or '*' for '%0' attribute", (StringRef)) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index f70c156e316a5..5fa5c22032d16 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7446,7 +7446,7 @@ ERROR(property_wrapper_effectful,none, ERROR(property_with_wrapper_conflict_attribute,none, "property %0 with a wrapper cannot also be " - "%select{lazy|@NSCopying|@NSManaged|weak|unowned|unmanaged}1", + "%select{lazy|@NSCopying|@NSManaged|@abi|weak|unowned|unmanaged}1", (Identifier, int)) ERROR(property_wrapper_not_single_var, none, "property wrapper can only apply to a single variable", ()) @@ -8456,9 +8456,6 @@ ERROR(attr_abi_extra_attr,none, ERROR(attr_abi_forbidden_attr,none, "unused '%0' %select{attribute|modifier}1 in '@abi'", (StringRef, bool)) -REMARK(abi_attr_inferred_attribute,none, - "inferred '%0' in '@abi' to match %select{attribute|modifier}1 on API", - (StringRef, bool)) ERROR(attr_abi_mismatched_attr,none, "'%0' %select{attribute|modifier}1 in '@abi' should match '%2'", @@ -8498,6 +8495,13 @@ ERROR(attr_abi_no_default_arguments,none, "affect the parameter's ABI", (Decl *)) +ERROR(attr_abi_no_macros,none, + "%kind0 cannot be expanded in '@abi' attribute", + (Decl *)) +ERROR(attr_abi_no_lazy,none, + "'lazy' is not compatible with '@abi' attribute", + ()) + // These macros insert 'final', 'non-final', or nothing depending on both the // current decl and its counterpart, such that 'non-final' is used if the // counterpart would be described as 'final' or 'static'. They must be kept in diff --git a/include/swift/Basic/LangOptions.h b/include/swift/Basic/LangOptions.h index 8a73b09290079..5d9cac773637b 100644 --- a/include/swift/Basic/LangOptions.h +++ b/include/swift/Basic/LangOptions.h @@ -269,9 +269,6 @@ namespace swift { /// Emit a remark on early exit in explicit interface build bool EnableSkipExplicitInterfaceModuleBuildRemarks = false; - /// Emit a remark when \c \@abi infers an attribute or modifier. - bool EnableABIInferenceRemarks = false; - /// /// Support for alternate usage modes /// diff --git a/include/swift/Option/Options.td b/include/swift/Option/Options.td index 0f5b00ad5c07b..94910cf5d9d0b 100644 --- a/include/swift/Option/Options.td +++ b/include/swift/Option/Options.td @@ -468,10 +468,6 @@ def remark_module_serialization : Flag<["-"], "Rmodule-serialization">, Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, HelpText<"Emit remarks about module serialization">; -def remark_abi_inference : Flag<["-"], "Rabi-inference">, - Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>, - HelpText<"Emit a remark when an '@abi' attribute adds an attribute or modifier to the ABI declaration based on its presence in the API">; - def emit_tbd : Flag<["-"], "emit-tbd">, HelpText<"Emit a TBD file">, Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>; diff --git a/lib/AST/Attr.cpp b/lib/AST/Attr.cpp index 12631530028cb..5e3f93ab8c77a 100644 --- a/lib/AST/Attr.cpp +++ b/lib/AST/Attr.cpp @@ -61,7 +61,7 @@ static_assert(IsTriviallyDestructible::value, DeclAttribute::APIBreakingToRemove | DeclAttribute::APIStableToRemove), \ #Name " needs to specify either APIBreakingToRemove or APIStableToRemove"); \ static_assert(DeclAttribute::hasOneBehaviorFor##Id(DeclAttribute::InABIAttrMask), \ - #Name " needs to specify exactly one of ForbiddenInABIAttr, UnconstrainedInABIAttr, EquivalentInABIAttr, InferredInABIAttr, or UnreachableInABIAttr"); + #Name " needs to specify exactly one of ForbiddenInABIAttr, UnconstrainedInABIAttr, EquivalentInABIAttr, or UnreachableInABIAttr"); #include "swift/AST/DeclAttr.def" #define TYPE_ATTR(_, Id) \ diff --git a/lib/AST/NameLookup.cpp b/lib/AST/NameLookup.cpp index f1eb3e9967f5f..3ee047c9c434d 100644 --- a/lib/AST/NameLookup.cpp +++ b/lib/AST/NameLookup.cpp @@ -2317,6 +2317,13 @@ void NominalTypeDecl::recordObjCMethod(AbstractFunctionDecl *method, if (!ObjCMethodLookup && !createObjCMethodLookup()) return; + // Only record API decls. + Decl *abiRoleDecl = method; + if (auto accessor = dyn_cast(method)) + abiRoleDecl = accessor->getStorage(); + if (!ABIRoleInfo(abiRoleDecl).providesAPI()) + return; + // Record the method. bool isInstanceMethod = method->isObjCInstanceMethod(); auto &vec = (*ObjCMethodLookup)[{selector, isInstanceMethod}].Methods; diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 3b5430331fb76..b0f625e9a2272 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1422,8 +1422,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args, Opts.EnableSkipExplicitInterfaceModuleBuildRemarks = Args.hasArg(OPT_remark_skip_explicit_interface_build); - Opts.EnableABIInferenceRemarks = Args.hasArg(OPT_remark_abi_inference); - if (Args.hasArg(OPT_experimental_skip_non_exportable_decls)) { // Only allow -experimental-skip-non-exportable-decls if either library // evolution is enabled (in which case the module's ABI is independent of diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index c2903b5cd681a..9ac7df44af22d 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3357,9 +3357,18 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes, } if (abiDecl) { - Attributes.add(new (Context) ABIAttr(abiDecl, - AtLoc, { Loc, rParenLoc }, - /*implicit=*/false)); + auto attr = new (Context) ABIAttr(abiDecl, AtLoc, { Loc, rParenLoc }, + /*implicit=*/false); + + // Diagnose syntactically invalid abiDecl kind here to match behavior of + // Swift parser. + if (!attr->canAppearOnDecl(abiDecl) && !isa(abiDecl)){ + diagnose(abiDecl->getLoc(), diag::attr_abi_incompatible_kind, + abiDecl->getDescriptiveKind()); + attr->setInvalid(); + } + + Attributes.add(attr); } break; diff --git a/lib/SIL/IR/SILDeclRef.cpp b/lib/SIL/IR/SILDeclRef.cpp index 134ecc7d77e8b..5c809011d2c53 100644 --- a/lib/SIL/IR/SILDeclRef.cpp +++ b/lib/SIL/IR/SILDeclRef.cpp @@ -883,6 +883,9 @@ SerializedKind_t SILDeclRef::getSerializedKind() const { auto *d = getDecl(); + ASSERT(ABIRoleInfo(d).providesAPI() + && "should not get serialization info from ABI-only decl"); + // Default and property wrapper argument generators are serialized if the // containing declaration is public. if (isDefaultArgGenerator() || (isPropertyWrapperBackingInitializer() && @@ -1021,6 +1024,9 @@ bool SILDeclRef::isNoinline() const { return false; auto *decl = getDecl(); + ASSERT(ABIRoleInfo(decl).providesAPI() + && "should not get inline attr from ABI-only decl"); + if (auto *attr = decl->getAttrs().getAttribute()) if (attr->getKind() == InlineKind::Never) return true; @@ -1051,6 +1057,9 @@ bool SILDeclRef::isAlwaysInline() const { return false; } + ASSERT(ABIRoleInfo(decl).providesAPI() + && "should not get inline attr from ABI-only decl"); + if (auto attr = decl->getAttrs().getAttribute()) if (attr->getKind() == InlineKind::Always) return true; @@ -1070,6 +1079,10 @@ bool SILDeclRef::isBackDeployed() const { return false; auto *decl = getDecl(); + + ASSERT(ABIRoleInfo(decl).providesAPI() + && "should not get backDeployed from ABI-only decl"); + if (auto afd = dyn_cast(decl)) return afd->isBackDeployed(getASTContext()); @@ -1198,6 +1211,9 @@ static std::string mangleClangDecl(Decl *decl, bool isForeign) { } std::string SILDeclRef::mangle(ManglingKind MKind) const { + ASSERT(!hasDecl() || ABIRoleInfo(getDecl()).providesAPI() + && "SILDeclRef mangling ABI decl directly?"); + using namespace Mangle; ASTMangler mangler(getASTContext()); @@ -1268,9 +1284,6 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const { if (auto *ACE = getAbstractClosureExpr()) return mangler.mangleClosureEntity(ACE, SKind); - ASSERT(ABIRoleInfo(getDecl()).providesAPI() - && "SILDeclRef mangling ABI decl directly?"); - // As a special case, functions can have manually mangled names. // Use the SILGen name only for the original non-thunked, non-curried entry // point. diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 656db55f364ef..a25769193e01d 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -1110,6 +1110,11 @@ void AttributeChecker::visitLazyAttr(LazyAttr *attr) { // are already lazily initialized). if (VD->isStatic() || varDC->isModuleScopeContext()) diagnoseAndRemoveAttr(attr, diag::lazy_on_already_lazy_global); + + // 'lazy' can't be used in or with `@abi` because it has auxiliary decls. + auto abiRole = ABIRoleInfo(D); + if (!abiRole.providesABI() || !abiRole.providesAPI()) + diagnoseAndRemoveAttr(attr, diag::attr_abi_no_lazy); } bool AttributeChecker::visitAbstractAccessControlAttr( @@ -4399,6 +4404,12 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) { } } + // Macros can't be attached to ABI-only decls. (If we diagnosed above, + // don't bother with this.) + if (attr->isValid() && !ABIRoleInfo(D).providesAPI()) { + diagnoseAndRemoveAttr(attr, diag::attr_abi_no_macros, macro); + } + return; } @@ -4480,16 +4491,25 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) { // function, storage with an explicit getter, or parameter of function type. if (nominal->getAttrs().hasAttribute()) { ValueDecl *decl; + ValueDecl *abiRelevantDecl; if (auto param = dyn_cast(D)) { decl = param; + abiRelevantDecl = dyn_cast( + param->getDeclContext()->getAsDecl()); } else if (auto func = dyn_cast(D)) { decl = func; + abiRelevantDecl = func; } else if (auto storage = dyn_cast(D)) { decl = storage; + abiRelevantDecl = storage; // Check whether this is a storage declaration that is not permitted // to have a result builder attached. auto shouldDiagnose = [&]() -> bool { + // We'll diagnose use in @abi later. + if (!ABIRoleInfo(abiRelevantDecl).providesAPI()) + return false; + // An uninitialized stored property in a struct can have a function // builder attached. if (auto var = dyn_cast(decl)) { @@ -4533,6 +4553,14 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) { return; } + // Result builders shouldn't be applied to an ABI-only decl because they + // have no ABI effect. + if (!ABIRoleInfo(abiRelevantDecl).providesAPI()) { + diagnoseAndRemoveAttr(attr, diag::attr_abi_forbidden_attr, + nominal->getNameStr(), /*isModifier=*/false); + return; + } + // Diagnose and ignore arguments. if (attr->hasArgs()) { diagnose(attr->getLocation(), diag::result_builder_arguments) diff --git a/lib/Sema/TypeCheckAttrABI.cpp b/lib/Sema/TypeCheckAttrABI.cpp index 1df97b9d35347..1049b7058f242 100644 --- a/lib/Sema/TypeCheckAttrABI.cpp +++ b/lib/Sema/TypeCheckAttrABI.cpp @@ -880,26 +880,6 @@ class ABIDeclChecker : public ASTComparisonVisitor { return false; - case DeclAttribute::InferredInABIAttr: - if (!abi && api->canClone()) { - // Infer an identical attribute. - abi = api->clone(ctx); - abi->setImplicit(true); - abiDecl->getAttrs().add(abi); - - if (ctx.LangOpts.EnableABIInferenceRemarks) { - SmallString<64> scratch; - auto abiAttrAsString = printAttr(abi, abiDecl, scratch); - - abiDecl->diagnose(diag::abi_attr_inferred_attribute, - abiAttrAsString, api->isDeclModifier()); - noteAttrHere(api, apiDecl, /*isMatch=*/true); - } - } - - // Other than the cloning behavior, Inferred behaves like Equivalent. - LLVM_FALLTHROUGH; - case DeclAttribute::EquivalentInABIAttr: // Diagnose if API doesn't have attribute. if (!api) { @@ -1152,6 +1132,7 @@ void checkABIAttrPBD(PatternBindingDecl *APBD, VarDecl *VD) { } // Check that each pattern has the same number of variables. + bool didDiagnose = false; for (auto i : range(PBD->getNumPatternEntries())) { SmallVector VDs; SmallVector AVDs; @@ -1161,18 +1142,24 @@ void checkABIAttrPBD(PatternBindingDecl *APBD, VarDecl *VD) { if (VDs.size() < AVDs.size()) { for (auto AVD : drop_begin(AVDs, VDs.size())) { - AVD->diagnose(diag::attr_abi_mismatched_var, - AVD, /*isABI=*/true); + AVD->diagnose(diag::attr_abi_mismatched_var, AVD, /*isABI=*/true); + didDiagnose = true; } } else if (VDs.size() > AVDs.size()) { for (auto VD : drop_begin(VDs, AVDs.size())) { - VD->diagnose(diag::attr_abi_mismatched_var, - VD, /*isABI=*/false); + VD->diagnose(diag::attr_abi_mismatched_var, VD, /*isABI=*/false); + didDiagnose = true; } } } + if (didDiagnose) + return; + + // Check the ABI PBD--this is what checks the underlying vars. + TypeChecker::typeCheckDecl(APBD); } + } // end anonymous namespace void TypeChecker::checkDeclABIAttribute(Decl *D, ABIAttr *attr) { diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index ca75adad13021..753b3d376a80f 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -618,15 +618,15 @@ static void checkGenericParams(GenericContext *ownerCtx) { /// Returns \c true if \p current and \p other are in the same source file /// \em and \c current appears before \p other in that file. static bool isBeforeInSameFile(Decl *current, Decl *other) { - if (current->getDeclContext()->getParentSourceFile() != - other->getDeclContext()->getParentSourceFile()) + if (current->getDeclContext()->getOutermostParentSourceFile() != + other->getDeclContext()->getOutermostParentSourceFile()) return false; - if (!current->getLoc().isValid()) + if (current->getLoc().isInvalid() || other->getLoc().isInvalid()) return false; return current->getASTContext().SourceMgr - .isBeforeInBuffer(current->getLoc(), other->getLoc()); + .isBefore(current->getLoc(), other->getLoc()); } template diff --git a/lib/Sema/TypeCheckMacros.cpp b/lib/Sema/TypeCheckMacros.cpp index aca42f25c8a92..2f3e1de638205 100644 --- a/lib/Sema/TypeCheckMacros.cpp +++ b/lib/Sema/TypeCheckMacros.cpp @@ -1395,6 +1395,12 @@ static SourceFile *evaluateAttachedMacro(MacroDecl *macro, Decl *attachedTo, } } + // Macros are so spectacularly not valid in an `@abi` attribute that we cannot + // even attempt to expand them. + if (!ABIRoleInfo(attachedTo).providesAPI()) { + return nullptr; + } + ASTContext &ctx = dc->getASTContext(); auto moduleDecl = dc->getParentModule(); diff --git a/lib/Sema/TypeCheckPropertyWrapper.cpp b/lib/Sema/TypeCheckPropertyWrapper.cpp index 7969b31658b1d..ed8dbea775570 100644 --- a/lib/Sema/TypeCheckPropertyWrapper.cpp +++ b/lib/Sema/TypeCheckPropertyWrapper.cpp @@ -481,11 +481,15 @@ AttachedPropertyWrappersRequest::evaluate(Evaluator &evaluator, continue; } + auto abiRole = ABIRoleInfo(var); + bool hasOrIsABI = !abiRole.providesAPI() || !abiRole.providesABI(); + // Note: Getting the semantic attrs here would trigger a request cycle. auto attachedAttrs = var->getAttrs(); // Check for conflicting attributes. - if (attachedAttrs.hasAttribute() || + if (hasOrIsABI || + attachedAttrs.hasAttribute() || attachedAttrs.hasAttribute() || attachedAttrs.hasAttribute() || (attachedAttrs.hasAttribute() && @@ -498,9 +502,11 @@ AttachedPropertyWrappersRequest::evaluate(Evaluator &evaluator, whichKind = 1; else if (attachedAttrs.hasAttribute()) whichKind = 2; + else if (hasOrIsABI) + whichKind = 3; else { auto attr = attachedAttrs.getAttribute(); - whichKind = 2 + static_cast(attr->get()); + whichKind = 3 + static_cast(attr->get()); } var->diagnose(diag::property_with_wrapper_conflict_attribute, var->getName(), whichKind); diff --git a/lib/Sema/TypeCheckStorage.cpp b/lib/Sema/TypeCheckStorage.cpp index 77aae38980431..23b7034d99c4f 100644 --- a/lib/Sema/TypeCheckStorage.cpp +++ b/lib/Sema/TypeCheckStorage.cpp @@ -849,6 +849,10 @@ IsSetterMutatingRequest::evaluate(Evaluator &evaluator, OpaqueReadOwnership OpaqueReadOwnershipRequest::evaluate(Evaluator &evaluator, AbstractStorageDecl *storage) const { + auto abiRole = ABIRoleInfo(storage); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getOpaqueReadOwnership(); + enum class DiagKind { BorrowedAttr, NoncopyableType @@ -3845,6 +3849,10 @@ void HasStorageRequest::cacheResult(bool hasStorage) const { StorageImplInfo StorageImplInfoRequest::evaluate(Evaluator &evaluator, AbstractStorageDecl *storage) const { + auto abiRole = ABIRoleInfo(storage); + if (!abiRole.providesAPI() && abiRole.getCounterpart()) + return abiRole.getCounterpart()->getImplInfo(); + if (auto *param = dyn_cast(storage)) { return StorageImplInfo::getSimpleStored( param->isImmutableInFunctionBody() diff --git a/test/Macros/macro_expand.swift b/test/Macros/macro_expand.swift index e961b08b960c2..2a6647884a9f6 100644 --- a/test/Macros/macro_expand.swift +++ b/test/Macros/macro_expand.swift @@ -1,23 +1,24 @@ // REQUIRES: swift_swift_parser, executable_test +// REQUIRES: swift_feature_ABIAttribute // RUN: %empty-directory(%t) // RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift // Diagnostics testing -// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS +// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -enable-experimental-feature ABIAttribute // Diagnostics testing by importing macros from a module // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library.swiftmodule %S/Inputs/freestanding_macro_library.swift -module-name freestanding_macro_library -load-plugin-library %t/%target-library-name(MacroDefinition) // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/freestanding_macro_library_2.swiftmodule %S/Inputs/freestanding_macro_library_2.swift -module-name freestanding_macro_library_2 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %t -// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -I %t -DIMPORT_MACRO_LIBRARY +// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -I %t -DIMPORT_MACRO_LIBRARY -enable-experimental-feature ABIAttribute -// RUN: not %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand.dia %s -emit-macro-expansion-files no-diagnostics -Rmacro-loading > %t/macro-printing.txt +// RUN: not %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS -serialize-diagnostics-path %t/macro_expand.dia %s -emit-macro-expansion-files no-diagnostics -Rmacro-loading > %t/macro-printing.txt -enable-experimental-feature ABIAttribute // RUN: c-index-test -read-diagnostics %t/macro_expand.dia 2>&1 | %FileCheck -check-prefix CHECK-DIAGS -dump-input=always %s // RUN: %FileCheck %s --check-prefix CHECK-MACRO-PRINTED < %t/macro-printing.txt -// RUN: not %target-swift-frontend -swift-version 5 -typecheck -diagnostic-style=swift -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS %s > %t/pretty-macro-diagnostics.txt 2>&1 +// RUN: not %target-swift-frontend -swift-version 5 -typecheck -diagnostic-style=swift -load-plugin-library %t/%target-library-name(MacroDefinition) -module-name MacroUser -DTEST_DIAGNOSTICS %s -enable-experimental-feature ABIAttribute > %t/pretty-macro-diagnostics.txt 2>&1 // RUN: %FileCheck %s --check-prefix PRETTY-DIAGS < %t/pretty-macro-diagnostics.txt // Debug info SIL testing @@ -134,6 +135,24 @@ class HasStoredPropertyClassInvalid { #AddStoredProperty((Self.self, 0).1) // expected-note {{in expansion of macro 'AddStoredProperty' here}} // CHECK-DIAGS: @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX[[@LINE-2]]_2_33_{{.*}}AddStoredPropertyfMf_.swift:1:22: error: covariant 'Self' type cannot be referenced from a stored property initializer } + +// Redeclaration checking should behave as though expansions are part of the +// source file. +struct RedeclChecking { + #varValue + + // expected-error@+1 {{invalid redeclaration of 'value'}} + var value: Int { 0 } +} + +// CHECK-DIAGS: macro_expand.swift:[[@LINE-3]]:7: error: invalid redeclaration of 'value' +// CHECK-DIAGS: @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX[[@LINE-8]]_2_33_4361AD9339943F52AE6186DD51E04E91Ll8varValuefMf_.swift:1:5: note: 'value' previously declared here +// CHECK-DIAGS: CONTENTS OF FILE @__swiftmacro_9MacroUser0023macro_expandswift_elFCffMX[[@LINE-9]]_2_33_4361AD9339943F52AE6186DD51E04E91Ll8varValuefMf_.swift: +// CHECK-DIAGS: var value: Int { +// CHECK-DIAGS: 1 +// CHECK-DIAGS: } +// CHECK-DIAGS: END CONTENTS OF FILE + #endif @freestanding(declaration) @@ -667,6 +686,29 @@ func testLocalAccessorMacroWithAutoclosure() { takesAutoclosure(1) } +#if swift(>=1.0) && TEST_DIAGNOSTICS +// Test that macros can't be used in @abi + +struct ABIAttrWithFreestandingMacro1 { + // expected-error@+1 {{cannot use pound literal in '@abi'}} + @abi(#varValue) + #varValue + // expected-note@-1 {{in expansion of macro 'varValue' here}} +} + +struct ABIAttrWithFreestandingMacro2 { + // expected-error@+1 {{cannot use pound literal in '@abi'}} + @abi(#varValue) + var value: Int { 0 } +} + +struct ABIAttrWithFreestandingMacro3 { + @abi(var value: Int) + #varValue +} + +#endif + #if TEST_DIAGNOSTICS @freestanding(expression) macro missingMacro() = #externalMacro(module: "MacroDefinition", type: "BluhBlah") diff --git a/test/Macros/macro_expand_peers.swift b/test/Macros/macro_expand_peers.swift index 99f8febe7fe7f..6f866a6ffd753 100644 --- a/test/Macros/macro_expand_peers.swift +++ b/test/Macros/macro_expand_peers.swift @@ -1,4 +1,5 @@ // REQUIRES: swift_swift_parser, executable_test +// REQUIRES: swift_feature_ABIAttribute // For _Concurrency. // UNSUPPORTED: use_os_stdlib @@ -6,12 +7,12 @@ // RUN: %empty-directory(%t) // RUN: %host-build-swift -swift-version 5 -emit-library -o %t/%target-library-name(MacroDefinition) -parse-as-library -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath -// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -DTEST_DIAGNOSTICS +// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -enable-experimental-feature ABIAttribute -DTEST_DIAGNOSTICS // Check with the imported macro library vs. the local declaration of the macro. // RUN: %target-swift-frontend -swift-version 5 -emit-module -o %t/macro_library.swiftmodule %S/Inputs/macro_library.swift -module-name macro_library -load-plugin-library %t/%target-library-name(MacroDefinition) -// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -DIMPORT_MACRO_LIBRARY -I %t -DTEST_DIAGNOSTICS +// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library -disable-availability-checking -DIMPORT_MACRO_LIBRARY -I %t -enable-experimental-feature ABIAttribute -DTEST_DIAGNOSTICS // RUN: %target-swift-frontend -swift-version 5 -typecheck -load-plugin-library %t/%target-library-name(MacroDefinition) -parse-as-library %s -disable-availability-checking -dump-macro-expansions > %t/expansions-dump.txt 2>&1 @@ -309,3 +310,26 @@ func closuresInPeerMacroCrash() {} @trait(Trait {}) @trait(Trait {}) var closuresInPeerMacroOnVariableCrash: Int = 0 + +// Test that macros can't be used in @abi + +#if TEST_DIAGNOSTICS +struct ABIAttrWithAttachedMacro { + // expected-error@+1 {{macro 'addCompletionHandler()' cannot be expanded in '@abi' attribute}} + @abi(@addCompletionHandler func fn1() async) + @addCompletionHandler func fn1() async {} + // From diagnostics in the expansion: + // expected-note@-2 3{{in expansion of macro 'addCompletionHandler' on instance method 'fn1()' here}} + // expected-note@-4 {{'fn1()' previously declared here}} + + // expected-error@+1 {{macro 'addCompletionHandler()' cannot be expanded in '@abi' attribute}} + @abi(@addCompletionHandler func fn2() async) + func fn2() async {} + + @abi(func fn3() async) + @addCompletionHandler func fn3() async {} + // From diagnostics in the expansion: + // expected-note@-2 2{{in expansion of macro 'addCompletionHandler' on instance method 'fn3()' here}} + // expected-note@-4 {{'fn3()' previously declared here}} +} +#endif diff --git a/test/attr/attr_abi.swift b/test/attr/attr_abi.swift index 96be8a8d29105..76f5fbd929cfd 100644 --- a/test/attr/attr_abi.swift +++ b/test/attr/attr_abi.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature Extern -enable-experimental-feature ABIAttribute -enable-experimental-feature AddressableParameters -enable-experimental-feature NoImplicitCopy -enable-experimental-feature SymbolLinkageMarkers -enable-experimental-feature StrictMemorySafety -enable-experimental-feature LifetimeDependence -enable-experimental-feature CImplementation -import-bridging-header %S/Inputs/attr_abi.h -parse-as-library -Rabi-inference -debugger-support +// RUN: %target-typecheck-verify-swift -enable-experimental-feature Extern -enable-experimental-feature ABIAttribute -enable-experimental-feature AddressableParameters -enable-experimental-feature NoImplicitCopy -enable-experimental-feature SymbolLinkageMarkers -enable-experimental-feature StrictMemorySafety -enable-experimental-feature LifetimeDependence -enable-experimental-feature CImplementation -import-bridging-header %S/Inputs/attr_abi.h -parse-as-library -debugger-support // REQUIRES: swift_feature_ABIAttribute // REQUIRES: swift_feature_AddressableParameters @@ -1267,6 +1267,61 @@ nonisolated func isolation17() async {} @abi(@concurrent func isolation19() async) nonisolated(nonsending) func isolation19() async {} +// CustomAttr for property wrapper -- banned in and with '@abi' +// Banned because we would need to design behavior for its auxiliary decls. +@propertyWrapper struct PropertyWrapper { + var wrappedValue: Int { fatalError() } +} + +struct CustomAttrPropertyWrapper { + @abi(@PropertyWrapper var v1: Int) // expected-error {{property 'v1' with a wrapper cannot also be @abi}} + @PropertyWrapper var v1: Int // expected-error {{property 'v1' with a wrapper cannot also be @abi}} + + @abi(@PropertyWrapper var v2: Int) // expected-error {{property 'v2' with a wrapper cannot also be @abi}} + var v2: Int + + @abi(var v3: Int) + @PropertyWrapper var v3: Int // expected-error {{property 'v3' with a wrapper cannot also be @abi}} +} + +// CustomAttr for attached macro -- see Macros/macro_expand_peers.swift +// Freestanding macro in @abi -- see Macros/macro_expand.swift + +// CustomAttr for result builder -- banned in '@abi' +// Has no ABI impact on either a parameter or a decl. +@resultBuilder struct ResultBuilder { + static func buildBlock(_ values: Int...) -> Int { values.reduce(0, +) } +} + +struct CustomAttrResultBuilder { + @abi(@ResultBuilder var v1: Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}} + @ResultBuilder var v1: Int { 0 } + + @abi(@ResultBuilder var v2: Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}} + var v2: Int { 0 } + + @abi(var v3: Int) + @ResultBuilder var v3: Int { 0 } + + @abi(@ResultBuilder func fn11() -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}} + @ResultBuilder func fn11() -> Int { 0 } + + @abi(@ResultBuilder func fn21() -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{8-22=}} + func fn21() -> Int { 0 } + + @abi(func fn31() -> Int) + @ResultBuilder func fn31() -> Int { 0 } + + @abi(func fn12(@ResultBuilder _: () -> Int) -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{18-32=}} + func fn12(@ResultBuilder _: () -> Int) -> Int { 0 } + + @abi(func fn22(@ResultBuilder _: () -> Int) -> Int) // expected-error {{unused 'ResultBuilder' attribute in '@abi'}} {{18-32=}} + func fn22(_: () -> Int) -> Int { 0 } + + @abi(func fn32(_: () -> Int) -> Int) + func fn32(@ResultBuilder _: () -> Int) -> Int { 0 } +} + // NSCopying - see attr/attr_abi_objc.swift // @LLDBDebuggerFunction -- banned in @abi @@ -1813,45 +1868,48 @@ func section2() {} @abi(func section3()) @_section("fnord") func section3() {} -// @inlinable -- automatically cloned into @abi -@abi(@inlinable func inlinable1()) +// @inlinable -- banned in @abi +// Although the inlining *does* occasionally get mangled, it's only done in the +// SpecializationManglers, which shouldn't get their serialization from an ABI +// attribute. +@abi(@inlinable func inlinable1()) // expected-error {{unused 'inlinable' attribute in '@abi'}} {{6-16=}} @inlinable func inlinable1() {} -@abi(@inlinable func inlinable2()) // expected-error {{extra 'inlinable' attribute in '@abi'}} {{6-16=}} +@abi(@inlinable func inlinable2()) // expected-error {{unused 'inlinable' attribute in '@abi'}} {{6-16=}} func inlinable2() {} -@abi(func inlinable3()) // expected-remark {{inferred '@inlinable' in '@abi' to match attribute on API}} -@inlinable func inlinable3() {} // expected-note {{matches attribute here}} +@abi(func inlinable3()) +@inlinable func inlinable3() {} -// @inline -- automatically cloned into @abi -@abi(@inline(never) func inline1()) +// @inlinable -- banned in @abi +@abi(@inline(never) func inline1()) // expected-error {{unused 'inline(never)' attribute in '@abi'}} {{6-20=}} @inline(never) func inline1() {} -@abi(@inline(never) func inline2()) // expected-error {{extra 'inline(never)' attribute in '@abi'}} {{6-20=}} +@abi(@inline(never) func inline2()) // expected-error {{unused 'inline(never)' attribute in '@abi'}} {{6-20=}} func inline2() {} -@abi(func inline3()) // expected-remark {{inferred '@inline(never)' in '@abi' to match attribute on API}} -@inline(never) func inline3() {} // expected-note {{matches attribute here}} +@abi(func inline3()) +@inline(never) func inline3() {} -// @_transparent -- automatically cloned into @abi -@abi(@_transparent func transparent1()) +// @_transparent -- banned in @abi +@abi(@_transparent func transparent1()) // expected-error {{unused '_transparent' attribute in '@abi'}} {{6-19=}} @_transparent func transparent1() {} -@abi(@_transparent func transparent2()) // expected-error {{extra '_transparent' attribute in '@abi'}} {{6-19=}} +@abi(@_transparent func transparent2()) // expected-error {{unused '_transparent' attribute in '@abi'}} {{6-19=}} func transparent2() {} -@abi(func transparent3()) // expected-remark {{inferred '@_transparent' in '@abi' to match attribute on API}} -@_transparent func transparent3() {} // expected-note {{matches attribute here}} +@abi(func transparent3()) +@_transparent func transparent3() {} -// @_alwaysEmitIntoClient -- automatically cloned into @abi -@abi(@_alwaysEmitIntoClient func alwaysEmitIntoClient1()) +// @_alwaysEmitIntoClient -- banned in @abi +@abi(@_alwaysEmitIntoClient func alwaysEmitIntoClient1()) // expected-error {{unused '_alwaysEmitIntoClient' attribute in '@abi'}} {{6-28=}} @_alwaysEmitIntoClient func alwaysEmitIntoClient1() {} -@abi(@_alwaysEmitIntoClient func alwaysEmitIntoClient2()) // expected-error {{extra '_alwaysEmitIntoClient' attribute in '@abi'}} {{6-28=}} +@abi(@_alwaysEmitIntoClient func alwaysEmitIntoClient2()) // expected-error {{unused '_alwaysEmitIntoClient' attribute in '@abi'}} {{6-28=}} func alwaysEmitIntoClient2() {} -@abi(func alwaysEmitIntoClient3()) // expected-remark {{inferred '@_alwaysEmitIntoClient' in '@abi' to match attribute on API}} -@_alwaysEmitIntoClient func alwaysEmitIntoClient3() {} // expected-note {{matches attribute here}} +@abi(func alwaysEmitIntoClient3()) +@_alwaysEmitIntoClient func alwaysEmitIntoClient3() {} // @_optimize(none) -- banned in @abi @abi(@_optimize(none) func optimize1()) // expected-error {{unused '_optimize(none)' attribute in '@abi'}} {{6-22=}} @@ -1891,16 +1949,17 @@ class Required { required init(i3: Void) { fatalError() } // expected-note {{should match modifier here}} } -// lazy -- automatically cloned into @abi +// lazy -- banned both in and with @abi +// This introduces auxiliary decls whose ABI could not be controlled. class Lazy { - @abi(lazy var v1: Int) - lazy var v1: Int = 0 + @abi(lazy var v1: Int) // expected-error {{'lazy' is not compatible with '@abi' attribute}} {{8-12=}} + lazy var v1: Int = 0 // expected-error {{'lazy' is not compatible with '@abi' attribute}} {{3-8=}} - @abi(lazy var v2: Int) // expected-error {{extra 'lazy' modifier in '@abi'}} {{8-12=}} + @abi(lazy var v2: Int) // expected-error {{'lazy' is not compatible with '@abi' attribute}} {{8-12=}} var v2: Int = 0 - @abi(var v3: Int) // expected-remark {{inferred 'lazy' in '@abi' to match modifier on API}} - lazy var v3: Int = 0 // expected-note {{matches modifier here}} + @abi(var v3: Int) + lazy var v3: Int = 0 // expected-error {{'lazy' is not compatible with '@abi' attribute}} {{3-8=}} } // @_fixed_layout -- banned in @abi @@ -1975,15 +2034,15 @@ extension DynamicReplacement { // @_weakLinked -- tested in attr/attr_weaklinked.swift -// @_borrowed -- automatically cloned into @abi +// @_borrowed -- banned in @abi protocol BorrowedAttr { - @abi(@_borrowed var v1: Int) + @abi(@_borrowed var v1: Int) // expected-error {{unused '_borrowed' attribute in '@abi'}} {{8-18=}} @_borrowed var v1: Int { get set } - @abi(var v2: Int) // expected-remark {{inferred '@_borrowed' in '@abi' to match attribute on API}} - @_borrowed var v2: Int { get set } // expected-note {{matches attribute here}} + @abi(var v2: Int) + @_borrowed var v2: Int { get set } - @abi(@_borrowed var v3: Int) // expected-error {{extra '_borrowed' attribute in '@abi'}} {{8-18=}} + @abi(@_borrowed var v3: Int) // expected-error {{unused '_borrowed' attribute in '@abi'}} {{8-18=}} var v3: Int { get set } } diff --git a/test/attr/attr_abi_objc.swift b/test/attr/attr_abi_objc.swift index 581d1e5ab358a..8f604bf79d8ec 100644 --- a/test/attr/attr_abi_objc.swift +++ b/test/attr/attr_abi_objc.swift @@ -1,4 +1,4 @@ -// RUN: %target-typecheck-verify-swift -enable-experimental-feature ABIAttribute -parse-as-library -Rabi-inference +// RUN: %target-typecheck-verify-swift -enable-experimental-feature ABIAttribute -parse-as-library // REQUIRES: swift_feature_ABIAttribute // REQUIRES: objc_interop