@@ -57,6 +57,27 @@ void recordMetrics(const SelectionTree &S, const LangOptions &Lang) {
57
57
SelectionUsedRecovery.record (0 , LanguageLabel); // unused.
58
58
}
59
59
60
+ SourceRange getSourceRange (const DynTypedNode &N) {
61
+ // MemberExprs to implicitly access anonymous fields should not claim any
62
+ // tokens for themselves. Given:
63
+ // struct A { struct { int b; }; };
64
+ // The clang AST reports the following nodes for an access to b:
65
+ // A().b;
66
+ // [----] MemberExpr, base = A().<anonymous>, member = b
67
+ // [----] MemberExpr: base = A(), member = <anonymous>
68
+ // [-] CXXConstructExpr
69
+ // For our purposes, we don't want the second MemberExpr to own any tokens,
70
+ // so we reduce its range to match the CXXConstructExpr.
71
+ // (It's not clear that changing the clang AST would be correct in general).
72
+ if (const auto *ME = N.get <MemberExpr>()) {
73
+ if (!ME->getMemberDecl ()->getDeclName ())
74
+ return ME->getBase ()
75
+ ? getSourceRange (DynTypedNode::create (*ME->getBase ()))
76
+ : SourceRange ();
77
+ }
78
+ return N.getSourceRange ();
79
+ }
80
+
60
81
// An IntervalSet maintains a set of disjoint subranges of an array.
61
82
//
62
83
// Initially, it contains the entire array.
@@ -608,7 +629,7 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
608
629
// An optimization for a common case: nodes outside macro expansions that
609
630
// don't intersect the selection may be recursively skipped.
610
631
bool canSafelySkipNode (const DynTypedNode &N) {
611
- SourceRange S = N. getSourceRange ();
632
+ SourceRange S = getSourceRange (N );
612
633
if (auto *TL = N.get <TypeLoc>()) {
613
634
// FIXME: TypeLoc::getBeginLoc()/getEndLoc() are pretty fragile
614
635
// heuristics. We should consider only pruning critical TypeLoc nodes, to
@@ -665,7 +686,7 @@ class SelectionVisitor : public RecursiveASTVisitor<SelectionVisitor> {
665
686
void pop () {
666
687
Node &N = *Stack.top ();
667
688
dlog (" {1}pop: {0}" , printNodeToString (N.ASTNode , PrintPolicy), indent (-1 ));
668
- claimRange (N.ASTNode . getSourceRange ( ), N.Selected );
689
+ claimRange (getSourceRange ( N.ASTNode ), N.Selected );
669
690
if (N.Selected == NoTokens)
670
691
N.Selected = SelectionTree::Unselected;
671
692
if (N.Selected || !N.Children .empty ()) {
@@ -868,13 +889,13 @@ const DeclContext &SelectionTree::Node::getDeclContext() const {
868
889
869
890
const SelectionTree::Node &SelectionTree::Node::ignoreImplicit () const {
870
891
if (Children.size () == 1 &&
871
- Children.front ()->ASTNode . getSourceRange ( ) == ASTNode. getSourceRange ())
892
+ getSourceRange ( Children.front ()->ASTNode ) == getSourceRange (ASTNode ))
872
893
return Children.front ()->ignoreImplicit ();
873
894
return *this ;
874
895
}
875
896
876
897
const SelectionTree::Node &SelectionTree::Node::outerImplicit () const {
877
- if (Parent && Parent->ASTNode . getSourceRange ( ) == ASTNode. getSourceRange ())
898
+ if (Parent && getSourceRange ( Parent->ASTNode ) == getSourceRange (ASTNode ))
878
899
return Parent->outerImplicit ();
879
900
return *this ;
880
901
}
0 commit comments