diff options
author | Nico Weber <nicolasweber@gmx.de> | 2011-12-23 20:58:04 +0000 |
---|---|---|
committer | Nico Weber <nicolasweber@gmx.de> | 2011-12-23 20:58:04 +0000 |
commit | ff91d240d431afbec18e25909caaf5c17f26e643 (patch) | |
tree | d02f9d52632765070556e55ee4bf6b32cfd7b620 /lib/Sema/SemaTemplate.cpp | |
parent | 17ba267cae596d5eb35fa0963ebcf73571572940 (diff) |
Fix several issues related to specializations and explicit instantiations.
Explicit instantiations following specializations are no-ops and hence have
no PointOfInstantiation. That was done correctly in most cases, but for a
specialization -> instantiation decl -> instantiation definition chain, the
definition didn't realize that it was a no-op. Fix that.
Also, when printing diagnostics for these no-ops, get the diag location from
the decl name location.
Add many test cases, one of them not yet passing (but it failed the same way
before this change). Fixes http://llvm.org/pr11558 and more.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@147225 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaTemplate.cpp')
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 30 |
1 files changed, 26 insertions, 4 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index d0c0f0bf2d..b0006e6ac2 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -5344,9 +5344,17 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, // translation unit, the definition shall follow the declaration. Diag(NewLoc, diag::err_explicit_instantiation_declaration_after_definition); - Diag(PrevPointOfInstantiation, - diag::note_explicit_instantiation_definition_here); - assert(PrevPointOfInstantiation.isValid() && + + // 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?"); HasNoEffect = true; return false; @@ -5383,6 +5391,20 @@ Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc, case TSK_ExplicitInstantiationDeclaration: // We're explicity instantiating a definition for something for which we // were previously asked to suppress instantiations. That's fine. + + // C++0x [temp.explicit]p4: + // For a given set of template parameters, if an explicit instantiation + // of a template appears after a declaration of an explicit + // specialization for that template, the explicit instantiation has no + // effect. + for (NamedDecl *Prev = PrevDecl; Prev; Prev = getPreviousDecl(Prev)) { + // Is there any previous explicit specialization declaration? + if (getTemplateSpecializationKind(Prev) == TSK_ExplicitSpecialization) { + HasNoEffect = true; + break; + } + } + return false; case TSK_ExplicitInstantiationDefinition: @@ -5677,7 +5699,7 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous) { // C++ [temp.expl.spec]p6: // If a template, a member template or the member of a class template is - // explicitly specialized then that spe- cialization shall be declared + // explicitly specialized then that specialization shall be declared // before the first use of that specialization that would cause an implicit // instantiation to take place, in every translation unit in which such a // use occurs; no diagnostic is required. |