Fix "note" of a duplicate explicit instantiation definition following a specialization.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147798 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 2527ac6..b6babb6 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -5234,6 +5234,23 @@
   }
 }
 
+/// \brief Compute the diagnostic location for an explicit instantiation
+//  declaration or definition.
+static SourceLocation DiagLocForExplicitInstantiation(
+    NamedDecl* Decl, SourceLocation PointOfInstantiation) {
+  // Explicit instantiations following a specialization have no effect and
+  // hence no PointOfInstantiation. In that case, walk decl backwards
+  // until a valid name loc is found.
+  SourceLocation PrevDiagLoc = PointOfInstantiation;
+  for (NamedDecl *Prev = Decl; Prev && !PrevDiagLoc.isValid();
+      Prev = getPreviousDecl(Prev)) {
+    PrevDiagLoc = Prev->getLocation();
+  }
+  assert(PrevDiagLoc.isValid() &&
+         "Explicit instantiation without point of instantiation?");
+  return PrevDiagLoc;
+}
+
 /// \brief Diagnose cases where we have an explicit template specialization
 /// before/after an explicit template instantiation, producing diagnostics
 /// for those cases where they are required and determining whether the
@@ -5348,14 +5365,8 @@
       // Explicit instantiations following a specialization have no effect and
       // hence no PrevPointOfInstantiation. In that case, walk decl backwards
       // until a valid name loc is found.
-      SourceLocation PrevDiagLoc = PrevPointOfInstantiation;
-      for (NamedDecl *Prev = PrevDecl; Prev && !PrevDiagLoc.isValid();
-          Prev = getPreviousDecl(Prev)) {
-        PrevDiagLoc = Prev->getLocation();
-      }
-      Diag(PrevDiagLoc, diag::note_explicit_instantiation_definition_here);
-      assert(PrevDiagLoc.isValid() &&
-             "Explicit instantiation without point of instantiation?");
+      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
+           diag::note_explicit_instantiation_definition_here);
       HasNoEffect = true;
       return false;
     }
@@ -5414,7 +5425,7 @@
       //       in a program,
       Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
         << PrevDecl;
-      Diag(PrevPointOfInstantiation,
+      Diag(DiagLocForExplicitInstantiation(PrevDecl, PrevPointOfInstantiation),
            diag::note_previous_explicit_instantiation);
       HasNoEffect = true;
       return false;
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
index 89f3438..aecbfb5 100644
--- a/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
@@ -302,15 +302,12 @@
 
   // And some more random tests.
 
-// FIXME: Enable this test. The error is printed fine, but the note is at some
-// weird source location that causes "previous explicit instantiation is here"
-// without anything after it to be printed. That happened before this patch too.
-//  namespace SII_WithDefinedTemplate {
-//    template <typename STRING_TYPE> class BasicStringPiece {};
-//    template <> class BasicStringPiece<int> { };
-//    template class BasicStringPiece<int>;
-//    template class BasicStringPiece<int>;
-//  }
+  namespace SII_WithDefinedTemplate {
+    template <typename STRING_TYPE> class BasicStringPiece {};
+    template <> class BasicStringPiece<int> { };
+    template class BasicStringPiece<int>;  // expected-note {{previous explicit instantiation is here}}
+    template class BasicStringPiece<int>;  // expected-error {{duplicate explicit instantiation of 'BasicStringPiece<int>'}}
+  }
 
   namespace SIS {
     template <typename STRING_TYPE> class BasicStringPiece;