diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/AST/ASTContext.cpp | 21 | ||||
-rw-r--r-- | lib/AST/Decl.cpp | 14 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 1 | ||||
-rw-r--r-- | lib/CodeGen/CGDecl.cpp | 1 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 44 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 15 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiate.cpp | 5 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateInstantiateDecl.cpp | 37 | ||||
-rw-r--r-- | lib/Serialization/ASTReaderDecl.cpp | 4 |
10 files changed, 123 insertions, 22 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 7acc22abcc..d01e2a12ab 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -518,6 +518,24 @@ ASTContext::setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, = new (*this) MemberSpecializationInfo(Tmpl, TSK, PointOfInstantiation); } +FunctionDecl *ASTContext::getClassScopeSpecializationPattern( + const FunctionDecl *FD){ + assert(FD && "Specialization is 0"); + llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos + = ClassScopeSpecilizationPattern.find(FD); + if (Pos == ClassScopeSpecilizationPattern.end()) + return 0; + + return Pos->second; +} + +void ASTContext::setClassScopeSpecializationPattern(FunctionDecl *FD, + FunctionDecl *Pattern) { + assert(FD && "Specialization is 0"); + assert(Pattern && "Class scope specialization pattern is 0"); + ClassScopeSpecilizationPattern[FD] = Pattern; +} + NamedDecl * ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos @@ -6439,5 +6457,6 @@ size_t ASTContext::getSideTableAllocatedMemory() const { + llvm::capacity_in_bytes(InstantiatedFromUnnamedFieldDecl) + llvm::capacity_in_bytes(OverriddenMethods) + llvm::capacity_in_bytes(Types) - + llvm::capacity_in_bytes(VariableArrayTypes); + + llvm::capacity_in_bytes(VariableArrayTypes) + + llvm::capacity_in_bytes(ClassScopeSpecilizationPattern); } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 6c7deca5fd..f917d32f5e 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -1922,13 +1922,17 @@ bool FunctionDecl::isImplicitlyInstantiable() const { switch (getTemplateSpecializationKind()) { case TSK_Undeclared: - case TSK_ExplicitSpecialization: case TSK_ExplicitInstantiationDefinition: return false; case TSK_ImplicitInstantiation: return true; + // It is possible to instantiate TSK_ExplicitSpecialization kind + // if the FunctionDecl has a class scope specialization pattern. + case TSK_ExplicitSpecialization: + return getClassScopeSpecializationPattern() != 0; + case TSK_ExplicitInstantiationDeclaration: // Handled below. break; @@ -1951,6 +1955,10 @@ bool FunctionDecl::isImplicitlyInstantiable() const { } FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { + // Handle class scope explicit specialization special case. + if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + return getClassScopeSpecializationPattern(); + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of @@ -1976,6 +1984,10 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { return 0; } +FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { + return getASTContext().getClassScopeSpecializationPattern(this); +} + const TemplateArgumentList * FunctionDecl::getTemplateSpecializationArgs() const { if (FunctionTemplateSpecializationInfo *Info diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 27d05baca2..5e5ec93e17 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -493,6 +493,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { case UsingDirective: case ClassTemplateSpecialization: case ClassTemplatePartialSpecialization: + case ClassScopeFunctionSpecialization: case ObjCImplementation: case ObjCCategory: case ObjCCategoryImpl: diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 870fe811f1..6e65e88bce 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -70,6 +70,7 @@ void CodeGenFunction::EmitDecl(const Decl &D) { case Decl::Friend: case Decl::FriendTemplate: case Decl::Block: + case Decl::ClassScopeFunctionSpecialization: assert(0 && "Declaration should not be in declstmts!"); case Decl::Function: // void X(); case Decl::Record: // struct/union/class X; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index b67c3d3e95..c1a6c60d28 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -1722,9 +1722,16 @@ bool Sema::MergeFunctionDecl(FunctionDecl *New, Decl *OldD) { // Preserve triviality. NewMethod->setTrivial(OldMethod->isTrivial()); + // MSVC allows explicit template specialization at class scope: + // 2 CXMethodDecls referring to the same function will be injected. + // We don't want a redeclartion error. + bool IsClassScopeExplicitSpecialization = + OldMethod->isFunctionTemplateSpecialization() && + NewMethod->isFunctionTemplateSpecialization(); bool isFriend = NewMethod->getFriendObjectKind(); - if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord()) { + if (!isFriend && NewMethod->getLexicalDeclContext()->isRecord() && + !IsClassScopeExplicitSpecialization) { // -- Member function declarations with the same name and the // same parameter types cannot be overloaded if any of them // is a static member function declaration. @@ -3226,6 +3233,7 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, Previous.clear(); bool Redeclaration = false; + bool AddToScope = true; if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) { if (TemplateParamLists.size()) { Diag(D.getIdentifierLoc(), diag::err_template_typedef); @@ -3236,7 +3244,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, } else if (R->isFunctionType()) { New = ActOnFunctionDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), - IsFunctionDefinition, Redeclaration); + IsFunctionDefinition, Redeclaration, + AddToScope); } else { New = ActOnVariableDeclarator(S, D, DC, R, TInfo, Previous, move(TemplateParamLists), @@ -3248,7 +3257,8 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, // If this has an identifier and is not an invalid redeclaration or // function template specialization, add it to the scope stack. - if (New->getDeclName() && !(Redeclaration && New->isInvalidDecl())) + if (New->getDeclName() && AddToScope && + !(Redeclaration && New->isInvalidDecl())) PushOnScopeChains(New, S); return New; @@ -4201,7 +4211,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, MultiTemplateParamsArg TemplateParamLists, - bool IsFunctionDefinition, bool &Redeclaration) { + bool IsFunctionDefinition, bool &Redeclaration, + bool &AddToScope) { assert(R.getTypePtr()->isFunctionType()); // TODO: consider using NameInfo for diagnostic. @@ -4266,6 +4277,7 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, FunctionTemplateDecl *FunctionTemplate = 0; bool isExplicitSpecialization = false; bool isFunctionTemplateSpecialization = false; + bool isDependentClassScopeExplicitSpecialization = false; if (!getLangOptions().CPlusPlus) { // Determine whether the function was written with a @@ -4769,10 +4781,11 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } else if (isFunctionTemplateSpecialization) { if (CurContext->isDependentContext() && CurContext->isRecord() && !isFriend) { - Diag(NewFD->getLocation(), diag::err_function_specialization_in_class) + isDependentClassScopeExplicitSpecialization = true; + Diag(NewFD->getLocation(), getLangOptions().Microsoft ? + diag::ext_function_specialization_in_class : + diag::err_function_specialization_in_class) << NewFD->getDeclName(); - NewFD->setInvalidDecl(); - return 0; } else if (CheckFunctionTemplateSpecialization(NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : 0), Previous)) @@ -4802,8 +4815,9 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // Perform semantic checking on the function declaration. - CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, - Redeclaration); + if (!isDependentClassScopeExplicitSpecialization) + CheckFunctionDeclaration(S, NewFD, Previous, isExplicitSpecialization, + Redeclaration); assert((NewFD->isInvalidDecl() || !Redeclaration || Previous.getResultKind() != LookupResult::FoundOverloaded) && @@ -4984,6 +4998,18 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, Context.setcudaConfigureCallDecl(NewFD); } } + + // Here we have an function template explicit specialization at class scope. + // The actually specialization will be postponed to template instatiation + // time via the ClassScopeFunctionSpecializationDecl node. + if (isDependentClassScopeExplicitSpecialization) { + ClassScopeFunctionSpecializationDecl *NewSpec = + ClassScopeFunctionSpecializationDecl::Create( + Context, CurContext, SourceLocation(), + cast<CXXMethodDecl>(NewFD)); + CurContext->addDecl(NewSpec); + AddToScope = false; + } return NewFD; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 05706d7d42..76461a0ca6 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -8652,10 +8652,11 @@ Decl *Sema::ActOnFriendFunctionDecl(Scope *S, Declarator &D, bool IsDefinition, } bool Redeclaration = false; + bool AddToScope = true; NamedDecl *ND = ActOnFunctionDeclarator(DCScope, D, DC, T, TInfo, Previous, move(TemplateParams), IsDefinition, - Redeclaration); + Redeclaration, AddToScope); if (!ND) return 0; assert(ND->getDeclContext() == DC); diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index ded352047a..a7d74ce7e8 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -4511,9 +4511,18 @@ static bool CheckTemplateSpecializationScope(Sema &S, } if (S.CurContext->isRecord() && !IsPartialSpecialization) { - S.Diag(Loc, diag::err_template_spec_decl_class_scope) - << Specialized; - return true; + if (S.getLangOptions().Microsoft) { + // Do not warn for class scope explicit specialization during + // instantiation, warning was already emitted during pattern + // semantic analysis. + if (!S.ActiveTemplateInstantiations.size()) + S.Diag(Loc, diag::ext_function_specialization_in_class) + << Specialized; + } else { + S.Diag(Loc, diag::err_template_spec_decl_class_scope) + << Specialized; + return true; + } } // C++ [temp.class.spec]p6: diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 67e2d871c3..830f06ae20 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -98,8 +98,9 @@ Sema::getTemplateInstantiationArgs(NamedDecl *D, // Add template arguments from a function template specialization. else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(Ctx)) { if (!RelativeToPrimary && - Function->getTemplateSpecializationKind() - == TSK_ExplicitSpecialization) + (Function->getTemplateSpecializationKind() == + TSK_ExplicitSpecialization && + !Function->getClassScopeSpecializationPattern())) break; if (const TemplateArgumentList *TemplateArgs diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 872bb87457..2554b82d97 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -1288,7 +1288,8 @@ Decl *TemplateDeclInstantiator::VisitFunctionDecl(FunctionDecl *D, Decl * TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, - TemplateParameterList *TemplateParams) { + TemplateParameterList *TemplateParams, + bool IsClassScopeSpecialization) { FunctionTemplateDecl *FunctionTemplate = D->getDescribedFunctionTemplate(); void *InsertPos = 0; if (FunctionTemplate && !TemplateParams) { @@ -1493,7 +1494,8 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, } bool Redeclaration = false; - SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration); + if (!IsClassScopeSpecialization) + SemaRef.CheckFunctionDeclaration(0, Method, Previous, false, Redeclaration); if (D->isPure()) SemaRef.CheckPureMethod(Method, SourceRange()); @@ -1512,7 +1514,7 @@ TemplateDeclInstantiator::VisitCXXMethodDecl(CXXMethodDecl *D, : Method); if (isFriend) Record->makeDeclVisibleInContext(DeclToAdd); - else + else if (!IsClassScopeSpecialization) Owner->addDecl(DeclToAdd); } @@ -1907,6 +1909,29 @@ Decl * TemplateDeclInstantiator return UD; } + +Decl *TemplateDeclInstantiator::VisitClassScopeFunctionSpecializationDecl( + ClassScopeFunctionSpecializationDecl *Decl) { + CXXMethodDecl *OldFD = Decl->getSpecialization(); + CXXMethodDecl *NewFD = cast<CXXMethodDecl>(VisitCXXMethodDecl(OldFD, 0, true)); + + LookupResult Previous(SemaRef, NewFD->getNameInfo(), Sema::LookupOrdinaryName, + Sema::ForRedeclaration); + + SemaRef.LookupQualifiedName(Previous, SemaRef.CurContext); + if (SemaRef.CheckFunctionTemplateSpecialization(NewFD, 0, Previous)) { + NewFD->setInvalidDecl(); + return NewFD; + } + + // Associate the specialization with the pattern. + FunctionDecl *Specialization = cast<FunctionDecl>(Previous.getFoundDecl()); + assert(Specialization && "Class scope Specialization is null"); + SemaRef.Context.setClassScopeSpecializationPattern(Specialization, OldFD); + + return NewFD; +} + Decl *Sema::SubstDecl(Decl *D, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs) { TemplateDeclInstantiator Instantiator(*this, Owner, TemplateArgs); @@ -2335,8 +2360,10 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, if (Function->isInvalidDecl() || Function->isDefined()) return; - // Never instantiate an explicit specialization. - if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization) + // Never instantiate an explicit specialization except if it is a class scope + // explicit specialization. + if (Function->getTemplateSpecializationKind() == TSK_ExplicitSpecialization && + !Function->getClassScopeSpecializationPattern()) return; // Find the function body that we'll be substituting. diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 02bd21fef0..e9d421f0ff 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -1568,6 +1568,10 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { D = ClassTemplatePartialSpecializationDecl::Create(*Context, Decl::EmptyShell()); break; + case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: + D = ClassScopeFunctionSpecializationDecl::Create(*Context, + Decl::EmptyShell()); + break; case DECL_FUNCTION_TEMPLATE: D = FunctionTemplateDecl::Create(*Context, Decl::EmptyShell()); break; |