diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.h | 11 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 38 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 17 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 4 |
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); } } |