diff options
59 files changed, 1119 insertions, 138 deletions
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html index f86835a9d1..9dcddfad60 100644 --- a/docs/LanguageExtensions.html +++ b/docs/LanguageExtensions.html @@ -32,6 +32,7 @@ td { </ul> <li><a href="#checking_upcoming_features">Checks for Upcoming Standard Language Features</a></li> <ul> + <li><a href="#cxx_alias_templates">C++0x alias templates</a></li> <li><a href="#cxx_attributes">C++0x attributes</a></li> <li><a href="#cxx_decltype">C++0x <tt>decltype()</tt></a></li> <li><a href="#cxx_default_function_template_args">C++0x default template arguments in function templates</a></li> @@ -378,6 +379,11 @@ not yet implemented will be noted.</p> <p>Use <tt>__has_feature(cxx_decltype)</tt> to determine if support for the <tt>decltype()</tt> specifier is enabled.</p> +<h3 id="cxx_alias_templates">C++0x alias templates</h3> + +<p>Use <tt>__has_feature(cxx_alias_templates)</tt> to determine if support for +C++0x's alias declarations and alias templates is enabled.</p> + <h3 id="cxx_attributes">C++0x attributes</h3> <p>Use <tt>__has_feature(cxx_attributes)</tt> to determine if support for diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index ddbe344cdf..dc50d614bf 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -30,6 +30,7 @@ class ClassTemplatePartialSpecializationDecl; class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; class TemplateTemplateParmDecl; +class TypeAliasTemplateDecl; /// \brief Stores a template parameter of any kind. typedef llvm::PointerUnion3<TemplateTypeParmDecl*, NonTypeTemplateParmDecl*, @@ -230,6 +231,7 @@ public: static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; } static bool classof(const TemplateTemplateParmDecl *D) { return true; } + static bool classof(const TypeAliasTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstTemplate && K <= lastTemplate; } @@ -672,6 +674,7 @@ public: static bool classof(const RedeclarableTemplateDecl *D) { return true; } static bool classof(const FunctionTemplateDecl *D) { return true; } static bool classof(const ClassTemplateDecl *D) { return true; } + static bool classof(const TypeAliasTemplateDecl *D) { return true; } static bool classofKind(Kind K) { return K >= firstRedeclarableTemplate && K <= lastRedeclarableTemplate; } @@ -2014,6 +2017,78 @@ public: friend class ASTDeclReader; }; +/// Declaration of an alias template. For example: +/// +/// template <typename T> using V = std::map<T*, int, MyCompare<T>>; +class TypeAliasTemplateDecl : public RedeclarableTemplateDecl, + public RedeclarableTemplate<TypeAliasTemplateDecl> { + static void DeallocateCommon(void *Ptr); + +protected: + typedef RedeclarableTemplate<TypeAliasTemplateDecl> redeclarable_base; + + typedef CommonBase Common; + + TypeAliasTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : RedeclarableTemplateDecl(TypeAliasTemplate, DC, L, Name, Params, Decl) { } + + CommonBase *newCommon(ASTContext &C); + + Common *getCommonPtr() { + return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); + } + +public: + /// Get the underlying function declaration of the template. + TypeAliasDecl *getTemplatedDecl() const { + return static_cast<TypeAliasDecl*>(TemplatedDecl); + } + + + TypeAliasTemplateDecl *getCanonicalDecl() { + return redeclarable_base::getCanonicalDecl(); + } + const TypeAliasTemplateDecl *getCanonicalDecl() const { + return redeclarable_base::getCanonicalDecl(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + TypeAliasTemplateDecl *getPreviousDeclaration() { + return redeclarable_base::getPreviousDeclaration(); + } + + /// \brief Retrieve the previous declaration of this function template, or + /// NULL if no such declaration exists. + const TypeAliasTemplateDecl *getPreviousDeclaration() const { + return redeclarable_base::getPreviousDeclaration(); + } + + TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() { + return redeclarable_base::getInstantiatedFromMemberTemplate(); + } + + + /// \brief Create a function template node. + static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + DeclarationName Name, + TemplateParameterList *Params, + NamedDecl *Decl); + + /// \brief Create an empty alias template node. + static TypeAliasTemplateDecl *Create(ASTContext &C, EmptyShell); + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypeAliasTemplateDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TypeAliasTemplate; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + /// Implementation of inline functions that require the template declarations inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) : Function(FTD) { } diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 930d19373c..33171bd003 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1368,6 +1368,11 @@ DEF_TRAVERSE_DECL(TypeAliasDecl, { // source. }) +DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, { + TRY_TO(TraverseDecl(D->getTemplatedDecl())); + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); + }) + DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { // A dependent using declaration which was marked with 'typename'. // template<class T> class A : public B<T> { using typename B<T>::foo; }; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 975a66fefa..c1c60c0c2e 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -3201,6 +3201,10 @@ public: /// Other template specialization types, for which the template name /// is dependent, may be canonical types. These types are always /// dependent. +/// +/// An instance of this type is followed by an array of TemplateArgument*s, +/// then, if the template specialization type is for a type alias template, +/// a QualType representing the non-canonical aliased type. class TemplateSpecializationType : public Type, public llvm::FoldingSetNode { /// \brief The name of the template being specialized. @@ -3212,7 +3216,8 @@ class TemplateSpecializationType TemplateSpecializationType(TemplateName T, const TemplateArgument *Args, - unsigned NumArgs, QualType Canon); + unsigned NumArgs, QualType Canon, + QualType Aliased); friend class ASTContext; // ASTContext creates these @@ -3247,6 +3252,16 @@ public: return isa<InjectedClassNameType>(getCanonicalTypeInternal()); } + /// True if this template specialization type is for a type alias + /// template. + bool isTypeAlias() const; + /// Get the aliased type, if this is a specialization of a type alias + /// template. + QualType getAliasedType() const { + assert(isTypeAlias() && "not a type alias template specialization"); + return *reinterpret_cast<const QualType*>(end()); + } + typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } @@ -3268,12 +3283,14 @@ public: const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h bool isSugared() const { - return !isDependentType() || isCurrentInstantiation(); + return !isDependentType() || isCurrentInstantiation() || isTypeAlias(); } QualType desugar() const { return getCanonicalTypeInternal(); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { Profile(ID, Template, getArgs(), NumArgs, Ctx); + if (isTypeAlias()) + getAliasedType().Profile(ID); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 9e69492e13..ddd08278c3 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -50,6 +50,7 @@ def Named : Decl<1>; def RedeclarableTemplate : DDecl<Template, 1>; def FunctionTemplate : DDecl<RedeclarableTemplate>; def ClassTemplate : DDecl<RedeclarableTemplate>; + def TypeAliasTemplate : DDecl<RedeclarableTemplate>; def TemplateTemplateParm : DDecl<Template>; def Using : DDecl<Named>; def UsingShadow : DDecl<Named>; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index e2ffe109c8..3a8a708afa 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -443,6 +443,8 @@ def ext_alias_declaration : ExtWarn< "alias declarations accepted as a C++0x extension">, InGroup<CXX0x>; def err_alias_declaration_not_identifier : Error< "name defined in alias declaration must be an identifier">; +def err_alias_declaration_specialization : Error< + "%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">; // C++0x override control def ext_override_control_keyword : Extension< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 26dfc88496..8b73f90126 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -544,6 +544,8 @@ def err_type_defined_in_result_type : Error< "%0 can not be defined in the result type of a function">; def err_type_defined_in_param_type : Error< "%0 can not be defined in a parameter type">; +def err_type_defined_in_alias_template : Error< + "%0 can not be defined in a type alias template">; def note_pure_virtual_function : Note< "unimplemented pure virtual method %0 in %1">; @@ -1674,7 +1676,7 @@ def err_template_arg_must_be_expr : Error< def err_template_arg_nontype_ambig : Error< "template argument for non-type template parameter is treated as type %0">; def err_template_arg_must_be_template : Error< - "template argument for template template parameter must be a class template">; + "template argument for template template parameter must be a class template%select{| or type alias template}0">; def ext_template_arg_local_type : ExtWarn< "template argument uses local type %0">, InGroup<LocalTypeTemplateArgs>; def ext_template_arg_unnamed_type : ExtWarn< @@ -1820,6 +1822,8 @@ def err_template_spec_needs_template_parameters : Error< def err_template_param_list_matches_nontemplate : Error< "template parameter list matching the non-templated nested type %0 should " "be empty ('template<>')">; +def err_alias_template_extra_headers : Error< + "extraneous template parameter list in alias template declaration">; def err_template_spec_extra_headers : Error< "extraneous template parameter list in template specialization or " "out-of-line template definition">; @@ -1897,6 +1901,8 @@ def note_function_template_spec_here : Note< "in instantiation of function template specialization %q0 requested here">; def note_template_static_data_member_def_here : Note< "in instantiation of static data member %q0 requested here">; +def note_template_type_alias_instantiation_here : Note< + "in instantiation of template type alias %0 requested here">; def note_default_arg_instantiation_here : Note< "in instantiation of default argument for '%0' required here">; @@ -2034,7 +2040,7 @@ def err_non_type_template_in_nested_name_specifier : Error< def err_template_id_not_a_type : Error< "template name refers to non-type template '%0'">; def note_template_declared_here : Note< - "%select{function template|class template|template template parameter}0 " + "%select{function template|class template|type alias template|template template parameter}0 " "%1 declared here">; // C++0x Variadic Templates @@ -2172,9 +2178,9 @@ def err_redefinition_different_type : Error< def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; def err_redefinition_different_typedef : Error< - "%select{typedef|type alias}0 redefinition with different types (%1 vs %2)">; + "%select{typedef|type alias|type alias template}0 redefinition with different types (%1 vs %2)">; def err_tag_reference_non_tag : Error< - "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template}0">; + "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template}0">; def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with " "%select{a declaration|a typedef|a type alias|a template}0 of the same name">; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 708c9b2084..8179b63f45 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1332,7 +1332,8 @@ public: CXXCatchContext, // C++ catch exception-declaration BlockLiteralContext, // Block literal declarator. TemplateTypeArgContext, // Template type argument. - AliasDeclContext // C++0x alias-declaration. + AliasDeclContext, // C++0x alias-declaration. + AliasTemplateContext // C++0x alias-declaration template. }; private: @@ -1474,6 +1475,7 @@ public: case TypeNameContext: case AliasDeclContext: + case AliasTemplateContext: case PrototypeContext: case ObjCPrototypeContext: case TemplateParamContext: @@ -1503,6 +1505,7 @@ public: case TypeNameContext: case AliasDeclContext: + case AliasTemplateContext: case ObjCPrototypeContext: case BlockLiteralContext: case TemplateTypeArgContext: @@ -1531,6 +1534,7 @@ public: case CXXCatchContext: case TypeNameContext: case AliasDeclContext: + case AliasTemplateContext: case BlockLiteralContext: case TemplateTypeArgContext: return false; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index fee483b7f9..4f8a61570e 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -944,6 +944,7 @@ public: void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); void CheckCastAlign(Expr *Op, QualType T, SourceRange TRange); + void CheckTypedefForVariablyModifiedType(Scope *S, TypedefNameDecl *D); NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, bool &Redeclaration); @@ -1652,6 +1653,10 @@ public: AssociatedNamespaceSet &AssociatedNamespaces, AssociatedClassSet &AssociatedClasses); + void FilterLookupForScope(LookupResult &R, DeclContext *Ctx, Scope *S, + bool ConsiderLinkage, + bool ExplicitInstantiationOrSpecialization); + bool DiagnoseAmbiguousLookup(LookupResult &Result); //@} @@ -2468,6 +2473,7 @@ public: SourceLocation TypenameLoc); Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, + MultiTemplateParamsArg TemplateParams, SourceLocation UsingLoc, UnqualifiedId &Name, TypeResult Type); @@ -3412,7 +3418,8 @@ public: TPC_FunctionTemplate, TPC_ClassTemplateMember, TPC_FriendFunctionTemplate, - TPC_FriendFunctionTemplateDefinition + TPC_FriendFunctionTemplateDefinition, + TPC_TypeAliasTemplate }; bool CheckTemplateParameterList(TemplateParameterList *NewParams, diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index 4d97f9bef8..a257772ee1 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -335,9 +335,9 @@ namespace clang { Decl *VisitLabelDecl(LabelDecl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); Decl *VisitNamespaceAliasDecl(NamespaceAliasDecl *D); - Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); Decl *VisitTypedefDecl(TypedefDecl *D); Decl *VisitTypeAliasDecl(TypeAliasDecl *D); + Decl *VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); Decl *VisitVarDecl(VarDecl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitFieldDecl(FieldDecl *D); @@ -415,6 +415,7 @@ namespace clang { bool SubstQualifier(const TagDecl *OldDecl, TagDecl *NewDecl); + Decl *InstantiateTypedefNameDecl(TypedefNameDecl *D, bool IsTypeAlias); ClassTemplatePartialSpecializationDecl * InstantiateClassTemplatePartialSpecialization( ClassTemplateDecl *ClassTemplate, diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 7b9e98d343..0b997563f9 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -761,6 +761,8 @@ namespace clang { DECL_NON_TYPE_TEMPLATE_PARM, /// \brief A TemplateTemplateParmDecl record. DECL_TEMPLATE_TEMPLATE_PARM, + /// \brief A TypeAliasTemplateDecl record. + DECL_TYPE_ALIAS_TEMPLATE, /// \brief A StaticAssertDecl record. DECL_STATIC_ASSERT, /// \brief A record containing CXXBaseSpecifiers. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index d6535e9f8c..a5ff664449 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -969,13 +969,18 @@ ASTContext::getTypeInfo(const Type *T) const { return getTypeInfo( cast<AttributedType>(T)->getEquivalentType().getTypePtr()); - case Type::TemplateSpecialization: + case Type::TemplateSpecialization: { assert(getCanonicalType(T) != T && "Cannot request the size of a dependent type"); - // FIXME: this is likely to be wrong once we support template - // aliases, since a template alias could refer to a typedef that - // has an __aligned__ attribute on it. - return getTypeInfo(getCanonicalType(T)); + const TemplateSpecializationType *TST = cast<TemplateSpecializationType>(T); + // A type alias template specialization may refer to a typedef with the + // aligned attribute on it. + if (TST->isTypeAlias()) + return getTypeInfo(TST->getAliasedType().getTypePtr()); + else + return getTypeInfo(getCanonicalType(T)); + } + } assert(Align && (Align & (Align-1)) == 0 && "Alignment must be power of 2"); @@ -2247,10 +2252,10 @@ TypeSourceInfo * ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, SourceLocation NameLoc, const TemplateArgumentListInfo &Args, - QualType CanonType) const { + QualType Underlying) const { assert(!Name.getAsDependentTemplateName() && "No dependent template names here!"); - QualType TST = getTemplateSpecializationType(Name, Args, CanonType); + QualType TST = getTemplateSpecializationType(Name, Args, Underlying); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); TemplateSpecializationTypeLoc TL @@ -2266,7 +2271,7 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, QualType ASTContext::getTemplateSpecializationType(TemplateName Template, const TemplateArgumentListInfo &Args, - QualType Canon) const { + QualType Underlying) const { assert(!Template.getAsDependentTemplateName() && "No dependent template names here!"); @@ -2278,35 +2283,46 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, ArgVec.push_back(Args[i].getArgument()); return getTemplateSpecializationType(Template, ArgVec.data(), NumArgs, - Canon); |