Skip to content

Commit 0c3f538

Browse files
committed
[AST] Allow ignoring macro expansions
Various requests expect to be walking over the current source file. While we could add checks to all these to skip decls outside of the current buffer, it's a little nicer to handle this during the walk instead. Allow ignoring nodes that are from macro expansions and add that flag to the various walks that expect it. Also add a new `getOriginalAttrs` that filters out attributes in generated source.
1 parent 00af28c commit 0c3f538

20 files changed

+186
-51
lines changed

include/swift/AST/ASTWalker.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,10 @@ class ASTWalker {
541541
/// TODO: Consider changing this to false by default.
542542
virtual bool shouldWalkSerializedTopLevelInternalDecls() { return true; }
543543

544+
/// Whether we should walk into expanded macros, whether it be from a
545+
/// \c MacroExpansionExpr or declarations created by attached macros.
546+
virtual bool shouldWalkMacroExpansions() { return true; }
547+
544548
/// walkToParameterListPre - This method is called when first visiting a
545549
/// ParameterList, before walking into its parameters.
546550
///

include/swift/AST/Attr.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ class ClassDecl;
5858
class GenericFunctionType;
5959
class LazyConformanceLoader;
6060
class LazyMemberLoader;
61+
class ModuleDecl;
6162
class PatternBindingInitializer;
6263
class TrailingWhereClause;
6364
class TypeExpr;
@@ -2581,6 +2582,59 @@ class DeclAttributes {
25812582
SourceLoc getStartLoc(bool forModifiers = false) const;
25822583
};
25832584

2585+
/// Attributes applied directly to the declaration.
2586+
///
2587+
/// We should really just have \c DeclAttributes and \c SemanticDeclAttributes,
2588+
/// but currently almost all callers expect the latter. Instead of changing all
2589+
/// callers of \c getAttrs, instead provide a way to retrieive the original
2590+
/// attributes.
2591+
class OrigDeclAttributes {
2592+
SmallVector<DeclAttribute *> attributes;
2593+
using AttrListTy = SmallVectorImpl<DeclAttribute *>;
2594+
2595+
public:
2596+
OrigDeclAttributes() = default;
2597+
2598+
OrigDeclAttributes(DeclAttributes semanticAttrs, ModuleDecl *mod);
2599+
2600+
2601+
using iterator = AttrListTy::iterator;
2602+
using const_iterator = AttrListTy::const_iterator;
2603+
2604+
iterator begin() { return attributes.begin(); }
2605+
iterator end() { return attributes.end(); }
2606+
const_iterator begin() const { return attributes.begin(); }
2607+
const_iterator end() const { return attributes.end(); }
2608+
2609+
template <typename AttrType, bool AllowInvalid>
2610+
using AttributeKindRange =
2611+
OptionalTransformRange<iterator_range<const_iterator>,
2612+
ToAttributeKind<AttrType, AllowInvalid>, const_iterator>;
2613+
2614+
template <typename AttrType, bool AllowInvalid = false>
2615+
AttributeKindRange<AttrType, AllowInvalid> getAttributes() const {
2616+
return AttributeKindRange<AttrType, AllowInvalid>(make_range(begin(), end()), ToAttributeKind<AttrType, AllowInvalid>());
2617+
}
2618+
2619+
/// Retrieve the first attribute of the given attribute class.
2620+
template <typename AttrType>
2621+
const AttrType *getAttribute(bool allowInvalid = false) const {
2622+
for (auto *attr : attributes) {
2623+
if (auto *specificAttr = dyn_cast<AttrType>(attr)) {
2624+
if (specificAttr->isValid() || allowInvalid)
2625+
return specificAttr;
2626+
}
2627+
}
2628+
return nullptr;
2629+
}
2630+
2631+
/// Determine whether there is an attribute with the given attribute class.
2632+
template <typename AttrType>
2633+
bool hasAttribute(bool allowInvalid = false) const {
2634+
return getAttribute<AttrType>(allowInvalid) != nullptr;
2635+
}
2636+
};
2637+
25842638
/// TypeAttributes - These are attributes that may be applied to types.
25852639
class TypeAttributes {
25862640
// Get a SourceLoc for every possible attribute that can be parsed in source.

include/swift/AST/Decl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,11 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
862862
/// with this declaration.
863863
ArrayRef<CustomAttr *> getRuntimeDiscoverableAttrs() const;
864864

865+
/// Returns the attributes that were directly attached to this declaration
866+
/// as written in source, ie. does not include attributes generated by macro
867+
/// expansions.
868+
OrigDeclAttributes getOriginalAttrs() const;
869+
865870
/// Returns the semantic attributes attached to this declaration,
866871
/// including attributes that are generated as the result of member
867872
/// attribute macro expansion.
@@ -923,6 +928,10 @@ class alignas(1 << DeclAlignInBits) Decl : public ASTAllocated<Decl> {
923928

924929
SourceLoc TrailingSemiLoc;
925930

931+
/// Whether this declaration is within a generated buffer, \c false if this
932+
/// declaration was constructed from a serialized module.
933+
bool isInGeneratedBuffer() const;
934+
926935
/// Returns the appropriate kind of entry point to generate for this class,
927936
/// based on its attributes.
928937
///

include/swift/AST/Module.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,10 @@ class ModuleDecl
349349
/// \c nullptr if the source location isn't in this module.
350350
SourceFile *getSourceFileContainingLocation(SourceLoc loc);
351351

352+
/// Whether the given location is inside a generated buffer, \c false if
353+
/// the given location isn't in this module.
354+
bool isInGeneratedBuffer(SourceLoc loc);
355+
352356
/// Creates a map from \c #filePath strings to corresponding \c #fileID
353357
/// strings, diagnosing any conflicts.
354358
///

include/swift/IDE/SourceEntityWalker.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,10 @@ class SourceEntityWalker {
201201

202202
virtual bool shouldWalkIntoGenericParams() { return true; }
203203

204+
/// Whether we should walk into expanded macros, whether it be from a
205+
/// \c MacroExpansionExpr or declarations created by attached macros.
206+
virtual bool shouldWalkMacroExpansions() { return false; }
207+
204208
protected:
205209
SourceEntityWalker() = default;
206210
SourceEntityWalker(const SourceEntityWalker &) = default;

include/swift/IDE/SyntaxModel.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ struct SyntaxStructureElement {
139139
struct SyntaxStructureNode {
140140
const Decl *Dcl = nullptr;
141141
SyntaxStructureKind Kind;
142-
DeclAttributes Attrs;
142+
OrigDeclAttributes Attrs;
143143
CharSourceRange Range;
144144
CharSourceRange BodyRange;
145145
CharSourceRange NameRange;

lib/AST/ASTWalker.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -432,9 +432,11 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
432432
bool visitMacroExpansionDecl(MacroExpansionDecl *MED) {
433433
if (MED->getArgs() && doIt(MED->getArgs()))
434434
return true;
435-
for (auto *decl : MED->getRewritten())
436-
if (doIt(decl))
437-
return true;
435+
if (Walker.shouldWalkMacroExpansions()) {
436+
for (auto *decl : MED->getRewritten())
437+
if (doIt(decl))
438+
return true;
439+
}
438440
return false;
439441
}
440442

@@ -1295,17 +1297,19 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
12951297
}
12961298

12971299
Expr *visitMacroExpansionExpr(MacroExpansionExpr *E) {
1298-
Expr *rewritten = nullptr;
1299-
if (E->getRewritten()) {
1300-
rewritten = doIt(E->getRewritten());
1301-
if (!rewritten) return nullptr;
1302-
}
13031300
ArgumentList *args = nullptr;
13041301
if (E->getArgs()) {
13051302
args = doIt(E->getArgs());
13061303
if (!args) return nullptr;
13071304
}
1308-
E->setRewritten(rewritten);
1305+
if (Walker.shouldWalkMacroExpansions()) {
1306+
Expr *rewritten = nullptr;
1307+
if (E->getRewritten()) {
1308+
rewritten = doIt(E->getRewritten());
1309+
if (!rewritten) return nullptr;
1310+
}
1311+
E->setRewritten(rewritten);
1312+
}
13091313
E->setArgs(args);
13101314
return E;
13111315
}
@@ -1421,6 +1425,9 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
14211425
}
14221426

14231427
bool shouldSkip(Decl *D) {
1428+
if (!Walker.shouldWalkMacroExpansions() && D->isInGeneratedBuffer())
1429+
return true;
1430+
14241431
if (auto *VD = dyn_cast<VarDecl>(D)) {
14251432
// VarDecls are walked via their NamedPattern, ignore them if we encounter
14261433
// then in the few cases where they are also pushed outside as members.

lib/AST/Attr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,14 @@ SourceLoc DeclAttributes::getStartLoc(bool forModifiers) const {
851851
return lastAttr ? lastAttr->getRangeWithAt().Start : SourceLoc();
852852
}
853853

854+
OrigDeclAttributes::OrigDeclAttributes(DeclAttributes allAttributes, ModuleDecl *mod) {
855+
for (auto *attr : allAttributes) {
856+
if (!mod->isInGeneratedBuffer(attr->AtLoc)) {
857+
attributes.emplace_back(attr);
858+
}
859+
}
860+
}
861+
854862
static void printAvailableAttr(const AvailableAttr *Attr, ASTPrinter &Printer,
855863
const PrintOptions &Options) {
856864
if (Attr->isLanguageVersionSpecific())

lib/AST/Decl.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -367,6 +367,10 @@ StringRef Decl::getDescriptiveKindName(DescriptiveDeclKind K) {
367367
llvm_unreachable("bad DescriptiveDeclKind");
368368
}
369369

370+
OrigDeclAttributes Decl::getOriginalAttrs() const {
371+
return OrigDeclAttributes(getAttrs(), getModuleContext());
372+
}
373+
370374
DeclAttributes Decl::getSemanticAttrs() const {
371375
auto mutableThis = const_cast<Decl *>(this);
372376
(void)evaluateOrDefault(getASTContext().evaluator,
@@ -684,7 +688,7 @@ SourceRange Decl::getSourceRangeIncludingAttrs() const {
684688

685689
// Otherwise, include attributes directly attached to the accessor.
686690
SourceLoc VarLoc = AD->getStorage()->getStartLoc();
687-
for (auto Attr : getAttrs()) {
691+
for (auto *Attr : getOriginalAttrs()) {
688692
if (!Attr->getRange().isValid())
689693
continue;
690694

@@ -703,19 +707,23 @@ SourceRange Decl::getSourceRangeIncludingAttrs() const {
703707
if (auto *PBD = dyn_cast<PatternBindingDecl>(this)) {
704708
for (auto i : range(PBD->getNumPatternEntries()))
705709
PBD->getPattern(i)->forEachVariable([&](VarDecl *VD) {
706-
for (auto Attr : VD->getAttrs())
710+
for (auto *Attr : VD->getOriginalAttrs())
707711
if (Attr->getRange().isValid())
708712
Range.widen(Attr->getRangeWithAt());
709713
});
710714
}
711715

712-
for (auto Attr : getAttrs()) {
716+
for (auto *Attr : getOriginalAttrs()) {
713717
if (Attr->getRange().isValid())
714718
Range.widen(Attr->getRangeWithAt());
715719
}
716720
return Range;
717721
}
718722

723+
bool Decl::isInGeneratedBuffer() const {
724+
return getModuleContext()->isInGeneratedBuffer(getStartLoc());
725+
}
726+
719727
SourceLoc Decl::getLocFromSource() const {
720728
switch (getKind()) {
721729
#define DECL(ID, X) \

lib/AST/Module.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,13 @@ SourceFile *ModuleDecl::getSourceFileContainingLocation(SourceLoc loc) {
648648
return foundSourceFile;
649649
}
650650

651+
bool ModuleDecl::isInGeneratedBuffer(SourceLoc loc) {
652+
SourceFile *file = getSourceFileContainingLocation(loc);
653+
if (!file)
654+
return false;
655+
return file->Kind == SourceFileKind::MacroExpansion;
656+
}
657+
651658
ArrayRef<SourceFile *>
652659
PrimarySourceFilesRequest::evaluate(Evaluator &evaluator,
653660
ModuleDecl *mod) const {

0 commit comments

Comments
 (0)