summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaTemplateInstantiate.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-03-03 04:44:36 +0000
committerDouglas Gregor <dgregor@apple.com>2009-03-03 04:44:36 +0000
commit463421deb1c3b6e5e41dba132853645cdd260195 (patch)
treef3ea367fd8b21403ab75a3f18a9adb14140db4f6 /clang/lib/Sema/SemaTemplateInstantiate.cpp
parent9c51e8f962d5d7bf7fabd7cbdd47770709228a2c (diff)
downloadbcm5719-llvm-463421deb1c3b6e5e41dba132853645cdd260195.tar.gz
bcm5719-llvm-463421deb1c3b6e5e41dba132853645cdd260195.zip
Implement the basics of implicit instantiation of class templates, in
response to attempts to diagnose an "incomplete" type. This will force us to use DiagnoseIncompleteType more regularly (rather than looking at isIncompleteType), but that's also a good thing. Implicit instantiation is still very simplistic, and will create a new definition for the class template specialization (as it should) but it only actually instantiates the base classes and attaches those. Actually instantiating class members will follow. Also, instantiate the types of non-type template parameters before checking them, allowing, e.g., template<typename T, T Value> struct Constant; to work properly. llvm-svn: 65924
Diffstat (limited to 'clang/lib/Sema/SemaTemplateInstantiate.cpp')
-rw-r--r--clang/lib/Sema/SemaTemplateInstantiate.cpp121
1 files changed, 121 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 6b434637776..faeebc06808 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -399,3 +399,124 @@ QualType Sema::InstantiateType(QualType T,
Loc, Entity);
return Instantiator(T);
}
+
+/// \brief Instantiate the base class specifiers of the given class
+/// template specialization.
+///
+/// Produces a diagnostic and returns true on error, returns false and
+/// attaches the instantiated base classes to the class template
+/// specialization if successful.
+bool
+Sema::InstantiateBaseSpecifiers(
+ ClassTemplateSpecializationDecl *ClassTemplateSpec,
+ ClassTemplateDecl *ClassTemplate) {
+ bool Invalid = false;
+ llvm::SmallVector<CXXBaseSpecifier*, 8> InstantiatedBases;
+ for (ClassTemplateSpecializationDecl::base_class_iterator
+ Base = ClassTemplate->getTemplatedDecl()->bases_begin(),
+ BaseEnd = ClassTemplate->getTemplatedDecl()->bases_end();
+ Base != BaseEnd && !Invalid; ++Base) {
+ if (!Base->getType()->isDependentType()) {
+ // FIXME: Allocate via ASTContext
+ InstantiatedBases.push_back(new CXXBaseSpecifier(*Base));
+ continue;
+ }
+
+ QualType BaseType = InstantiateType(Base->getType(),
+ ClassTemplateSpec->getTemplateArgs(),
+ ClassTemplateSpec->getNumTemplateArgs(),
+ Base->getSourceRange().getBegin(),
+ DeclarationName());
+ if (BaseType.isNull()) {
+ Invalid = true;
+ continue;
+ }
+
+ if (CXXBaseSpecifier *InstantiatedBase
+ = CheckBaseSpecifier(ClassTemplateSpec,
+ Base->getSourceRange(),
+ Base->isVirtual(),
+ Base->getAccessSpecifierAsWritten(),
+ BaseType,
+ /*FIXME: Not totally accurate */
+ Base->getSourceRange().getBegin()))
+ InstantiatedBases.push_back(InstantiatedBase);
+ else
+ Invalid = true;
+ }
+
+ if (AttachBaseSpecifiers(ClassTemplateSpec, &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();
+
+ if (!Template->getTemplatedDecl()->getDefinition(Context)) {
+ Diag(ClassTemplateSpec->getLocation(),
+ diag::err_template_implicit_instantiate_undefined)
+ << Context.getTypeDeclType(ClassTemplateSpec);
+ Diag(Template->getTemplatedDecl()->getLocation(),
+ diag::note_template_decl_here);
+ return true;
+ }
+
+ // Note that this is an instantiation.
+ ClassTemplateSpec->setSpecializationKind(
+ ExplicitInstantiation? TSK_ExplicitInstantiation
+ : TSK_ImplicitInstantiation);
+
+
+ bool Invalid = false;
+
+ // Enter the scope of this instantiation. We don't use
+ // PushDeclContext because we don't have a scope.
+ DeclContext *PreviousContext = CurContext;
+ CurContext = ClassTemplateSpec;
+
+ // Start the definition of this instantiation.
+ ClassTemplateSpec->startDefinition();
+
+ // FIXME: Create the injected-class-name for the
+ // instantiation. Should this be a typedef or something like it?
+
+ // Instantiate the base class specifiers.
+ if (InstantiateBaseSpecifiers(ClassTemplateSpec, Template))
+ Invalid = true;
+
+ // FIXME: Instantiate all of the members.
+
+ // Add any implicitly-declared members that we might need.
+ AddImplicitlyDeclaredMembersToClass(ClassTemplateSpec);
+
+ // Finish the definition of this instantiation.
+ // FIXME: ActOnFields does more checking, which we'll eventually need.
+ ClassTemplateSpec->completeDefinition(Context);
+
+ // Exit the scope of this instantiation.
+ CurContext = PreviousContext;
+
+ return Invalid;
+}
OpenPOWER on IntegriCloud