[libclang] Avoid having the cursor of an expression replace the declaration cursor
when the expression source range overlaps the declaration range. This can happen for C++ constructor expressions whose range generally include the variable declaration, e.g.: MyCXXClass foo; // Make sure pointing at 'foo' returns a VarDecl cursor. rdar://9124499. llvm-svn: 133930
This commit is contained in:
parent
66cd1dacbc
commit
d289104e29
|
@ -31,6 +31,10 @@ struct YDerived : Y {
|
||||||
X getAnotherX() { return member; }
|
X getAnotherX() { return member; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void test() {
|
||||||
|
X foo;
|
||||||
|
}
|
||||||
|
|
||||||
// RUN: c-index-test -cursor-at=%s:12:20 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
|
// RUN: c-index-test -cursor-at=%s:12:20 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
|
||||||
// RUN: c-index-test -cursor-at=%s:13:21 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
|
// RUN: c-index-test -cursor-at=%s:13:21 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
|
||||||
// RUN: c-index-test -cursor-at=%s:13:28 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
|
// RUN: c-index-test -cursor-at=%s:13:28 %s | FileCheck -check-prefix=CHECK-VALUE-REF %s
|
||||||
|
@ -61,3 +65,6 @@ struct YDerived : Y {
|
||||||
// RUN: c-index-test -cursor-at=%s:27:10 %s | FileCheck -check-prefix=CHECK-IMPLICIT-MEMREF %s
|
// RUN: c-index-test -cursor-at=%s:27:10 %s | FileCheck -check-prefix=CHECK-IMPLICIT-MEMREF %s
|
||||||
// RUN: c-index-test -cursor-at=%s:31:28 %s | FileCheck -check-prefix=CHECK-IMPLICIT-MEMREF %s
|
// RUN: c-index-test -cursor-at=%s:31:28 %s | FileCheck -check-prefix=CHECK-IMPLICIT-MEMREF %s
|
||||||
// CHECK-IMPLICIT-MEMREF: MemberRefExpr=member:21:7
|
// CHECK-IMPLICIT-MEMREF: MemberRefExpr=member:21:7
|
||||||
|
|
||||||
|
// RUN: c-index-test -cursor-at=%s:35:5 %s | FileCheck -check-prefix=CHECK-DECL %s
|
||||||
|
// CHECK-DECL: VarDecl=foo:35:5
|
||||||
|
|
|
@ -3393,10 +3393,33 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||||
return createCXString((const char*) 0);
|
return createCXString((const char*) 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct GetCursorData {
|
||||||
|
SourceLocation TokenBeginLoc;
|
||||||
|
CXCursor &BestCursor;
|
||||||
|
|
||||||
|
GetCursorData(SourceLocation tokenBegin, CXCursor &outputCursor)
|
||||||
|
: TokenBeginLoc(tokenBegin), BestCursor(outputCursor) { }
|
||||||
|
};
|
||||||
|
|
||||||
enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
|
enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
|
||||||
CXCursor parent,
|
CXCursor parent,
|
||||||
CXClientData client_data) {
|
CXClientData client_data) {
|
||||||
CXCursor *BestCursor = static_cast<CXCursor *>(client_data);
|
GetCursorData *Data = static_cast<GetCursorData *>(client_data);
|
||||||
|
CXCursor *BestCursor = &Data->BestCursor;
|
||||||
|
|
||||||
|
if (clang_isExpression(cursor.kind) &&
|
||||||
|
clang_isDeclaration(BestCursor->kind)) {
|
||||||
|
Decl *D = getCursorDecl(*BestCursor);
|
||||||
|
|
||||||
|
// Avoid having the cursor of an expression replace the declaration cursor
|
||||||
|
// when the expression source range overlaps the declaration range.
|
||||||
|
// This can happen for C++ constructor expressions whose range generally
|
||||||
|
// include the variable declaration, e.g.:
|
||||||
|
// MyCXXClass foo; // Make sure pointing at 'foo' returns a VarDecl cursor.
|
||||||
|
if (D->getLocation().isValid() && Data->TokenBeginLoc.isValid() &&
|
||||||
|
D->getLocation() == Data->TokenBeginLoc)
|
||||||
|
return CXChildVisit_Break;
|
||||||
|
}
|
||||||
|
|
||||||
// If our current best cursor is the construction of a temporary object,
|
// If our current best cursor is the construction of a temporary object,
|
||||||
// don't replace that cursor with a type reference, because we want
|
// don't replace that cursor with a type reference, because we want
|
||||||
|
@ -3441,8 +3464,9 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
|
||||||
// FIXME: Would be great to have a "hint" cursor, then walk from that
|
// FIXME: Would be great to have a "hint" cursor, then walk from that
|
||||||
// hint cursor upward until we find a cursor whose source range encloses
|
// hint cursor upward until we find a cursor whose source range encloses
|
||||||
// the region of interest, rather than starting from the translation unit.
|
// the region of interest, rather than starting from the translation unit.
|
||||||
|
GetCursorData ResultData(SLoc, Result);
|
||||||
CXCursor Parent = clang_getTranslationUnitCursor(TU);
|
CXCursor Parent = clang_getTranslationUnitCursor(TU);
|
||||||
CursorVisitor CursorVis(TU, GetCursorVisitor, &Result,
|
CursorVisitor CursorVis(TU, GetCursorVisitor, &ResultData,
|
||||||
Decl::MaxPCHLevel, true, SourceLocation(SLoc));
|
Decl::MaxPCHLevel, true, SourceLocation(SLoc));
|
||||||
CursorVis.VisitChildren(Parent);
|
CursorVis.VisitChildren(Parent);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue