Skip to content

Commit 81492d1

Browse files
committed
[Macros] Requestify member attribute macro expansion directly.
Having a request for semantic declaration attributes while still allowing the original linked list to be mutated directly can cause use-after-frees on pointers to old decl attributes. For now, introduce a request that expands member attribute macros with a side effect of adding the new attributes to the list. We can revisit this once attribute mutation via getAttrs() is audited across the frontend.
1 parent 6fcd3f6 commit 81492d1

8 files changed

+87
-139
lines changed

include/swift/AST/Attr.h

-49
Original file line numberDiff line numberDiff line change
@@ -2613,55 +2613,6 @@ class DeclAttributes {
26132613
SourceLoc getStartLoc(bool forModifiers = false) const;
26142614
};
26152615

2616-
/// Semantic attributes that are applied to a declaration.
2617-
///
2618-
/// This attribute list can include attributes that are not written in
2619-
/// source on a declaration, such as attributes that are applied during
2620-
/// macro expansion or inferred from the declaration context.
2621-
class SemanticDeclAttributes {
2622-
llvm::SmallVector<DeclAttribute *, 4> attrList;
2623-
2624-
public:
2625-
SemanticDeclAttributes() {}
2626-
2627-
/// Add a constructed DeclAttribute to this list.
2628-
void add(DeclAttribute *attr) {
2629-
attrList.push_back(attr);
2630-
}
2631-
2632-
using SemanticAttrList = llvm::SmallVectorImpl<DeclAttribute *>;
2633-
2634-
template <typename AttrType, bool AllowInvalid>
2635-
using AttributeKindRange =
2636-
OptionalTransformRange<iterator_range<SemanticAttrList::const_iterator>,
2637-
ToAttributeKind<AttrType, AllowInvalid>,
2638-
SemanticAttrList::const_iterator>;
2639-
2640-
template <typename AttrType, bool AllowInvalid = false>
2641-
AttributeKindRange<AttrType, AllowInvalid> getAttributes() const {
2642-
return AttributeKindRange<AttrType, AllowInvalid>(
2643-
make_range(attrList.begin(), attrList.end()),
2644-
ToAttributeKind<AttrType, AllowInvalid>());
2645-
}
2646-
2647-
/// Retrieve the first attribute of the given attribute class.
2648-
template <typename AttrType>
2649-
const AttrType *getAttribute(bool allowInvalid = false) const {
2650-
for (auto attr : attrList)
2651-
if (auto *specificAttr = dyn_cast<AttrType>(attr))
2652-
if (specificAttr->isValid() || allowInvalid)
2653-
return specificAttr;
2654-
2655-
return nullptr;
2656-
}
2657-
2658-
/// Determine whether there is an attribute with the given attribute class.
2659-
template <typename AttrType>
2660-
bool hasAttribute(bool allowInvalid = false) const {
2661-
return getAttribute<AttrType>(allowInvalid) != nullptr;
2662-
}
2663-
};
2664-
26652616
/// TypeAttributes - These are attributes that may be applied to types.
26662617
class TypeAttributes {
26672618
// Get a SourceLoc for every possible attribute that can be parsed in source.

include/swift/AST/Decl.h

+4-5
Original file line numberDiff line numberDiff line change
@@ -850,11 +850,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
850850
return Attrs;
851851
}
852852

853-
/// Returns the semantic attributes attached to this declaration.
854-
///
855-
/// \c getSemanticAttrs is intended to be a requestified replacement
856-
/// for \c getAttrs
857-
SemanticDeclAttributes getSemanticAttrs() const;
853+
/// Returns the semantic attributes attached to this declaration,
854+
/// including attributes that are generated as the result of member
855+
/// attribute macro expansion.
856+
DeclAttributes getSemanticAttrs() const;
858857

859858
/// Returns the innermost enclosing decl with an availability annotation.
860859
const Decl *getInnermostDeclWithAvailability() const;

include/swift/AST/TypeCheckRequests.h

+18-20
Original file line numberDiff line numberDiff line change
@@ -742,26 +742,6 @@ class AttachedPropertyWrappersRequest :
742742
bool isCached() const { return true; }
743743
};
744744

