Merge pending instantiations instead of overwriting existing ones.
Check whether a pending instantiation needs to be instantiated (or whether an instantiation already exists).
Verify the size of the PendingInstantiations record (was only checking size of existing PendingInstantiations).

Migrate Obj-C++ part of redecl-merge into separate test, now that this is growing.
templates.mm: test that CodeGen has seen exactly one definition of template instantiations.
redecl-merge.m: use "@" specifier for expected-diagnostics.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164993 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index 639ef93..a897d86 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -2223,13 +2223,15 @@
 
     case PENDING_IMPLICIT_INSTANTIATIONS:
       if (PendingInstantiations.size() % 2 != 0) {
+        Error("Invalid existing PendingInstantiations");
+        return Failure;
+      }
+
+      if (Record.size() % 2 != 0) {
         Error("Invalid PENDING_IMPLICIT_INSTANTIATIONS block");
         return Failure;
       }
-        
-      // Later lists of pending instantiations overwrite earlier ones.
-      // FIXME: This is most certainly wrong for modules.
-      PendingInstantiations.clear();
+
       for (unsigned I = 0, N = Record.size(); I != N; /* in loop */) {
         PendingInstantiations.push_back(getGlobalDeclID(F, Record[I++]));
         PendingInstantiations.push_back(
@@ -5592,7 +5594,11 @@
     ValueDecl *D = cast<ValueDecl>(GetDecl(PendingInstantiations[Idx++]));
     SourceLocation Loc
       = SourceLocation::getFromRawEncoding(PendingInstantiations[Idx++]);
-    Pending.push_back(std::make_pair(D, Loc));
+
+    // For modules, find out whether an instantiation already exists
+    if (!getContext().getLangOpts().Modules
+        || needPendingInstantiation(D))
+      Pending.push_back(std::make_pair(D, Loc));
   }  
   PendingInstantiations.clear();
 }
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index fb4192f..85740de 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -2156,7 +2156,7 @@
   // loading, and some declarations may still be initializing.
   if (isConsumerInterestedIn(D))
     InterestingDecls.push_back(D);
-  
+
   return D;
 }
 
@@ -2504,3 +2504,60 @@
     }
   }
 }
+
+/// \brief Return a template specialization of ND (should be a TemplateDecl)
+///  that matches FD or TD.
+static NamedDecl* findMatchingSpecialization(FunctionDecl* FD,
+                                             ClassTemplateSpecializationDecl*TD,
+                                             NamedDecl* ND) {
+  TemplateDecl* Templt = dyn_cast<TemplateDecl>(ND);
+  if (!Templt) return 0;
+  if (FD) {
+    FunctionTemplateDecl* FTD = dyn_cast<FunctionTemplateDecl>(Templt);
+    if (!FTD) return 0;
+    const TemplateArgumentList* TmpltArgs = FD->getTemplateSpecializationArgs();
+    assert(TmpltArgs || "Template without arguments");
+    void* InsertionPoint;
+    return FTD->findSpecialization(TmpltArgs->data(), TmpltArgs->size(),
+                                   InsertionPoint);
+  } else {
+    ClassTemplateDecl* CTD = dyn_cast<ClassTemplateDecl>(Templt);
+    if (!CTD) return 0;
+    const TemplateArgumentList& TmpltArgs = TD->getTemplateArgs();
+    void* InsertionPoint;
+    return CTD->findSpecialization(TmpltArgs.data(), TmpltArgs.size(),
+                                   InsertionPoint);
+  }
+  return 0;
+}
+
+/// \brief Find out whether an instantiation (outside the module) already exists
+bool ASTReader::needPendingInstantiation(ValueDecl* D) const {
+  DeclContext *DC = D->getDeclContext()->getRedeclContext();
+  DeclarationName Name = D->getDeclName();
+  assert(Name && "unnamed template");
+
+  FunctionDecl* FD = dyn_cast<FunctionDecl>(D);
+  ClassTemplateSpecializationDecl* CD
+    = FD ? 0 : dyn_cast<ClassTemplateSpecializationDecl>(D);
+
+  NamedDecl* FoundSpecialization = 0;
+  if (DC->isTranslationUnit() && SemaObj) {
+    IdentifierResolver &IdResolver = SemaObj->IdResolver;
+    for (IdentifierResolver::iterator I = IdResolver.begin(Name), 
+           IEnd = IdResolver.end();
+         I != IEnd && !FoundSpecialization; ++I)
+      FoundSpecialization = findMatchingSpecialization(FD, CD, *I);
+  } else {
+    // templates are redeclarables, i.e. they must have been merged into
+    // the primary context. Use localUncachedLookup to not pick up template
+    // decls from modules again.
+    llvm::SmallVector<NamedDecl*, 6> Results;
+    DC->getPrimaryContext()->localUncachedLookup(Name, Results);
+    for (llvm::SmallVector<NamedDecl *, 6>::const_iterator
+           I = Results.begin(), E = Results.end();
+         I != E && FoundSpecialization; ++I)
+      FoundSpecialization = findMatchingSpecialization(FD, CD, *I);
+  }
+  return FoundSpecialization && isSameEntity(FoundSpecialization, D);
+}