[libclang] Indexing API: Fully index implict template instantiations.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150267 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h
index c1cde7f..3c0e0fc 100644
--- a/include/clang/AST/ASTConsumer.h
+++ b/include/clang/AST/ASTConsumer.h
@@ -24,6 +24,7 @@
   class SemaConsumer; // layering violation required for safe SemaConsumer
   class TagDecl;
   class VarDecl;
+  class FunctionDecl;
 
 /// ASTConsumer - This is an abstract interface that should be implemented by
 /// clients that read ASTs.  This abstraction layer allows the client to be
@@ -67,6 +68,12 @@
   /// can be defined in declspecs).
   virtual void HandleTagDeclDefinition(TagDecl *D) {}
 
+  /// \brief Invoked when a function is implicitly instantiated.
+  /// Note that at this point point it does not have a body, its body is
+  /// instantiated at the end of the translation unit and passed to
+  /// HandleTopLevelDecl.
+  virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {}
+
   /// \brief Handle the specified top-level declaration that occurred inside
   /// and ObjC container.
   /// The default implementation ignored them.
diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h
index 0c4f7dc..8814aa3 100644
--- a/include/clang/Frontend/MultiplexConsumer.h
+++ b/include/clang/Frontend/MultiplexConsumer.h
@@ -39,6 +39,7 @@
   virtual void HandleInterestingDecl(DeclGroupRef D);
   virtual void HandleTranslationUnit(ASTContext &Ctx);
   virtual void HandleTagDeclDefinition(TagDecl *D);
+  virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D);
   virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D);
   virtual void CompleteTentativeDefinition(VarDecl *D);
   virtual void HandleVTable(CXXRecordDecl *RD, bool DefinitionRequired);
diff --git a/lib/Frontend/MultiplexConsumer.cpp b/lib/Frontend/MultiplexConsumer.cpp
index 5afa1cd..cef4590 100644
--- a/lib/Frontend/MultiplexConsumer.cpp
+++ b/lib/Frontend/MultiplexConsumer.cpp
@@ -224,6 +224,11 @@
     Consumers[i]->HandleTagDeclDefinition(D);
 }
 
+void MultiplexConsumer::HandleCXXImplicitFunctionInstantiation(FunctionDecl *D){
+  for (size_t i = 0, e = Consumers.size(); i != e; ++i)
+    Consumers[i]->HandleCXXImplicitFunctionInstantiation(D);
+}
+
 void MultiplexConsumer::HandleTopLevelDeclInObjCContainer(DeclGroupRef D) {
   for (size_t i = 0, e = Consumers.size(); i != e; ++i)
     Consumers[i]->HandleTopLevelDeclInObjCContainer(D);
diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp
index 7be1a44..baf4d64 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -18,6 +18,7 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/AnalysisBasedWarnings.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ASTConsumer.h"
 #include "clang/AST/ASTMutationListener.h"
 #include "clang/AST/CXXInheritance.h"
 #include "clang/AST/DeclObjC.h"
@@ -9483,8 +9484,11 @@
         // expression evaluator needing to call back into Sema if it sees a
         // call to such a function.
         InstantiateFunctionDefinition(Loc, Func);
-      else
+      else {
         PendingInstantiations.push_back(std::make_pair(Func, Loc));
+        // Notify the consumer that a function was implicitly instantiated.
+        Consumer.HandleCXXImplicitFunctionInstantiation(Func);
+      }
     }
   } else {
     // Walk redefinitions, as some of them may be instantiable.
diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp
index d2eb402..3e92669 100644
--- a/tools/libclang/IndexDecl.cpp
+++ b/tools/libclang/IndexDecl.cpp
@@ -220,6 +220,15 @@
     return true;
   }
 
+  bool VisitClassTemplateSpecializationDecl(
+                                           ClassTemplateSpecializationDecl *D) {
+    // FIXME: Notify subsequent callbacks that info comes from implicit
+    // instantiation.
+    if (D->isThisDeclarationADefinition())
+      IndexCtx.indexTagDecl(D);
+    return true;
+  }
+
   bool VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
     IndexCtx.handleFunctionTemplate(D);
     FunctionDecl *FD = D->getTemplatedDecl();