745-
/// Request the semantic attributes attached to the given declaration.
746-
class AttachedSemanticAttrsRequest :
747-
public SimpleRequest<AttachedSemanticAttrsRequest,
748-
SemanticDeclAttributes(Decl *),
749-
RequestFlags::Cached> {
750-
public:
751-
using SimpleRequest::SimpleRequest;
752-
753-
private:
754-
friend SimpleRequest;
755-
756-
// Evaluation.
757-
SemanticDeclAttributes
758-
evaluate(Evaluator &evaluator, Decl *decl) const;
759-
760-
public:
761-
// Caching
762-
bool isCached() const { return true; }
763-
};
764-
765745
/// Request the raw (possibly unbound generic) type of the property wrapper
766746
/// that is attached to the given variable.
767747
class AttachedPropertyWrapperTypeRequest :
@@ -3840,6 +3820,24 @@ class ExpandMacroExpansionDeclRequest
38403820
bool isCached() const { return true; }
38413821
};
38423822

3823+
/// Expand all member attribute macros attached to the given
3824+
/// declaration.
3825+
class ExpandMemberAttributeMacros
3826+
: public SimpleRequest<ExpandMemberAttributeMacros,
3827+
bool(Decl *),
3828+
RequestFlags::Cached> {
3829+
public:
3830+
using SimpleRequest::SimpleRequest;
3831+
3832+
private:
3833+
friend SimpleRequest;
3834+
3835+
bool evaluate(Evaluator &evaluator, Decl *decl) const;
3836+
3837+
public:
3838+
bool isCached() const { return true; }
3839+
};
3840+
38433841
/// Resolve an external macro given its module and type name.
38443842
class ExternalMacroDefinitionRequest
38453843
: public SimpleRequest<ExternalMacroDefinitionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

