Fix USRs for 'extern' variables declaration in functions/method bodies.
Fix USRs for @synthesize.
Add more USR tests.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101954 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp
index d67f97a..58870b9 100644
--- a/tools/CIndex/CIndexUSRs.cpp
+++ b/tools/CIndex/CIndexUSRs.cpp
@@ -46,11 +46,13 @@
   void VisitNamespaceDecl(NamespaceDecl *D);
   void VisitObjCClassDecl(ObjCClassDecl *CD);
   void VisitObjCContainerDecl(ObjCContainerDecl *CD);
-  void VisitObjCMethodDecl(ObjCMethodDecl *MD);
   void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P);
+  void VisitObjCMethodDecl(ObjCMethodDecl *MD);
   void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+  void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
   void VisitTagDecl(TagDecl *D);
   void VisitTypedefDecl(TypedefDecl *D);
+  void VisitVarDecl(VarDecl *D);
 
   /// Generate the string component containing the location of the
   ///  declaration.
@@ -132,7 +134,7 @@
     return;
   }
   VisitDeclContext(D->getDeclContext());
-  Out << "@FI@" << s;
+  Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@") << s;
 }
 
 void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
@@ -153,6 +155,24 @@
     GenNamedDecl(s);
 }
 
+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->hasExternalStorage())
+    VisitDeclContext(D->getDeclContext());
+
+  const std::string &s = D->getNameAsString();
+  // The string can be empty if the declaration has no name; e.g., it is
+  // the ParmDecl with no name for declaration of a function pointer type, e.g.:
+  //  	void  (*f)(void *);
+  // In this case, don't generate a USR.
+  if (s.empty())
+    IgnoreResults = true;
+  else
+    GenNamedDecl(s);
+}
+
 void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
   VisitDeclContext(D->getDeclContext());
   Out << "@N@" << D;
@@ -223,6 +243,15 @@
   GenObjCProperty(D->getName());
 }
 
+void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+  if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
+    VisitObjCPropertyDecl(PD);
+    return;
+  }
+
+  IgnoreResults = true;
+}
+
 void USRGenerator::VisitTagDecl(TagDecl *D) {
   D = D->getCanonicalDecl();
   VisitDeclContext(D->getDeclContext());
@@ -369,6 +398,9 @@
   if (SUG->ignoreResults())
     return createCXString("");
 
+  // For development testing.
+  // assert(SUG.str().size() > 2);
+
     // Return a copy of the string that must be disposed by the caller.
   return createCXString(SUG.str(), true);
 }