diff --git a/tools/libclang/IndexTypeSourceInfo.cpp b/tools/libclang/IndexTypeSourceInfo.cpp
index e326404..012e422 100644
--- a/tools/libclang/IndexTypeSourceInfo.cpp
+++ b/tools/libclang/IndexTypeSourceInfo.cpp
@@ -72,10 +72,14 @@
   }
 
   bool VisitTemplateSpecializationTypeLoc(TemplateSpecializationTypeLoc TL) {
-    if (const TemplateSpecializationType *T = TL.getTypePtr())
+    if (const TemplateSpecializationType *T = TL.getTypePtr()) {
       if (const TemplateDecl *D = T->getTemplateName().getAsTemplateDecl())
         IndexCtx.handleReference(D, TL.getTemplateNameLoc(),
                                  Parent, ParentDC);
+      if (CXXRecordDecl *RD = T->getAsCXXRecordDecl())
+        IndexCtx.handleReference(RD, TL.getTemplateNameLoc(),
+                                 Parent, ParentDC);
+    }
     return true;
   }
 };
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index c42ef23..a70a341 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -135,6 +135,15 @@
   /// The default implementation forwards to HandleTopLevelDecl but we don't
   /// care about them when indexing, so have an empty definition.
   virtual void HandleInterestingDecl(DeclGroupRef D) {}
+
+  virtual void HandleTagDeclDefinition(TagDecl *D) {
+    if (IndexCtx.isTemplateImplicitInstantiation(D))
+      IndexCtx.indexDecl(D);
+  }
+
+  virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {
+    IndexCtx.indexDecl(D);
+  }
 };
 
 //===----------------------------------------------------------------------===//
@@ -185,7 +194,7 @@
     indexDiagnostics(CXTU, IndexCtx);
   }
 
-  virtual TranslationUnitKind getTranslationUnitKind() { return TU_Prefix; }
+  virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; }
   virtual bool hasCodeCompletionSupport() const { return false; }
 };
 
diff --git a/tools/libclang/IndexingContext.cpp b/tools/libclang/IndexingContext.cpp
index 059d842..47d7ff4 100644
--- a/tools/libclang/IndexingContext.cpp
+++ b/tools/libclang/IndexingContext.cpp
@@ -282,9 +282,23 @@
   DInfo.numAttributes = AttrList.getNumAttrs();
 
   getContainerInfo(D->getDeclContext(), DInfo.SemanticContainer);
-  getContainerInfo(D->getLexicalDeclContext(), DInfo.LexicalContainer);
   DInfo.semanticContainer = &DInfo.SemanticContainer;
-  DInfo.lexicalContainer = &DInfo.LexicalContainer;
+
+  if (D->getLexicalDeclContext() == D->getDeclContext()) {
+    DInfo.lexicalContainer = &DInfo.SemanticContainer;
+  } else if (isTemplateImplicitInstantiation(D)) {
+    // Implicit instantiations have the lexical context of where they were
+    // instantiated first. We choose instead the semantic context because:
+    // 1) at the time that we see the instantiation we have not seen the
+    //   function where it occurred yet.
+    // 2) the lexical context of the first instantiation is not useful
+    //   information anyway.
+    DInfo.lexicalContainer = &DInfo.SemanticContainer;
+  } else {
+    getContainerInfo(D->getLexicalDeclContext(), DInfo.LexicalContainer);
+    DInfo.lexicalContainer = &DInfo.LexicalContainer;
+  }
+
   if (DInfo.isContainer) {
     getContainerInfo(getEntityContainer(D), DInfo.DeclAsContainer);
     DInfo.declAsContainer = &DInfo.DeclAsContainer;
@@ -1036,3 +1050,14 @@
     return false;
   return true;
 }
+
+bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
+  if (const ClassTemplateSpecializationDecl *
+        SD = dyn_cast<ClassTemplateSpecializationDecl>(D)) {
+    return SD->getSpecializationKind() == TSK_ImplicitInstantiation;
+  }
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+    return FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation;
+  }
+  return false;
+}
diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h
index ef8e24e..38f7563 100644
--- a/tools/libclang/IndexingContext.h
+++ b/tools/libclang/IndexingContext.h
@@ -20,6 +20,7 @@
   class ClassTemplateDecl;
   class FunctionTemplateDecl;
   class TypeAliasTemplateDecl;
+  class ClassTemplateSpecializationDecl;
 
 namespace cxindex {
   class IndexingContext;
@@ -426,6 +427,8 @@
   CXIdxClientEntity getClientEntity(const Decl *D) const;
   void setClientEntity(const Decl *D, CXIdxClientEntity client);
 
+  static bool isTemplateImplicitInstantiation(const Decl *D);
+
 private:
   bool handleDecl(const NamedDecl *D,
                   SourceLocation Loc, CXCursor Cursor,