Skip to content

Commit ee9c066

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 95c3011 commit ee9c066

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
@@ -536,6 +536,14 @@ SWIFT_NAME("getter:BridgedPatternBindingInitializer.asDeclContext(self:)")
536536
BridgedDeclContext BridgedPatternBindingInitializer_asDeclContext(
537537
BridgedPatternBindingInitializer cInit);
538538

539+
SWIFT_NAME("BridgedCustomAttributeInitializer.create(declContext:)")
540+
BridgedCustomAttributeInitializer
541+
BridgedCustomAttributeInitializer_create(BridgedDeclContext cDeclContext);
542+
543+
SWIFT_NAME("getter:BridgedCustomAttributeInitializer.asDeclContext(self:)")
544+
BridgedDeclContext BridgedCustomAttributeInitializer_asDeclContext(
545+
BridgedCustomAttributeInitializer cInit);
546+
539547
SWIFT_NAME("getter:BridgedClosureExpr.asDeclContext(self:)")
540548
BridgedDeclContext
541549
BridgedClosureExpr_asDeclContext(BridgedClosureExpr cClosure);
@@ -613,7 +621,7 @@ SWIFT_NAME(
613621
"BridgedCustomAttr.createParsed(_:atLoc:type:initContext:argumentList:)")
614622
BridgedCustomAttr BridgedCustomAttr_createParsed(
615623
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
616-
BridgedNullablePatternBindingInitializer cInitContext,
624+
BridgedNullableCustomAttributeInitializer cInitContext,
617625
BridgedNullableArgumentList cArgumentList);
618626

619627
SWIFT_NAME("BridgedDocumentationAttr.createParsed(_:atLoc:range:metadata:"

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;
@@ -1861,13 +1862,13 @@ class ClangImporterSynthesizedTypeAttr : public DeclAttribute {
18611862
class CustomAttr final : public DeclAttribute {
18621863
TypeExpr *typeExpr;
18631864
ArgumentList *argList;
1864-
PatternBindingInitializer *initContext;
1865+
CustomAttributeInitializer *initContext;
18651866
Expr *semanticInit = nullptr;
18661867

18671868
mutable unsigned isArgUnsafeBit : 1;
18681869

18691870
CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
1870-
PatternBindingInitializer *initContext, ArgumentList *argList,
1871+
CustomAttributeInitializer *initContext, ArgumentList *argList,
18711872
bool implicit);
18721873

18731874
public:
@@ -1878,7 +1879,7 @@ class CustomAttr final : public DeclAttribute {
18781879
}
18791880

18801881
static CustomAttr *create(ASTContext &ctx, SourceLoc atLoc, TypeExpr *type,
1881-
PatternBindingInitializer *initContext,
1882+
CustomAttributeInitializer *initContext,
18821883
ArgumentList *argList, bool implicit = false);
18831884

18841885
TypeExpr *getTypeExpr() const { return typeExpr; }
@@ -1911,7 +1912,7 @@ class CustomAttr final : public DeclAttribute {
19111912
Expr *getSemanticInit() const { return semanticInit; }
19121913
void setSemanticInit(Expr *expr) { semanticInit = expr; }
19131914

1914-
PatternBindingInitializer *getInitContext() const { return initContext; }
1915+
CustomAttributeInitializer *getInitContext() const { return initContext; }
19151916

19161917
static bool classof(const DeclAttribute *DA) {
19171918
return DA->getKind() == DeclAttrKind::Custom;
@@ -3041,6 +3042,10 @@ class DeclAttributes {
30413042
const_cast<const DeclAttributes *>(this)->getEffectiveSendableAttr());
30423043
}
30433044

3045+
/// Try to find the custom attribute initializer within the list of
3046+
/// attributes.
3047+
CustomAttributeInitializer *findCustomAttributeInitializer() const;
3048+
30443049
public:
30453050
template <typename ATTR, bool AllowInvalid>
30463051
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);
@@ -1162,7 +1162,7 @@ class Parser {
11621162
/// Parse a specific attribute.
11631163
ParserStatus parseDeclAttribute(DeclAttributes &Attributes, SourceLoc AtLoc,
11641164
SourceLoc AtEndLoc,
1165-
PatternBindingInitializer *&initContext,
1165+
CustomAttributeInitializer *&initContext,
11661166
bool isFromClangAttribute = false);
11671167

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

11821182
ParserStatus parseNewDeclAttribute(DeclAttributes &Attributes,
11831183
SourceLoc AtLoc, DeclAttrKind DK,
@@ -1479,7 +1479,7 @@ class Parser {
14791479

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

14851485
ParserResult<TypeRepr> parseOldStyleProtocolComposition();

lib/AST/ASTDumper.cpp

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

19131913
case DeclContextKind::Initializer:
1914-
switch (cast<Initializer>(dc)->getInitializerKind()) {
1915-
case InitializerKind::PatternBinding:
1916-
os << "pattern binding initializer";
1917-
break;
1918-
case InitializerKind::DefaultArgument:
1919-
os << "default argument initializer";
1920-
break;
1921-
case InitializerKind::PropertyWrapper:
1922-
os << "property wrapper initializer";
1923-
break;
1924-
}
1914+
simple_display(os, cast<Initializer>(dc));
19251915
break;
19261916

19271917
case DeclContextKind::TopLevelCodeDecl:

lib/AST/ASTMangler.cpp

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

lib/AST/Attr.cpp

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

26342634
CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
2635-
PatternBindingInitializer *initContext,
2635+
CustomAttributeInitializer *initContext,
26362636
ArgumentList *argList, bool implicit)
26372637
: DeclAttribute(DeclAttrKind::Custom, atLoc, range, implicit),
26382638
typeExpr(type), argList(argList), initContext(initContext) {
@@ -2641,7 +2641,7 @@ CustomAttr::CustomAttr(SourceLoc atLoc, SourceRange range, TypeExpr *type,
26412641
}
26422642

26432643
CustomAttr *CustomAttr::create(ASTContext &ctx, SourceLoc atLoc, TypeExpr *type,
2644-
PatternBindingInitializer *initContext,
2644+
CustomAttributeInitializer *initContext,
26452645
ArgumentList *argList, bool implicit) {
26462646
assert(type);
26472647
SourceRange range(atLoc, type->getSourceRange().End);
@@ -2881,3 +2881,13 @@ bool swift::hasAttribute(const LangOptions &langOpts,
28812881

28822882
return false;
28832883
}
2884+
2885+
CustomAttributeInitializer *
2886+
DeclAttributes::findCustomAttributeInitializer() const {
2887+
for (auto custom : getAttributes<CustomAttr>()) {
2888+
if (auto initContext = custom->getInitContext())
2889+
return initContext;
2890+
}
2891+
2892+
return nullptr;
2893+
}

lib/AST/Bridging/DeclAttributeBridging.cpp

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

135135
BridgedCustomAttr BridgedCustomAttr_createParsed(
136136
BridgedASTContext cContext, BridgedSourceLoc cAtLoc, BridgedTypeRepr cType,
137-
BridgedNullablePatternBindingInitializer cInitContext,
137+
BridgedNullableCustomAttributeInitializer cInitContext,
138138
BridgedNullableArgumentList cArgumentList) {
139139
ASTContext &context = cContext.unbridged();
140140
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)