Skip to content

Commit c3fbc6e

Browse files
committed
Introduce a new Initializer subclass for the arguments of custom attributes
Since the introduction of custom attributes (as part of property wrappers), we've modeled the context of expressions within these attributes as PatternBindingInitializers. These PatternBindingInitializers would get wired in to the variable declarations they apply to, establishing the appropriate declaration context hierarchy. This worked because property wrappers only every applied to---you guessed it!---properties, so the PatternBindingInitializer would always get filled in. When custom attributes were extended to apply to anything for the purposes of macros, the use of PatternBindingInitializer became less appropriate. Specifically, the binding declaration would never get filled in (it's always NULL), so any place in the compiler that accesses the binding might have to deal with it being NULL, which is a new requirement. Few did, crashes ensued. Rather than continue to play whack-a-mole with the abused PatternBindingInitializer, introduce a new CustomAttributeInitializer to model the context of custom attribute arguments. When the attributes are assigned to a declaration that has a PatternBindingInitializer, we reparent this new initializer to the PatternBindingInitializer. This helps separate out the logic for custom attributes vs. actual initializers. Fixes swiftlang#76409 / rdar://136997841
1 parent f1a10a0 commit c3fbc6e

21 files changed

+160
-74
lines changed

include/swift/AST/ASTBridging.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,14 @@ SWIFT_NAME("getter:BridgedPatternBindingInitializer.asDeclContext(self:)")
533533
BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
534534
BridgedPatternBindingInitializer cInit);
535535

536+
SWIFT_NAME("BridgedCustomAttributeInitializer.create(declContext:)")
537+
BridgedCustomAttributeInitializer
538+
BridgedCustomAttributeInitializer_create(BridgedDeclContext cDeclContext);
539+
540+
SWIFT_NAME("getter:BridgedCustomAttributeInitializer.asDeclContext(self:)")
541+
BridgedDeclContext BridgedCustomAttributeInitializer_asDeclContext(
542+
BridgedCustomAttributeInitializer cInit);
543+
536544
SWIFT_NAME("getter:BridgedClosureExpr.asDeclContext(self:)")
537545
BridgedDeclContext
538546
BridgedClosureExpr_asDeclContext(BridgedClosureExpr cClosure);
@@ -609,7 +617,7 @@ SWIFT_NAME(
609617
"BridgedCustomAttr.createParsed(_:atLoc:type:initContext:argumentList:)")
610618
BridgedCustomAttr BridgedCustomAttr_createParsed(
611619
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
612-
BridgedNullablePatternBindingInitializer cInitContext,
620+
BridgedNullableCustomAttributeInitializer cInitContext,
613621
BridgedNullableArgumentList cArgumentList);
614622

