Skip to content

Commit 196f787

Browse files
authored
Merge pull request #80383 from beccadax/abi-inspected-your-appearance-again
More `@abi` checking
2 parents 5ed3342 + 97bb6b1 commit 196f787

22 files changed

+251
-99
lines changed

include/swift/AST/Attr.h

+2-9
Original file line numberDiff line numberDiff line change
@@ -380,21 +380,14 @@ class DeclAttribute : public AttributeBase {
380380
/// valid if they match.
381381
EquivalentInABIAttr = 1ull << 18,
382382

383-
/// Attribute can be used in an \c \@abi attribute, but must match
384-
/// equivalent on API decl; if omitted, API decl's attribute will be
385-
/// cloned. Use where you would want to use \c EquivalentInABIAttr but
386-
/// repeating the attribute is judged too burdensome.
387-
InferredInABIAttr = 1ull << 19,
388-
389383
/// Use for attributes which are \em only valid on declarations that cannot
390384
/// have an \c @abi attribute, such as \c ImportDecl .
391-
UnreachableInABIAttr = 1ull << 20,
385+
UnreachableInABIAttr = 1ull << 19,
392386
};
393387

394388
enum : uint64_t {
395389
InABIAttrMask = ForbiddenInABIAttr | UnconstrainedInABIAttr
396-
| EquivalentInABIAttr | InferredInABIAttr
397-
| UnreachableInABIAttr
390+
| EquivalentInABIAttr | UnreachableInABIAttr
398391
};
399392

400393
LLVM_READNONE

include/swift/AST/DeclAttr.def

