]> granicus.if.org Git - clang/commitdiff
Add USR support for C++ namespaces, and unify mangling of location information in...
authorTed Kremenek <kremenek@apple.com>
Thu, 6 May 2010 23:38:28 +0000 (23:38 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 6 May 2010 23:38:28 +0000 (23:38 +0000)
for anonymous symbols.

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

test/Index/usrs.cpp [new file with mode: 0644]
test/Index/usrs.m
tools/libclang/CIndexUSRs.cpp

diff --git a/test/Index/usrs.cpp b/test/Index/usrs.cpp
new file mode 100644 (file)
index 0000000..a0d910d
--- /dev/null
@@ -0,0 +1,73 @@
+namespace foo {
+  int x;
+  void bar(int z);
+}
+namespace bar {
+  typedef int QType;
+  void bar(QType z);
+}
+
+class ClsA {
+public:
+  int a, b;
+  ClsA(int A, int B) : a(A), b(B) {}
+};
+
+namespace foo {
+  class ClsB : public ClsA {
+  public:
+    ClsB() : ClsA(1, 2) {}
+    int result() const;
+  };
+}
+
+int foo::ClsB::result() const {
+  return a + b;
+}
+
+namespace {
+  class ClsC : public foo::ClsB {};
+  int w;
+}
+
+int z;
+
+namespace foo { namespace taz {
+  int x;
+  static inline int add(int a, int b) { return a + b; }
+  void sub(int a, int b);
+}
+}
+
+// RUN: c-index-test -test-load-source-usrs all %s | FileCheck %s
+// CHECK: usrs.cpp c:@N@foo Extent=[1:11 - 4:2]
+// CHECK: usrs.cpp c:@N@foo@x Extent=[2:3 - 2:8]
+// CHECK: usrs.cpp c:@N@foo@F@bar Extent=[3:8 - 3:18]
+// CHECK: usrs.cpp c:usrs.cpp@3:12@N@foo@F@bar@z Extent=[3:12 - 3:17]
+// CHECK: usrs.cpp c:@N@bar Extent=[5:11 - 8:2]
+// CHECK: usrs.cpp c:usrs.cpp@6:15@N@bar@T@QType Extent=[6:15 - 6:20]
+// CHECK: usrs.cpp c:@N@bar@F@bar Extent=[7:8 - 7:20]
+// CHECK: usrs.cpp c:usrs.cpp@7:12@N@bar@F@bar@z Extent=[7:12 - 7:19]
+// CHECK: usrs.cpp c:@C@ClsA Extent=[10:1 - 14:2]
+// CHECK: usrs.cpp c:@C@ClsA@FI@a Extent=[12:7 - 12:8]
+// CHECK: usrs.cpp c:@C@ClsA@FI@b Extent=[12:10 - 12:11]
+// CHECK: usrs.cpp c:@C@ClsA@F@ClsA Extent=[13:3 - 13:37]
+// CHECK: usrs.cpp c:usrs.cpp@13:8@C@ClsA@F@ClsA@A Extent=[13:8 - 13:13]
+// CHECK: usrs.cpp c:usrs.cpp@13:15@C@ClsA@F@ClsA@B Extent=[13:15 - 13:20]
+// CHECK: usrs.cpp c:@N@foo Extent=[16:11 - 22:2]
+// CHECK: usrs.cpp c:@N@foo@C@ClsB Extent=[17:3 - 21:4]
+// CHECK: usrs.cpp c:@N@foo@C@ClsB@F@ClsB Extent=[19:5 - 19:27]
+// CHECK: usrs.cpp c:@N@foo@C@ClsB@F@result Extent=[20:9 - 20:17]
+// CHECK: usrs.cpp c:@N@foo@C@ClsB@F@result Extent=[24:16 - 26:2]
+// CHECK: usrs.cpp c:@aN@C@ClsC Extent=[29:3 - 29:35]
+// CHECK: usrs.cpp c:@aN@w Extent=[30:3 - 30:8]
+// CHECK: usrs.cpp c:@z Extent=[33:1 - 33:6]
+// CHECK: usrs.cpp c:@N@foo Extent=[35:11 - 40:2]
+// CHECK: usrs.cpp c:@N@foo@N@taz Extent=[35:27 - 39:2]
+// CHECK: usrs.cpp c:@N@foo@N@taz@x Extent=[36:3 - 36:8]
+// CHECK: usrs.cpp c:usrs.cpp@37:21@N@foo@N@taz@F@add Extent=[37:21 - 37:56]
+// CHECK: usrs.cpp c:usrs.cpp@37:25@N@foo@N@taz@F@add@a Extent=[37:25 - 37:30]
+// CHECK: usrs.cpp c:usrs.cpp@37:32@N@foo@N@taz@F@add@b Extent=[37:32 - 37:37]
+// CHECK: usrs.cpp c:@N@foo@N@taz@F@sub Extent=[38:8 - 38:25]
+// CHECK: usrs.cpp c:usrs.cpp@38:12@N@foo@N@taz@F@sub@a Extent=[38:12 - 38:17]
+// CHECK: usrs.cpp c:usrs.cpp@38:19@N@foo@N@taz@F@sub@b Extent=[38:19 - 38:24]
index eb0817c27c810e9fb271dd3a729ebe80cab23826..bffd0ee4bbc75010dd11a6e129bc9713ba089344 100644 (file)
@@ -49,18 +49,18 @@ int z;
 static int local_func(int x) { return x; }
 
 // CHECK: usrs.m c:usrs.m@3:19@F@my_helper Extent=[3:19 - 3:60]
-// CHECK: usrs.m c:usrs.m@3:29@x Extent=[3:29 - 3:34]
-// CHECK: usrs.m c:usrs.m@3:36@y Extent=[3:36 - 3:41]
-// CHECK: usrs.m c:@Ea@usrs.m@5:1 Extent=[5:1 - 8:2]
-// CHECK: usrs.m c:@Ea@usrs.m@5:1@ABA Extent=[6:3 - 6:6]
-// CHECK: usrs.m c:@Ea@usrs.m@5:1@CADABA Extent=[7:3 - 7:9]
-// CHECK: usrs.m c:@Ea@usrs.m@10:1 Extent=[10:1 - 13:2]
-// CHECK: usrs.m c:@Ea@usrs.m@10:1@FOO Extent=[11:3 - 11:6]
-// CHECK: usrs.m c:@Ea@usrs.m@10:1@BAR Extent=[12:3 - 12:6]
+// CHECK: usrs.m c:usrs.m@3:29@F@my_helper@x Extent=[3:29 - 3:34]
+// CHECK: usrs.m c:usrs.m@3:36@F@my_helper@y Extent=[3:36 - 3:41]
+// CHECK: usrs.m c:usrs.m@5:1@Ea Extent=[5:1 - 8:2]
+// CHECK: usrs.m c:usrs.m@5:1@Ea@ABA Extent=[6:3 - 6:6]
+// CHECK: usrs.m c:usrs.m@5:1@Ea@CADABA Extent=[7:3 - 7:9]
+// CHECK: usrs.m c:usrs.m@10:1@Ea Extent=[10:1 - 13:2]
+// CHECK: usrs.m c:usrs.m@10:1@Ea@FOO Extent=[11:3 - 11:6]
+// CHECK: usrs.m c:usrs.m@10:1@Ea@BAR Extent=[12:3 - 12:6]
 // CHECK: usrs.m c:@SA@MyStruct Extent=[15:9 - 18:2]
 // CHECK: usrs.m c:@SA@MyStruct@FI@wa Extent=[16:7 - 16:9]
 // CHECK: usrs.m c:@SA@MyStruct@FI@moo Extent=[17:7 - 17:10]
-// CHECK: usrs.m c:@T@usrs.m@18:3@MyStruct Extent=[18:3 - 18:11]
+// CHECK: usrs.m c:usrs.m@18:3@T@MyStruct Extent=[18:3 - 18:11]
 // CHECK: usrs.m c:@E@Pizza Extent=[20:1 - 23:2]
 // CHECK: usrs.m c:@E@Pizza@CHEESE Extent=[21:3 - 21:9]
 // CHECK: usrs.m c:@E@Pizza@MUSHROOMS Extent=[22:3 - 22:12]
@@ -72,16 +72,16 @@ static int local_func(int x) { return x; }
 // CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[30:1 - 30:17]
 // CHECK: usrs.m c:objc(cs)Foo(im)d1 Extent=[31:15 - 31:17]
 // CHECK: usrs.m c:objc(cs)Foo(im)setD1: Extent=[31:15 - 31:17]
-// CHECK: usrs.m c:usrs.m@31:15@d1 Extent=[31:15 - 31:17]
+// CHECK: usrs.m c:usrs.m@31:15objc(cs)Foo(im)setD1:@d1 Extent=[31:15 - 31:17]
 // CHECK: usrs.m c:objc(cs)Foo Extent=[34:1 - 45:2]
 // CHECK: usrs.m c:objc(cs)Foo(im)godzilla Extent=[35:1 - 39:2]
-// CHECK: usrs.m c:usrs.m@36:10@a Extent=[36:10 - 36:19]
-// CHECK: usrs.m c:@z Extent=[37:10 - 37:15]
+// CHECK: usrs.m c:usrs.m@36:10objc(cs)Foo(im)godzilla@a Extent=[36:10 - 36:19]
+// CHECK: usrs.m c:objc(cs)Foo(im)godzilla@z Extent=[37:10 - 37:15]
 // CHECK: usrs.m c:objc(cs)Foo(cm)kingkong Extent=[40:1 - 43:2]
-// CHECK: usrs.m c:usrs.m@41:3@local_var Extent=[41:3 - 41:16]
+// CHECK: usrs.m c:usrs.m@41:3objc(cs)Foo(cm)kingkong@local_var Extent=[41:3 - 41:16]
 // CHECK: usrs.m c:objc(cs)Foo@d1 Extent=[44:13 - 44:15]
 // CHECK: usrs.m c:objc(cs)Foo(py)d1 Extent=[44:1 - 44:15]
 // CHECK: usrs.m c:@z Extent=[47:1 - 47:6]
 // CHECK: usrs.m c:usrs.m@49:12@F@local_func Extent=[49:12 - 49:43]
-// CHECK: usrs.m c:usrs.m@49:23@x Extent=[49:23 - 49:28]
+// CHECK: usrs.m c:usrs.m@49:23@F@local_func@x Extent=[49:23 - 49:28]
 
index f3c74e85316f5f074f6a74f04d4eff06a07bc2c9..cc481d230e8bc5c6afeb3141ca6dc62f8f6c99c0 100644 (file)
@@ -31,9 +31,10 @@ class USRGenerator : public DeclVisitor<USRGenerator> {
   llvm::raw_ostream &Out;
   bool IgnoreResults;
   ASTUnit *AU;
+  bool generatedLoc;
 public:
   USRGenerator(ASTUnit *au, llvm::raw_ostream &out)
-    : Out(out), IgnoreResults(false), AU(au) {}
+    : Out(out), IgnoreResults(false), AU(au), generatedLoc(false) {}
 
   bool ignoreResults() const { return IgnoreResults; }
 
@@ -55,7 +56,7 @@ public:
 
   /// Generate the string component containing the location of the
   ///  declaration.
-  void GenLoc(const Decl *D);
+  bool GenLoc(const Decl *D);
 
   /// String generation methods used both by the visitation methods
   /// and from other clients that want to directly generate USRs.  These
@@ -114,6 +115,16 @@ public:
 // Generating USRs from ASTS.
 //===----------------------------------------------------------------------===//
 
+static bool InAnonymousNamespace(const Decl *D) {
+  if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(D->getDeclContext()))
+    return ND->isAnonymousNamespace();
+  return false;
+}
+
+static inline bool ShouldGenerateLocation(const NamedDecl *D) {
+  return D->getLinkage() != ExternalLinkage && !InAnonymousNamespace(D);
+}
+
 void USRGenerator::VisitDeclContext(DeclContext *DC) {
   if (NamedDecl *D = dyn_cast<NamedDecl>(DC))
     Visit(D);
@@ -131,15 +142,11 @@ void USRGenerator::VisitFieldDecl(FieldDecl *D) {
 }
 
 void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
-  if (D->getLinkage() != ExternalLinkage) {
-    GenLoc(D);
-    if (IgnoreResults)
-      return;
-  }
-  else
-    VisitDeclContext(D->getDeclContext());
+  if (ShouldGenerateLocation(D) && GenLoc(D))
+    return;
 
-  Out << "@F@" << D;
+  VisitDeclContext(D->getDeclContext());
+  Out << "@F@" << D->getNameAsString();
 }
 
 void USRGenerator::VisitNamedDecl(NamedDecl *D) {
@@ -159,11 +166,10 @@ void USRGenerator::VisitVarDecl(VarDecl *D) {
   // VarDecls can be declared 'extern' within a function or method body,
   // but their enclosing DeclContext is the function, not the TU.  We need
   // to check the storage class to correctly generate the USR.
-  if (D->getLinkage() != ExternalLinkage) {
-    GenLoc(D);
-    if (IgnoreResults)
-      return;
-  }
+  if (ShouldGenerateLocation(D) && GenLoc(D))
+    return;
+
+  VisitDeclContext(D->getDeclContext());
 
   // Variables always have simple names.
   llvm::StringRef s = D->getName();
@@ -179,8 +185,14 @@ void USRGenerator::VisitVarDecl(VarDecl *D) {
 }
 
 void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
+  if (D->isAnonymousNamespace()) {
+    Out << "@aN";
+    return;
+  }
+
   VisitDeclContext(D->getDeclContext());
-  Out << "@N@" << D;
+  if (!IgnoreResults)
+    Out << "@N@" << D->getName();
 }
 
 void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
@@ -258,8 +270,14 @@ void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
 }
 
 void USRGenerator::VisitTagDecl(TagDecl *D) {
+  // Add the location of the tag decl to handle resolution across
+  // translation units.
+  if (ShouldGenerateLocation(D) && GenLoc(D))
+    return;
+  
   D = D->getCanonicalDecl();
   VisitDeclContext(D->getDeclContext());
+
   switch (D->getTagKind()) {
     case TagDecl::TK_struct: Out << "@S"; break;
     case TagDecl::TK_class:  Out << "@C"; break;
@@ -274,15 +292,6 @@ void USRGenerator::VisitTagDecl(TagDecl *D) {
     Out << (TD ? 'A' : 'a');
   }
 
-  // Add the location of the tag decl to handle resolution across
-  // translation units.
-  if (D->getLinkage() == NoLinkage) {
-    Out << '@';
-    GenLoc(D);
-    if (IgnoreResults)
-      return;
-  }
-
   if (s.empty()) {
     if (TD)
       Out << '@' << TD;
@@ -292,25 +301,25 @@ void USRGenerator::VisitTagDecl(TagDecl *D) {
 }
 
 void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
+  if (ShouldGenerateLocation(D) && GenLoc(D))
+    return;
   DeclContext *DC = D->getDeclContext();
   if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
     Visit(DCN);
   Out << "@T@";
-  if (D->getLinkage() == NoLinkage) {
-    GenLoc(D);
-    if (IgnoreResults)
-      return;
-    Out << '@';
-  }
   Out << D->getName();
 }
 
-void USRGenerator::GenLoc(const Decl *D) {
+bool USRGenerator::GenLoc(const Decl *D) {
+  if (generatedLoc)
+    return IgnoreResults;
+  generatedLoc = true;
+
   const SourceManager &SM = AU->getSourceManager();
   SourceLocation L = D->getLocStart();
   if (L.isInvalid()) {
     IgnoreResults = true;
-    return;
+    return true;
   }
   L = SM.getInstantiationLoc(L);
   const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);
@@ -322,11 +331,13 @@ void USRGenerator::GenLoc(const Decl *D) {
   else {
     // This case really isn't interesting.
     IgnoreResults = true;
-    return;
+    return true;
   }
   Out << '@'
       << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':'
       << SM.getColumnNumber(Decomposed.first, Decomposed.second);
+  
+  return IgnoreResults;
 }
 
 //===----------------------------------------------------------------------===//
@@ -383,6 +394,7 @@ static CXString getDeclCursorUSR(const CXCursor &C) {
         // Generate USRs for all entities with external linkage.
         break;
       case NoLinkage:
+      case UniqueExternalLinkage:
         // We allow enums, typedefs, and structs that have no linkage to
         // have USRs that are anchored to the file they were defined in
         // (e.g., the header).  This is a little gross, but in principal
@@ -390,14 +402,12 @@ static CXString getDeclCursorUSR(const CXCursor &C) {
         // are referred to across multiple translation units.
         if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
             isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND) ||
-            isa<VarDecl>(ND))
+            isa<VarDecl>(ND) || isa<NamespaceDecl>(ND))
           break;
         // Fall-through.
       case InternalLinkage:
         if (isa<FunctionDecl>(ND))
           break;
-      case UniqueExternalLinkage:
-        return createCXString("");
     }
 
   StringUSRGenerator SUG(&C);