]> granicus.if.org Git - clang/commitdiff
Fix "note" of a duplicate explicit instantiation definition following a specialization.
authorNico Weber <nicolasweber@gmx.de>
Mon, 9 Jan 2012 19:52:25 +0000 (19:52 +0000)
committerNico Weber <nicolasweber@gmx.de>
Mon, 9 Jan 2012 19:52:25 +0000 (19:52 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147798 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaTemplate.cpp
test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp

index 2527ac6a1cb2e1aeeecd083d9ae4ae066e31eb01..b6babb6f75f7e70432a3b4ea0c5d86ee2d88c104 100644 (file)
@@ -5234,6 +5234,23 @@ static void StripImplicitInstantiation(NamedDecl *D) {
   }
 }
 
+/// \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 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
       // 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 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
       //       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;
index 89f343869f294fe4a08883a330b58c384ea1d5b1..aecbfb5649f3ca46cedd5ca5352df4bdb9f91620 100644 (file)
@@ -302,15 +302,12 @@ namespace spec_vs_expl_inst {
 
   // 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;