summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp169
1 files changed, 103 insertions, 66 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 4d271a38309..60423f9f472 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -26,7 +26,7 @@ using namespace clang;
Sema::InstantiatingTemplate::
InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation,
- ClassTemplateSpecializationDecl *Entity,
+ CXXRecordDecl *Entity,
SourceRange InstantiationRange)
: SemaRef(SemaRef) {
@@ -100,11 +100,13 @@ void Sema::PrintInstantiationStack() {
++Active) {
switch (Active->Kind) {
case ActiveTemplateInstantiation::TemplateInstantiation: {
- ClassTemplateSpecializationDecl *Spec
- = cast<ClassTemplateSpecializationDecl>((Decl*)Active->Entity);
+ unsigned DiagID = diag::note_template_member_class_here;
+ CXXRecordDecl *Record = (CXXRecordDecl *)Active->Entity;
+ if (isa<ClassTemplateSpecializationDecl>(Record))
+ DiagID = diag::note_template_class_instantiation_here;
Diags.Report(FullSourceLoc(Active->PointOfInstantiation, SourceMgr),
- diag::note_template_class_instantiation_here)
- << Context.getTypeDeclType(Spec)
+ DiagID)
+ << Context.getTypeDeclType(Record)
<< Active->InstantiationRange;
break;
}
@@ -591,14 +593,14 @@ QualType Sema::InstantiateType(QualType T,
/// attaches the instantiated base classes to the class template
/// specialization if successful.
bool
-Sema::InstantiateBaseSpecifiers(
- ClassTemplateSpecializationDecl *ClassTemplateSpec,
- ClassTemplateDecl *ClassTemplate) {
+Sema::InstantiateBaseSpecifiers(CXXRecordDecl *Instantiation,
+ CXXRecordDecl *Pattern,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
bool Invalid = false;
llvm::SmallVector<CXXBaseSpecifier*, 8> InstantiatedBases;
- for (ClassTemplateSpecializationDecl::base_class_iterator
- Base = ClassTemplate->getTemplatedDecl()->bases_begin(),
- BaseEnd = ClassTemplate->getTemplatedDecl()->bases_end();
+ for (ClassTemplateSpecializationDecl::base_class_iterator
+ Base = Pattern->bases_begin(), BaseEnd = Pattern->bases_end();
Base != BaseEnd; ++Base) {
if (!Base->getType()->isDependentType()) {
// FIXME: Allocate via ASTContext
@@ -607,8 +609,7 @@ Sema::InstantiateBaseSpecifiers(
}
QualType BaseType = InstantiateType(Base->getType(),
- ClassTemplateSpec->getTemplateArgs(),
- ClassTemplateSpec->getNumTemplateArgs(),
+ TemplateArgs, NumTemplateArgs,
Base->getSourceRange().getBegin(),
DeclarationName());
if (BaseType.isNull()) {
@@ -617,7 +618,7 @@ Sema::InstantiateBaseSpecifiers(
}
if (CXXBaseSpecifier *InstantiatedBase
- = CheckBaseSpecifier(ClassTemplateSpec,
+ = CheckBaseSpecifier(Instantiation,
Base->getSourceRange(),
Base->isVirtual(),
Base->getAccessSpecifierAsWritten(),
@@ -630,81 +631,82 @@ Sema::InstantiateBaseSpecifiers(
}
if (!Invalid &&
- AttachBaseSpecifiers(ClassTemplateSpec, &InstantiatedBases[0],
+ AttachBaseSpecifiers(Instantiation, &InstantiatedBases[0],
InstantiatedBases.size()))
Invalid = true;
return Invalid;
}
-bool
-Sema::InstantiateClassTemplateSpecialization(
- ClassTemplateSpecializationDecl *ClassTemplateSpec,
- bool ExplicitInstantiation) {
- // Perform the actual instantiation on the canonical declaration.
- ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
- Context.getCanonicalDecl(ClassTemplateSpec));
-
- // We can only instantiate something that hasn't already been
- // instantiated or specialized. Fail without any diagnostics: our
- // caller will provide an error message.
- if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared)
- return true;
-
- // FIXME: Push this class template instantiation onto the
- // instantiation stack, checking for recursion that exceeds a
- // certain depth.
-
- // FIXME: Perform class template partial specialization to select
- // the best template.
- ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
-
- RecordDecl *Pattern = cast_or_null<RecordDecl>(
- Template->getTemplatedDecl()->getDefinition(Context));
- if (!Pattern) {
- Diag(ClassTemplateSpec->getLocation(),
- diag::err_template_implicit_instantiate_undefined)
- << Context.getTypeDeclType(ClassTemplateSpec);
- Diag(Template->getTemplatedDecl()->getLocation(),
- diag::note_template_decl_here);
+/// \brief Instantiate the definition of a class from a given pattern.
+///
+/// \param PointOfInstantiation The point of instantiation within the
+/// source code.
+///
+/// \param Instantiation is the declaration whose definition is being
+/// instantiated. This will be either a class template specialization
+/// or a member class of a class template specialization.
+///
+/// \param Pattern is the pattern from which the instantiation
+/// occurs. This will be either the declaration of a class template or
+/// the declaration of a member class of a class template.
+///
+/// \param TemplateArgs The template arguments to be substituted into
+/// the pattern.
+///
+/// \param NumTemplateArgs The number of templates arguments in
+/// TemplateArgs.
+///
+/// \returns true if an error occurred, false otherwise.
+bool
+Sema::InstantiateClass(SourceLocation PointOfInstantiation,
+ CXXRecordDecl *Instantiation, CXXRecordDecl *Pattern,
+ const TemplateArgument *TemplateArgs,
+ unsigned NumTemplateArgs) {
+ bool Invalid = false;
+
+ CXXRecordDecl *PatternDef
+ = cast_or_null<CXXRecordDecl>(Pattern->getDefinition(Context));
+ if (!PatternDef) {
+ if (Pattern == Instantiation->getInstantiatedFromMemberClass()) {
+ Diag(PointOfInstantiation,
+ diag::err_implicit_instantiate_member_undefined)
+ << Context.getTypeDeclType(Instantiation);
+ Diag(Pattern->getLocation(), diag::note_member_of_template_here);
+ } else {
+ Diag(PointOfInstantiation,
+ diag::err_template_implicit_instantiate_undefined)
+ << Context.getTypeDeclType(Instantiation);
+ Diag(Pattern->getLocation(), diag::note_template_decl_here);
+ }
return true;
}
+ Pattern = PatternDef;
- // Note that this is an instantiation.
- ClassTemplateSpec->setSpecializationKind(
- ExplicitInstantiation? TSK_ExplicitInstantiation
- : TSK_ImplicitInstantiation);
-
-
- bool Invalid = false;
-
- InstantiatingTemplate Inst(*this, ClassTemplateSpec->getLocation(),
- ClassTemplateSpec);
+ InstantiatingTemplate Inst(*this, Instantiation->getLocation(),
+ Instantiation);
if (Inst)
return true;
// Enter the scope of this instantiation. We don't use
// PushDeclContext because we don't have a scope.
DeclContext *PreviousContext = CurContext;
- CurContext = ClassTemplateSpec;
+ CurContext = Instantiation;
// Start the definition of this instantiation.
- ClassTemplateSpec->startDefinition();
+ Instantiation->startDefinition();
// Instantiate the base class specifiers.
- if (InstantiateBaseSpecifiers(ClassTemplateSpec, Template))
+ if (InstantiateBaseSpecifiers(Instantiation, Pattern, TemplateArgs,
+ NumTemplateArgs))
Invalid = true;
- // FIXME: Create the injected-class-name for the
- // instantiation. Should this be a typedef or something like it?
-
llvm::SmallVector<DeclTy *, 32> Fields;
for (RecordDecl::decl_iterator Member = Pattern->decls_begin(),
MemberEnd = Pattern->decls_end();
Member != MemberEnd; ++Member) {
- Decl *NewMember = InstantiateDecl(*Member, ClassTemplateSpec,
- ClassTemplateSpec->getTemplateArgs(),
- ClassTemplateSpec->getNumTemplateArgs());
+ Decl *NewMember = InstantiateDecl(*Member, Instantiation,
+ TemplateArgs, NumTemplateArgs);
if (NewMember) {
if (NewMember->isInvalidDecl())
Invalid = true;
@@ -719,12 +721,12 @@ Sema::InstantiateClassTemplateSpecialization(
}
// Finish checking fields.
- ActOnFields(0, ClassTemplateSpec->getLocation(), ClassTemplateSpec,
+ ActOnFields(0, Instantiation->getLocation(), Instantiation,
&Fields[0], Fields.size(), SourceLocation(), SourceLocation(),
0);
// Add any implicitly-declared members that we might need.
- AddImplicitlyDeclaredMembersToClass(ClassTemplateSpec);
+ AddImplicitlyDeclaredMembersToClass(Instantiation);
// Exit the scope of this instantiation.
CurContext = PreviousContext;
@@ -732,6 +734,41 @@ Sema::InstantiateClassTemplateSpecialization(
return Invalid;
}
+bool
+Sema::InstantiateClassTemplateSpecialization(
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ bool ExplicitInstantiation) {
+ // Perform the actual instantiation on the canonical declaration.
+ ClassTemplateSpec = cast<ClassTemplateSpecializationDecl>(
+ Context.getCanonicalDecl(ClassTemplateSpec));
+
+ // We can only instantiate something that hasn't already been
+ // instantiated or specialized. Fail without any diagnostics: our
+ // caller will provide an error message.
+ if (ClassTemplateSpec->getSpecializationKind() != TSK_Undeclared)
+ return true;
+
+ // FIXME: Push this class template instantiation onto the
+ // instantiation stack, checking for recursion that exceeds a
+ // certain depth.
+
+ // FIXME: Perform class template partial specialization to select
+ // the best template.
+ ClassTemplateDecl *Template = ClassTemplateSpec->getSpecializedTemplate();
+
+ CXXRecordDecl *Pattern = Template->getTemplatedDecl();
+
+ // Note that this is an instantiation.
+ ClassTemplateSpec->setSpecializationKind(
+ ExplicitInstantiation? TSK_ExplicitInstantiation
+ : TSK_ImplicitInstantiation);
+
+ return InstantiateClass(ClassTemplateSpec->getLocation(),
+ ClassTemplateSpec, Pattern,
+ ClassTemplateSpec->getTemplateArgs(),
+ ClassTemplateSpec->getNumTemplateArgs());
+}
+
/// \brief Instantiate a sequence of nested-name-specifiers into a
/// scope specifier.
CXXScopeSpec
OpenPOWER on IntegriCloud