aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaTemplate.cpp
diff options
context:
space:
mode:
authorNico Weber <nicolasweber@gmx.de>2011-12-23 20:58:04 +0000
committerNico Weber <nicolasweber@gmx.de>2011-12-23 20:58:04 +0000
commitff91d240d431afbec18e25909caaf5c17f26e643 (patch)
treed02f9d52632765070556e55ee4bf6b32cfd7b620 /lib/Sema/SemaTemplate.cpp
parent17ba267cae596d5eb35fa0963ebcf73571572940 (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.cpp30
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.