diff options
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 14 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 41 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 23 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 2 | ||||
-rw-r--r-- | lib/Sema/SemaType.cpp | 9 |
5 files changed, 67 insertions, 22 deletions
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2070335a61..267eea8a1b 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -4161,11 +4161,14 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, TemplateParameterLists.release(); return Result.get(); } else { - // FIXME: diagnose the extraneous 'template<>', once we recover - // slightly better in ParseTemplate.cpp from bogus template - // parameters. + // The "template<>" header is extraneous. + Diag(TemplateParams->getTemplateLoc(), diag::err_template_tag_noparams) + << ElaboratedType::getNameForTagKind(Kind) << Name; + isExplicitSpecialization = true; } } + + TemplateParameterLists.release(); } DeclContext *SearchDC = CurContext; @@ -4493,6 +4496,11 @@ CreateNewDecl: } } + // If this is a specialization of a member class (of a class template), + // check the specialization. + if (isExplicitSpecialization && CheckMemberSpecialization(New, PrevDecl)) + Invalid = true; + if (Invalid) New->setInvalidDecl(); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 5c6ec0004a..219d73146e 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2360,15 +2360,13 @@ static TemplateSpecializationKind getTemplateSpecializationKind(NamedDecl *D) { if (!D) return TSK_Undeclared; - if (ClassTemplateSpecializationDecl *CTS - = dyn_cast<ClassTemplateSpecializationDecl>(D)) - return CTS->getSpecializationKind(); + if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) + return Record->getTemplateSpecializationKind(); if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) return Function->getTemplateSpecializationKind(); if (VarDecl *Var = dyn_cast<VarDecl>(D)) return Var->getTemplateSpecializationKind(); - // FIXME: member classes of class templates! return TSK_Undeclared; } @@ -3192,23 +3190,46 @@ Sema::CheckMemberSpecialization(NamedDecl *Member, NamedDecl *&PrevDecl) { // FIXME: Check for specialization-after-instantiation errors and such. // Note that this is an explicit instantiation of a member. + // the original declaration to note that it is an explicit specialization + // (if it was previously an implicit instantiation). This latter step + // makes bookkeeping easier. if (isa<FunctionDecl>(Member)) { - // FIXME: We're also setting the original instantiation we found to be - // an explicit specialization, although I'd rather not have to do this. - cast<FunctionDecl>(Instantiation)->setTemplateSpecializationKind( - TSK_ExplicitSpecialization); + FunctionDecl *InstantiationFunction = cast<FunctionDecl>(Instantiation); + if (InstantiationFunction->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationFunction->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationFunction->setLocation(Member->getLocation()); + } + cast<FunctionDecl>(Member)->setInstantiationOfMemberFunction( cast<CXXMethodDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); } else if (isa<VarDecl>(Member)) { + VarDecl *InstantiationVar = cast<VarDecl>(Instantiation); + if (InstantiationVar->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationVar->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationVar->setLocation(Member->getLocation()); + } + Context.setInstantiatedFromStaticDataMember(cast<VarDecl>(Member), cast<VarDecl>(InstantiatedFrom), TSK_ExplicitSpecialization); } else { assert(isa<CXXRecordDecl>(Member) && "Only member classes remain"); - // FIXME: Record TSK_ExplicitSpecialization. + CXXRecordDecl *InstantiationClass = cast<CXXRecordDecl>(Instantiation); + if (InstantiationClass->getTemplateSpecializationKind() == + TSK_ImplicitInstantiation) { + InstantiationClass->setTemplateSpecializationKind( + TSK_ExplicitSpecialization); + InstantiationClass->setLocation(Member->getLocation()); + } + cast<CXXRecordDecl>(Member)->setInstantiationOfMemberClass( - cast<CXXRecordDecl>(InstantiatedFrom)); + cast<CXXRecordDecl>(InstantiatedFrom), + TSK_ExplicitSpecialization); } // Save the caller the trouble of having to figure out which declaration diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 2f7af60e05..ec00d9805c 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -972,20 +972,30 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, 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) { if (FunctionDecl *Function = dyn_cast<FunctionDecl>(*D)) { - if (Function->getInstantiatedFromMemberFunction()) + if (Function->getInstantiatedFromMemberFunction()) { + // If this member was explicitly specialized, do nothing. + if (Function->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization) + continue; + Function->setTemplateSpecializationKind(TSK); - if (!Function->getBody() && TSK != TSK_ExplicitInstantiationDeclaration) + } + + 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) + continue; + Var->setTemplateSpecializationKind(TSK); - if (TSK != TSK_ExplicitInstantiationDeclaration) + if (TSK == TSK_ExplicitInstantiationDefinition) InstantiateStaticDataMemberDefinition(PointOfInstantiation, Var); } } else if (CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(*D)) { @@ -994,6 +1004,11 @@ Sema::InstantiateClassMembers(SourceLocation PointOfInstantiation, assert(Record->getInstantiatedFromMemberClass() && "Missing instantiated-from-template information"); + + // If this member was explicitly specialized, do nothing. + if (Record->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + continue; + if (!Record->getDefinition(Context)) InstantiateClass(PointOfInstantiation, Record, Record->getInstantiatedFromMemberClass(), diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index bafcea054e..b354827e01 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -454,7 +454,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { if (D->getAccess() != AS_none) Record->setAccess(D->getAccess()); if (!D->isInjectedClassName()) - Record->setInstantiationOfMemberClass(D); + Record->setInstantiationOfMemberClass(D, TSK_ImplicitInstantiation); // If the original function was part of a friend declaration, // inherit its namespace state. diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 402bc9db08..da72197f0c 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1849,10 +1849,11 @@ bool Sema::RequireCompleteType(SourceLocation Loc, QualType T, = dyn_cast<CXXRecordDecl>(Record->getDecl())) { if (CXXRecordDecl *Pattern = Rec->getInstantiatedFromMemberClass()) { // This record was instantiated from a class within a template. - return InstantiateClass(Loc, Rec, Pattern, - getTemplateInstantiationArgs(Rec), - TSK_ImplicitInstantiation, - /*Complain=*/diag != 0); + if (Rec->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) + return InstantiateClass(Loc, Rec, Pattern, + getTemplateInstantiationArgs(Rec), + TSK_ImplicitInstantiation, + /*Complain=*/diag != 0); } } } |