]> granicus.if.org Git - clang/commitdiff
Encapsulate within CXCursor the notion of whether a VarDecl* is the first Decl in...
authorTed Kremenek <kremenek@apple.com>
Mon, 1 Nov 2010 23:26:51 +0000 (23:26 +0000)
committerTed Kremenek <kremenek@apple.com>
Mon, 1 Nov 2010 23:26:51 +0000 (23:26 +0000)
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 <rdar://problem/8595749>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117973 91177308-0d34-0410-b5e6-96231b3b80d8

test/Index/usrs.m
tools/libclang/CIndex.cpp
tools/libclang/CXCursor.cpp
tools/libclang/CXCursor.h

index 4b3de5c480ab610a5b604cbbe7d151d26915328c..03ddfd31ee900bfca50ffc8246da34670ef013c4 100644 (file)
@@ -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]
+
+
 
index 44493497bdbb2e442e1032242a8cb8a94b94c04e..4413766b028e6c54647ccb37e488a087da89a417 100644 (file)
@@ -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<ObjCInterfaceDecl>(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<VarDecl>(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<VarDecl>(D)) {
+      if (!cxcursor::isFirstInDeclGroup(C))
+        R.setBegin(VD->getLocation());
+    }
+    return R;
+  }
   return SourceRange();}
 
 extern "C" {
index d506400407f070d0db38d08f679edffdbddd0e24..9dd94f972ef27dcb6ddb474f751cc462b34feb40 100644 (file)
@@ -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;
+}
+
index a31a32207673ae9fb532db9b1145597c590e64ff..7e518edef9699d201e738ee00f91ab1226c52159 100644 (file)
@@ -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