@@ -6794,11 +6794,18 @@ class AnnotateTokensWorker {
6794
6794
SourceManager &SrcMgr;
6795
6795
bool HasContextSensitiveKeywords;
6796
6796
6797
+ struct PostChildrenAction {
6798
+ CXCursor cursor;
6799
+ enum Action { Invalid, Ignore, Postpone } action;
6800
+ };
6801
+ using PostChildrenActions = SmallVector<PostChildrenAction, 0 >;
6802
+
6797
6803
struct PostChildrenInfo {
6798
6804
CXCursor Cursor;
6799
6805
SourceRange CursorRange;
6800
6806
unsigned BeforeReachingCursorIdx;
6801
6807
unsigned BeforeChildrenTokenIdx;
6808
+ PostChildrenActions ChildActions;
6802
6809
};
6803
6810
SmallVector<PostChildrenInfo, 8 > PostChildrenInfos;
6804
6811
@@ -6844,7 +6851,13 @@ class AnnotateTokensWorker {
6844
6851
6845
6852
void VisitChildren (CXCursor C) { AnnotateVis.VisitChildren (C); }
6846
6853
enum CXChildVisitResult Visit (CXCursor cursor, CXCursor parent);
6854
+ bool IsIgnoredChildCursor (CXCursor cursor) const ;
6855
+ PostChildrenActions DetermineChildActions (CXCursor Cursor) const ;
6856
+
6847
6857
bool postVisitChildren (CXCursor cursor);
6858
+ void HandlePostPonedChildCursors (const PostChildrenInfo &Info);
6859
+ void HandlePostPonedChildCursor (CXCursor Cursor, unsigned StartTokenIndex);
6860
+
6848
6861
void AnnotateTokens ();
6849
6862
6850
6863
// / Determine whether the annotator saw any cursors that have
@@ -6865,6 +6878,67 @@ void AnnotateTokensWorker::AnnotateTokens() {
6865
6878
AnnotateVis.visitFileRegion ();
6866
6879
}
6867
6880
6881
+ bool AnnotateTokensWorker::IsIgnoredChildCursor (CXCursor cursor) const {
6882
+ if (PostChildrenInfos.empty ())
6883
+ return false ;
6884
+
6885
+ for (const auto &ChildAction : PostChildrenInfos.back ().ChildActions ) {
6886
+ if (ChildAction.cursor == cursor &&
6887
+ ChildAction.action == PostChildrenAction::Ignore) {
6888
+ return true ;
6889
+ }
6890
+ }
6891
+
6892
+ return false ;
6893
+ }
6894
+
6895
+ const CXXOperatorCallExpr *GetSubscriptOrCallOperator (CXCursor Cursor) {
6896
+ if (!clang_isExpression (Cursor.kind ))
6897
+ return nullptr ;
6898
+
6899
+ const Expr *E = getCursorExpr (Cursor);
6900
+ if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E)) {
6901
+ const OverloadedOperatorKind Kind = OCE->getOperator ();
6902
+ if (Kind == OO_Call || Kind == OO_Subscript)
6903
+ return OCE;
6904
+ }
6905
+
6906
+ return nullptr ;
6907
+ }
6908
+
6909
+ AnnotateTokensWorker::PostChildrenActions
6910
+ AnnotateTokensWorker::DetermineChildActions (CXCursor Cursor) const {
6911
+ PostChildrenActions actions;
6912
+
6913
+ // The DeclRefExpr of CXXOperatorCallExpr refering to the custom operator is
6914
+ // visited before the arguments to the operator call. For the Call and
6915
+ // Subscript operator the range of this DeclRefExpr includes the whole call
6916
+ // expression, so that all tokens in that range would be mapped to the
6917
+ // operator function, including the tokens of the arguments. To avoid that,
6918
+ // ensure to visit this DeclRefExpr as last node.
6919
+ if (const auto *OCE = GetSubscriptOrCallOperator (Cursor)) {
6920
+ const Expr *Callee = OCE->getCallee ();
6921
+ if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(Callee)) {
6922
+ const Expr *SubExpr = ICE->getSubExpr ();
6923
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
6924
+ const Decl *parentDecl = getCursorParentDecl (Cursor);
6925
+ CXTranslationUnit TU = clang_Cursor_getTranslationUnit (Cursor);
6926
+
6927
+ // Visit the DeclRefExpr as last.
6928
+ CXCursor cxChild = MakeCXCursor (DRE, parentDecl, TU);
6929
+ actions.push_back ({cxChild, PostChildrenAction::Postpone});
6930
+
6931
+ // The parent of the DeclRefExpr, an ImplicitCastExpr, has an equally
6932
+ // wide range as the DeclRefExpr. We can skip visiting this entirely.
6933
+ cxChild = MakeCXCursor (ICE, parentDecl, TU);
6934
+ actions.push_back ({cxChild, PostChildrenAction::Ignore});
6935
+ }
6936
+ }
6937
+ }
6938
+
6939
+ return actions;
6940
+ }
6941
+
6868
6942
static inline void updateCursorAnnotation (CXCursor &Cursor,
6869
6943
const CXCursor &updateC) {
6870
6944
if (clang_isInvalid (updateC.kind ) || !clang_isInvalid (Cursor.kind ))
@@ -6941,7 +7015,10 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
6941
7015
SourceRange cursorRange = getRawCursorExtent (cursor);
6942
7016
if (cursorRange.isInvalid ())
6943
7017
return CXChildVisit_Recurse;
6944
-
7018
+
7019
+ if (IsIgnoredChildCursor (cursor))
7020
+ return CXChildVisit_Continue;
7021
+
6945
7022
if (!HasContextSensitiveKeywords) {
6946
7023
// Objective-C properties can have context-sensitive keywords.
6947
7024
if (cursor.kind == CXCursor_ObjCPropertyDecl) {
@@ -7089,6 +7166,7 @@ AnnotateTokensWorker::Visit(CXCursor cursor, CXCursor parent) {
7089
7166
Info.CursorRange = cursorRange;
7090
7167
Info.BeforeReachingCursorIdx = BeforeReachingCursorIdx;
7091
7168
Info.BeforeChildrenTokenIdx = NextToken ();
7169
+ Info.ChildActions = DetermineChildActions (cursor);
7092
7170
PostChildrenInfos.push_back (Info);
7093
7171
7094
7172
return CXChildVisit_Recurse;
@@ -7101,6 +7179,8 @@ bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {
7101
7179
if (!clang_equalCursors (Info.Cursor , cursor))
7102
7180
return false ;
7103
7181
7182
+ HandlePostPonedChildCursors (Info);
7183
+
7104
7184
const unsigned BeforeChildren = Info.BeforeChildrenTokenIdx ;
7105
7185
const unsigned AfterChildren = NextToken ();
7106
7186
SourceRange cursorRange = Info.CursorRange ;
@@ -7127,6 +7207,56 @@ bool AnnotateTokensWorker::postVisitChildren(CXCursor cursor) {
7127
7207
return false ;
7128
7208
}
7129
7209
7210
+ void AnnotateTokensWorker::HandlePostPonedChildCursors (
7211
+ const PostChildrenInfo &Info) {
7212
+ for (const auto &ChildAction : Info.ChildActions ) {
7213
+ if (ChildAction.action == PostChildrenAction::Postpone) {
7214
+ HandlePostPonedChildCursor (ChildAction.cursor ,
7215
+ Info.BeforeChildrenTokenIdx );
7216
+ }
7217
+ }
7218
+ }
7219
+
7220
+ void AnnotateTokensWorker::HandlePostPonedChildCursor (
7221
+ CXCursor Cursor, unsigned StartTokenIndex) {
7222
+ const auto flags = CXNameRange_WantQualifier | CXNameRange_WantQualifier;
7223
+ unsigned I = StartTokenIndex;
7224
+
7225
+ // The bracket tokens of a Call or Subscript operator are mapped to
7226
+ // CallExpr/CXXOperatorCallExpr because we skipped visiting the corresponding
7227
+ // DeclRefExpr. Remap these tokens to the DeclRefExpr cursors.
7228
+ for (unsigned RefNameRangeNr = 0 ; I < NumTokens; RefNameRangeNr++) {
7229
+ const CXSourceRange CXRefNameRange =
7230
+ clang_getCursorReferenceNameRange (Cursor, flags, RefNameRangeNr);
7231
+ if (clang_Range_isNull (CXRefNameRange))
7232
+ break ; // All ranges handled.
7233
+
7234
+ SourceRange RefNameRange = cxloc::translateCXSourceRange (CXRefNameRange);
7235
+ while (I < NumTokens) {
7236
+ const SourceLocation TokenLocation = GetTokenLoc (I);
7237
+ if (!TokenLocation.isValid ())
7238
+ break ;
7239
+
7240
+ // Adapt the end range, because LocationCompare() reports
7241
+ // RangeOverlap even for the not-inclusive end location.
7242
+ const SourceLocation fixedEnd =
7243
+ RefNameRange.getEnd ().getLocWithOffset (-1 );
7244
+ RefNameRange = SourceRange (RefNameRange.getBegin (), fixedEnd);
7245
+
7246
+ const RangeComparisonResult ComparisonResult =
7247
+ LocationCompare (SrcMgr, TokenLocation, RefNameRange);
7248
+
7249
+ if (ComparisonResult == RangeOverlap) {
7250
+ Cursors[I++] = Cursor;
7251
+ } else if (ComparisonResult == RangeBefore) {
7252
+ ++I; // Not relevant token, check next one.
7253
+ } else if (ComparisonResult == RangeAfter) {
7254
+ break ; // All tokens updated for current range, check next.
7255
+ }
7256
+ }
7257
+ }
7258
+ }
7259
+
7130
7260
static enum CXChildVisitResult AnnotateTokensVisitor (CXCursor cursor,
7131
7261
CXCursor parent,
7132
7262
CXClientData client_data) {
0 commit comments