From 6653798ff5ce6deb58112777e21307ccc453133d Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 17 Nov 2010 17:14:07 +0000 Subject: [PATCH] When comparing the source range of a declaration against the region of interest (e.g., as used by clang_getCursor()), count the decl-specifier-seq as part of the source range, as we do for clang_annotateTokens(). Makes clang_getCursor() work properly for the result types of functions, for example. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@119514 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Index/TestClassDecl.m | 4 +-- test/Index/TestClassForwardDecl.m | 4 +-- test/Index/c-index-getCursor-test.m | 10 +++--- tools/libclang/CIndex.cpp | 54 +++++++++++++++++++++++++---- 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/test/Index/TestClassDecl.m b/test/Index/TestClassDecl.m index 8cbe5cd5e9..1aa26ac77c 100644 --- a/test/Index/TestClassDecl.m +++ b/test/Index/TestClassDecl.m @@ -20,8 +20,8 @@ void function(Foo * arg) // CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:10:12 // CHECK-scan: [8:11 - 10:1] Invalid Cursor => NoDeclFound // CHECK-scan: [10:1 - 11:5] ObjCInterfaceDecl=Foo:10:12 -// CHECK-scan: [11:5 - 13:6] Invalid Cursor => NoDeclFound -// CHECK-scan: [13:6 - 13:15] FunctionDecl=function:13:6 (Definition) +// CHECK-scan: [11:5 - 13:1] Invalid Cursor => NoDeclFound +// CHECK-scan: [13:1 - 13:15] FunctionDecl=function:13:6 (Definition) // CHECK-scan: [13:15 - 13:18] ObjCClassRef=Foo:10:12 // CHECK-scan: [13:18 - 13:24] ParmDecl=arg:13:21 (Definition) // CHECK-scan: [13:24 - 14:1] FunctionDecl=function:13:6 (Definition) diff --git a/test/Index/TestClassForwardDecl.m b/test/Index/TestClassForwardDecl.m index a042bd873d..8a83140789 100644 --- a/test/Index/TestClassForwardDecl.m +++ b/test/Index/TestClassForwardDecl.m @@ -15,8 +15,8 @@ void function(Foo * arg) // CHECK-scan: [1:1 - 8:1] Invalid Cursor => NoDeclFound // CHECK-scan: [8:1 - 8:8] UnexposedDecl=[8:8] // CHECK-scan: [8:8 - 8:11] ObjCClassRef=Foo:8:8 -// CHECK-scan: [8:11 - 10:6] Invalid Cursor => NoDeclFound -// CHECK-scan: [10:6 - 10:15] FunctionDecl=function:10:6 (Definition) +// CHECK-scan: [8:11 - 10:1] Invalid Cursor => NoDeclFound +// CHECK-scan: [10:1 - 10:15] FunctionDecl=function:10:6 (Definition) // CHECK-scan: [10:15 - 10:18] ObjCClassRef=Foo:8:8 // CHECK-scan: [10:18 - 10:24] ParmDecl=arg:10:21 (Definition) // CHECK-scan: [10:24 - 11:1] FunctionDecl=function:10:6 (Definition) diff --git a/test/Index/c-index-getCursor-test.m b/test/Index/c-index-getCursor-test.m index 3cf1b6dcfa..91482eb798 100644 --- a/test/Index/c-index-getCursor-test.m +++ b/test/Index/c-index-getCursor-test.m @@ -94,8 +94,8 @@ void f() { // CHECK: [31:18 - 31:21] ObjCSuperClassRef=Bar:12:12 // CHECK: [31:21 - 31:23] ObjCInterfaceDecl=Baz:31:12 // CHECK: [31:23 - 31:27] ObjCProtocolRef=SubP:27:1 -// CHECK: [31:27 - 33:9] ObjCInterfaceDecl=Baz:31:12 -// CHECK: [33:9 - 33:16] ObjCIvarDecl=_anIVar:33:9 (Definition) +// CHECK: [31:27 - 33:5] ObjCInterfaceDecl=Baz:31:12 +// CHECK: [33:5 - 33:16] ObjCIvarDecl=_anIVar:33:9 (Definition) // CHECK: [33:16 - 36:1] ObjCInterfaceDecl=Baz:31:12 // CHECK: [36:1 - 36:4] ObjCInstanceMethodDecl=bazMethod:36:1 // CHECK: [36:4 - 36:7] ObjCClassRef=Foo:3:12 @@ -105,8 +105,8 @@ void f() { // CHECK: [40:1 - 41:3] EnumDecl=:40:1 (Definition) // CHECK: [41:3 - 41:11] EnumConstantDecl=someEnum:41:3 (Definition) // CHECK: [41:11 - 42:2] EnumDecl=:40:1 (Definition) -// CHECK: [42:2 - 44:5] Invalid Cursor => NoDeclFound -// CHECK: [44:5 - 44:11] FunctionDecl=main:44:5 (Definition) +// CHECK: [42:2 - 44:1] Invalid Cursor => NoDeclFound +// CHECK: [44:1 - 44:11] FunctionDecl=main:44:5 (Definition) // CHECK: [44:11 - 44:19] ParmDecl=argc:44:15 (Definition) // CHECK: [44:19 - 44:27] FunctionDecl=main:44:5 (Definition) // CHECK: [44:27 - 44:38] ParmDecl=argv:44:34 (Definition) @@ -163,6 +163,6 @@ void f() { // CHECK: [52:36 - 52:37] CallExpr=main:44:5 // CHECK: [52:37 - 53:2] UnexposedStmt= // CHECK: [55:9 - 55:26] macro definition=CONCAT -// CHECK: [57:6 - 57:10] FunctionDecl=f:57:6 (Definition) +// CHECK: [57:1 - 57:10] FunctionDecl=f:57:6 (Definition) // CHECK: [58:4 - 58:8] VarDecl=my_var:58:8 (Definition) // CHECK: [58:8 - 58:14] macro instantiation=CONCAT:55:9 diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 585c9c8d7a..e6c208b2ea 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -354,6 +354,8 @@ public: } // end anonymous namespace static SourceRange getRawCursorExtent(CXCursor C); +static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr); + RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) { return RangeCompare(AU->getSourceManager(), R, RegionOfInterest); @@ -534,10 +536,10 @@ bool CursorVisitor::VisitBlockDecl(BlockDecl *B) { llvm::Optional CursorVisitor::shouldVisitCursor(CXCursor Cursor) { if (RegionOfInterest.isValid()) { - SourceRange Range = getRawCursorExtent(Cursor); + SourceRange Range = getFullCursorExtent(Cursor, AU->getSourceManager()); if (Range.isInvalid()) return llvm::Optional(); - + switch (CompareRegionOfInterest(Range)) { case RangeBefore: // This declaration comes before the region of interest; skip it. @@ -1839,7 +1841,7 @@ void EnqueueVisitor::VisitInitListExpr(InitListExpr *IE) { EnqueueChildren(IE); } void EnqueueVisitor::VisitMemberExpr(MemberExpr *M) { - WL.push_back(MemberExprParts(M, Parent)); + WL.push_back(MemberExprParts(M, Parent)); AddStmt(M->getBase()); } void EnqueueVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) { @@ -3097,7 +3099,8 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { unsigned SearchLine, SearchColumn; CXFile ResultFile; unsigned ResultLine, ResultColumn; - CXString SearchFileName, ResultFileName, KindSpelling; + CXString SearchFileName, ResultFileName, KindSpelling, USR; + const char *IsDef = clang_isCursorDefinition(Result)? " (Definition)" : ""; CXSourceLocation ResultLoc = clang_getCursorLocation(Result); clang_getInstantiationLocation(Loc, &SearchFile, &SearchLine, &SearchColumn, @@ -3107,13 +3110,16 @@ CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) { SearchFileName = clang_getFileName(SearchFile); ResultFileName = clang_getFileName(ResultFile); KindSpelling = clang_getCursorKindSpelling(Result.kind); - fprintf(stderr, "clang_getCursor(%s:%d:%d) = %s(%s:%d:%d)\n", + USR = clang_getCursorUSR(Result); + fprintf(stderr, "clang_getCursor(%s:%d:%d) = %s(%s:%d:%d):%s%s\n", clang_getCString(SearchFileName), SearchLine, SearchColumn, clang_getCString(KindSpelling), - clang_getCString(ResultFileName), ResultLine, ResultColumn); + clang_getCString(ResultFileName), ResultLine, ResultColumn, + clang_getCString(USR), IsDef); clang_disposeString(SearchFileName); clang_disposeString(ResultFileName); clang_disposeString(KindSpelling); + clang_disposeString(USR); } return Result; @@ -3363,7 +3369,41 @@ static SourceRange getRawCursorExtent(CXCursor C) { } return R; } - return SourceRange();} + return SourceRange(); +} + +/// \brief Retrieves the "raw" cursor extent, which is then extended to include +/// the decl-specifier-seq for declarations. +static SourceRange getFullCursorExtent(CXCursor C, SourceManager &SrcMgr) { + if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) { + Decl *D = cxcursor::getCursorDecl(C); + SourceRange R = D->getSourceRange(); + + if (const DeclaratorDecl *DD = dyn_cast(D)) { + if (TypeSourceInfo *TI = DD->getTypeSourceInfo()) { + TypeLoc TL = TI->getTypeLoc(); + SourceLocation TLoc = TL.getSourceRange().getBegin(); + if (TLoc.isValid() && R.getBegin().isValid() && + SrcMgr.isBeforeInTranslationUnit(TLoc, R.getBegin())) + R.setBegin(TLoc); + } + + // FIXME: Multiple variables declared in a single declaration + // currently lack the information needed to correctly determine their + // ranges when accounting for the type-specifier. We use context + // stored in the CXCursor to determine if the VarDecl is in a DeclGroup, + // and if so, whether it is the first decl. + if (VarDecl *VD = dyn_cast(D)) { + if (!cxcursor::isFirstInDeclGroup(C)) + R.setBegin(VD->getLocation()); + } + } + + return R; + } + + return getRawCursorExtent(C); +} extern "C" {