aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-10-27 18:42:08 +0000
committerDouglas Gregor <dgregor@apple.com>2009-10-27 18:42:08 +0000
commit0d03514da06dffb39a260a1228ea3fd01d196fa4 (patch)
tree32e1a998727fc763ea7fcfec36946da6d3a1e88c /lib/Sema
parent6c813e1cb719a328f01619c3d44910be4e79e4d5 (diff)
An explicit instantiation definition only instantiations those class
members that have a definition. Also, use CheckSpecializationInstantiationRedecl as part of this instantiation to make sure that we diagnose the various kinds of problems that can occur with explicit instantiations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@85270 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h8
-rw-r--r--lib/Sema/SemaTemplate.cpp80
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp122
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp15
4 files changed, 144 insertions, 81 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index a40cdf390c..32f4ce0732 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -2577,6 +2577,14 @@ public:
MultiTemplateParamsArg TemplateParameterLists,
Declarator &D);
+ bool
+ CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPointOfInstantiation,
+ bool &SuppressNew);
+
bool CheckFunctionTemplateSpecialization(FunctionDecl *FD,
bool HasExplicitTemplateArgs,
SourceLocation LAngleLoc,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 4419ad04a2..638e00cb1d 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -3073,8 +3073,6 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
/// for those cases where they are required and determining whether the
/// new specialization/instantiation will have any effect.
///
-/// \param S the semantic analysis object.
-///
/// \param NewLoc the location of the new explicit specialization or
/// instantiation.
///
@@ -3092,14 +3090,13 @@ Sema::ActOnStartOfFunctionTemplateDef(Scope *FnBodyScope,
///
/// \returns true if there was an error that should prevent the introduction of
/// the new declaration into the AST, false otherwise.
-static bool
-CheckSpecializationInstantiationRedecl(Sema &S,
- SourceLocation NewLoc,
- TemplateSpecializationKind NewTSK,
- NamedDecl *PrevDecl,
- TemplateSpecializationKind PrevTSK,
- SourceLocation PrevPointOfInstantiation,
- bool &SuppressNew) {
+bool
+Sema::CheckSpecializationInstantiationRedecl(SourceLocation NewLoc,
+ TemplateSpecializationKind NewTSK,
+ NamedDecl *PrevDecl,
+ TemplateSpecializationKind PrevTSK,
+ SourceLocation PrevPointOfInstantiation,
+ bool &SuppressNew) {
SuppressNew = false;
switch (NewTSK) {
@@ -3137,9 +3134,9 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// 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.
- S.Diag(NewLoc, diag::err_specialization_after_instantiation)
+ Diag(NewLoc, diag::err_specialization_after_instantiation)
<< PrevDecl;
- S.Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
+ Diag(PrevPointOfInstantiation, diag::note_instantiation_required_here)
<< (PrevTSK != TSK_ImplicitInstantiation);
return true;
@@ -3172,10 +3169,10 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// If an entity is the subject of both an explicit instantiation
// declaration and an explicit instantiation definition in the same
// translation unit, the definition shall follow the declaration.
- S.Diag(NewLoc,
- diag::err_explicit_instantiation_declaration_after_definition);
- S.Diag(PrevPointOfInstantiation,
- diag::note_explicit_instantiation_definition_here);
+ Diag(NewLoc,
+ diag::err_explicit_instantiation_declaration_after_definition);
+ Diag(PrevPointOfInstantiation,
+ diag::note_explicit_instantiation_definition_here);
assert(PrevPointOfInstantiation.isValid() &&
"Explicit instantiation without point of instantiation?");
SuppressNew = true;
@@ -3201,10 +3198,10 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// In C++98/03 mode, we only give an extension warning here, because it
// is not not harmful to try to explicitly instantiate something that
// has been explicitly specialized.
- if (!S.getLangOptions().CPlusPlus0x) {
- S.Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
+ if (!getLangOptions().CPlusPlus0x) {
+ Diag(NewLoc, diag::ext_explicit_instantiation_after_specialization)
<< PrevDecl;
- S.Diag(PrevDecl->getLocation(),
+ Diag(PrevDecl->getLocation(),
diag::note_previous_template_specialization);
}
SuppressNew = true;
@@ -3220,10 +3217,10 @@ CheckSpecializationInstantiationRedecl(Sema &S,
// For a given template and a given set of template-arguments,
// - an explicit instantiation definition shall appear at most once
// in a program,
- S.Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
+ Diag(NewLoc, diag::err_explicit_instantiation_duplicate)
<< PrevDecl;
- S.Diag(PrevPointOfInstantiation,
- diag::note_previous_explicit_instantiation);
+ Diag(PrevPointOfInstantiation,
+ diag::note_previous_explicit_instantiation);
SuppressNew = true;
return false;
}
@@ -3336,7 +3333,7 @@ Sema::CheckFunctionTemplateSpecialization(FunctionDecl *FD,
// 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.
@@ -3662,7 +3659,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
if (PrevDecl) {
bool SuppressNew = false;
- if (CheckSpecializationInstantiationRedecl(*this, TemplateNameLoc, TSK,
+ if (CheckSpecializationInstantiationRedecl(TemplateNameLoc, TSK,
PrevDecl,
PrevDecl->getSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
@@ -3738,7 +3735,11 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Specialization->getDefinition(Context));
if (!Def)
InstantiateClassTemplateSpecialization(TemplateNameLoc, Specialization, TSK);
- else // Instantiate the members of this class template specialization.
+
+ // Instantiate the members of this class template specialization.
+ Def = cast_or_null<ClassTemplateSpecializationDecl>(
+ Specialization->getDefinition(Context));
+ if (Def)
InstantiateClassTemplateSpecializationMembers(TemplateNameLoc, Def, TSK);
return DeclPtrTy::make(Specialization);
@@ -3820,7 +3821,7 @@ Sema::ActOnExplicitInstantiation(Scope *S,
MemberSpecializationInfo *MSInfo = PrevDecl->getMemberSpecializationInfo();
bool SuppressNew = false;
assert(MSInfo && "No member specialization information?");
- if (CheckSpecializationInstantiationRedecl(*this, TemplateLoc, TSK,
+ if (CheckSpecializationInstantiationRedecl(TemplateLoc, TSK,
PrevDecl,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
@@ -3844,13 +3845,21 @@ Sema::ActOnExplicitInstantiation(Scope *S,
Diag(Pattern->getLocation(), diag::note_forward_declaration)
<< Pattern;
return true;
- } else if (InstantiateClass(NameLoc, Record, Def,
- getTemplateInstantiationArgs(Record),
- TSK))
- return true;
- } else // Instantiate all of the members of the class.
- InstantiateClassMembers(NameLoc, RecordDef,
- getTemplateInstantiationArgs(Record), TSK);
+ } else {
+ if (InstantiateClass(NameLoc, Record, Def,
+ getTemplateInstantiationArgs(Record),
+ TSK))
+ return true;
+
+ RecordDef = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ if (!RecordDef)
+ return true;
+ }
+ }
+
+ // Instantiate all of the members of the class.
+ InstantiateClassMembers(NameLoc, RecordDef,
+ getTemplateInstantiationArgs(Record), TSK);
// FIXME: We don't have any representation for explicit instantiations of
// member classes. Such a representation is not needed for compilation, but it
@@ -3969,8 +3978,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
MemberSpecializationInfo *MSInfo = Prev->getMemberSpecializationInfo();
assert(MSInfo && "Missing static data member specialization info?");
bool SuppressNew = false;
- if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
- Prev,
+ if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK, Prev,
MSInfo->getTemplateSpecializationKind(),
MSInfo->getPointOfInstantiation(),
SuppressNew))
@@ -4069,7 +4077,7 @@ Sema::DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
if (PrevDecl) {
bool SuppressNew = false;
- if (CheckSpecializationInstantiationRedecl(*this, D.getIdentifierLoc(), TSK,
+ if (CheckSpecializationInstantiationRedecl(D.getIdentifierLoc(), TSK,
PrevDecl,
PrevDecl->getTemplateSpecializationKind(),
PrevDecl->getPointOfInstantiation(),
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 22d1e165f0..14930134da 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -914,13 +914,6 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
if (!Invalid)
Consumer.HandleTagDeclDefinition(Instantiation);
- // If this is an explicit instantiation, instantiate our members, too.
- if (!Invalid && TSK != TSK_ImplicitInstantiation) {
- Inst.Clear();
- InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs,
- TSK);
- }
-
return Invalid;
}
@@ -944,9 +937,6 @@ Sema::InstantiateClassTemplateSpecialization(
// declaration (C++0x [temp.explicit]p10); go ahead and perform the
// explicit instantiation.
ClassTemplateSpec->setSpecializationKind(TSK);
- InstantiateClassTemplateSpecializationMembers(PointOfInstantiation,
- ClassTemplateSpec,
- TSK);
return false;
}
@@ -1089,48 +1079,112 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
DEnd = Instantiation->decls_end();
D != DEnd; ++D) {
+ bool SuppressNew = false;
if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) {
- if (Function->getInstantiatedFromMemberFunction()) {
- // If this member was explicitly specialized, do nothing.
- if (Function->getTemplateSpecializationKind() ==
- TSK_ExplicitSpecialization)
+ if (FunctionDecl *Pattern
+ = Function->getInstantiatedFromMemberFunction()) {
+ MemberSpecializationInfo *MSInfo
+ = Function->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Function,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
continue;
- Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ if (Function->getBody())
+ continue;
+
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (!Pattern->getBody())
+ continue;
+
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+
+ InstantiateFunctionDefinition(PointOfInstantiation, Function);
+ } else {
+ Function->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ }
}
-
- if (!Function->getBody() && TSK == TSK_ExplicitInstantiationDefinition)
- InstantiateFunctionDefinition(PointOfInstantiation, Function);
} else if (VarDecl *Var = dyn_cast<VarDecl>(*D)) {
if (Var->isStaticDataMember()) {
- // If this member was explicitly specialized, do nothing.
- if (Var->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ MemberSpecializationInfo *MSInfo = Var->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Var,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
continue;
- Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
-
- if (TSK == TSK_ExplicitInstantiationDefinition)
+ if (TSK == TSK_ExplicitInstantiationDefinition) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (!Var->getInstantiatedFromStaticDataMember()
+ ->getOutOfLineDefinition())
+ continue;
+
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var);
- }
+ } else {
+ Var->setTemplateSpecializationKind(TSK, PointOfInstantiation);
+ }
+ }
} else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) {
if (Record->isInjectedClassName())
continue;
- assert(Record->getInstantiatedFromMemberClass() &&
- "Missing instantiated-from-template information");
-
- // If this member was explicitly specialized, do nothing.
- if (Record->getTemplateSpecializationKind() == TSK_ExplicitSpecialization)
+ MemberSpecializationInfo *MSInfo = Record->getMemberSpecializationInfo();
+ assert(MSInfo && "No member specialization information?");
+ if (CheckSpecializationInstantiationRedecl(PointOfInstantiation, TSK,
+ Record,
+ MSInfo->getTemplateSpecializationKind(),
+ MSInfo->getPointOfInstantiation(),
+ SuppressNew) ||
+ SuppressNew)
continue;
- if (!Record->getDefinition(Context))
- InstantiateClass(PointOfInstantiation, Record,
- Record->getInstantiatedFromMemberClass(),
+ CXXRecordDecl *Pattern = Record->getInstantiatedFromMemberClass();
+ assert(Pattern && "Missing instantiated-from-template information");
+
+ if (!Record->getDefinition(Context)) {
+ if (!Pattern->getDefinition(Context)) {
+ // C++0x [temp.explicit]p8:
+ // An explicit instantiation definition that names a class template
+ // specialization explicitly instantiates the class template
+ // specialization and is only an explicit instantiation definition
+ // of members whose definition is visible at the point of
+ // instantiation.
+ if (TSK == TSK_ExplicitInstantiationDeclaration) {
+ MSInfo->setTemplateSpecializationKind(TSK);
+ MSInfo->setPointOfInstantiation(PointOfInstantiation);
+ }
+
+ continue;
+ }
+
+ InstantiateClass(PointOfInstantiation, Record, Pattern,
TemplateArgs,
TSK);
+ }
- InstantiateClassMembers(PointOfInstantiation, Record, TemplateArgs,
- TSK);
+ Pattern = cast_or_null<CXXRecordDecl>(Record->getDefinition(Context));
+ if (Pattern)
+ InstantiateClassMembers(PointOfInstantiation, Pattern, TemplateArgs,
+ TSK);
}
}
}
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 422a7bc04d..c9319c58ae 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1231,24 +1231,17 @@ void Sema::InstantiateStaticDataMemberDefinition(
// Find the out-of-line definition of this static data member.
VarDecl *Def = Var->getInstantiatedFromStaticDataMember();
- bool FoundOutOfLineDef = false;
assert(Def && "This data member was not instantiated from a template?");
- assert(Def->isStaticDataMember() && "Not a static data member?");
- for (VarDecl::redecl_iterator RD = Def->redecls_begin(),
- RDEnd = Def->redecls_end();
- RD != RDEnd; ++RD) {
- if (RD->getLexicalDeclContext()->isFileContext()) {
- Def = *RD;
- FoundOutOfLineDef = true;
- }
- }
+ assert(Def->isStaticDataMember() && "Not a static data member?");
+ Def = Def->getOutOfLineDefinition();
- if (!FoundOutOfLineDef) {
+ if (!Def) {
// We did not find an out-of-line definition of this static data member,
// so we won't perform any instantiation. Rather, we rely on the user to
// instantiate this definition (or provide a specialization for it) in
// another translation unit.
if (DefinitionRequired) {
+ Def = Var->getInstantiatedFromStaticDataMember();
Diag(PointOfInstantiation,
diag::err_explicit_instantiation_undefined_member)
<< 2 << Var->getDeclName() << Var->getDeclContext();