[cfe-commits] r137573 - in /cfe/trunk: include/clang/AST/ include/clang/Basic/ include/clang/Sema/ include/clang/Serialization/ lib/AST/ lib/CodeGen/ lib/Sema/ lib/Serialization/ test/SemaTemplate/ tools/libclang/
Nico Weber
thakis at chromium.org
Sun Aug 14 09:10:18 PDT 2011
Hi Francois,
one question below.
On Sat, Aug 13, 2011 at 8:52 PM, Francois Pichet <pichet2000 at gmail.com> wrote:
> Author: fpichet
> Date: Sat Aug 13 22:52:19 2011
> New Revision: 137573
>
> URL: http://llvm.org/viewvc/llvm-project?rev=137573&view=rev
> Log:
> Implement function template specialization at class scope extension in Microsoft mode. A new AST node is introduced: ClassScopeFunctionSpecialization. This node holds a FunctionDecl that is not yet specialized; then during the class template instantiation the ClassScopeFunctionSpecialization will spawn the actual function specialization.
>
> Example:
> template <class T>
> class A {
> public:
> template <class U> void f(U p) { }
> template <> void f(int p) { } // <== class scope specialization
> };
>
> This extension is necessary to parse MSVC standard C++ headers, MFC and ATL code.
> BTW, with this feature in, clang can parse (-fsyntax-only) all the MSVC 2010 standard header files without any error.
Great news :-)
>
> Added:
> cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp
> Modified:
> cfe/trunk/include/clang/AST/ASTContext.h
> cfe/trunk/include/clang/AST/Decl.h
> cfe/trunk/include/clang/AST/DeclTemplate.h
> cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> cfe/trunk/include/clang/Basic/DeclNodes.td
> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> cfe/trunk/include/clang/Sema/Sema.h
> cfe/trunk/include/clang/Sema/Template.h
> cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> cfe/trunk/lib/AST/ASTContext.cpp
> cfe/trunk/lib/AST/Decl.cpp
> cfe/trunk/lib/AST/DeclBase.cpp
> cfe/trunk/lib/CodeGen/CGDecl.cpp
> cfe/trunk/lib/Sema/SemaDecl.cpp
> cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> cfe/trunk/lib/Sema/SemaTemplate.cpp
> cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
> cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> cfe/trunk/tools/libclang/CIndex.cpp
>
> Modified: cfe/trunk/include/clang/AST/ASTContext.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/ASTContext.h (original)
> +++ cfe/trunk/include/clang/AST/ASTContext.h Sat Aug 13 22:52:19 2011
> @@ -152,6 +152,11 @@
> /// \brief Mapping from __block VarDecls to their copy initialization expr.
> llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits;
>
> + /// \brief Mapping from class scope functions specialization to their
> + /// templateS pattern.
> + llvm::DenseMap<const FunctionDecl*, FunctionDecl*>
> + ClassScopeSpecilizationPattern;
> +
> /// \brief Representation of a "canonical" template template parameter that
> /// is used in canonical template names.
> class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode {
> @@ -382,6 +387,11 @@
> MemberSpecializationInfo *getInstantiatedFromStaticDataMember(
> const VarDecl *Var);
>
> + FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD);
> +
> + void setClassScopeSpecializationPattern(FunctionDecl *FD,
> + FunctionDecl *Pattern);
> +
> /// \brief Note that the static data member \p Inst is an instantiation of
> /// the static data member template \p Tmpl of a class template.
> void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl,
>
> Modified: cfe/trunk/include/clang/AST/Decl.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Decl.h?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/Decl.h (original)
> +++ cfe/trunk/include/clang/AST/Decl.h Sat Aug 13 22:52:19 2011
> @@ -1851,7 +1851,11 @@
> bool isFunctionTemplateSpecialization() const {
> return getPrimaryTemplate() != 0;
> }
> -
> +
> + /// \brief Retrieve the class scope template pattern that this function
> + /// template specialization is instantiated from.
> + FunctionDecl *getClassScopeSpecializationPattern() const;
> +
> /// \brief If this function is actually a function template specialization,
> /// retrieve information about this function template specialization.
> /// Otherwise, returns NULL.
>
> Modified: cfe/trunk/include/clang/AST/DeclTemplate.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclTemplate.h?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/DeclTemplate.h (original)
> +++ cfe/trunk/include/clang/AST/DeclTemplate.h Sat Aug 13 22:52:19 2011
> @@ -2097,6 +2097,58 @@
> friend class ASTDeclWriter;
> };
>
> +/// Declaration of a function specialization at template class scope.
> +/// This is a non standard extension needed to support MSVC.
> +/// For example:
> +/// template <class T>
> +/// class A {
> +/// template <class U> void foo(U a) { }
> +/// template<> void foo(int a) { }
> +/// }
> +///
> +/// "template<> foo(int a)" will be saved in Specialization as a normal
> +/// CXXMethodDecl. Then during an instantiation of class A, it will be
> +/// transformed into an actual function specialization.
> +class ClassScopeFunctionSpecializationDecl : public Decl {
> +private:
> + ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc,
> + CXXMethodDecl *FD)
> + : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc),
> + Specialization(FD) {}
> +
> + ClassScopeFunctionSpecializationDecl(EmptyShell Empty)
> + : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {}
> +
> + CXXMethodDecl *Specialization;
> +
> +public:
> + CXXMethodDecl *getSpecialization() const { return Specialization; }
> +
> + static ClassScopeFunctionSpecializationDecl *Create(ASTContext &C,
> + DeclContext *DC,
> + SourceLocation Loc,
> + CXXMethodDecl *FD) {
> + return new (C) ClassScopeFunctionSpecializationDecl(DC , Loc, FD);
> + }
> +
> + static ClassScopeFunctionSpecializationDecl *Create(ASTContext &Context,
> + EmptyShell Empty) {
> + return new (Context)ClassScopeFunctionSpecializationDecl(0,
> + SourceLocation(), 0);
> + }
> + // Implement isa/cast/dyncast/etc.
> + static bool classof(const Decl *D) { return classofKind(D->getKind()); }
> + static bool classofKind(Kind K) {
> + return K == Decl::ClassScopeFunctionSpecialization;
> + }
> + static bool classof(const ClassScopeFunctionSpecializationDecl *D) {
> + return true;
> + }
> +
> + friend class ASTDeclReader;
> + friend class ASTDeclWriter;
> +};
> +
> /// Implementation of inline functions that require the template declarations
> inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD)
> : Function(FTD) { }
>
> Modified: cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/RecursiveASTVisitor.h?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/AST/RecursiveASTVisitor.h (original)
> +++ cfe/trunk/include/clang/AST/RecursiveASTVisitor.h Sat Aug 13 22:52:19 2011
> @@ -1114,6 +1114,10 @@
> }
> })
>
> +DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
> + TRY_TO(TraverseDecl(D->getSpecialization()));
> + })
> +
> DEF_TRAVERSE_DECL(LinkageSpecDecl, { })
>
> DEF_TRAVERSE_DECL(ObjCClassDecl, {
>
> Modified: cfe/trunk/include/clang/Basic/DeclNodes.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DeclNodes.td?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DeclNodes.td (original)
> +++ cfe/trunk/include/clang/Basic/DeclNodes.td Sat Aug 13 22:52:19 2011
> @@ -74,3 +74,4 @@
> def FriendTemplate : Decl;
> def StaticAssert : Decl;
> def Block : Decl, DeclContext;
> +def ClassScopeFunctionSpecialization : Decl;
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Sat Aug 13 22:52:19 2011
> @@ -2028,6 +2028,9 @@
> "parameter}0">;
> def err_function_specialization_in_class : Error<
> "cannot specialize a function %0 within class scope">;
> +def ext_function_specialization_in_class : ExtWarn<
> + "explicit specialization of %0 within class scope in a Microsoft extension">,
Should this be "…_is_ a Microsoft extension"?
> + InGroup<Microsoft>;
> def ext_explicit_specialization_storage_class : ExtWarn<
> "explicit specialization cannot have a storage class">;
> def err_explicit_specialization_inconsistent_storage_class : Error<
>
> Modified: cfe/trunk/include/clang/Sema/Sema.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Sema.h (original)
> +++ cfe/trunk/include/clang/Sema/Sema.h Sat Aug 13 22:52:19 2011
> @@ -1002,7 +1002,8 @@
> LookupResult &Previous,
> MultiTemplateParamsArg TemplateParamLists,
> bool IsFunctionDefinition,
> - bool &Redeclaration);
> + bool &Redeclaration,
> + bool &AddToScope);
> bool AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
> void DiagnoseHiddenVirtualMethods(CXXRecordDecl *DC, CXXMethodDecl *MD);
> void CheckFunctionDeclaration(Scope *S,
>
> Modified: cfe/trunk/include/clang/Sema/Template.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Template.h?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Sema/Template.h (original)
> +++ cfe/trunk/include/clang/Sema/Template.h Sat Aug 13 22:52:19 2011
> @@ -350,7 +350,8 @@
> TemplateParameterList *TemplateParams = 0);
> Decl *VisitCXXRecordDecl(CXXRecordDecl *D);
> Decl *VisitCXXMethodDecl(CXXMethodDecl *D,
> - TemplateParameterList *TemplateParams = 0);
> + TemplateParameterList *TemplateParams = 0,
> + bool IsClassScopeSpecialization = false);
> Decl *VisitCXXConstructorDecl(CXXConstructorDecl *D);
> Decl *VisitCXXDestructorDecl(CXXDestructorDecl *D);
> Decl *VisitCXXConversionDecl(CXXConversionDecl *D);
> @@ -367,6 +368,8 @@
> Decl *VisitUsingShadowDecl(UsingShadowDecl *D);
> Decl *VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D);
> Decl *VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D);
> + Decl *VisitClassScopeFunctionSpecializationDecl(
> + ClassScopeFunctionSpecializationDecl *D);
>
> // Base case. FIXME: Remove once we can instantiate everything.
> Decl *VisitDecl(Decl *D) {
>
> Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)
> +++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Sat Aug 13 22:52:19 2011
> @@ -826,7 +826,10 @@
> DECL_INDIRECTFIELD,
> /// \brief A NonTypeTemplateParmDecl record that stores an expanded
> /// non-type template parameter pack.
> - DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK
> + DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK,
> + /// \brief A ClassScopeFunctionSpecializationDecl record a class scope
> + /// function specialization. (Microsoft extension).
> + DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION
> };
>
> /// \brief Record codes for each kind of statement or expression.
>
> Modified: cfe/trunk/lib/AST/ASTContext.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/ASTContext.cpp (original)
> +++ cfe/trunk/lib/AST/ASTContext.cpp Sat Aug 13 22:52:19 2011
> @@ -518,6 +518,24 @@
> = 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 @@
> + 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);
> }
>
> Modified: cfe/trunk/lib/AST/Decl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Decl.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/Decl.cpp (original)
> +++ cfe/trunk/lib/AST/Decl.cpp Sat Aug 13 22:52:19 2011
> @@ -1922,13 +1922,17 @@
>
> 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 @@
> }
>
> 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 @@
> return 0;
> }
>
> +FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const {
> + return getASTContext().getClassScopeSpecializationPattern(this);
> +}
> +
> const TemplateArgumentList *
> FunctionDecl::getTemplateSpecializationArgs() const {
> if (FunctionTemplateSpecializationInfo *Info
>
> Modified: cfe/trunk/lib/AST/DeclBase.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/DeclBase.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/AST/DeclBase.cpp (original)
> +++ cfe/trunk/lib/AST/DeclBase.cpp Sat Aug 13 22:52:19 2011
> @@ -493,6 +493,7 @@
> case UsingDirective:
> case ClassTemplateSpecialization:
> case ClassTemplatePartialSpecialization:
> + case ClassScopeFunctionSpecialization:
> case ObjCImplementation:
> case ObjCCategory:
> case ObjCCategoryImpl:
>
> Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original)
> +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Sat Aug 13 22:52:19 2011
> @@ -70,6 +70,7 @@
> 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;
>
> Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDecl.cpp Sat Aug 13 22:52:19 2011
> @@ -1722,9 +1722,16 @@
> // 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 @@
> 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 @@
> } 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 @@
>
> // 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 @@
> 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 @@
> 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 @@
> } 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 @@
> }
>
> // 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 @@
> 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;
> }
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Sat Aug 13 22:52:19 2011
> @@ -8652,10 +8652,11 @@
> }
>
> 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);
>
> Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Sat Aug 13 22:52:19 2011
> @@ -4511,9 +4511,18 @@
> }
>
> 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:
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiate.cpp Sat Aug 13 22:52:19 2011
> @@ -98,8 +98,9 @@
> // 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
>
> Modified: cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaTemplateInstantiateDecl.cpp Sat Aug 13 22:52:19 2011
> @@ -1288,7 +1288,8 @@
>
> 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 @@
> }
>
> 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 @@
> : Method);
> if (isFriend)
> Record->makeDeclVisibleInContext(DeclToAdd);
> - else
> + else if (!IsClassScopeSpecialization)
> Owner->addDecl(DeclToAdd);
> }
>
> @@ -1907,6 +1909,29 @@
> 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 @@
> 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.
>
> Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
> +++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Sat Aug 13 22:52:19 2011
> @@ -1568,6 +1568,10 @@
> 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;
>
> Added: cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp?rev=137573&view=auto
> ==============================================================================
> --- cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp (added)
> +++ cfe/trunk/test/SemaTemplate/ms-function-specialization-class-scope.cpp Sat Aug 13 22:52:19 2011
> @@ -0,0 +1,71 @@
> +// RUN: %clang_cc1 -fms-extensions -fsyntax-only -verify %s
> +
> +
> +class A {
> +public:
> + template <class U>
> + A(U p) {
> + }
> + template <>
> + A(int p) { // expected-warning{{explicit specialization of 'A' within class scope in a Microsoft extension}}
> + }
> +
> + template <class U>
> + void f(U p) {
> + }
> +
> + template <>
> + void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope in a Microsoft extension}}
> + }
> +
> + void f(int p) {
> + }
> +};
> +
> +void test1()
> +{
> + A a(3);
> + char* b ;
> + a.f(b);
> + a.f<int>(99);
> + a.f(100);
> +}
> +
> +
> +
> +
> +template <class T>
> +class B {
> +public:
> + template <class U>
> + B(U p) {
> + }
> + template <>
> + B(int p) { // expected-warning{{explicit specialization of 'B<T>' within class scope in a Microsoft extension}}
> + }
> +
> + template <class U>
> + void f(U p) {
> + T y = 9;
> + }
> +
> +
> + template <>
> + void f(int p) { // expected-warning{{explicit specialization of 'f' within class scope in a Microsoft extension}}
> + T a = 3;
> + }
> +
> + void f(int p) {
> + T a = 3;
> + }
> +};
> +
> +void test2()
> +{
> + B<char> b(3);
> + char* ptr;
> + b.f(ptr);
> + b.f<int>(99);
> + b.f(100);
> +}
> +
>
> Modified: cfe/trunk/tools/libclang/CIndex.cpp
> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=137573&r1=137572&r2=137573&view=diff
> ==============================================================================
> --- cfe/trunk/tools/libclang/CIndex.cpp (original)
> +++ cfe/trunk/tools/libclang/CIndex.cpp Sat Aug 13 22:52:19 2011
> @@ -4048,6 +4048,7 @@
> case Decl::StaticAssert:
> case Decl::Block:
> case Decl::Label: // FIXME: Is this right??
> + case Decl::ClassScopeFunctionSpecialization:
> return C;
>
> // Declaration kinds that don't make any sense here, but are
>
>
> _______________________________________________
> cfe-commits mailing list
> cfe-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list