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
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index f3c74e8..cc481d2 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -31,9 +31,10 @@
   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 @@
 
   /// 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 @@
 // 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::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 @@
   // 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::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::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 @@
     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::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 @@
   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 @@
         // 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 @@
         // 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);