From: Nico Weber Date: Mon, 9 Jan 2012 19:52:25 +0000 (+0000) Subject: Fix "note" of a duplicate explicit instantiation definition following a specialization. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d1d512a9cd1923566a52e57b7e1e8ae65392f66b;p=clang 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 2527ac6a1c..b6babb6f75 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -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; 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 89f343869f..aecbfb5649 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 @@ 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 class BasicStringPiece {}; -// template <> class BasicStringPiece { }; -// template class BasicStringPiece; -// template class BasicStringPiece; -// } + namespace SII_WithDefinedTemplate { + template class BasicStringPiece {}; + template <> class BasicStringPiece { }; + template class BasicStringPiece; // expected-note {{previous explicit instantiation is here}} + template class BasicStringPiece; // expected-error {{duplicate explicit instantiation of 'BasicStringPiece'}} + } namespace SIS { template class BasicStringPiece;