+6-6
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ SIMPLE_DECL_ATTR(NSManaged, NSManaged,
143143

144144
CONTEXTUAL_SIMPLE_DECL_ATTR(lazy, Lazy,
145145
OnVar,
146-
DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr,
146+
DeclModifier | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | UnconstrainedInABIAttr,
147147
16)
148148

149149
SIMPLE_DECL_ATTR(LLDBDebuggerFunction, LLDBDebuggerFunction,
@@ -163,7 +163,7 @@ SIMPLE_DECL_ATTR(unsafe_no_objc_tagged_pointer, UnsafeNoObjCTaggedPointer,
163163

164164
DECL_ATTR(inline, Inline,
165165
OnVar | OnSubscript | OnAbstractFunction,
166-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr,
166+
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
167167
20)
168168

169169
DECL_ATTR(_semantics, Semantics,
@@ -193,7 +193,7 @@ CONTEXTUAL_SIMPLE_DECL_ATTR(postfix, Postfix,
193193

194194
SIMPLE_DECL_ATTR(_transparent, Transparent,
195195
OnFunc | OnAccessor | OnConstructor | OnVar | OnDestructor,
196-
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr,
196+
UserInaccessible | ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
197197
26)
198198

199199
SIMPLE_DECL_ATTR(requires_stored_property_inits, RequiresStoredPropertyInits,
@@ -216,7 +216,7 @@ SIMPLE_DECL_ATTR(_fixed_layout, FixedLayout,
216216

217217
SIMPLE_DECL_ATTR(inlinable, Inlinable,
218218
OnVar | OnSubscript | OnAbstractFunction,
219-
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr,
219+
ABIStableToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
220220
32)
221221

222222
DECL_ATTR(_specialize, Specialize,
@@ -456,7 +456,7 @@ DECL_ATTR(_dynamicReplacement, DynamicReplacement,
456456

457457
SIMPLE_DECL_ATTR(_borrowed, Borrowed,
458458
OnVar | OnSubscript,
459-
UserInaccessible | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr,
459+
UserInaccessible | NotSerialized | ABIBreakingToAdd | ABIBreakingToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
460460
81)
461461

462462
DECL_ATTR(_private, PrivateImport,
@@ -466,7 +466,7 @@ DECL_ATTR(_private, PrivateImport,
466466

467467
SIMPLE_DECL_ATTR(_alwaysEmitIntoClient, AlwaysEmitIntoClient,
468468
OnVar | OnSubscript | OnAbstractFunction,
469-
UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | InferredInABIAttr,
469+
UserInaccessible | ABIBreakingToAdd | ABIStableToRemove | APIStableToAdd | APIStableToRemove | ForbiddenInABIAttr,
470470
83)
471471

472472
SIMPLE_DECL_ATTR(_implementationOnly, ImplementationOnly,

include/swift/AST/DiagnosticsParse.def

+5
Original file line numberDiff line numberDiff line change
@@ -1571,6 +1571,11 @@ ERROR(attr_unsupported_on_target, none,
15711571
ERROR(attr_name_unsupported_on_target, none,
15721572
"attribute '%0' is unsupported on target '%1'", (StringRef, StringRef))
15731573

1574+
// abi attribute
1575+
ERROR(attr_abi_incompatible_kind,none,
1576+
"cannot use %0 in '@abi'",
1577+
(DescriptiveDeclKind))
1578+
15741579
// availability
15751580
ERROR(attr_availability_platform,none,
15761581
"expected platform name or '*' for '%0' attribute", (StringRef))

include/swift/AST/DiagnosticsSema.def

+8-4
Original file line numberDiff line numberDiff line change
@@ -7457,7 +7457,7 @@ ERROR(property_wrapper_effectful,none,
74577457

74587458
ERROR(property_with_wrapper_conflict_attribute,none,
74597459
"property %0 with a wrapper cannot also be "
7460-
"%select{lazy|@NSCopying|@NSManaged|weak|unowned|unmanaged}1",
7460+
"%select{lazy|@NSCopying|@NSManaged|@abi|weak|unowned|unmanaged}1",
74617461
(Identifier, int))
74627462
ERROR(property_wrapper_not_single_var, none,
74637463
"property wrapper can only apply to a single variable", ())
@@ -8467,9 +8467,6 @@ ERROR(attr_abi_extra_attr,none,
84678467
ERROR(attr_abi_forbidden_attr,none,
84688468
"unused '%0' %select{attribute|modifier}1 in '@abi'",
84698469
(StringRef, bool))
8470-
REMARK(abi_attr_inferred_attribute,none,
8471-
"inferred '%0' in '@abi' to match %select{attribute|modifier}1 on API",
8472-
(StringRef, bool))
84738470

84748471
ERROR(attr_abi_mismatched_attr,none,
84758472
"'%0' %select{attribute|modifier}1 in '@abi' should match '%2'",
@@ -8509,6 +8506,13 @@ ERROR(attr_abi_no_default_arguments,none,
85098506
"affect the parameter's ABI",
85108507
(Decl *))
85118508
8509+
ERROR(attr_abi_no_macros,none,
8510+
"%kind0 cannot be expanded in '@abi' attribute",
8511+
(Decl *))
8512+
ERROR(attr_abi_no_lazy,none,
8513+
"'lazy' is not compatible with '@abi' attribute",
8514+
())
8515+
85128516
// These macros insert 'final', 'non-final', or nothing depending on both the
85138517
// current decl and its counterpart, such that 'non-final' is used if the
85148518
// counterpart would be described as 'final' or 'static'. They must be kept in

include/swift/Basic/LangOptions.h

-3
Original file line numberDiff line numberDiff line change
@@ -269,9 +269,6 @@ namespace swift {
269269
/// Emit a remark on early exit in explicit interface build
270270
bool EnableSkipExplicitInterfaceModuleBuildRemarks = false;
271271

272-
/// Emit a remark when \c \@abi infers an attribute or modifier.
273-
bool EnableABIInferenceRemarks = false;
274-
275272
///
276273
/// Support for alternate usage modes
277274
///

include/swift/Option/Options.td

-4
Original file line numberDiff line numberDiff line change
@@ -468,10 +468,6 @@ def remark_module_serialization : Flag<["-"], "Rmodule-serialization">,
468468
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
469469
HelpText<"Emit remarks about module serialization">;
470470

471-
def remark_abi_inference : Flag<["-"], "Rabi-inference">,
472-
Flags<[FrontendOption, DoesNotAffectIncrementalBuild]>,
473-
HelpText<"Emit a remark when an '@abi' attribute adds an attribute or modifier to the ABI declaration based on its presence in the API">;
474-
475471
def emit_tbd : Flag<["-"], "emit-tbd">,
476472
HelpText<"Emit a TBD file">,
477473
Flags<[FrontendOption, NoInteractiveOption, SupplementaryOutput]>;

lib/AST/Attr.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ static_assert(IsTriviallyDestructible<DeclAttributes>::value,
6161
DeclAttribute::APIBreakingToRemove | DeclAttribute::APIStableToRemove), \
6262
#Name " needs to specify either APIBreakingToRemove or APIStableToRemove"); \
6363
static_assert(DeclAttribute::hasOneBehaviorFor##Id(DeclAttribute::InABIAttrMask), \
64-
#Name " needs to specify exactly one of ForbiddenInABIAttr, UnconstrainedInABIAttr, EquivalentInABIAttr, InferredInABIAttr, or UnreachableInABIAttr");
64+
#Name " needs to specify exactly one of ForbiddenInABIAttr, UnconstrainedInABIAttr, EquivalentInABIAttr, or UnreachableInABIAttr");
6565
#include "swift/AST/DeclAttr.def"
6666

6767
#define TYPE_ATTR(_, Id) \

lib/AST/FeatureSet.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -709,8 +709,12 @@ FeatureSet swift::getUniqueFeaturesUsed(Decl *decl) {
709709
// Remove all the features used by all enclosing declarations.
710710
Decl *enclosingDecl = decl;
711711
while (!features.empty()) {
712+
// If we were in an @abi attribute, collect from the API counterpart.
713+
auto abiRole = ABIRoleInfo(enclosingDecl);
714+
if (!abiRole.providesAPI() && abiRole.getCounterpart())
715+
enclosingDecl = abiRole.getCounterpart();
712716
// Find the next outermost enclosing declaration.
713-
if (auto accessor = dyn_cast<AccessorDecl>(enclosingDecl))
717+
else if (auto accessor = dyn_cast<AccessorDecl>(enclosingDecl))
714718
enclosingDecl = accessor->getStorage();
715719
else
716720
enclosingDecl = enclosingDecl->getDeclContext()->getAsDecl();

lib/AST/NameLookup.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -2317,6 +2317,13 @@ void NominalTypeDecl::recordObjCMethod(AbstractFunctionDecl *method,
23172317
if (!ObjCMethodLookup && !createObjCMethodLookup())
23182318
return;
23192319

2320+
// Only record API decls.
2321+
Decl *abiRoleDecl = method;
2322+
if (auto accessor = dyn_cast<AccessorDecl>(method))
2323+
abiRoleDecl = accessor->getStorage();
2324+
if (!ABIRoleInfo(abiRoleDecl).providesAPI())
2325+
return;
2326+
23202327
// Record the method.
23212328
bool isInstanceMethod = method->isObjCInstanceMethod();
23222329
auto &vec = (*ObjCMethodLookup)[{selector, isInstanceMethod}].Methods;

lib/Frontend/CompilerInvocation.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -1422,8 +1422,6 @@ static bool ParseLangArgs(LangOptions &Opts, ArgList &Args,
14221422

14231423
Opts.EnableSkipExplicitInterfaceModuleBuildRemarks = Args.hasArg(OPT_remark_skip_explicit_interface_build);
14241424

1425-
Opts.EnableABIInferenceRemarks = Args.hasArg(OPT_remark_abi_inference);
1426-
14271425
if (Args.hasArg(OPT_experimental_skip_non_exportable_decls)) {
14281426
// Only allow -experimental-skip-non-exportable-decls if either library
14291427
// evolution is enabled (in which case the module's ABI is independent of

lib/Parse/ParseDecl.cpp

+12-3
Original file line numberDiff line numberDiff line change
@@ -3359,9 +3359,18 @@ ParserStatus Parser::parseNewDeclAttribute(DeclAttributes &Attributes,
33593359
}
33603360

33613361
if (abiDecl) {
3362-
Attributes.add(new (Context) ABIAttr(abiDecl,
3363-
AtLoc, { Loc, rParenLoc },
3364-
/*implicit=*/false));
3362+
auto attr = new (Context) ABIAttr(abiDecl, AtLoc, { Loc, rParenLoc },
3363+
/*implicit=*/false);
3364+
3365+
// Diagnose syntactically invalid abiDecl kind here to match behavior of
3366+
// Swift parser.
3367+
if (!attr->canAppearOnDecl(abiDecl) && !isa<PatternBindingDecl>(abiDecl)){
3368+
diagnose(abiDecl->getLoc(), diag::attr_abi_incompatible_kind,
3369+
abiDecl->getDescriptiveKind());
3370+
attr->setInvalid();
3371+
}
3372+
3373+
Attributes.add(attr);
33653374
}
33663375

33673376
break;

lib/SIL/IR/SILDeclRef.cpp

+16-3
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,9 @@ SerializedKind_t SILDeclRef::getSerializedKind() const {
883883

884884
auto *d = getDecl();
885885

886+
ASSERT(ABIRoleInfo(d).providesAPI()
887+
&& "should not get serialization info from ABI-only decl");
888+
886889
// Default and property wrapper argument generators are serialized if the
887890
// containing declaration is public.
888891
if (isDefaultArgGenerator() || (isPropertyWrapperBackingInitializer() &&
@@ -1021,6 +1024,9 @@ bool SILDeclRef::isNoinline() const {
10211024
return false;
10221025

10231026
auto *decl = getDecl();
1027+
ASSERT(ABIRoleInfo(decl).providesAPI()
1028+
&& "should not get inline attr from ABI-only decl");
1029+
10241030
if (auto *attr = decl->getAttrs().getAttribute<InlineAttr>())
10251031
if (attr->getKind() == InlineKind::Never)
10261032
return true;
@@ -1051,6 +1057,9 @@ bool SILDeclRef::isAlwaysInline() const {
10511057
return false;
10521058
}
10531059

1060+
ASSERT(ABIRoleInfo(decl).providesAPI()
1061+
&& "should not get inline attr from ABI-only decl");
1062+
10541063
if (auto attr = decl->getAttrs().getAttribute<InlineAttr>())
10551064
if (attr->getKind() == InlineKind::Always)
10561065
return true;
@@ -1070,6 +1079,10 @@ bool SILDeclRef::isBackDeployed() const {
10701079
return false;
10711080

10721081
auto *decl = getDecl();
1082+
1083+
ASSERT(ABIRoleInfo(decl).providesAPI()
1084+
&& "should not get backDeployed from ABI-only decl");
1085+
10731086
if (auto afd = dyn_cast<AbstractFunctionDecl>(decl))
10741087
return afd->isBackDeployed(getASTContext());
10751088

@@ -1198,6 +1211,9 @@ static std::string mangleClangDecl(Decl *decl, bool isForeign) {
11981211
}
11991212

12001213
std::string SILDeclRef::mangle(ManglingKind MKind) const {
1214+
ASSERT(!hasDecl() || ABIRoleInfo(getDecl()).providesAPI()
1215+
&& "SILDeclRef mangling ABI decl directly?");
1216+
12011217
using namespace Mangle;
12021218
ASTMangler mangler(getASTContext());
12031219

@@ -1268,9 +1284,6 @@ std::string SILDeclRef::mangle(ManglingKind MKind) const {
12681284
if (auto *ACE = getAbstractClosureExpr())
12691285
return mangler.mangleClosureEntity(ACE, SKind);
12701286

1271-
ASSERT(ABIRoleInfo(getDecl()).providesAPI()
1272-
&& "SILDeclRef mangling ABI decl directly?");
1273-
12741287
// As a special case, functions can have manually mangled names.
12751288
// Use the SILGen name only for the original non-thunked, non-curried entry
12761289
// point.

lib/Sema/TypeCheckAttr.cpp

+28
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,11 @@ void AttributeChecker::visitLazyAttr(LazyAttr *attr) {
11101110
// are already lazily initialized).
11111111
if (VD->isStatic() || varDC->isModuleScopeContext())
11121112
diagnoseAndRemoveAttr(attr, diag::lazy_on_already_lazy_global);
1113+
1114+
// 'lazy' can't be used in or with `@abi` because it has auxiliary decls.
1115+
auto abiRole = ABIRoleInfo(D);
1116+
if (!abiRole.providesABI() || !abiRole.providesAPI())
1117+
diagnoseAndRemoveAttr(attr, diag::attr_abi_no_lazy);
11131118
}
11141119

11151120
bool AttributeChecker::visitAbstractAccessControlAttr(
@@ -4406,6 +4411,12 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
44064411
}
44074412
}
44084413

4414+
// Macros can't be attached to ABI-only decls. (If we diagnosed above,
4415+
// don't bother with this.)
4416+
if (attr->isValid() && !ABIRoleInfo(D).providesAPI()) {
4417+
diagnoseAndRemoveAttr(attr, diag::attr_abi_no_macros, macro);
4418+
}
4419+
44094420
return;
44104421
}
44114422

@@ -4487,16 +4498,25 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
44874498
// function, storage with an explicit getter, or parameter of function type.
44884499
if (nominal->getAttrs().hasAttribute<ResultBuilderAttr>()) {
44894500
ValueDecl *decl;
4501+
ValueDecl *abiRelevantDecl;
44904502
if (auto param = dyn_cast<ParamDecl>(D)) {
44914503
decl = param;
4504+
abiRelevantDecl = dyn_cast<ValueDecl>(
4505+
param->getDeclContext()->getAsDecl());
44924506
} else if (auto func = dyn_cast<FuncDecl>(D)) {
44934507
decl = func;
4508+
abiRelevantDecl = func;
44944509
} else if (auto storage = dyn_cast<AbstractStorageDecl>(D)) {
44954510
decl = storage;
4511+
abiRelevantDecl = storage;
44964512

44974513
// Check whether this is a storage declaration that is not permitted
44984514
// to have a result builder attached.
44994515
auto shouldDiagnose = [&]() -> bool {
4516+
// We'll diagnose use in @abi later.
4517+
if (!ABIRoleInfo(abiRelevantDecl).providesAPI())
4518+
return false;
4519+
45004520
// An uninitialized stored property in a struct can have a function
45014521
// builder attached.
45024522
if (auto var = dyn_cast<VarDecl>(decl)) {
@@ -4540,6 +4560,14 @@ void AttributeChecker::visitCustomAttr(CustomAttr *attr) {
45404560
return;
45414561
}
45424562

4563+
// Result builders shouldn't be applied to an ABI-only decl because they
4564+
// have no ABI effect.
4565+
if (!ABIRoleInfo(abiRelevantDecl).providesAPI()) {
4566+
diagnoseAndRemoveAttr(attr, diag::attr_abi_forbidden_attr,
4567+
nominal->getNameStr(), /*isModifier=*/false);
4568+
return;
4569+
}
4570+
45434571
// Diagnose and ignore arguments.
45444572
if (attr->hasArgs()) {
45454573
diagnose(attr->getLocation(), diag::result_builder_arguments)

0 commit comments

Comments
 (0)