aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/Sema.h11
-rw-r--r--lib/Sema/SemaTemplate.cpp20
-rw-r--r--lib/Sema/SemaTemplateInstantiate.cpp38
-rw-r--r--lib/Sema/SemaTemplateInstantiateDecl.cpp17
-rw-r--r--lib/Sema/SemaType.cpp4
5 files changed, 59 insertions, 31 deletions
diff --git a/lib/Sema/Sema.h b/lib/Sema/Sema.h
index d088387b05..1c118ab64e 100644
--- a/lib/Sema/Sema.h
+++ b/lib/Sema/Sema.h
@@ -3011,21 +3011,24 @@ public:
InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs,
- bool ExplicitInstantiation,
+ TemplateSpecializationKind TSK,
bool Complain = true);
bool
InstantiateClassTemplateSpecialization(
ClassTemplateSpecializationDecl *ClassTemplateSpec,
- bool ExplicitInstantiation, bool Complain = true);
+ TemplateSpecializationKind TSK,
+ bool Complain = true);
void InstantiateClassMembers(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation,
- const MultiLevelTemplateArgumentList &TemplateArgs);
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK);
void InstantiateClassTemplateSpecializationMembers(
SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *ClassTemplateSpec);
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK);
NestedNameSpecifier *
SubstNestedNameSpecifier(NestedNameSpecifier *NNS,
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index 76b6d7ecaa..c243765bec 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -2934,7 +2934,8 @@ Sema::ActOnExplicitInstantiation(Scope *S,
bool SpecializationRequiresInstantiation = true;
if (PrevDecl) {
- if (PrevDecl->getSpecializationKind() == TSK_ExplicitInstantiation) {
+ if (PrevDecl->getSpecializationKind()
+ == TSK_ExplicitInstantiationDefinition) {
// This particular specialization has already been declared or
// instantiated. We cannot explicitly instantiate it.
Diag(TemplateNameLoc, diag::err_explicit_instantiation_duplicate)
@@ -3028,16 +3029,19 @@ Sema::ActOnExplicitInstantiation(Scope *S,
//
// This check comes when we actually try to perform the
// instantiation.
+ TemplateSpecializationKind TSK
+ = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
if (SpecializationRequiresInstantiation)
- InstantiateClassTemplateSpecialization(Specialization, true);
+ InstantiateClassTemplateSpecialization(Specialization, TSK);
else // Instantiate the members of this class template specialization.
- InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization);
+ InstantiateClassTemplateSpecializationMembers(TemplateLoc, Specialization,
+ TSK);
return DeclPtrTy::make(Specialization);
}
// Explicit instantiation of a member class of a class template.
-// FIXME: Implement extern template semantics.
Sema::DeclResult
Sema::ActOnExplicitInstantiation(Scope *S,
SourceLocation ExternLoc,
@@ -3092,17 +3096,21 @@ Sema::ActOnExplicitInstantiation(Scope *S,
}
}
+ TemplateSpecializationKind TSK
+ = ExternLoc.isInvalid()? TSK_ExplicitInstantiationDefinition
+ : TSK_ExplicitInstantiationDeclaration;
+
if (!Record->getDefinition(Context)) {
// If the class has a definition, instantiate it (and all of its
// members, recursively).
Pattern = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
if (Pattern && InstantiateClass(TemplateLoc, Record, Pattern,
getTemplateInstantiationArgs(Record),
- /*ExplicitInstantiation=*/true))
+ TSK))
return true;
} else // Instantiate all of the members of the class.
InstantiateClassMembers(TemplateLoc, Record,
- getTemplateInstantiationArgs(Record));
+ 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
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index 0c47e996c8..55e81aecbc 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -623,8 +623,7 @@ Sema::SubstBaseSpecifiers(CXXRecordDecl *Instantiation,
/// \param TemplateArgs The template arguments to be substituted into
/// the pattern.
///
-/// \param ExplicitInstantiation whether this is an explicit instantiation
-/// (otherwise, it is an implicit instantiation).
+/// \param TSK the kind of implicit or explicit instantiation to perform.
///
/// \param Complain whether to complain if the class cannot be instantiated due
/// to the lack of a definition.
@@ -634,7 +633,7 @@ bool
Sema::InstantiateClass(SourceLocation PointOfInstantiation,
CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
const MultiLevelTemplateArgumentList &TemplateArgs,
- bool ExplicitInstantiation,
+ TemplateSpecializationKind TSK,
bool Complain) {
bool Invalid = false;
@@ -650,7 +649,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Diag(Pattern->getLocation(), diag::note_member_of_template_here);
} else {
Diag(PointOfInstantiation, diag::err_template_instantiate_undefined)
- << ExplicitInstantiation
+ << (TSK != TSK_ImplicitInstantiation)
<< Context.getTypeDeclType(Instantiation);
Diag(Pattern->getLocation(), diag::note_template_decl_here);
}
@@ -708,9 +707,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
Consumer.HandleTagDeclDefinition(Instantiation);
// If this is an explicit instantiation, instantiate our members, too.
- if (!Invalid && ExplicitInstantiation) {
+ if (!Invalid && TSK != TSK_ImplicitInstantiation) {
Inst.Clear();
- InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs);
+ InstantiateClassMembers(PointOfInstantiation, Instantiation, TemplateArgs,
+ TSK);
}
return Invalid;
@@ -719,7 +719,7 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
bool
Sema::InstantiateClassTemplateSpecialization(
ClassTemplateSpecializationDecl *ClassTemplateSpec,
- bool ExplicitInstantiation,
+ TemplateSpecializationKind TSK,
bool Complain) {
// Perform the actual instantiation on the canonical declaration.
ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
@@ -798,14 +798,12 @@ Sema::InstantiateClassTemplateSpecialization(
}
// Note that this is an instantiation.
- ClassTemplateSpec->setSpecializationKind(
- ExplicitInstantiation? TSK_ExplicitInstantiation
- : TSK_ImplicitInstantiation);
+ ClassTemplateSpec->setSpecializationKind(TSK);
bool Result = InstantiateClass(ClassTemplateSpec->getLocation(),
ClassTemplateSpec, Pattern,
getTemplateInstantiationArgs(ClassTemplateSpec),
- ExplicitInstantiation,
+ TSK,
Complain);
for (unsigned I = 0, N = Matched.size(); I != N; ++I) {
@@ -822,8 +820,10 @@ Sema::InstantiateClassTemplateSpecialization(
/// or a member class of a template.
void
Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
- CXXRecordDecl *Instantiation,
- const MultiLevelTemplateArgumentList &TemplateArgs) {
+ CXXRecordDecl *Instantiation,
+ const MultiLevelTemplateArgumentList &TemplateArgs,
+ TemplateSpecializationKind TSK) {
+ // FIXME: extern templates
for (DeclContext::decl_iterator D = Instantiation->decls_begin(),
DEnd = Instantiation->decls_end();
D != DEnd; ++D) {
@@ -839,7 +839,8 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
"Missing instantiated-from-template information");
InstantiateClass(PointOfInstantiation, Record,
Record->getInstantiatedFromMemberClass(),
- TemplateArgs, true);
+ TemplateArgs,
+ TSK);
}
}
}
@@ -848,9 +849,11 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation,
/// \brief Instantiate the definitions of all of the members of the
/// given class template specialization, which was named as part of an
/// explicit instantiation.
-void Sema::InstantiateClassTemplateSpecializationMembers(
+void
+Sema::InstantiateClassTemplateSpecializationMembers(
SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *ClassTemplateSpec) {
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ TemplateSpecializationKind TSK) {
// C++0x [temp.explicit]p7:
// An explicit instantiation that names a class template
// specialization is an explicit instantion of the same kind
@@ -860,7 +863,8 @@ void Sema::InstantiateClassTemplateSpecializationMembers(
// containing the explicit instantiation, except as described
// below.
InstantiateClassMembers(PointOfInstantiation, ClassTemplateSpec,
- getTemplateInstantiationArgs(ClassTemplateSpec));
+ getTemplateInstantiationArgs(ClassTemplateSpec),
+ TSK);
}
Sema::OwningStmtResult
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 807115eb67..b63fc400a5 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -402,6 +402,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
Decl *
TemplateDeclInstantiator::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
+ // FIXME: Dig out the out-of-line definition of this function template?
+
TemplateParameterList *TempParams = D->getTemplateParameters();
TemplateParameterList *InstParams = SubstTemplateParams(TempParams);
if (!InstParams)
@@ -496,7 +498,7 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D) {
D->getStorageClass(),
D->isInline(), D->hasWrittenPrototype());
Function->setLexicalDeclContext(Owner);
-
+
// Attach the parameters
for (unsigned P = 0; P < Params.size(); ++P)
Params[P]->setOwningFunction(Function);
@@ -622,7 +624,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D,
Method->getDeclName(),
TemplateParams, Method);
if (D->isOutOfLine())
- FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
+ FunctionTemplate->setLexicalDeclContext(D->getLexicalDeclContext());
Method->setDescribedFunctionTemplate(FunctionTemplate);
} else if (!FunctionTemplate)
Method->setInstantiationOfMemberFunction(D);
@@ -979,6 +981,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
if (!Pattern)
return;
+ // C++0x [temp.explicit]p9:
+ // Except for inline functions, other explicit instantiation declarations
+ // have the effect of suppressing the implicit instantiation of the entity
+ // to which they refer.
+ if (Function->getTemplateSpecializationKind()
+ == TSK_ExplicitInstantiationDeclaration &&
+ PatternDecl->isOutOfLine() && !PatternDecl->isInline())
+ return;
+
InstantiatingTemplate Inst(*this, PointOfInstantiation, Function);
if (Inst)
return;
@@ -1080,6 +1091,8 @@ void Sema::InstantiateStaticDataMemberDefinition(
return;
}
+ // FIXME: extern templates
+
InstantiatingTemplate Inst(*this, PointOfInstantiation, Var);
if (Inst)
return;
diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp
index 11bbe4e2de..80cdcd5464 100644
--- a/lib/Sema/SemaType.cpp
+++ b/lib/Sema/SemaType.cpp
@@ -1781,7 +1781,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
if (Loc.isValid())
ClassTemplateSpec->setLocation(Loc);
return InstantiateClassTemplateSpecialization(ClassTemplateSpec,
- /*ExplicitInstantiation=*/false,
+ TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
}
} else if (CXXRecordDecl *Rec
@@ -1790,7 +1790,7 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T,
// This record was instantiated from a class within a template.
return InstantiateClass(Loc, Rec, Pattern,
getTemplateInstantiationArgs(Rec),
- /*ExplicitInstantiation=*/false,
+ TSK_ImplicitInstantiation,
/*Complain=*/diag != 0);
}
}