44
44
#include " llvm/Support/SaveAndRestore.h"
45
45
using namespace swift ;
46
46
47
+ static const Decl *
48
+ concreteSyntaxDeclForAvailableAttribute (const Decl *AbstractSyntaxDecl);
49
+
47
50
ExportContext::ExportContext (
48
51
DeclContext *DC, AvailabilityRange runningOSVersion,
49
52
FragileFunctionKind kind, bool spi, bool exported, bool implicit,
@@ -451,6 +454,8 @@ class TypeRefinementContextBuilder : private ASTWalker {
451
454
};
452
455
std::vector<ContextInfo> ContextStack;
453
456
457
+ llvm::SmallVector<const Decl *, 4 > ConcreteDeclStack;
458
+
454
459
// / Represents an entry in a stack of pending decl body type refinement
455
460
// / contexts. TRCs in this stack should be pushed onto \p ContextStack when
456
461
// / \p BodyStmt is encountered.
@@ -540,12 +545,27 @@ class TypeRefinementContextBuilder : private ASTWalker {
540
545
return MacroWalking::Arguments;
541
546
}
542
547
548
+ bool shouldSkipDecl (Decl *D) const {
549
+ // Implicit decls don't have source locations so they cannot have a TRC.
550
+ if (D->isImplicit ())
551
+ return true ;
552
+
553
+ // Only visit a node that has a corresponding concrete syntax node if we are
554
+ // already walking that concrete syntax node.
555
+ auto *concreteDecl = concreteSyntaxDeclForAvailableAttribute (D);
556
+ if (concreteDecl != D) {
557
+ if (ConcreteDeclStack.empty () || ConcreteDeclStack.back () != concreteDecl)
558
+ return true ;
559
+ }
560
+
561
+ return false ;
562
+ }
563
+
543
564
PreWalkAction walkToDeclPre (Decl *D) override {
544
565
PrettyStackTraceDecl trace (stackTraceAction (), D);
545
566
546
- // Implicit decls don't have source locations so they cannot have a TRC.
547
- if (D->isImplicit ())
548
- return Action::Continue ();
567
+ if (shouldSkipDecl (D))
568
+ return Action::SkipNode ();
549
569
550
570
// The AST of this decl may not be ready to traverse yet if it hasn't been
551
571
// full typechecked. If that's the case, we leave a placeholder node in the
@@ -561,10 +581,21 @@ class TypeRefinementContextBuilder : private ASTWalker {
561
581
562
582
// Create TRCs that cover only the body of the declaration.
563
583
buildContextsForBodyOfDecl (D);
584
+
585
+ // If this decl is the concrete syntax decl for some abstract syntax decl,
586
+ // push it onto the stack so that the abstract syntax decls may be visited.
587
+ auto *abstractDecl = abstractSyntaxDeclForAvailableAttribute (D);
588
+ if (abstractDecl != D) {
589
+ ConcreteDeclStack.push_back (D);
590
+ }
564
591
return Action::Continue ();
565
592
}
566
593
567
594
PostWalkAction walkToDeclPost (Decl *D) override {
595
+ if (!ConcreteDeclStack.empty () && ConcreteDeclStack.back () == D) {
596
+ ConcreteDeclStack.pop_back ();
597
+ }
598
+
568
599
while (ContextStack.back ().ScopeNode .getAsDecl () == D) {
569
600
ContextStack.pop_back ();
570
601
}
@@ -652,16 +683,9 @@ class TypeRefinementContextBuilder : private ASTWalker {
652
683
if (isa<AbstractStorageDecl>(D) && D->getDeclContext ()->isLocalContext ())
653
684
return nullptr ;
654
685
655
- // Don't introduce for variable declarations that have a parent pattern
656
- // binding; all of the relevant information is on the pattern binding.
657
- if (auto var = dyn_cast<VarDecl>(D)) {
658
- if (var->getParentPatternBinding ())
659
- return nullptr ;
660
- }
661
-
662
- // Don't introduce for enum element declarations. All the relevant
663
- // information is on the enum case declaration.
664
- if (isa<EnumElementDecl>(D))
686
+ // Don't introduce for abstract syntax nodes that have separate concrete
687
+ // syntax nodes. The TRC will be introduced for the concrete node instead.
688
+ if (concreteSyntaxDeclForAvailableAttribute (D) != D)
665
689
return nullptr ;
666
690
667
691
// Declarations with an explicit availability attribute always get a TRC.
@@ -1686,7 +1710,8 @@ concreteSyntaxDeclForAvailableAttribute(const Decl *AbstractSyntaxDecl) {
1686
1710
// event, multiple variables can be introduced with a single 'var'),
1687
1711
// so suggest adding an attribute to the PatterningBindingDecl instead.
1688
1712
if (auto *VD = dyn_cast<VarDecl>(AbstractSyntaxDecl)) {
1689
- return VD->getParentPatternBinding ();
1713
+ if (auto *PBD = VD->getParentPatternBinding ())
1714
+ return PBD;
1690
1715
}
1691
1716
1692
1717
// Similarly suggest applying the Fix-It to the parent enum case rather than
0 commit comments