From: Ted Kremenek Date: Mon, 1 Nov 2010 23:26:51 +0000 (+0000) Subject: Encapsulate within CXCursor the notion of whether a VarDecl* is the first Decl in... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=007a7c9d8dcdb2e9cd94b6075108bfc4c90e6ccd;p=clang Encapsulate within CXCursor the notion of whether a VarDecl* is the first Decl in a DeclGroup. We use this to recover some context that is currently not modeled directly in the AST. Currently VarDecl's cannot properly determine their source range because they have no context on whether or not they appear in a DeclGroup. For the meantime, this bandaid suffices in libclang since that is where the correct SourceRange is directly needed. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117973 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/test/Index/usrs.m b/test/Index/usrs.m index 4b3de5c480..03ddfd31ee 100644 --- a/test/Index/usrs.m +++ b/test/Index/usrs.m @@ -69,6 +69,13 @@ static int local_func(int x) { return x; } - (id) meth4 { return 0; } @end +void aux_1(int, int, int); +int test_multi_declaration(void) { + int foo = 1, bar = 2, baz = 3; + aux_1(foo, bar, baz); + return 0; +} + // CHECK: usrs.m c:usrs.m@85@F@my_helper Extent=[3:19 - 3:60] // CHECK: usrs.m c:usrs.m@95@F@my_helper@x Extent=[3:29 - 3:34] // CHECK: usrs.m c:usrs.m@102@F@my_helper@y Extent=[3:36 - 3:41] @@ -119,4 +126,139 @@ static int local_func(int x) { return x; } // CHECK: usrs.m c:objc(cs)CWithExt(im)meth3 Extent=[66:1 - 66:27] // CHECK: usrs.m c:objc(cy)CWithExt@Bar Extent=[68:1 - 70:2] // CHECK: usrs.m c:objc(cy)CWithExt@Bar(im)meth4 Extent=[69:1 - 69:27] +// CHECK: usrs.m c:@F@aux_1 Extent=[72:6 - 72:26] +// CHECK: usrs.m c:@F@test_multi_declaration Extent=[73:5 - 77:2] +// CHECK: usrs.m c:usrs.m@980@F@test_multi_declaration@foo Extent=[74:3 - 74:14] +// CHECK: usrs.m c:usrs.m@980@F@test_multi_declaration@bar Extent=[74:16 - 74:23] +// CHECK: usrs.m c:usrs.m@980@F@test_multi_declaration@baz Extent=[74:25 - 74:32] + +// RUN: c-index-test -test-load-source all %s | FileCheck -check-prefix=CHECK-source %s +// CHECK-source: usrs.m:3:19: FunctionDecl=my_helper:3:19 (Definition) Extent=[3:19 - 3:60] +// CHECK-source: usrs.m:3:33: ParmDecl=x:3:33 (Definition) Extent=[3:29 - 3:34] +// CHECK-source: usrs.m:3:40: ParmDecl=y:3:40 (Definition) Extent=[3:36 - 3:41] +// CHECK-source: usrs.m:3:43: UnexposedStmt= Extent=[3:43 - 3:60] +// CHECK-source: usrs.m:3:45: UnexposedStmt= Extent=[3:45 - 3:57] +// CHECK-source: usrs.m:3:52: UnexposedExpr= Extent=[3:52 - 3:57] +// CHECK-source: usrs.m:3:52: DeclRefExpr=x:3:33 Extent=[3:52 - 3:53] +// CHECK-source: usrs.m:3:56: DeclRefExpr=y:3:40 Extent=[3:56 - 3:57] +// CHECK-source: usrs.m:5:1: EnumDecl=:5:1 (Definition) Extent=[5:1 - 8:2] +// CHECK-source: usrs.m:6:3: EnumConstantDecl=ABA:6:3 (Definition) Extent=[6:3 - 6:6] +// CHECK-source: usrs.m:7:3: EnumConstantDecl=CADABA:7:3 (Definition) Extent=[7:3 - 7:9] +// CHECK-source: usrs.m:10:1: EnumDecl=:10:1 (Definition) Extent=[10:1 - 13:2] +// CHECK-source: usrs.m:11:3: EnumConstantDecl=FOO:11:3 (Definition) Extent=[11:3 - 11:6] +// CHECK-source: usrs.m:12:3: EnumConstantDecl=BAR:12:3 (Definition) Extent=[12:3 - 12:6] +// CHECK-source: usrs.m:15:9: StructDecl=:15:9 (Definition) Extent=[15:9 - 18:2] +// CHECK-source: usrs.m:16:7: FieldDecl=wa:16:7 (Definition) Extent=[16:7 - 16:9] +// CHECK-source: usrs.m:17:7: FieldDecl=moo:17:7 (Definition) Extent=[17:7 - 17:10] +// CHECK-source: usrs.m:18:3: TypedefDecl=MyStruct:18:3 (Definition) Extent=[18:3 - 18:11] +// CHECK-source: usrs.m:15:9: TypeRef=MyStruct:15:9 Extent=[15:9 - 15:15] +// CHECK-source: usrs.m:20:6: EnumDecl=Pizza:20:6 (Definition) Extent=[20:1 - 23:2] +// CHECK-source: usrs.m:21:3: EnumConstantDecl=CHEESE:21:3 (Definition) Extent=[21:3 - 21:9] +// CHECK-source: usrs.m:22:3: EnumConstantDecl=MUSHROOMS:22:3 (Definition) Extent=[22:3 - 22:12] +// CHECK-source: usrs.m:25:12: ObjCInterfaceDecl=Foo:25:12 Extent=[25:1 - 32:5] +// CHECK-source: usrs.m:26:6: ObjCIvarDecl=x:26:6 (Definition) Extent=[26:6 - 26:7] +// CHECK-source: usrs.m:26:3: TypeRef=id:0:0 Extent=[26:3 - 26:5] +// CHECK-source: usrs.m:27:6: ObjCIvarDecl=y:27:6 (Definition) Extent=[27:6 - 27:7] +// CHECK-source: usrs.m:27:3: TypeRef=id:0:0 Extent=[27:3 - 27:5] +// CHECK-source: usrs.m:31:15: ObjCPropertyDecl=d1:31:15 Extent=[31:15 - 31:17] +// CHECK-source: usrs.m:29:1: ObjCInstanceMethodDecl=godzilla:29:1 Extent=[29:1 - 29:17] +// CHECK-source: usrs.m:29:4: TypeRef=id:0:0 Extent=[29:4 - 29:6] +// CHECK-source: usrs.m:30:1: ObjCClassMethodDecl=kingkong:30:1 Extent=[30:1 - 30:17] +// CHECK-source: usrs.m:30:4: TypeRef=id:0:0 Extent=[30:4 - 30:6] +// CHECK-source: usrs.m:31:15: ObjCInstanceMethodDecl=d1:31:15 Extent=[31:15 - 31:17] +// CHECK-source: usrs.m:31:15: ObjCInstanceMethodDecl=setD1::31:15 Extent=[31:15 - 31:17] +// CHECK-source: usrs.m:31:15: ParmDecl=d1:31:15 (Definition) Extent=[31:15 - 31:17] +// CHECK-source: usrs.m:34:1: ObjCImplementationDecl=Foo:34:1 (Definition) Extent=[34:1 - 45:2] +// CHECK-source: usrs.m:35:1: ObjCInstanceMethodDecl=godzilla:35:1 (Definition) [Overrides @29:1] Extent=[35:1 - 39:2] +// CHECK-source: usrs.m:35:4: TypeRef=id:0:0 Extent=[35:4 - 35:6] +// CHECK-source: usrs.m:35:17: UnexposedStmt= Extent=[35:17 - 39:2] +// CHECK-source: usrs.m:36:3: UnexposedStmt= Extent=[36:3 - 36:20] +// CHECK-source: usrs.m:36:14: VarDecl=a:36:14 (Definition) Extent=[36:10 - 36:19] +// CHECK-source: usrs.m:36:18: UnexposedExpr= Extent=[36:18 - 36:19] +// CHECK-source: usrs.m:37:3: UnexposedStmt= Extent=[37:3 - 37:16] +// CHECK-source: usrs.m:37:14: VarDecl=z:37:14 Extent=[37:10 - 37:15] +// CHECK-source: usrs.m:38:3: UnexposedStmt= Extent=[38:3 - 38:11] +// CHECK-source: usrs.m:38:10: UnexposedExpr= Extent=[38:10 - 38:11] +// CHECK-source: usrs.m:38:10: UnexposedExpr= Extent=[38:10 - 38:11] +// CHECK-source: usrs.m:40:1: ObjCClassMethodDecl=kingkong:40:1 (Definition) [Overrides @30:1] Extent=[40:1 - 43:2] +// CHECK-source: usrs.m:40:4: TypeRef=id:0:0 Extent=[40:4 - 40:6] +// CHECK-source: usrs.m:40:17: UnexposedStmt= Extent=[40:17 - 43:2] +// CHECK-source: usrs.m:41:3: UnexposedStmt= Extent=[41:3 - 41:17] +// CHECK-source: usrs.m:41:7: VarDecl=local_var:41:7 (Definition) Extent=[41:3 - 41:16] +// CHECK-source: usrs.m:42:3: UnexposedStmt= Extent=[42:3 - 42:11] +// CHECK-source: usrs.m:42:10: UnexposedExpr= Extent=[42:10 - 42:11] +// CHECK-source: usrs.m:42:10: UnexposedExpr= Extent=[42:10 - 42:11] +// CHECK-source: usrs.m:44:13: ObjCIvarDecl=d1:44:13 (Definition) Extent=[44:13 - 44:15] +// CHECK-source: usrs.m:44:13: UnexposedDecl=:44:13 (Definition) Extent=[44:1 - 44:15] +// CHECK-source: usrs.m:47:5: VarDecl=z:47:5 Extent=[47:1 - 47:6] +// CHECK-source: usrs.m:49:12: FunctionDecl=local_func:49:12 (Definition) Extent=[49:12 - 49:43] +// CHECK-source: usrs.m:49:27: ParmDecl=x:49:27 (Definition) Extent=[49:23 - 49:28] +// CHECK-source: usrs.m:49:30: UnexposedStmt= Extent=[49:30 - 49:43] +// CHECK-source: usrs.m:49:32: UnexposedStmt= Extent=[49:32 - 49:40] +// CHECK-source: usrs.m:49:39: DeclRefExpr=x:49:27 Extent=[49:39 - 49:40] +// CHECK-source: usrs.m:51:12: ObjCInterfaceDecl=CWithExt:51:12 Extent=[51:1 - 53:5] +// CHECK-source: usrs.m:52:1: ObjCInstanceMethodDecl=meth1:52:1 Extent=[52:1 - 52:14] +// CHECK-source: usrs.m:52:4: TypeRef=id:0:0 Extent=[52:4 - 52:6] +// CHECK-source: usrs.m:54:12: ObjCCategoryDecl=:54:12 Extent=[54:1 - 56:5] +// CHECK-source: usrs.m:54:12: ObjCClassRef=CWithExt:51:12 Extent=[54:12 - 54:20] +// CHECK-source: usrs.m:55:1: ObjCInstanceMethodDecl=meth2:55:1 Extent=[55:1 - 55:14] +// CHECK-source: usrs.m:55:4: TypeRef=id:0:0 Extent=[55:4 - 55:6] +// CHECK-source: usrs.m:57:12: ObjCCategoryDecl=:57:12 Extent=[57:1 - 59:5] +// CHECK-source: usrs.m:57:12: ObjCClassRef=CWithExt:51:12 Extent=[57:12 - 57:20] +// CHECK-source: usrs.m:58:1: ObjCInstanceMethodDecl=meth3:58:1 Extent=[58:1 - 58:14] +// CHECK-source: usrs.m:58:4: TypeRef=id:0:0 Extent=[58:4 - 58:6] +// CHECK-source: usrs.m:60:12: ObjCCategoryDecl=Bar:60:12 Extent=[60:1 - 62:5] +// CHECK-source: usrs.m:60:12: ObjCClassRef=CWithExt:51:12 Extent=[60:12 - 60:20] +// CHECK-source: usrs.m:61:1: ObjCInstanceMethodDecl=meth4:61:1 Extent=[61:1 - 61:14] +// CHECK-source: usrs.m:61:4: TypeRef=id:0:0 Extent=[61:4 - 61:6] +// CHECK-source: usrs.m:63:1: ObjCImplementationDecl=CWithExt:63:1 (Definition) Extent=[63:1 - 67:2] +// CHECK-source: usrs.m:64:1: ObjCInstanceMethodDecl=meth1:64:1 (Definition) [Overrides @52:1] Extent=[64:1 - 64:27] +// CHECK-source: usrs.m:64:4: TypeRef=id:0:0 Extent=[64:4 - 64:6] +// CHECK-source: usrs.m:64:14: UnexposedStmt= Extent=[64:14 - 64:27] +// CHECK-source: usrs.m:64:16: UnexposedStmt= Extent=[64:16 - 64:24] +// CHECK-source: usrs.m:64:23: UnexposedExpr= Extent=[64:23 - 64:24] +// CHECK-source: usrs.m:64:23: UnexposedExpr= Extent=[64:23 - 64:24] +// CHECK-source: usrs.m:65:1: ObjCInstanceMethodDecl=meth2:65:1 (Definition) [Overrides @55:1] Extent=[65:1 - 65:27] +// CHECK-source: usrs.m:65:4: TypeRef=id:0:0 Extent=[65:4 - 65:6] +// CHECK-source: usrs.m:65:14: UnexposedStmt= Extent=[65:14 - 65:27] +// CHECK-source: usrs.m:65:16: UnexposedStmt= Extent=[65:16 - 65:24] +// CHECK-source: usrs.m:65:23: UnexposedExpr= Extent=[65:23 - 65:24] +// CHECK-source: usrs.m:65:23: UnexposedExpr= Extent=[65:23 - 65:24] +// CHECK-source: usrs.m:66:1: ObjCInstanceMethodDecl=meth3:66:1 (Definition) [Overrides @58:1] Extent=[66:1 - 66:27] +// CHECK-source: usrs.m:66:4: TypeRef=id:0:0 Extent=[66:4 - 66:6] +// CHECK-source: usrs.m:66:14: UnexposedStmt= Extent=[66:14 - 66:27] +// CHECK-source: usrs.m:66:16: UnexposedStmt= Extent=[66:16 - 66:24] +// CHECK-source: usrs.m:66:23: UnexposedExpr= Extent=[66:23 - 66:24] +// CHECK-source: usrs.m:66:23: UnexposedExpr= Extent=[66:23 - 66:24] +// CHECK-source: usrs.m:68:1: ObjCCategoryImplDecl=Bar:68:1 (Definition) Extent=[68:1 - 70:2] +// CHECK-source: usrs.m:68:1: ObjCClassRef=CWithExt:51:12 Extent=[68:1 - 68:2] +// CHECK-source: usrs.m:69:1: ObjCInstanceMethodDecl=meth4:69:1 (Definition) [Overrides @61:1] Extent=[69:1 - 69:27] +// CHECK-source: usrs.m:69:4: TypeRef=id:0:0 Extent=[69:4 - 69:6] +// CHECK-source: usrs.m:69:14: UnexposedStmt= Extent=[69:14 - 69:27] +// CHECK-source: usrs.m:69:16: UnexposedStmt= Extent=[69:16 - 69:24] +// CHECK-source: usrs.m:69:23: UnexposedExpr= Extent=[69:23 - 69:24] +// CHECK-source: usrs.m:69:23: UnexposedExpr= Extent=[69:23 - 69:24] +// CHECK-source: usrs.m:72:6: FunctionDecl=aux_1:72:6 Extent=[72:6 - 72:26] +// CHECK-source: usrs.m:72:15: ParmDecl=:72:15 (Definition) Extent=[72:12 - 72:16] +// CHECK-source: usrs.m:72:20: ParmDecl=:72:20 (Definition) Extent=[72:17 - 72:21] +// CHECK-source: usrs.m:72:25: ParmDecl=:72:25 (Definition) Extent=[72:22 - 72:26] +// CHECK-source: usrs.m:73:5: FunctionDecl=test_multi_declaration:73:5 (Definition) Extent=[73:5 - 77:2] +// CHECK-source: usrs.m:73:34: UnexposedStmt= Extent=[73:34 - 77:2] +// CHECK-source: usrs.m:74:3: UnexposedStmt= Extent=[74:3 - 74:33] +// CHECK-source: usrs.m:74:7: VarDecl=foo:74:7 (Definition) Extent=[74:3 - 74:14] +// CHECK-source: usrs.m:74:13: UnexposedExpr= Extent=[74:13 - 74:14] +// CHECK-source: usrs.m:74:16: VarDecl=bar:74:16 Extent=[74:16 - 74:23] +// CHECK-source: usrs.m:74:22: UnexposedExpr= Extent=[74:22 - 74:23] +// CHECK-source: usrs.m:74:25: VarDecl=baz:74:25 Extent=[74:25 - 74:32] +// CHECK-source: usrs.m:74:31: UnexposedExpr= Extent=[74:31 - 74:32] +// CHECK-source: usrs.m:75:3: CallExpr=aux_1:72:6 Extent=[75:3 - 75:23] +// CHECK-source: usrs.m:75:3: UnexposedExpr=aux_1:72:6 Extent=[75:3 - 75:8] +// CHECK-source: usrs.m:75:3: DeclRefExpr=aux_1:72:6 Extent=[75:3 - 75:8] +// CHECK-source: usrs.m:75:9: DeclRefExpr=foo:74:7 Extent=[75:9 - 75:12] +// CHECK-source: usrs.m:75:14: DeclRefExpr=bar:74:16 Extent=[75:14 - 75:17] +// CHECK-source: usrs.m:75:19: DeclRefExpr=baz:74:25 Extent=[75:19 - 75:22] +// CHECK-source: usrs.m:76:3: UnexposedStmt= Extent=[76:3 - 76:11] +// CHECK-source: usrs.m:76:10: UnexposedExpr= Extent=[76:10 - 76:11] + + diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 44493497bd..4413766b02 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -1357,10 +1357,12 @@ bool CursorVisitor::VisitCaseStmt(CaseStmt *S) { } bool CursorVisitor::VisitDeclStmt(DeclStmt *S) { + bool isFirst = true; for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end(); D != DEnd; ++D) { - if (*D && Visit(MakeCXCursor(*D, TU))) + if (*D && Visit(MakeCXCursor(*D, TU, isFirst))) return true; + isFirst = false; } return false; @@ -2926,6 +2928,16 @@ CXSourceLocation clang_getCursorLocation(CXCursor C) { SourceLocation Loc = D->getLocation(); if (ObjCInterfaceDecl *Class = dyn_cast(D)) Loc = Class->getClassLoc(); + // 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)) + Loc = VD->getLocation(); + } + return cxloc::translateSourceLocation(getCursorContext(C), Loc); } @@ -2988,9 +3000,20 @@ static SourceRange getRawCursorExtent(CXCursor C) { if (C.kind == CXCursor_InclusionDirective) return cxcursor::getCursorInclusionDirective(C)->getSourceRange(); - if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) - return getCursorDecl(C)->getSourceRange(); - + if (C.kind >= CXCursor_FirstDecl && C.kind <= CXCursor_LastDecl) { + Decl *D = cxcursor::getCursorDecl(C); + SourceRange R = D->getSourceRange(); + // 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 SourceRange();} extern "C" { diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp index d506400407..9dd94f972e 100644 --- a/tools/libclang/CXCursor.cpp +++ b/tools/libclang/CXCursor.cpp @@ -20,6 +20,7 @@ #include "clang/AST/DeclObjC.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang-c/Index.h" #include "llvm/Support/ErrorHandling.h" using namespace clang; @@ -49,9 +50,12 @@ CXCursor cxcursor::MakeCXCursor(const Attr *A, Decl *Parent, ASTUnit *TU) { return C; } -CXCursor cxcursor::MakeCXCursor(Decl *D, ASTUnit *TU) { +CXCursor cxcursor::MakeCXCursor(Decl *D, ASTUnit *TU, + bool FirstInDeclGroup) { assert(D && TU && "Invalid arguments!"); - CXCursor C = { getCursorKindForDecl(D), { D, 0, TU } }; + CXCursor C = { getCursorKindForDecl(D), + { D, (void*) (FirstInDeclGroup ? 1 : 0), TU } + }; return C; } @@ -470,3 +474,11 @@ bool cxcursor::operator==(CXCursor X, CXCursor Y) { return X.kind == Y.kind && X.data[0] == Y.data[0] && X.data[1] == Y.data[1] && X.data[2] == Y.data[2]; } + +// FIXME: Remove once we can model DeclGroups and their appropriate ranges +// properly in the ASTs. +bool cxcursor::isFirstInDeclGroup(CXCursor C) { + assert(clang_isDeclaration(C.kind)); + return ((uintptr_t) (C.data[1])) != 0; +} + diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h index a31a322076..7e518edef9 100644 --- a/tools/libclang/CXCursor.h +++ b/tools/libclang/CXCursor.h @@ -45,7 +45,8 @@ class TypeDecl; namespace cxcursor { CXCursor MakeCXCursor(const clang::Attr *A, clang::Decl *Parent, ASTUnit *TU); -CXCursor MakeCXCursor(clang::Decl *D, ASTUnit *TU); +CXCursor MakeCXCursor(clang::Decl *D, ASTUnit *TU, + bool FirstInDeclGroup = true); CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent, ASTUnit *TU); CXCursor MakeCXCursorInvalid(CXCursorKind K); @@ -183,6 +184,10 @@ inline bool operator!=(CXCursor X, CXCursor Y) { return !(X == Y); } +/// \brief Return true if the cursor represents a declaration that is the +/// first in a declaration group. +bool isFirstInDeclGroup(CXCursor C); + }} // end namespace: clang::cxcursor #endif