diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/AST/Decl.cpp | 4 | ||||
-rw-r--r-- | clang/lib/Sema/Sema.h | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 24 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiate.cpp | 32 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 14 |
6 files changed, 66 insertions, 15 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 638d1cfd46e..429729ea3b0 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -737,8 +737,8 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { const TemplateArgumentList * FunctionDecl::getTemplateSpecializationArgs() const { if (FunctionTemplateSpecializationInfo *Info - = TemplateOrSpecialization - .dyn_cast<FunctionTemplateSpecializationInfo*>()) { + = TemplateOrSpecialization + .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArguments; } return 0; diff --git a/clang/lib/Sema/Sema.h b/clang/lib/Sema/Sema.h index 40e7426e973..fed2fbc0816 100644 --- a/clang/lib/Sema/Sema.h +++ b/clang/lib/Sema/Sema.h @@ -551,6 +551,7 @@ public: bool IsFunctionDefinition, bool &Redeclaration); void CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, + bool IsExplicitSpecialization, bool &Redeclaration, bool &OverloadableAttrRequired); void CheckMain(FunctionDecl *FD); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 69426ee7554..a1582a900f9 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -1735,6 +1735,10 @@ Sema::HandleDeclarator(Scope *S, Declarator &D, return DeclPtrTy(); } + if (!DC->isDependentContext() && + RequireCompleteDeclContext(D.getCXXScopeSpec())) + return DeclPtrTy(); + LookupResult Res; LookupQualifiedName(Res, DC, Name, LookupOrdinaryName, true); PrevDecl = Res.getAsSingleDecl(Context); @@ -2807,11 +2811,11 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, } else if (isExplicitSpecialization && isa<CXXMethodDecl>(NewFD) && CheckMemberSpecialization(NewFD, PrevDecl)) NewFD->setInvalidDecl(); - + // Perform semantic checking on the function declaration. bool OverloadableAttrRequired = false; // FIXME: HACK! - CheckFunctionDeclaration(NewFD, PrevDecl, Redeclaration, - /*FIXME:*/OverloadableAttrRequired); + CheckFunctionDeclaration(NewFD, PrevDecl, isExplicitSpecialization, + Redeclaration, /*FIXME:*/OverloadableAttrRequired); if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) { // An out-of-line member function declaration must also be a @@ -2914,8 +2918,12 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, /// that have been instantiated via C++ template instantiation (called /// via InstantiateDecl). /// +/// \param IsExplicitSpecialiation whether this new function declaration is +/// an explicit specialization of the previous declaration. +/// /// This sets NewFD->isInvalidDecl() to true if there was an error. void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, + bool IsExplicitSpecialization, bool &Redeclaration, bool &OverloadableAttrRequired) { // If NewFD is already known erroneous, don't do any of this checking. @@ -2990,7 +2998,7 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, if (FunctionTemplateDecl *OldTemplateDecl = dyn_cast<FunctionTemplateDecl>(OldDecl)) { - NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); + NewFD->setPreviousDeclaration(OldTemplateDecl->getTemplatedDecl()); FunctionTemplateDecl *NewTemplateDecl = NewFD->getDescribedFunctionTemplate(); assert(NewTemplateDecl && "Template/non-template mismatch"); @@ -2999,6 +3007,14 @@ void Sema::CheckFunctionDeclaration(FunctionDecl *NewFD, NamedDecl *&PrevDecl, Method->setAccess(OldTemplateDecl->getAccess()); NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); } + + // If this is an explicit specialization of a member that is a function + // template, mark it as a member specialization. + if (IsExplicitSpecialization && + NewTemplateDecl->getInstantiatedFromMemberTemplate()) { + NewTemplateDecl->setMemberSpecialization(); + assert(OldTemplateDecl->isMemberSpecialization()); + } } else { if (isa<CXXMethodDecl>(NewFD)) // Set access for out-of-line definitions NewFD->setAccess(OldDecl->getAccess()); diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 74120498573..3ee15a5b4d8 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -716,6 +716,12 @@ Sema::CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, assert(T->isDependentType() && "Class template type is not dependent?"); (void)T; + // If we are providing an explicit specialization of a member that is a + // class template, make a note of that. + if (PrevClassTemplate && + PrevClassTemplate->getInstantiatedFromMemberTemplate()) + PrevClassTemplate->setMemberSpecialization(); + // Set the access specifier. if (!Invalid && TUK != TUK_Friend) SetMemberAccessSpecifier(NewTemplate, PrevClassTemplate, AS); diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp index ec00d9805c0..65260c8e1e6 100644 --- a/clang/lib/Sema/SemaTemplateInstantiate.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp @@ -46,15 +46,31 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D) { break; Result.addOuterTemplateArguments(&Spec->getTemplateInstantiationArgs()); + + // If this class template specialization was instantiated from a + // specialized member that is a class template, we're done. + assert(Spec->getSpecializedTemplate() && "No class template?"); + if (Spec->getSpecializedTemplate()->isMemberSpecialization()) + break; } - // Add template arguments from a function template specialization. else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) { - // FIXME: Check whether this is an explicit specialization. + if (Function->getTemplateSpecializationKind() + == TSK_ExplicitSpecialization) + break; + if (const TemplateArgumentList *TemplateArgs - = Function->getTemplateSpecializationArgs()) + = Function->getTemplateSpecializationArgs()) { + // Add the template arguments for this specialization. Result.addOuterTemplateArguments(TemplateArgs); + // If this function was instantiated from a specialized member that is + // a function template, we're done. + assert(Function->getPrimaryTemplate() && "No function template?"); + if (Function->getPrimaryTemplate()->isMemberSpecialization()) + break; + } + // If this is a friend declaration and it declares an entity at // namespace scope, take arguments from its lexical parent // instead of its semantic parent. @@ -940,9 +956,15 @@ Sema::InstantiateClassTemplateSpecialization( // -- If no matches are found, the instantiation is generated // from the primary template. ClassTemplateDecl *OrigTemplate = Template; - while (OrigTemplate->getInstantiatedFromMemberTemplate()) + while (OrigTemplate->getInstantiatedFromMemberTemplate()) { + // If we've found an explicit specialization of this class template, + // stop here and use that as the pattern. + if (OrigTemplate->isMemberSpecialization()) + break; + OrigTemplate = OrigTemplate->getInstantiatedFromMemberTemplate(); - + } + Pattern = OrigTemplate->getTemplatedDecl(); } diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index b03734346c4..33fa28866e5 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -581,7 +581,7 @@ Decl *TemplateDeclInstantiator::VisitCXXRecordDecl(CXXRecordDecl *D) { PrevDecl = 0; } - SemaRef.CheckFunctionDeclaration(Function, PrevDecl, Redeclaration, + SemaRef.CheckFunctionDeclaration(Function, PrevDecl, false, Redeclaration, /*FIXME:*/OverloadableAttrRequired); // If the original function was part of a friend declaration, @@ -748,7 +748,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, bool Redeclaration = false; bool OverloadableAttrRequired = false; - SemaRef.CheckFunctionDeclaration(Method, PrevDecl, Redeclaration, + SemaRef.CheckFunctionDeclaration(Method, PrevDecl, false, Redeclaration, /*FIXME:*/OverloadableAttrRequired); if (!FunctionTemplate && (!Method->isInvalidDecl() || !PrevDecl) && @@ -1057,9 +1057,15 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, // Find the function body that we'll be substituting. const FunctionDecl *PatternDecl = 0; if (FunctionTemplateDecl *Primary = Function->getPrimaryTemplate()) { - while (Primary->getInstantiatedFromMemberTemplate()) + while (Primary->getInstantiatedFromMemberTemplate()) { + // If we have hit a point where the user provided a specialization of + // this template, we're done looking. + if (Primary->isMemberSpecialization()) + break; + Primary = Primary->getInstantiatedFromMemberTemplate(); - + } + PatternDecl = Primary->getTemplatedDecl(); } else PatternDecl = Function->getInstantiatedFromMemberFunction(); |