615623
SWIFT_NAME(

include/swift/AST/ASTBridgingWrappers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ AST_BRIDGING_WRAPPER_NULLABLE(GenericParamList)
8383
AST_BRIDGING_WRAPPER_NULLABLE(TrailingWhereClause)
8484
AST_BRIDGING_WRAPPER_NULLABLE(ParameterList)
8585
AST_BRIDGING_WRAPPER_NULLABLE(PatternBindingInitializer)
86+
AST_BRIDGING_WRAPPER_NULLABLE(CustomAttributeInitializer)
8687
AST_BRIDGING_WRAPPER_NONNULL(TypeAttributes)
8788
AST_BRIDGING_WRAPPER_NONNULL(CustomAttribute)
8889
AST_BRIDGING_WRAPPER_NULLABLE(ArgumentList)

include/swift/AST/Attr.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ class AbstractFunctionDecl;
6060
class FuncDecl;
6161
class ClassDecl;
6262
class AccessorDecl;
63+
class CustomAttributeInitializer;
6364
class GenericFunctionType;
6465
class LazyConformanceLoader;
6566
class LazyMemberLoader;
@@ -1846,13 +1847,13 @@ class ClangImporterSynthesizedTypeAttr : public DeclAttribute {
18461847
class CustomAttr final : public DeclAttribute {
18471848
TypeExpr *typeExpr;
18481849
ArgumentList *argList;
1849-
PatternBindingInitializer *initContext;
1850+
CustomAttributeInitializer *initContext;
18501851
Expr *semanticInit = nullptr;
18511852

18521853
mutable unsigned isArgUnsafeBit : 1;
18531854

18541855
CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
1855-
PatternBindingInitializer *initContext, ArgumentList *argList,
1856+
CustomAttributeInitializer *initContext, ArgumentList *argList,
18561857
bool implicit);
18571858

18581859
public:
@@ -1863,7 +1864,7 @@ class CustomAttr final : public DeclAttribute {
18631864
}
18641865

18651866
static CustomAttr *create(ASTContext &ctx, SourceLoc atLoc, TypeExpr *type,
1866-
PatternBindingInitializer *initContext,
1867+
CustomAttributeInitializer *initContext,
18671868
ArgumentList *argList, bool implicit = false);
18681869

18691870
TypeExpr *getTypeExpr() const { return typeExpr; }
@@ -1896,7 +1897,7 @@ class CustomAttr final : public DeclAttribute {
18961897
Expr *getSemanticInit() const { return semanticInit; }
18971898
void setSemanticInit(Expr *expr) { semanticInit = expr; }
18981899

1899-
PatternBindingInitializer *getInitContext() const { return initContext; }
1900+
CustomAttributeInitializer *getInitContext() const { return initContext; }
19001901

19011902
static bool classof(const DeclAttribute *DA) {
19021903
return DA->getKind() == DeclAttrKind::Custom;
@@ -3064,6 +3065,10 @@ class DeclAttributes {
30643065
const_cast<const DeclAttributes *>(this)->getEffectiveSendableAttr());
30653066
}
30663067

3068+
/// Try to find the custom attribute initializer within the list of
3069+
/// attributes.
3070+
CustomAttributeInitializer *findCustomAttributeInitializer() const;
3071+
30673072
public:
30683073
template <typename ATTR, bool AllowInvalid>
30693074
using AttributeKindRange =

include/swift/AST/Initializer.h

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222

2323
#include "swift/AST/DeclContext.h"
2424

25+
namespace llvm {
26+
class raw_ostream;
27+
}
28+
2529
namespace swift {
2630
class ParamDecl;
2731
class PatternBindingDecl;
@@ -36,6 +40,9 @@ enum class InitializerKind : uint8_t {
3640

3741
/// A property wrapper initialization expression.
3842
PropertyWrapper,
43+
44+
/// An expression within a custom attribute.
45+
CustomAttribute,
3946
};
4047

4148
/// An Initializer is a kind of DeclContext used for expressions that
@@ -176,6 +183,34 @@ class PropertyWrapperInitializer : public Initializer {
176183
}
177184
};
178185

186+
/// An expression within a custom attribute. The parent context is the
187+
/// context in which the attributed declaration occurs.
188+
class CustomAttributeInitializer : public Initializer {
189+
public:
190+
explicit CustomAttributeInitializer(DeclContext *parent)
191+
: Initializer(InitializerKind::CustomAttribute, parent) {}
192+
193+
static CustomAttributeInitializer *create(DeclContext *parent) {
194+
return new (parent->getASTContext()) CustomAttributeInitializer(parent);
195+
}
196+
197+
void setEnclosingInitializer(Initializer *newParent) {
198+
setParent(newParent);
199+
}
200+
201+
static bool classof(const DeclContext *DC) {
202+
if (auto init = dyn_cast<Initializer>(DC))
203+
return classof(init);
204+
return false;
205+
}
206+
207+
static bool classof(const Initializer *I) {
208+
return I->getInitializerKind() == InitializerKind::CustomAttribute;
209+
}
210+
};
211+
212+
void simple_display(llvm::raw_ostream &out, Initializer *init);
213+
179214
} // end namespace swift
180215

181216
#endif

include/swift/Parse/Parser.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -999,7 +999,7 @@ class Parser {
999999
/// Parse an #if ... #endif containing only attributes.
10001000
ParserStatus parseIfConfigAttributes(
10011001
DeclAttributes &attributes, bool ifConfigsAreDeclAttrs,
1002-
PatternBindingInitializer *initContext);
1002+
CustomAttributeInitializer *&initContext);
10031003

10041004
/// Parse a #error or #warning diagnostic.
10051005
ParserResult<PoundDiagnosticDecl> parseDeclPoundDiagnostic();
@@ -1027,7 +1027,7 @@ class Parser {
10271027
/// This is the inner loop, which can be called recursively.
10281028
ParserStatus parseDeclAttributeList(DeclAttributes &Attributes,
10291029
bool IfConfigsAreDeclAttrs,
1030-
PatternBindingInitializer *initContext);
1030+
CustomAttributeInitializer *&initContext);
10311031

10321032
/// Parse the optional attributes before a closure declaration.
10331033
ParserStatus parseClosureDeclAttributeList(DeclAttributes &Attributes);
@@ -1163,7 +1163,7 @@ class Parser {
11631163
/// Parse a specific attribute.
11641164
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
11651165
SourceLoc AtEndLoc,
1166-
PatternBindingInitializer *&initContext,
1166+
CustomAttributeInitializer *&initContext,
11671167
bool isFromClangAttribute = false);
11681168

11691169
bool isCustomAttributeArgument();
@@ -1178,7 +1178,7 @@ class Parser {
11781178
/// will get filled in by this function. The same variable should be provided
11791179
/// for every custom attribute within the same attribute list.
11801180
ParserResult<CustomAttr> parseCustomAttribute(
1181-
SourceLoc atLoc, PatternBindingInitializer *&initContext);
1181+
SourceLoc atLoc, CustomAttributeInitializer *&initContext);
11821182

11831183
ParserStatus parseNewDeclAttribute(DeclAttributes &Attributes,
11841184
SourceLoc AtLoc, DeclAttrKind DK,
@@ -1480,7 +1480,7 @@ class Parser {
14801480

14811481
ParserStatus parseTypeAttribute(TypeOrCustomAttr &result, SourceLoc AtLoc,
14821482
SourceLoc AtEndLoc, ParseTypeReason reason,
1483-
PatternBindingInitializer *&initContext,
1483+
CustomAttributeInitializer *&initContext,
14841484
bool justChecking = false);
14851485

14861486
ParserResult<TypeRepr> parseOldStyleProtocolComposition();

lib/AST/ASTDumper.cpp

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1809,17 +1809,7 @@ void swift::printContext(raw_ostream &os, DeclContext *dc) {
18091809
break;
18101810

18111811
case DeclContextKind::Initializer:
1812-
switch (cast<Initializer>(dc)->getInitializerKind()) {
1813-
case InitializerKind::PatternBinding:
1814-
os << "pattern binding initializer";
1815-
break;
1816-
case InitializerKind::DefaultArgument:
1817-
os << "default argument initializer";
1818-
break;
1819-
case InitializerKind::PropertyWrapper:
1820-
os << "property wrapper initializer";
1821-
break;
1822-
}
1812+
simple_display(os, cast<Initializer>(dc));
18231813
break;
18241814

18251815
case DeclContextKind::TopLevelCodeDecl:

lib/AST/ASTMangler.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2540,6 +2540,12 @@ void ASTMangler::appendContext(const DeclContext *ctx,
25402540
}
25412541
return;
25422542
}
2543+
2544+
case InitializerKind::CustomAttribute: {
2545+
BaseEntitySignature nullBase(nullptr);
2546+
appendContext(ctx->getParent(), nullBase, useModuleName);
2547+
return;
2548+
}
25432549
}
25442550
llvm_unreachable("bad initializer kind");
25452551
}

lib/AST/Attr.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,7 +2899,7 @@ ProtocolDecl *ImplementsAttr::getProtocol(DeclContext *dc) const {
28992899
}
29002900

29012901
CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
2902-
PatternBindingInitializer *initContext,
2902+
CustomAttributeInitializer *initContext,
29032903
ArgumentList *argList, bool implicit)
29042904
: DeclAttribute(DeclAttrKind::Custom, atLoc, range, implicit),
29052905
typeExpr(type), argList(argList), initContext(initContext) {
@@ -2908,7 +2908,7 @@ CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
29082908
}
29092909

29102910
CustomAttr *CustomAttr::create(ASTContext &ctx, SourceLoc atLoc, TypeExpr *type,
2911-
PatternBindingInitializer *initContext,
2911+
CustomAttributeInitializer *initContext,
29122912
ArgumentList *argList, bool implicit) {
29132913
assert(type);
29142914
SourceRange range(atLoc, type->getSourceRange().End);
@@ -3148,3 +3148,13 @@ bool swift::hasAttribute(const LangOptions &langOpts,
31483148

31493149
return false;
31503150
}
3151+
3152+
CustomAttributeInitializer *
3153+
DeclAttributes::findCustomAttributeInitializer() const {
3154+
for (auto custom : getAttributes<CustomAttr>()) {
3155+
if (auto initContext = custom->getInitContext())
3156+
return initContext;
3157+
}
3158+
3159+
return nullptr;
3160+
}

lib/AST/Bridging/DeclAttributeBridging.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ BridgedCDeclAttr BridgedCDeclAttr_createParsed(BridgedASTContext cContext,
132132

133133
BridgedCustomAttr BridgedCustomAttr_createParsed(
134134
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
135-
BridgedNullablePatternBindingInitializer cInitContext,
135+
BridgedNullableCustomAttributeInitializer cInitContext,
136136
BridgedNullableArgumentList cArgumentList) {
137137
ASTContext &context = cContext.unbridged();
138138
return CustomAttr::create(

lib/AST/Bridging/DeclContextBridging.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
3131
return cInit.unbridged();
3232
}
3333

34+
BridgedCustomAttributeInitializer
35+
BridgedCustomAttributeInitializer_create(BridgedDeclContext cDeclContext) {
36+
return CustomAttributeInitializer::create(cDeclContext.unbridged());
37+
}
38+
39+
BridgedDeclContext BridgedCustomAttributeInitializer_asDeclContext(
40+
BridgedCustomAttributeInitializer cInit) {
41+
return cInit.unbridged();
42+
}
43+
3444
BridgedDeclContext
3545
BridgedClosureExpr_asDeclContext(BridgedClosureExpr cClosure) {
3646
return cClosure.unbridged();

0 commit comments

Comments
 (0)