From cbd66f00cfe5c4412f8efd6e66b0bb6bae956f7c Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 6 May 2010 23:38:28 +0000 Subject: [PATCH] Add USR support for C++ namespaces, and unify mangling of location information in USRs for anonymous symbols. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103212 91177308-0d34-0410-b5e6-96231b3b80d8 --- test/Index/usrs.cpp | 73 ++++++++++++++++++++++++++++++ test/Index/usrs.m | 28 ++++++------ tools/libclang/CIndexUSRs.cpp | 84 ++++++++++++++++++++--------------- 3 files changed, 134 insertions(+), 51 deletions(-) create mode 100644 test/Index/usrs.cpp diff --git a/test/Index/usrs.cpp b/test/Index/usrs.cpp new file mode 100644 index 0000000000..a0d910d9a8 --- /dev/null +++ b/test/Index/usrs.cpp @@ -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] diff --git a/test/Index/usrs.m b/test/Index/usrs.m index eb0817c27c..bffd0ee4bb 100644 --- a/test/Index/usrs.m +++ b/test/Index/usrs.m @@ -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] diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index f3c74e8531..cc481d230e 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -31,9 +31,10 @@ class USRGenerator : public DeclVisitor { 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(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(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(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 &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(ND) || isa(ND) || isa(ND) || isa(ND) || - isa(ND)) + isa(ND) || isa(ND)) break; // Fall-through. case InternalLinkage: if (isa(ND)) break; - case UniqueExternalLinkage: - return createCXString(""); } StringUSRGenerator SUG(&C); -- 2.40.0