+3-3
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,6 @@ SWIFT_REQUEST(TypeChecker, AttachedPropertyWrapperTypeRequest,
2929
SWIFT_REQUEST(TypeChecker, AttachedPropertyWrappersRequest,
3030
llvm::TinyPtrVector<CustomAttr *>(VarDecl *), Cached,
3131
NoLocationInfo)
32-
SWIFT_REQUEST(TypeChecker, AttachedSemanticAttrsRequest,
33-
SemanticDeclAttributes(Decl *), Cached,
34-
NoLocationInfo)
3532
SWIFT_REQUEST(TypeChecker, CallerSideDefaultArgExprRequest,
3633
Expr *(DefaultArgumentExpr *), SeparatelyCached, NoLocationInfo)
3734
SWIFT_REQUEST(TypeChecker, CheckInconsistentImplementationOnlyImportsRequest,
@@ -455,6 +452,9 @@ SWIFT_REQUEST(TypeChecker, ExternalMacroDefinitionRequest,
455452
SWIFT_REQUEST(TypeChecker, ExpandMacroExpansionDeclRequest,
456453
ArrayRef<Decl *>(MacroExpansionDecl *),
457454
Cached, NoLocationInfo)
455+
SWIFT_REQUEST(TypeChecker, ExpandMemberAttributeMacros,
456+
bool(Decl *),
457+
Cached, NoLocationInfo)
458458
SWIFT_REQUEST(TypeChecker, SynthesizeRuntimeMetadataAttrGenerator,
459459
Expr *(CustomAttr *, ValueDecl *),
460460
Cached, NoLocationInfo)

lib/AST/Decl.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -365,11 +365,13 @@ StringRef Decl::getDescriptiveKindName(DescriptiveDeclKind K) {
365365
llvm_unreachable("bad DescriptiveDeclKind");
366366
}
367367

368-
SemanticDeclAttributes Decl::getSemanticAttrs() const {
368+
DeclAttributes Decl::getSemanticAttrs() const {
369369
auto mutableThis = const_cast<Decl *>(this);
370-
return evaluateOrDefault(getASTContext().evaluator,
371-
AttachedSemanticAttrsRequest{mutableThis},
372-
SemanticDeclAttributes());
370+
evaluateOrDefault(getASTContext().evaluator,
371+
ExpandMemberAttributeMacros{mutableThis},
372+
false);
373+
374+
return getAttrs();
373375
}
374376

375377
const Decl *Decl::getInnermostDeclWithAvailability() const {

lib/Sema/TypeCheckAttr.cpp

-39
Original file line numberDiff line numberDiff line change
@@ -7385,45 +7385,6 @@ ValueDecl *RenamedDeclRequest::evaluate(Evaluator &evaluator,
73857385
return renamedDecl;
73867386
}
73877387

7388-
SemanticDeclAttributes
7389-
AttachedSemanticAttrsRequest::evaluate(Evaluator &evaluator, Decl *decl) const {
7390-
// For now, this returns the same thing as 'getAttrs' using
7391-
// the SemanticDeclAttribtues representation.
7392-
SemanticDeclAttributes semanticAttrs;
7393-
for (auto attr : decl->getAttrs()) {
7394-
semanticAttrs.add(attr);
7395-
}
7396-
7397-
auto *parentDecl = decl->getDeclContext()->getAsDecl();
7398-
if (!parentDecl)
7399-
return semanticAttrs;
7400-
7401-
auto parentAttrs = parentDecl->getSemanticAttrs();
7402-
for (auto customAttrConst: parentAttrs.getAttributes<CustomAttr>()) {
7403-
auto customAttr = const_cast<CustomAttr *>(customAttrConst);
7404-
auto customAttrDecl = evaluateOrDefault(
7405-
evaluator,
7406-
CustomAttrDeclRequest{
7407-
customAttr,
7408-
parentDecl->getInnermostDeclContext()
7409-
},
7410-
nullptr);
7411-
if (!customAttrDecl)
7412-
continue;
7413-
7414-
auto macroDecl = customAttrDecl.dyn_cast<MacroDecl *>();
7415-
if (!macroDecl)
7416-
continue;
7417-
7418-
if (!macroDecl->getMacroRoles().contains(MacroRole::MemberAttribute))
7419-
continue;
7420-
7421-
expandAttributes(customAttr, macroDecl, decl, semanticAttrs);
7422-
}
7423-
7424-
return semanticAttrs;
7425-
}
7426-
74277388
template <typename ATTR>
74287389
static void forEachCustomAttribute(
74297390
ValueDecl *decl,

lib/Sema/TypeCheckMacros.cpp

+55-17
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,41 @@ ExternalMacroDefinitionRequest::evaluate(
308308
return ExternalMacroDefinition{nullptr};
309309
}
310310

311+
bool ExpandMemberAttributeMacros::evaluate(Evaluator &evaluator,
312+
Decl *decl) const {
313+
auto *parentDecl = decl->getDeclContext()->getAsDecl();
314+
if (!parentDecl)
315+
return false;
316+
317+
bool addedAttributes = false;
318+
auto parentAttrs = parentDecl->getSemanticAttrs();
319+
for (auto customAttrConst: parentAttrs.getAttributes<CustomAttr>()) {
320+
auto customAttr = const_cast<CustomAttr *>(customAttrConst);
321+
auto customAttrDecl = evaluateOrDefault(
322+
evaluator,
323+
CustomAttrDeclRequest{
324+
customAttr,
325+
parentDecl->getInnermostDeclContext()
326+
},
327+
nullptr);
328+
329+
if (!customAttrDecl)
330+
continue;
331+
332+
auto macroDecl = customAttrDecl.dyn_cast<MacroDecl *>();
333+
if (!macroDecl)
334+
continue;
335+
336+
if (!macroDecl->getMacroRoles().contains(MacroRole::MemberAttribute))
337+
continue;
338+
339+
addedAttributes |= expandAttributes(customAttr, macroDecl, decl);
340+
}
341+
342+
return addedAttributes;
343+
}
344+
345+
311346
/// Determine whether the given source file is from an expansion of the given
312347
/// macro.
313348
static bool isFromExpansionOfMacro(SourceFile *sourceFile, MacroDecl *macro) {
@@ -856,8 +891,7 @@ void swift::expandAccessors(
856891
// FIXME: Almost entirely duplicated code from `expandAccessors`.
857892
// Factor this out into an `expandAttachedMacro` function, with
858893
// arguments for the PrettyStackTrace string, 'attachedTo' decl, etc.
859-
void swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member,
860-
SemanticDeclAttributes &result) {
894+
bool swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member) {
861895
auto *dc = member->getInnermostDeclContext();
862896
ASTContext &ctx = dc->getASTContext();
863897
SourceManager &sourceMgr = ctx.SourceMgr;
@@ -867,43 +901,43 @@ void swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member,
867901
auto attrSourceFile =
868902
moduleDecl->getSourceFileContainingLocation(attr->AtLoc);
869903
if (!attrSourceFile)
870-
return;
904+
return false;
871905

872906
auto declSourceFile =
873907
moduleDecl->getSourceFileContainingLocation(member->getStartLoc());
874908
if (!declSourceFile)
875-
return;
909+
return false;
876910

877911
Decl *parentDecl = member->getDeclContext()->getAsDecl();
878912
if (!parentDecl)
879-
return;
913+
return false;
880914

881915
auto parentDeclSourceFile =
882916
moduleDecl->getSourceFileContainingLocation(parentDecl->getLoc());
883917
if (!parentDeclSourceFile)
884-
return;
918+
return false;
885919

886920
// Evaluate the macro.
887921
NullTerminatedStringRef evaluatedSource;
888922

889923
if (isFromExpansionOfMacro(attrSourceFile, macro) ||
890924
isFromExpansionOfMacro(declSourceFile, macro)) {
891925
member->diagnose(diag::macro_recursive, macro->getName());
892-
return;
926+
return false;
893927
}
894928

895929
auto macroDef = macro->getDefinition();
896930
switch (macroDef.kind) {
897931
case MacroDefinition::Kind::Undefined:
898932
case MacroDefinition::Kind::Invalid:
899933
// Already diagnosed as an error elsewhere.
900-
return;
934+
return false;
901935

902936
case MacroDefinition::Kind::Builtin: {
903937
switch (macroDef.getBuiltinKind()) {
904938
case BuiltinMacroKind::ExternalMacro:
905939
// FIXME: Error here.
906-
return;
940+
return false;
907941
}
908942
}
909943

@@ -923,29 +957,29 @@ void swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member,
923957
macro->getName()
924958
);
925959
macro->diagnose(diag::decl_declared_here, macro->getName());
926-
return;
960+
return false;
927961
}
928962

929963
// Make sure macros are enabled before we expand.
930964
if (!ctx.LangOpts.hasFeature(Feature::Macros)) {
931965
member->diagnose(diag::macro_experimental);
932-
return;
966+
return false;
933967
}
934968

935969
#if SWIFT_SWIFT_PARSER
936970
PrettyStackTraceDecl debugStack("expanding attribute macro", member);
937971

938972
auto astGenAttrSourceFile = attrSourceFile->exportedSourceFile;
939973
if (!astGenAttrSourceFile)
940-
return;
974+
return false;
941975

942976
auto astGenDeclSourceFile = declSourceFile->exportedSourceFile;
943977
if (!astGenDeclSourceFile)
944-
return;
978+
return false;
945979

946980
auto astGenParentDeclSourceFile = parentDeclSourceFile->exportedSourceFile;
947981
if (!astGenParentDeclSourceFile)
948-
return;
982+
return false;
949983

950984
Decl *searchDecl = member;
951985
if (auto *var = dyn_cast<VarDecl>(member))
@@ -961,13 +995,13 @@ void swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member,
961995
astGenParentDeclSourceFile, parentDecl->getStartLoc().getOpaquePointerValue(),
962996
&evaluatedSourceAddress, &evaluatedSourceLength);
963997
if (!evaluatedSourceAddress)
964-
return;
998+
return false;
965999
evaluatedSource = NullTerminatedStringRef(evaluatedSourceAddress,
9661000
(size_t)evaluatedSourceLength);
9671001
break;
9681002
#else
9691003
member->diagnose(diag::macro_unsupported);
970-
return;
1004+
return false;
9711005
#endif
9721006
}
9731007
}
@@ -1029,6 +1063,7 @@ void swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member,
10291063
PrettyStackTraceDecl debugStack(
10301064
"type checking expanded declaration macro", member);
10311065

1066+
bool addedAttributes = false;
10321067
auto topLevelDecls = macroSourceFile->getTopLevelDecls();
10331068
for (auto decl : topLevelDecls) {
10341069
// FIXME: We want to type check decl attributes applied to
@@ -1040,7 +1075,10 @@ void swift::expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member,
10401075

10411076
// Add the new attributes to the semantic attribute list.
10421077
for (auto *attr : decl->getAttrs()) {
1043-
result.add(attr);
1078+
addedAttributes = true;
1079+
member->getAttrs().add(attr);
10441080
}
10451081
}
1082+
1083+
return addedAttributes;
10461084
}

lib/Sema/TypeCheckMacros.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ void expandAccessors(
5151

5252
/// Expand the attributes for the given member declaration based
5353
/// on the custom attribute that references the given macro.
54-
void expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member,
55-
SemanticDeclAttributes &result);
54+
bool expandAttributes(CustomAttr *attr, MacroDecl *macro, Decl *member);
5655

5756
} // end namespace swift
5857

0 commit comments

Comments
 (0)