From: Richard Smith Date: Fri, 15 Apr 2011 14:24:37 +0000 (+0000) Subject: Support for C++11 (non-template) alias declarations. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=162e1c1b487352434552147967c3dd296ebee2f7;p=clang Support for C++11 (non-template) alias declarations. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129567 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 4d93afd105..715a360c4b 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -1101,10 +1101,12 @@ enum CXCursorKind { CXCursor_NamespaceAlias = 33, /** \brief A C++ using directive. */ CXCursor_UsingDirective = 34, - /** \brief A using declaration. */ + /** \brief A C++ using declaration. */ CXCursor_UsingDeclaration = 35, + /** \brief A C++ alias declaration */ + CXCursor_TypeAliasDecl = 36, CXCursor_FirstDecl = CXCursor_UnexposedDecl, - CXCursor_LastDecl = CXCursor_UsingDeclaration, + CXCursor_LastDecl = CXCursor_TypeAliasDecl, /* References */ CXCursor_FirstRef = 40, /* Decl references */ diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 7a62af7eea..63d6d0096b 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -71,7 +71,7 @@ namespace clang { class TemplateTypeParmDecl; class TranslationUnitDecl; class TypeDecl; - class TypedefDecl; + class TypedefNameDecl; class UsingDecl; class UsingShadowDecl; class UnresolvedSetIterator; @@ -664,9 +664,9 @@ public: } /// getTypedefType - Return the unique reference to the type for the - /// specified typename decl. - QualType getTypedefType(const TypedefDecl *Decl, QualType Canon = QualType()) - const; + /// specified typedef-name decl. + QualType getTypedefType(const TypedefNameDecl *Decl, + QualType Canon = QualType()) const; QualType getRecordType(const RecordDecl *Decl) const; diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 44b04dfa1f..9255b280d6 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -1995,17 +1995,21 @@ public: }; -class TypedefDecl : public TypeDecl, public Redeclarable { +/// Base class for declarations which introduce a typedef-name. +class TypedefNameDecl : public TypeDecl, public Redeclarable { /// UnderlyingType - This is the type the typedef is set to. TypeSourceInfo *TInfo; - TypedefDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypeDecl(Typedef, DC, IdLoc, Id, StartLoc), TInfo(TInfo) {} - protected: - typedef Redeclarable redeclarable_base; - virtual TypedefDecl *getNextRedeclaration() { return RedeclLink.getNext(); } + TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + TypeSourceInfo *TInfo) + : TypeDecl(DK, DC, IdLoc, Id, StartLoc), TInfo(TInfo) {} + + typedef Redeclarable redeclarable_base; + virtual TypedefNameDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } public: typedef redeclarable_base::redecl_iterator redecl_iterator; @@ -2016,19 +2020,15 @@ public: return redeclarable_base::redecls_end(); } - static TypedefDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, TypeSourceInfo *TInfo); - TypeSourceInfo *getTypeSourceInfo() const { return TInfo; } - /// Retrieves the canonical declaration of this typedef. - TypedefDecl *getCanonicalDecl() { + /// Retrieves the canonical declaration of this typedef-name. + TypedefNameDecl *getCanonicalDecl() { return getFirstDeclaration(); } - const TypedefDecl *getCanonicalDecl() const { + const TypedefNameDecl *getCanonicalDecl() const { return getFirstDeclaration(); } @@ -2039,6 +2039,26 @@ public: TInfo = newType; } + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypedefNameDecl *D) { return true; } + static bool classofKind(Kind K) { + return K >= firstTypedefName && K <= lastTypedefName; + } +}; + +/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' +/// type specifier. +class TypedefDecl : public TypedefNameDecl { + TypedefDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(Typedef, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypedefDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + SourceRange getSourceRange() const; // Implement isa/cast/dyncast/etc. @@ -2047,6 +2067,26 @@ public: static bool classofKind(Kind K) { return K == Typedef; } }; +/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x +/// alias-declaration. +class TypeAliasDecl : public TypedefNameDecl { + TypeAliasDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo) + : TypedefNameDecl(TypeAlias, DC, StartLoc, IdLoc, Id, TInfo) {} + +public: + static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, TypeSourceInfo *TInfo); + + SourceRange getSourceRange() const; + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classof(const TypeAliasDecl *D) { return true; } + static bool classofKind(Kind K) { return K == TypeAlias; } +}; + /// TagDecl - Represents the declaration of a struct/union/class/enum. class TagDecl : public TypeDecl, public DeclContext, public Redeclarable { @@ -2096,17 +2136,17 @@ private: // to be used for the (uncommon) case of out-of-line declarations. typedef QualifierInfo ExtInfo; - /// TypedefDeclOrQualifier - If the (out-of-line) tag declaration name + /// TypedefNameDeclOrQualifier - If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); /// otherwise, if the tag declaration is anonymous and it is part of - /// a typedef, it points to the TypedefDecl (used for mangling); - /// otherwise, it is a null (TypedefDecl) pointer. - llvm::PointerUnion TypedefDeclOrQualifier; + /// a typedef or alias, it points to the TypedefNameDecl (used for mangling); + /// otherwise, it is a null (TypedefNameDecl) pointer. + llvm::PointerUnion TypedefNameDeclOrQualifier; - bool hasExtInfo() const { return TypedefDeclOrQualifier.is(); } - ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get(); } + bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is(); } + ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get(); } const ExtInfo *getExtInfo() const { - return TypedefDeclOrQualifier.get(); + return TypedefNameDeclOrQualifier.get(); } protected: @@ -2114,7 +2154,7 @@ protected: SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl, SourceLocation StartL) : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), - TypedefDeclOrQualifier((TypedefDecl*) 0) { + TypedefNameDeclOrQualifier((TypedefNameDecl*) 0) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); TagDeclKind = TK; @@ -2219,11 +2259,11 @@ public: bool isUnion() const { return getTagKind() == TTK_Union; } bool isEnum() const { return getTagKind() == TTK_Enum; } - TypedefDecl *getTypedefForAnonDecl() const { - return hasExtInfo() ? 0 : TypedefDeclOrQualifier.get(); + TypedefNameDecl *getTypedefNameForAnonDecl() const { + return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get(); } - void setTypedefForAnonDecl(TypedefDecl *TDD); + void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); /// \brief Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index d4a90fbefd..0b3993d88e 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -1357,6 +1357,13 @@ DEF_TRAVERSE_DECL(TypedefDecl, { // source. }) +DEF_TRAVERSE_DECL(TypeAliasDecl, { + TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); + // We shouldn't traverse D->getTypeForDecl(); it's a result of + // declaring the type alias, not something that was written in the + // source. + }) + DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, { // A dependent using declaration which was marked with 'typename'. // template class A : public B { using typename B::foo; }; diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index e74a9c9dd6..5d1588726b 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -73,7 +73,7 @@ namespace llvm { namespace clang { class ASTContext; - class TypedefDecl; + class TypedefNameDecl; class TemplateDecl; class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; @@ -2625,18 +2625,18 @@ public: class TypedefType : public Type { - TypedefDecl *Decl; + TypedefNameDecl *Decl; protected: - TypedefType(TypeClass tc, const TypedefDecl *D, QualType can) + TypedefType(TypeClass tc, const TypedefNameDecl *D, QualType can) : Type(tc, can, can->isDependentType(), can->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false), - Decl(const_cast(D)) { + Decl(const_cast(D)) { assert(!isa(can) && "Invalid canonical type"); } friend class ASTContext; // ASTContext creates these. public: - TypedefDecl *getDecl() const { return Decl; } + TypedefNameDecl *getDecl() const { return Decl; } bool isSugared() const { return true; } QualType desugar() const; diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 8c97a4225b..d1ce52b3dd 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -527,7 +527,7 @@ class TypedefTypeLoc : public InheritingConcreteTypeLoc { public: - TypedefDecl *getTypedefDecl() const { + TypedefNameDecl *getTypedefNameDecl() const { return getTypePtr()->getDecl(); } }; diff --git a/include/clang/Basic/DeclNodes.td b/include/clang/Basic/DeclNodes.td index 2ec7427cf7..9e69492e13 100644 --- a/include/clang/Basic/DeclNodes.td +++ b/include/clang/Basic/DeclNodes.td @@ -17,7 +17,9 @@ def Named : Decl<1>; def NamespaceAlias : DDecl; def Label : DDecl; def Type : DDecl; - def Typedef : DDecl; + def TypedefName : DDecl; + def Typedef : DDecl; + def TypeAlias : DDecl; def UnresolvedUsingTypename : DDecl; def Tag : DDecl, DeclContext; def Enum : DDecl; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 26cb8e14d6..09ac5fe02f 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -430,6 +430,12 @@ def err_missing_whitespace_digraph : Error< def warn_deleted_function_accepted_as_extension: ExtWarn< "deleted function definition accepted as a C++0x extension">, InGroup; +// C++0x alias-declaration +def ext_alias_declaration : ExtWarn< + "alias declarations accepted as a C++0x extension">, InGroup; +def err_alias_declaration_not_identifier : Error< + "name defined in alias declaration must be an identifier">; + // C++0x override control def ext_override_control_keyword : Extension< "'%0' keyword accepted as a C++0x extension">, InGroup; diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index bddfff2f6e..747a657a4b 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -545,7 +545,7 @@ def ext_using_undefined_std : ExtWarn< // C++ exception specifications def err_exception_spec_in_typedef : Error< - "exception specifications are not allowed in typedefs">; + "exception specifications are not allowed in %select{typedefs|type aliases}0">; def err_distant_exception_spec : Error< "exception specifications are not allowed beyond a single level " "of indirection">; @@ -795,7 +795,7 @@ def err_destructor_redeclared : Error<"destructor cannot be redeclared">; def err_destructor_with_params : Error<"destructor cannot have any parameters">; def err_destructor_variadic : Error<"destructor cannot be variadic">; def err_destructor_typedef_name : Error< - "destructor cannot be declared using a typedef %0 of the class name">; + "destructor cannot be declared using a %select{typedef|type alias}1 %0 of the class name">; def err_destructor_name : Error< "expected the class name after '~' to name the enclosing class">; def err_destructor_class_name : Error< @@ -932,7 +932,7 @@ def err_auto_not_allowed : Error< "'auto' not allowed %select{in function prototype|in struct member" "|in union member|in class member|in exception declaration" "|in template parameter|in block literal|in template argument" - "|in typedef|in function return type|here}0">; + "|in typedef|in type alias|in function return type|here}0">; def err_auto_var_requires_init : Error< "declaration of variable %0 with type %1 requires an initializer">; def err_auto_new_requires_ctor_arg : Error< @@ -1321,7 +1321,7 @@ def err_ident_list_in_fn_declaration : Error< def ext_param_not_declared : Extension< "parameter %0 was not declared, defaulting to type 'int'">; def err_param_typedef_of_void : Error< - "empty parameter list defined with a typedef of 'void' not allowed in C++">; + "empty parameter list defined with a %select{typedef|type alias}0 of 'void' not allowed%select{ in C++|}0">; def err_param_default_argument : Error< "C does not support default arguments">; def err_param_default_argument_redefinition : Error< @@ -2133,17 +2133,17 @@ 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< - "typedef redefinition with different types (%0 vs %1)">; + "%select{typedef|type alias}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 template}0">; + "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template}0">; def err_tag_reference_conflict : Error< "implicit declaration introduced by elaborated type conflicts with " - "%select{a declaration|a typedef|a template}0 of the same name">; + "%select{a declaration|a typedef|a type alias|a template}0 of the same name">; def err_dependent_tag_decl : Error< "%select{declaration|definition}0 of %select{struct|union|class|enum}1 " "in a dependent scope">; def err_tag_definition_of_typedef : Error< - "definition of type %0 conflicts with typedef of the same name">; + "definition of type %0 conflicts with %select{typedef|type alias}1 of the same name">; def err_conflicting_types : Error<"conflicting types for %0">; def err_nested_redefinition : Error<"nested redefinition of %0">; def err_use_with_wrong_tag : Error< @@ -2295,6 +2295,8 @@ def note_protected_by_cleanup : Note< "jump bypasses initialization of variable with __attribute__((cleanup))">; def note_protected_by_vla_typedef : Note< "jump bypasses initialization of VLA typedef">; +def note_protected_by_vla_type_alias : Note< + "jump bypasses initialization of VLA type alias">; def note_protected_by_vla : Note< "jump bypasses initialization of variable length array">; def note_protected_by_objc_try : Note< diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 08d0d00cbf..1f67292f15 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1325,7 +1325,8 @@ public: TemplateParamContext,// Within a template parameter list. CXXCatchContext, // C++ catch exception-declaration BlockLiteralContext, // Block literal declarator. - TemplateTypeArgContext // Template type argument. + TemplateTypeArgContext, // Template type argument. + AliasDeclContext // C++0x alias-declaration. }; private: @@ -1466,6 +1467,7 @@ public: return false; case TypeNameContext: + case AliasDeclContext: case PrototypeContext: case ObjCPrototypeContext: case TemplateParamContext: @@ -1494,6 +1496,7 @@ public: return true; case TypeNameContext: + case AliasDeclContext: case ObjCPrototypeContext: case BlockLiteralContext: case TemplateTypeArgContext: @@ -1521,6 +1524,7 @@ public: case TemplateParamContext: case CXXCatchContext: case TypeNameContext: + case AliasDeclContext: case BlockLiteralContext: case TemplateTypeArgContext: return false; diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index f9d7d9aecd..df3c6643e3 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -128,7 +128,9 @@ namespace clang { class TemplatePartialOrderingContext; class TemplateTemplateParmDecl; class Token; + class TypeAliasDecl; class TypedefDecl; + class TypedefNameDecl; class TypeLoc; class UnqualifiedId; class UnresolvedLookupExpr; @@ -255,7 +257,7 @@ public: /// ExtVectorDecls - This is a list all the extended vector types. This allows /// us to associate a raw vector type with one of the ext_vector type names. /// This is only necessary for issuing pretty diagnostics. - llvm::SmallVector ExtVectorDecls; + llvm::SmallVector ExtVectorDecls; /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. llvm::OwningPtr FieldCollector; @@ -814,6 +816,7 @@ public: void RegisterLocallyScopedExternCDecl(NamedDecl *ND, const LookupResult &Previous, Scope *S); + bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); void DiagnoseFunctionSpecifiers(Declarator& D); void CheckShadow(Scope *S, VarDecl *D, const LookupResult& R); void CheckShadow(Scope *S, VarDecl *D); @@ -821,6 +824,8 @@ public: NamedDecl* ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, bool &Redeclaration); + NamedDecl* ActOnTypedefNameDecl(Scope* S, DeclContext* DC, TypedefNameDecl *D, + LookupResult &Previous, bool &Redeclaration); NamedDecl* ActOnVariableDeclarator(Scope* S, Declarator& D, DeclContext* DC, QualType R, TypeSourceInfo *TInfo, LookupResult &Previous, @@ -1076,7 +1081,7 @@ public: /// Subroutines of ActOnDeclarator(). TypedefDecl *ParseTypedefDecl(Scope *S, Declarator &D, QualType T, TypeSourceInfo *TInfo); - void MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls); + void MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls); bool MergeFunctionDecl(FunctionDecl *New, Decl *Old); bool MergeCompatibleFunctionDecls(FunctionDecl *New, FunctionDecl *Old); void mergeObjCMethodDecls(ObjCMethodDecl *New, const ObjCMethodDecl *Old); @@ -2309,6 +2314,11 @@ public: AttributeList *AttrList, bool IsTypeName, SourceLocation TypenameLoc); + Decl *ActOnAliasDeclaration(Scope *CurScope, + AccessSpecifier AS, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type); /// AddCXXDirectInitializerToDecl - This action is called immediately after /// ActOnDeclarator, when a C++ direct initializer is present. diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index 53f4a9d8c8..4d97f9bef8 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -335,7 +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 *VisitVarDecl(VarDecl *D); Decl *VisitAccessSpecDecl(AccessSpecDecl *D); Decl *VisitFieldDecl(FieldDecl *D); diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index e00fb3ae8b..4df6a29c1b 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -642,6 +642,8 @@ namespace clang { DECL_TRANSLATION_UNIT = 50, /// \brief A TypedefDecl record. DECL_TYPEDEF, + /// \brief A TypeAliasDecl record. + DECL_TYPEALIAS, /// \brief An EnumDecl record. DECL_ENUM, /// \brief A RecordDecl record. diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 849f349e18..f723f2a8b7 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -907,7 +907,7 @@ ASTContext::getTypeInfo(const Type *T) const { return getTypeInfo(cast(T)->getInnerType().getTypePtr()); case Type::Typedef: { - const TypedefDecl *Typedef = cast(T)->getDecl(); + const TypedefNameDecl *Typedef = cast(T)->getDecl(); std::pair Info = getTypeInfo(Typedef->getUnderlyingType().getTypePtr()); // If the typedef has an aligned attribute on it, it overrides any computed @@ -2032,7 +2032,7 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { assert(Decl && "Passed null for Decl param"); assert(!Decl->TypeForDecl && "TypeForDecl present in slow case"); - if (const TypedefDecl *Typedef = dyn_cast(Decl)) + if (const TypedefNameDecl *Typedef = dyn_cast(Decl)) return getTypedefType(Typedef); assert(!isa(Decl) && @@ -2059,9 +2059,10 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { } /// getTypedefType - Return the unique reference to the type for the -/// specified typename decl. +/// specified typedef name decl. QualType -ASTContext::getTypedefType(const TypedefDecl *Decl, QualType Canonical) const { +ASTContext::getTypedefType(const TypedefNameDecl *Decl, + QualType Canonical) const { if (Decl->TypeForDecl) return QualType(Decl->TypeForDecl, 0); if (Canonical.isNull()) @@ -4577,7 +4578,7 @@ CanQualType ASTContext::getFromTargetType(unsigned Type) const { /// bool ASTContext::isObjCNSObjectType(QualType Ty) const { if (const TypedefType *TDT = dyn_cast(Ty)) { - if (TypedefDecl *TD = TDT->getDecl()) + if (TypedefNameDecl *TD = TDT->getDecl()) if (TD->getAttr()) return true; } diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index b7b9df55e3..897b4a4c1f 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -100,7 +100,7 @@ break; \ // Don't desugar through the primary typedef of an anonymous type. if (const TagType *UTT = Underlying->getAs()) if (const TypedefType *QTT = dyn_cast(QT)) - if (UTT->getDecl()->getTypedefForAnonDecl() == QTT->getDecl()) + if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl()) break; // Record that we actually looked through an opaque type here. diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 2179c950a4..2b15904fdb 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -97,7 +97,9 @@ namespace { bool IsStructuralMatch(ClassTemplateDecl *From, ClassTemplateDecl *To); Decl *VisitDecl(Decl *D); Decl *VisitNamespaceDecl(NamespaceDecl *D); + Decl *VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias); Decl *VisitTypedefDecl(TypedefDecl *D); + Decl *VisitTypeAliasDecl(TypeAliasDecl *D); Decl *VisitEnumDecl(EnumDecl *D); Decl *VisitRecordDecl(RecordDecl *D); Decl *VisitEnumConstantDecl(EnumConstantDecl *D); @@ -1194,11 +1196,11 @@ bool StructuralEquivalenceContext::Finish() { if (RecordDecl *Record2 = dyn_cast(D2)) { // Check for equivalent structure names. IdentifierInfo *Name1 = Record1->getIdentifier(); - if (!Name1 && Record1->getTypedefForAnonDecl()) - Name1 = Record1->getTypedefForAnonDecl()->getIdentifier(); + if (!Name1 && Record1->getTypedefNameForAnonDecl()) + Name1 = Record1->getTypedefNameForAnonDecl()->getIdentifier(); IdentifierInfo *Name2 = Record2->getIdentifier(); - if (!Name2 && Record2->getTypedefForAnonDecl()) - Name2 = Record2->getTypedefForAnonDecl()->getIdentifier(); + if (!Name2 && Record2->getTypedefNameForAnonDecl()) + Name2 = Record2->getTypedefNameForAnonDecl()->getIdentifier(); if (!::IsStructurallyEquivalent(Name1, Name2) || !::IsStructurallyEquivalent(*this, Record1, Record2)) Equivalent = false; @@ -1210,11 +1212,11 @@ bool StructuralEquivalenceContext::Finish() { if (EnumDecl *Enum2 = dyn_cast(D2)) { // Check for equivalent enum names. IdentifierInfo *Name1 = Enum1->getIdentifier(); - if (!Name1 && Enum1->getTypedefForAnonDecl()) - Name1 = Enum1->getTypedefForAnonDecl()->getIdentifier(); + if (!Name1 && Enum1->getTypedefNameForAnonDecl()) + Name1 = Enum1->getTypedefNameForAnonDecl()->getIdentifier(); IdentifierInfo *Name2 = Enum2->getIdentifier(); - if (!Name2 && Enum2->getTypedefForAnonDecl()) - Name2 = Enum2->getTypedefForAnonDecl()->getIdentifier(); + if (!Name2 && Enum2->getTypedefNameForAnonDecl()) + Name2 = Enum2->getTypedefNameForAnonDecl()->getIdentifier(); if (!::IsStructurallyEquivalent(Name1, Name2) || !::IsStructurallyEquivalent(*this, Enum1, Enum2)) Equivalent = false; @@ -1222,8 +1224,8 @@ bool StructuralEquivalenceContext::Finish() { // Enum/non-enum mismatch Equivalent = false; } - } else if (TypedefDecl *Typedef1 = dyn_cast(D1)) { - if (TypedefDecl *Typedef2 = dyn_cast(D2)) { + } else if (TypedefNameDecl *Typedef1 = dyn_cast(D1)) { + if (TypedefNameDecl *Typedef2 = dyn_cast(D2)) { if (!::IsStructurallyEquivalent(Typedef1->getIdentifier(), Typedef2->getIdentifier()) || !::IsStructurallyEquivalent(*this, @@ -1536,8 +1538,8 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { } QualType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { - TypedefDecl *ToDecl - = dyn_cast_or_null(Importer.Import(T->getDecl())); + TypedefNameDecl *ToDecl + = dyn_cast_or_null(Importer.Import(T->getDecl())); if (!ToDecl) return QualType(); @@ -1995,7 +1997,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { return ToNamespace; } -Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { +Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. DeclContext *DC, *LexicalDC; DeclarationName Name; @@ -2014,7 +2016,8 @@ Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { ++Lookup.first) { if (!(*Lookup.first)->isInIdentifierNamespace(IDNS)) continue; - if (TypedefDecl *FoundTypedef = dyn_cast(*Lookup.first)) { + if (TypedefNameDecl *FoundTypedef = + dyn_cast(*Lookup.first)) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) return Importer.Imported(D, FoundTypedef); @@ -2040,10 +2043,17 @@ Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { // Create the new typedef node. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); SourceLocation StartL = Importer.Import(D->getLocStart()); - TypedefDecl *ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, - StartL, Loc, - Name.getAsIdentifierInfo(), - TInfo); + TypedefNameDecl *ToTypedef; + if (IsAlias) + ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, + StartL, Loc, + Name.getAsIdentifierInfo(), + TInfo); + else + ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, + StartL, Loc, + Name.getAsIdentifierInfo(), + TInfo); ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToTypedef); @@ -2052,6 +2062,14 @@ Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { return ToTypedef; } +Decl *ASTNodeImporter::VisitTypedefDecl(TypedefDecl *D) { + return VisitTypedefNameDecl(D, /*IsAlias=*/false); +} + +Decl *ASTNodeImporter::VisitTypeAliasDecl(TypeAliasDecl *D) { + return VisitTypedefNameDecl(D, /*IsAlias=*/true); +} + Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the major distinguishing characteristics of this enum. DeclContext *DC, *LexicalDC; @@ -2063,8 +2081,8 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Figure out what enum name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; - if (!SearchName && D->getTypedefForAnonDecl()) { - SearchName = Importer.Import(D->getTypedefForAnonDecl()->getDeclName()); + if (!SearchName && D->getTypedefNameForAnonDecl()) { + SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOptions().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; @@ -2079,7 +2097,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { continue; Decl *Found = *Lookup.first; - if (TypedefDecl *Typedef = dyn_cast(Found)) { + if (TypedefNameDecl *Typedef = dyn_cast(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs()) Found = Tag->getDecl(); } @@ -2164,8 +2182,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { // Figure out what structure name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; - if (!SearchName && D->getTypedefForAnonDecl()) { - SearchName = Importer.Import(D->getTypedefForAnonDecl()->getDeclName()); + if (!SearchName && D->getTypedefNameForAnonDecl()) { + SearchName = Importer.Import(D->getTypedefNameForAnonDecl()->getDeclName()); IDNS = Decl::IDNS_Ordinary; } else if (Importer.getToContext().getLangOptions().CPlusPlus) IDNS |= Decl::IDNS_Ordinary; @@ -2181,7 +2199,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { continue; Decl *Found = *Lookup.first; - if (TypedefDecl *Typedef = dyn_cast(Found)) { + if (TypedefNameDecl *Typedef = dyn_cast(Found)) { if (const TagType *Tag = Typedef->getUnderlyingType()->getAs()) Found = Tag->getDecl(); } @@ -3997,19 +4015,19 @@ Decl *ASTImporter::Import(Decl *FromD) { if (TagDecl *FromTag = dyn_cast(FromD)) { // Keep track of anonymous tags that have an associated typedef. - if (FromTag->getTypedefForAnonDecl()) + if (FromTag->getTypedefNameForAnonDecl()) AnonTagsWithPendingTypedefs.push_back(FromTag); - } else if (TypedefDecl *FromTypedef = dyn_cast(FromD)) { + } else if (TypedefNameDecl *FromTypedef = dyn_cast(FromD)) { // When we've finished transforming a typedef, see whether it was the // typedef for an anonymous tag. for (llvm::SmallVector::iterator FromTag = AnonTagsWithPendingTypedefs.begin(), FromTagEnd = AnonTagsWithPendingTypedefs.end(); FromTag != FromTagEnd; ++FromTag) { - if ((*FromTag)->getTypedefForAnonDecl() == FromTypedef) { + if ((*FromTag)->getTypedefNameForAnonDecl() == FromTypedef) { if (TagDecl *ToTag = cast_or_null(Import(*FromTag))) { // We found the typedef for an anonymous tag; link them. - ToTag->setTypedefForAnonDecl(cast(ToD)); + ToTag->setTypedefNameForAnonDecl(cast(ToD)); AnonTagsWithPendingTypedefs.erase(FromTag); break; } diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index ca9ec18b39..9ffe1f8656 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -415,7 +415,7 @@ FindNestedNameSpecifierMember(const CXXBaseSpecifier *Specifier, Path.Decls.first != Path.Decls.second; ++Path.Decls.first) { // FIXME: Refactor the "is it a nested-name-specifier?" check - if (isa(*Path.Decls.first) || + if (isa(*Path.Decls.first) || (*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag)) return true; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 99a180662d..05ea2d239b 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -405,7 +405,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, LVFlags F) { // has the typedef name for linkage purposes (7.1.3); or } else if (const TagDecl *Tag = dyn_cast(D)) { // Unnamed tags have no linkage. - if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) + if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) return LinkageInfo::none(); // If this is a class template specialization, consider the @@ -477,7 +477,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, LVFlags F) { isa(D) || isa(D) || (isa(D) && - (D->getDeclName() || cast(D)->getTypedefForAnonDecl())))) + (D->getDeclName() || cast(D)->getTypedefNameForAnonDecl())))) return LinkageInfo::none(); LinkageInfo LV; @@ -2082,8 +2082,8 @@ TagDecl* TagDecl::getCanonicalDecl() { return getFirstDeclaration(); } -void TagDecl::setTypedefForAnonDecl(TypedefDecl *TDD) { - TypedefDeclOrQualifier = TDD; +void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { + TypedefNameDeclOrQualifier = TDD; if (TypeForDecl) const_cast(TypeForDecl)->ClearLinkageCache(); ClearLinkageCache(); @@ -2131,7 +2131,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (QualifierLoc) { // Make sure the extended qualifier info is allocated. if (!hasExtInfo()) - TypedefDeclOrQualifier = new (getASTContext()) ExtInfo; + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set qualifier info. getExtInfo()->QualifierLoc = QualifierLoc; } @@ -2140,7 +2140,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { getASTContext().Deallocate(getExtInfo()); - TypedefDeclOrQualifier = (TypedefDecl*) 0; + TypedefNameDeclOrQualifier = (TypedefNameDecl*) 0; } else getExtInfo()->QualifierLoc = QualifierLoc; @@ -2155,7 +2155,7 @@ void TagDecl::setTemplateParameterListsInfo(ASTContext &Context, // Make sure the extended decl info is allocated. if (!hasExtInfo()) // Allocate external info struct. - TypedefDeclOrQualifier = new (getASTContext()) ExtInfo; + TypedefNameDeclOrQualifier = new (getASTContext()) ExtInfo; // Set the template parameter lists info. getExtInfo()->setTemplateParameterListsInfo(Context, NumTPLists, TPLists); } @@ -2393,6 +2393,13 @@ TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, return new (C) TypedefDecl(DC, StartLoc, IdLoc, Id, TInfo); } +TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + TypeSourceInfo *TInfo) { + return new (C) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo); +} + SourceRange TypedefDecl::getSourceRange() const { SourceLocation RangeEnd = getLocation(); if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { @@ -2402,6 +2409,13 @@ SourceRange TypedefDecl::getSourceRange() const { return SourceRange(getLocStart(), RangeEnd); } +SourceRange TypeAliasDecl::getSourceRange() const { + SourceLocation RangeEnd = getLocStart(); + if (TypeSourceInfo *TInfo = getTypeSourceInfo()) + RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); + return SourceRange(getLocStart(), RangeEnd); +} + FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, StringLiteral *Str, SourceLocation AsmLoc, diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index c081b0d4a9..673b718ba0 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -427,6 +427,7 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { return IDNS_Ordinary | IDNS_Type; case Typedef: + case TypeAlias: case UnresolvedUsingTypename: case TemplateTypeParm: return IDNS_Ordinary | IDNS_Type; diff --git a/lib/AST/DeclPrinter.cpp b/lib/AST/DeclPrinter.cpp index 87ba5909d9..973ac6d5af 100644 --- a/lib/AST/DeclPrinter.cpp +++ b/lib/AST/DeclPrinter.cpp @@ -45,6 +45,7 @@ namespace { void VisitTranslationUnitDecl(TranslationUnitDecl *D); void VisitTypedefDecl(TypedefDecl *D); + void VisitTypeAliasDecl(TypeAliasDecl *D); void VisitEnumDecl(EnumDecl *D); void VisitRecordDecl(RecordDecl *D); void VisitEnumConstantDecl(EnumConstantDecl *D); @@ -110,7 +111,7 @@ static QualType GetBaseType(QualType T) { } static QualType getDeclType(Decl* D) { - if (TypedefDecl* TDD = dyn_cast(D)) + if (TypedefNameDecl* TDD = dyn_cast(D)) return TDD->getUnderlyingType(); if (ValueDecl* VD = dyn_cast(D)) return VD->getType(); @@ -308,6 +309,11 @@ void DeclPrinter::VisitTypedefDecl(TypedefDecl *D) { Out << S; } +void DeclPrinter::VisitTypeAliasDecl(TypeAliasDecl *D) { + Out << "using " << D->getNameAsString() << " = " + << D->getUnderlyingType().getAsString(Policy); +} + void DeclPrinter::VisitEnumDecl(EnumDecl *D) { Out << "enum "; if (D->isScoped()) { diff --git a/lib/AST/DumpXML.cpp b/lib/AST/DumpXML.cpp index 8355b2d901..7d593bc46f 100644 --- a/lib/AST/DumpXML.cpp +++ b/lib/AST/DumpXML.cpp @@ -543,12 +543,20 @@ struct XMLDumper : public XMLDeclVisitor, // TypedefDecl void visitTypedefDeclAttrs(TypedefDecl *D) { - visitRedeclarableAttrs(D); + visitRedeclarableAttrs(D); } void visitTypedefDeclChildren(TypedefDecl *D) { dispatch(D->getTypeSourceInfo()->getTypeLoc()); } + // TypeAliasDecl + void visitTypeAliasDeclAttrs(TypeAliasDecl *D) { + visitRedeclarableAttrs(D); + } + void visitTypeAliasDeclChildren(TypeAliasDecl *D) { + dispatch(D->getTypeSourceInfo()->getTypeLoc()); + } + // TagDecl void visitTagDeclAttrs(TagDecl *D) { visitRedeclarableAttrs(D); diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp index 2ff1d2db48..6f4edc3894 100644 --- a/lib/AST/ItaniumMangle.cpp +++ b/lib/AST/ItaniumMangle.cpp @@ -748,7 +748,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // We must have an anonymous struct. const TagDecl *TD = cast(ND); - if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { + if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { assert(TD->getDeclContext() == D->getDeclContext() && "Typedef should not be in another decl context!"); assert(D->getDeclName().getAsIdentifierInfo() && diff --git a/lib/AST/MicrosoftMangle.cpp b/lib/AST/MicrosoftMangle.cpp index af7a017664..046c33ddda 100644 --- a/lib/AST/MicrosoftMangle.cpp +++ b/lib/AST/MicrosoftMangle.cpp @@ -314,7 +314,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND, // We must have an anonymous struct. const TagDecl *TD = cast(ND); - if (const TypedefDecl *D = TD->getTypedefForAnonDecl()) { + if (const TypedefNameDecl *D = TD->getTypedefNameForAnonDecl()) { assert(TD->getDeclContext() == D->getDeclContext() && "Typedef should not be in another decl context!"); assert(D->getDeclName().getAsIdentifierInfo() && diff --git a/lib/AST/StmtDumper.cpp b/lib/AST/StmtDumper.cpp index e167441c44..f74556931d 100644 --- a/lib/AST/StmtDumper.cpp +++ b/lib/AST/StmtDumper.cpp @@ -236,6 +236,9 @@ void StmtDumper::DumpDeclarator(Decl *D) { if (TypedefDecl *localType = dyn_cast(D)) { OS << "\"typedef " << localType->getUnderlyingType().getAsString() << ' ' << localType << '"'; + } else if (TypeAliasDecl *localType = dyn_cast(D)) { + OS << "\"using " << localType << " = " + << localType->getUnderlyingType().getAsString() << '"'; } else if (ValueDecl *VD = dyn_cast(D)) { OS << "\""; // Emit storage class for vardecls. diff --git a/lib/AST/StmtIterator.cpp b/lib/AST/StmtIterator.cpp index 9a7265a043..9bf4aeaae8 100644 --- a/lib/AST/StmtIterator.cpp +++ b/lib/AST/StmtIterator.cpp @@ -98,7 +98,7 @@ bool StmtIteratorBase::HandleDecl(Decl* D) { if (VD->getInit()) return true; } - else if (TypedefDecl* TD = dyn_cast(D)) { + else if (TypedefNameDecl* TD = dyn_cast(D)) { if (const VariableArrayType* VAPtr = FindVA(TD->getUnderlyingType().getTypePtr())) { setVAPtr(VAPtr); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 62e17f0448..ba3251b88b 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -1578,7 +1578,7 @@ static CachedProperties computeCachedProperties(const Type *T) { NamedDecl::LinkageInfo LV = Tag->getLinkageAndVisibility(); bool IsLocalOrUnnamed = Tag->getDeclContext()->isFunctionOrMethod() || - (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()); + (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()); return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed); } diff --git a/lib/AST/TypePrinter.cpp b/lib/AST/TypePrinter.cpp index 79fbcaa434..a8f9559b29 100644 --- a/lib/AST/TypePrinter.cpp +++ b/lib/AST/TypePrinter.cpp @@ -546,7 +546,7 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) { Buffer += Spec->getIdentifier()->getName(); Buffer += TemplateArgsStr; } else if (TagDecl *Tag = dyn_cast(DC)) { - if (TypedefDecl *Typedef = Tag->getTypedefForAnonDecl()) + if (TypedefNameDecl *Typedef = Tag->getTypedefNameForAnonDecl()) Buffer += Typedef->getIdentifier()->getName(); else if (Tag->getIdentifier()) Buffer += Tag->getIdentifier()->getName(); @@ -569,7 +569,7 @@ void TypePrinter::printTag(TagDecl *D, std::string &InnerString) { // We don't print tags unless this is an elaborated type. // In C, we just assume every RecordType is an elaborated type. if (!(Policy.LangOpts.CPlusPlus || Policy.SuppressTagKeyword || - D->getTypedefForAnonDecl())) { + D->getTypedefNameForAnonDecl())) { HasKindDecoration = true; Buffer += D->getKindName(); Buffer += ' '; @@ -583,7 +583,7 @@ void TypePrinter::printTag(TagDecl *D, std::string &InnerString) { if (const IdentifierInfo *II = D->getIdentifier()) Buffer += II->getNameStart(); - else if (TypedefDecl *Typedef = D->getTypedefForAnonDecl()) { + else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) { assert(Typedef->getIdentifier() && "Typedef without identifier?"); Buffer += Typedef->getIdentifier()->getNameStart(); } else { diff --git a/lib/CodeGen/CGDecl.cpp b/lib/CodeGen/CGDecl.cpp index 9b400cbe2a..d496982b81 100644 --- a/lib/CodeGen/CGDecl.cpp +++ b/lib/CodeGen/CGDecl.cpp @@ -91,8 +91,9 @@ void CodeGenFunction::EmitDecl(const Decl &D) { return EmitVarDecl(VD); } - case Decl::Typedef: { // typedef int X; - const TypedefDecl &TD = cast(D); + case Decl::Typedef: // typedef int X; + case Decl::TypeAlias: { // using X = int; [C++0x] + const TypedefNameDecl &TD = cast(D); QualType Ty = TD.getUnderlyingType(); if (Ty->isVariablyModifiedType()) diff --git a/lib/CodeGen/CodeGenTBAA.cpp b/lib/CodeGen/CodeGenTBAA.cpp index 3f2c6cabf2..622b9a5587 100644 --- a/lib/CodeGen/CodeGenTBAA.cpp +++ b/lib/CodeGen/CodeGenTBAA.cpp @@ -155,7 +155,7 @@ CodeGenTBAA::getTBAAInfo(QualType QTy) { // theoretically implement this by combining information about all the // members into a single identifying MDNode. if (!Features.CPlusPlus && - ETy->getDecl()->getTypedefForAnonDecl()) + ETy->getDecl()->getTypedefNameForAnonDecl()) return MetadataCache[Ty] = getChar(); // In C++ mode, types have linkage, so we can rely on the ODR and diff --git a/lib/CodeGen/CodeGenTypes.cpp b/lib/CodeGen/CodeGenTypes.cpp index 13aa23d8d0..731114bcca 100644 --- a/lib/CodeGen/CodeGenTypes.cpp +++ b/lib/CodeGen/CodeGenTypes.cpp @@ -387,7 +387,7 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) { OS << TD->getQualifiedNameAsString(); else TD->printName(OS); - } else if (const TypedefDecl *TDD = TD->getTypedefForAnonDecl()) { + } else if (const TypedefNameDecl *TDD = TD->getTypedefNameForAnonDecl()) { // FIXME: We should not have to check for a null decl context here. // Right now we do it because the implicit Obj-C decls don't have one. if (TDD->getDeclContext()) diff --git a/lib/Frontend/ASTConsumers.cpp b/lib/Frontend/ASTConsumers.cpp index f198d955e8..ecd6ef442a 100644 --- a/lib/Frontend/ASTConsumers.cpp +++ b/lib/Frontend/ASTConsumers.cpp @@ -335,8 +335,9 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC, Out << " " << FD << '\n'; break; } - case Decl::Typedef: { - TypedefDecl* TD = cast(*I); + case Decl::Typedef: + case Decl::TypeAlias: { + TypedefNameDecl* TD = cast(*I); Out << " " << TD << '\n'; break; } diff --git a/lib/Index/DeclReferenceMap.cpp b/lib/Index/DeclReferenceMap.cpp index d6e30ab396..3fd4336230 100644 --- a/lib/Index/DeclReferenceMap.cpp +++ b/lib/Index/DeclReferenceMap.cpp @@ -55,7 +55,7 @@ void RefMapper::VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) { } void RefMapper::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - NamedDecl *ND = TL.getTypedefDecl(); + NamedDecl *ND = TL.getTypedefNameDecl(); Map.insert(std::make_pair(ND, ASTLocation(CurrentDecl, ND, TL.getNameLoc()))); } diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index a384fab935..119bf0f762 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -253,7 +253,7 @@ Decl *Parser::ParseUsingDirectiveOrDeclaration(unsigned Context, return ParseUsingDirective(Context, UsingLoc, DeclEnd, attrs); } - // Otherwise, it must be a using-declaration. + // Otherwise, it must be a using-declaration or an alias-declaration. // Using declarations can't have attributes. ProhibitAttributes(attrs); @@ -323,14 +323,17 @@ Decl *Parser::ParseUsingDirective(unsigned Context, IdentLoc, NamespcName, attrs.getList()); } -/// ParseUsingDeclaration - Parse C++ using-declaration. Assumes that -/// 'using' was already seen. +/// ParseUsingDeclaration - Parse C++ using-declaration or alias-declaration. +/// Assumes that 'using' was already seen. /// /// using-declaration: [C++ 7.3.p3: namespace.udecl] /// 'using' 'typename'[opt] ::[opt] nested-name-specifier /// unqualified-id /// 'using' :: unqualified-id /// +/// alias-declaration: C++0x [decl.typedef]p2 +/// 'using' identifier = type-id ; +/// Decl *Parser::ParseUsingDeclaration(unsigned Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, @@ -340,10 +343,6 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, SourceLocation TypenameLoc; bool IsTypeName; - // TODO: in C++0x, if we have template parameters this must be a - // template alias: - // template <...> using id = type; - // Ignore optional 'typename'. // FIXME: This is wrong; we should parse this as a typename-specifier. if (Tok.is(tok::kw_typename)) { @@ -377,17 +376,48 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } - // Parse (optional) attributes (most likely GNU strong-using extension). ParsedAttributes attrs(AttrFactory); - MaybeParseGNUAttributes(attrs); + + // Maybe this is an alias-declaration. + bool IsAliasDecl = Tok.is(tok::equal); + TypeResult TypeAlias; + if (IsAliasDecl) { + // TODO: Do we want to support attributes somewhere in an alias declaration? + // Can't follow GCC since it doesn't support them yet! + ConsumeToken(); + + if (!getLang().CPlusPlus0x) + Diag(Tok.getLocation(), diag::ext_alias_declaration); + + // Name must be an identifier. + if (Name.getKind() != UnqualifiedId::IK_Identifier) { + Diag(Name.StartLocation, diag::err_alias_declaration_not_identifier); + // No removal fixit: can't recover from this. + SkipUntil(tok::semi); + return 0; + } else if (IsTypeName) + Diag(TypenameLoc, diag::err_alias_declaration_not_identifier) + << FixItHint::CreateRemoval(SourceRange(TypenameLoc, + SS.isNotEmpty() ? SS.getEndLoc() : TypenameLoc)); + else if (SS.isNotEmpty()) + Diag(SS.getBeginLoc(), diag::err_alias_declaration_not_identifier) + << FixItHint::CreateRemoval(SS.getRange()); + + TypeAlias = ParseTypeName(0, Declarator::AliasDeclContext); + } else + // Parse (optional) attributes (most likely GNU strong-using extension). + MaybeParseGNUAttributes(attrs); // Eat ';'. DeclEnd = Tok.getLocation(); ExpectAndConsume(tok::semi, diag::err_expected_semi_after, - !attrs.empty() ? "attributes list" : "using declaration", + !attrs.empty() ? "attributes list" : + IsAliasDecl ? "alias declaration" : "using declaration", tok::semi); // Diagnose an attempt to declare a templated using-declaration. + // TODO: in C++0x, alias-declarations can be templates: + // template <...> using id = type; if (TemplateInfo.Kind) { SourceRange R = TemplateInfo.getSourceRange(); Diag(UsingLoc, diag::err_templated_using_declaration) @@ -399,6 +429,10 @@ Decl *Parser::ParseUsingDeclaration(unsigned Context, return 0; } + if (IsAliasDecl) + return Actions.ActOnAliasDeclaration(getCurScope(), AS, UsingLoc, Name, + TypeAlias); + return Actions.ActOnUsingDeclaration(getCurScope(), AS, true, UsingLoc, SS, Name, attrs.getList(), IsTypeName, TypenameLoc); diff --git a/lib/Rewrite/RewriteObjC.cpp b/lib/Rewrite/RewriteObjC.cpp index b6aeaa200b..9e08afafe7 100644 --- a/lib/Rewrite/RewriteObjC.cpp +++ b/lib/Rewrite/RewriteObjC.cpp @@ -4953,7 +4953,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) { QualType DeclT; if (VarDecl *VD = dyn_cast(ND)) DeclT = VD->getType(); - else if (TypedefDecl *TDD = dyn_cast(ND)) + else if (TypedefNameDecl *TDD = dyn_cast(ND)) DeclT = TDD->getUnderlyingType(); else if (FieldDecl *FD = dyn_cast(ND)) DeclT = FD->getType(); @@ -5736,7 +5736,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) { RewriteTypeOfDecl(VD); } } - if (TypedefDecl *TD = dyn_cast(SD)) { + if (TypedefNameDecl *TD = dyn_cast(SD)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); else if (TD->getUnderlyingType()->isFunctionPointerType()) @@ -5906,7 +5906,7 @@ void RewriteObjC::HandleDeclInMainFile(Decl *D) { } return; } - if (TypedefDecl *TD = dyn_cast(D)) { + if (TypedefNameDecl *TD = dyn_cast(D)) { if (isTopLevelBlockPointerType(TD->getUnderlyingType())) RewriteBlockPointerDecl(TD); else if (TD->getUnderlyingType()->isFunctionPointerType()) diff --git a/lib/Sema/JumpDiagnostics.cpp b/lib/Sema/JumpDiagnostics.cpp index b73f0e9f14..867d78fef6 100644 --- a/lib/Sema/JumpDiagnostics.cpp +++ b/lib/Sema/JumpDiagnostics.cpp @@ -149,6 +149,11 @@ static std::pair return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0); } + if (const TypeAliasDecl *TD = dyn_cast(D)) { + if (TD->getUnderlyingType()->isVariablyModifiedType()) + return std::make_pair((unsigned) diag::note_protected_by_vla_type_alias, 0); + } + return std::make_pair(0U, 0U); } diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp index 4f9bf1c5ed..411d424dd8 100644 --- a/lib/Sema/SemaAccess.cpp +++ b/lib/Sema/SemaAccess.cpp @@ -1011,16 +1011,16 @@ static void DiagnoseAccessPath(Sema &S, // Find an original declaration. while (D->isOutOfLine()) { NamedDecl *PrevDecl = 0; - if (isa(D)) - PrevDecl = cast(D)->getPreviousDeclaration(); - else if (isa(D)) - PrevDecl = cast(D)->getPreviousDeclaration(); - else if (isa(D)) - PrevDecl = cast(D)->getPreviousDeclaration(); - else if (isa(D)) { + if (VarDecl *VD = dyn_cast(D)) + PrevDecl = VD->getPreviousDeclaration(); + else if (FunctionDecl *FD = dyn_cast(D)) + PrevDecl = FD->getPreviousDeclaration(); + else if (TypedefNameDecl *TND = dyn_cast(D)) + PrevDecl = TND->getPreviousDeclaration(); + else if (TagDecl *TD = dyn_cast(D)) { if (isa(D) && cast(D)->isInjectedClassName()) break; - PrevDecl = cast(D)->getPreviousDeclaration(); + PrevDecl = TD->getPreviousDeclaration(); } if (!PrevDecl) break; D = PrevDecl; diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index fe7efb88d5..7049f6b01d 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -255,7 +255,7 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) { QualType T = Context.getTypeDeclType(cast(SD)); if (T->isDependentType()) return true; - else if (TypedefDecl *TD = dyn_cast(SD)) { + else if (TypedefNameDecl *TD = dyn_cast(SD)) { if (TD->getUnderlyingType()->isRecordType() || (Context.getLangOptions().CPlusPlus0x && TD->getUnderlyingType()->isEnumeralType())) @@ -549,7 +549,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, } else if (isa(SD)) { RecordTypeLoc RecordTL = TLB.push(T); RecordTL.setNameLoc(IdentifierLoc); - } else if (isa(SD)) { + } else if (isa(SD)) { TypedefTypeLoc TypedefTL = TLB.push(T); TypedefTL.setNameLoc(IdentifierLoc); } else if (isa(SD)) { diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp index 7d222d4393..9dec259696 100644 --- a/lib/Sema/SemaChecking.cpp +++ b/lib/Sema/SemaChecking.cpp @@ -2964,9 +2964,9 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T, if (const EnumType *SourceEnum = Source->getAs()) if (const EnumType *TargetEnum = Target->getAs()) if ((SourceEnum->getDecl()->getIdentifier() || - SourceEnum->getDecl()->getTypedefForAnonDecl()) && + SourceEnum->getDecl()->getTypedefNameForAnonDecl()) && (TargetEnum->getDecl()->getIdentifier() || - TargetEnum->getDecl()->getTypedefForAnonDecl()) && + TargetEnum->getDecl()->getTypedefNameForAnonDecl()) && SourceEnum != TargetEnum) { if (isFromSystemMacro(S, CC)) return; diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp index 12ce270c74..ab1eb0587a 100644 --- a/lib/Sema/SemaCodeComplete.cpp +++ b/lib/Sema/SemaCodeComplete.cpp @@ -1837,7 +1837,7 @@ static const char *GetCompletionTypeString(QualType T, // Anonymous tag types are constant strings. if (const TagType *TagT = dyn_cast(T)) if (TagDecl *Tag = TagT->getDecl()) - if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) { + if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) { switch (Tag->getTagKind()) { case TTK_Struct: return "struct "; case TTK_Class: return "class "; @@ -1940,7 +1940,7 @@ static std::string FormatFunctionParameter(ASTContext &Context, // Look through typedefs. if (TypedefTypeLoc *TypedefTL = dyn_cast(&TL)) { if (TypeSourceInfo *InnerTSInfo - = TypedefTL->getTypedefDecl()->getTypeSourceInfo()) { + = TypedefTL->getTypedefNameDecl()->getTypeSourceInfo()) { TL = InnerTSInfo->getTypeLoc().getUnqualifiedLoc(); continue; } @@ -2640,6 +2640,7 @@ CXCursorKind clang::getCursorKindForDecl(Decl *D) { case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl; case Decl::ParmVar: return CXCursor_ParmDecl; case Decl::Typedef: return CXCursor_TypedefDecl; + case Decl::TypeAlias: return CXCursor_TypeAliasDecl; case Decl::Var: return CXCursor_VarDecl; case Decl::Namespace: return CXCursor_Namespace; case Decl::NamespaceAlias: return CXCursor_NamespaceAlias; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 7c32a381df..7be9316e37 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -946,12 +946,12 @@ NamedDecl *Sema::LazilyCreateBuiltin(IdentifierInfo *II, unsigned bid, return New; } -/// MergeTypeDefDecl - We just parsed a typedef 'New' which has the +/// MergeTypedefNameDecl - We just parsed a typedef 'New' which has the /// same name and scope as a previous declaration 'Old'. Figure out /// how to resolve this situation, merging decls or emitting /// diagnostics as appropriate. If there was an error, set New to be invalid. /// -void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { +void Sema::MergeTypedefNameDecl(TypedefNameDecl *New, LookupResult &OldDecls) { // If the new decl is known invalid already, don't bother doing any // merging checks. if (New->isInvalidDecl()) return; @@ -1011,7 +1011,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // Determine the "old" type we'll use for checking and diagnostics. QualType OldType; - if (TypedefDecl *OldTypedef = dyn_cast(Old)) + if (TypedefNameDecl *OldTypedef = dyn_cast(Old)) OldType = OldTypedef->getUnderlyingType(); else OldType = Context.getTypeDeclType(Old); @@ -1022,8 +1022,11 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { if (OldType != New->getUnderlyingType() && Context.getCanonicalType(OldType) != Context.getCanonicalType(New->getUnderlyingType())) { + int Kind = 0; + if (isa(Old)) + Kind = 1; Diag(New->getLocation(), diag::err_redefinition_different_typedef) - << New->getUnderlyingType() << OldType; + << Kind << New->getUnderlyingType() << OldType; if (Old->getLocation().isValid()) Diag(Old->getLocation(), diag::note_previous_definition); return New->setInvalidDecl(); @@ -1033,8 +1036,8 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // declaration was a typedef. // FIXME: this is a potential source of wierdness if the type // spellings don't match exactly. - if (isa(Old)) - New->setPreviousDeclaration(cast(Old)); + if (TypedefNameDecl *Typedef = dyn_cast(Old)) + New->setPreviousDeclaration(Typedef); if (getLangOptions().Microsoft) return; @@ -1068,7 +1071,7 @@ void Sema::MergeTypeDefDecl(TypedefDecl *New, LookupResult &OldDecls) { // }; // // since that was the intent of DR56. - if (!isa(Old)) + if (!isa(Old)) return; Diag(New->getLocation(), diag::err_redefinition) @@ -2553,6 +2556,26 @@ Decl *Sema::ActOnDeclarator(Scope *S, Declarator &D) { return HandleDeclarator(S, D, MultiTemplateParamsArg(*this), false); } +/// DiagnoseClassNameShadow - Implement C++ [class.mem]p13: +/// If T is the name of a class, then each of the following shall have a +/// name different from T: +/// - every static data member of class T; +/// - every member function of class T +/// - every member of class T that is itself a type; +/// \returns true if the declaration name violates these rules. +bool Sema::DiagnoseClassNameShadow(DeclContext *DC, + DeclarationNameInfo NameInfo) { + DeclarationName Name = NameInfo.getName(); + + if (CXXRecordDecl *Record = dyn_cast(DC)) + if (Record->getIdentifier() && Record->getDeclName() == Name) { + Diag(NameInfo.getLoc(), diag::err_member_name_of_class) << Name; + return true; + } + + return false; +} + Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, MultiTemplateParamsArg TemplateParamLists, bool IsFunctionDefinition) { @@ -2640,23 +2663,12 @@ Decl *Sema::HandleDeclarator(Scope *S, Declarator &D, D.setInvalidType(); } } - - // C++ [class.mem]p13: - // If T is the name of a class, then each of the following shall have a - // name different from T: - // - every static data member of class T; - // - every member function of class T - // - every member of class T that is itself a type; - if (CXXRecordDecl *Record = dyn_cast(DC)) - if (Record->getIdentifier() && Record->getDeclName() == Name) { - Diag(D.getIdentifierLoc(), diag::err_member_name_of_class) - << Name; - - // If this is a typedef, we'll end up spewing multiple diagnostics. - // Just return early; it's safer. - if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - return 0; - } + + if (DiagnoseClassNameShadow(DC, NameInfo)) + // If this is a typedef, we'll end up spewing multiple diagnostics. + // Just return early; it's safer. + if (D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) + return 0; NamedDecl *New; @@ -2951,6 +2963,15 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, // Handle attributes prior to checking for duplicates in MergeVarDecl ProcessDeclAttributes(S, NewTD, D); + return ActOnTypedefNameDecl(S, DC, NewTD, Previous, Redeclaration); +} + +/// ActOnTypedefNameDecl - Perform semantic checking for a declaration which +/// declares a typedef-name, either using the 'typedef' type specifier or via +/// a C++0x [dcl.typedef]p2 alias-declaration: 'using T = A;'. +NamedDecl* +Sema::ActOnTypedefNameDecl(Scope *S, DeclContext *DC, TypedefNameDecl *NewTD, + LookupResult &Previous, bool &Redeclaration) { // C99 6.7.7p2: If a typedef name specifies a variably modified type // then it shall have block scope. // Note that variably modified types must be fixed before merging the decl so @@ -2966,18 +2987,17 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, TryToFixInvalidVariablyModifiedType(T, Context, SizeIsNegative, Oversized); if (!FixedTy.isNull()) { - Diag(D.getIdentifierLoc(), diag::warn_illegal_constant_array_size); + Diag(NewTD->getLocation(), diag::warn_illegal_constant_array_size); NewTD->setTypeSourceInfo(Context.getTrivialTypeSourceInfo(FixedTy)); } else { if (SizeIsNegative) - Diag(D.getIdentifierLoc(), diag::err_typecheck_negative_array_size); + Diag(NewTD->getLocation(), diag::err_typecheck_negative_array_size); else if (T->isVariableArrayType()) - Diag(D.getIdentifierLoc(), diag::err_vla_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vla_decl_in_file_scope); else if (Oversized.getBoolValue()) - Diag(D.getIdentifierLoc(), diag::err_array_too_large) - << Oversized.toString(10); + Diag(NewTD->getLocation(), diag::err_array_too_large) << Oversized.toString(10); else - Diag(D.getIdentifierLoc(), diag::err_vm_decl_in_file_scope); + Diag(NewTD->getLocation(), diag::err_vm_decl_in_file_scope); NewTD->setInvalidDecl(); } } @@ -2989,7 +3009,7 @@ Sema::ActOnTypedefDeclarator(Scope* S, Declarator& D, DeclContext* DC, /*ExplicitInstantiationOrSpecialization=*/false); if (!Previous.empty()) { Redeclaration = true; - MergeTypeDefDecl(NewTD, Previous); + MergeTypedefNameDecl(NewTD, Previous); } // If this is the C FILE type, notify the AST context. @@ -4061,8 +4081,13 @@ Sema::ActOnFunctionDeclarator(Scope* S, Declarator& D, DeclContext* DC, // In C++, the empty parameter-type-list must be spelled "void"; a // typedef of void is not permitted. if (getLangOptions().CPlusPlus && - Param->getType().getUnqualifiedType() != Context.VoidTy) - Diag(Param->getLocation(), diag::err_param_typedef_of_void); + Param->getType().getUnqualifiedType() != Context.VoidTy) { + bool IsTypeAlias = false; + if (const TypedefType *TT = Param->getType()->getAs()) + IsTypeAlias = isa(TT->getDecl()); + Diag(Param->getLocation(), diag::err_param_typedef_of_void) + << IsTypeAlias; + } } else if (FTI.NumArgs > 0 && FTI.ArgInfo[0].Param != 0) { for (unsigned i = 0, e = FTI.NumArgs; i != e; ++i) { ParmVarDecl *Param = cast(FTI.ArgInfo[i].Param); @@ -6117,7 +6142,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, // Do nothing if the tag is not anonymous or already has an // associated typedef (from an earlier typedef in this decl group). if (tagFromDeclSpec->getIdentifier()) break; - if (tagFromDeclSpec->getTypedefForAnonDecl()) break; + if (tagFromDeclSpec->getTypedefNameForAnonDecl()) break; // A well-formed anonymous tag must always be a TUK_Definition. assert(tagFromDeclSpec->isThisDeclarationADefinition()); @@ -6127,7 +6152,7 @@ TypedefDecl *Sema::ParseTypedefDecl(Scope *S, Declarator &D, QualType T, break; // Otherwise, set this is the anon-decl typedef for the tag. - tagFromDeclSpec->setTypedefForAnonDecl(NewTD); + tagFromDeclSpec->setTypedefNameForAnonDecl(NewTD); break; } @@ -6468,7 +6493,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // okay according to the likely resolution of an open issue; // see http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#407 if (getLangOptions().CPlusPlus) { - if (TypedefDecl *TD = dyn_cast(PrevDecl)) { + if (TypedefNameDecl *TD = dyn_cast(PrevDecl)) { if (const TagType *TT = TD->getUnderlyingType()->getAs()) { TagDecl *Tag = TT->getDecl(); if (Tag->getDeclName() == Name && @@ -6626,7 +6651,8 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, !Previous.isForRedeclaration()) { unsigned Kind = 0; if (isa(PrevDecl)) Kind = 1; - else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 3; Diag(NameLoc, diag::err_tag_reference_non_tag) << Kind; Diag(PrevDecl->getLocation(), diag::note_declared_at); Invalid = true; @@ -6640,17 +6666,19 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } else if (TUK == TUK_Reference || TUK == TUK_Friend) { unsigned Kind = 0; if (isa(PrevDecl)) Kind = 1; - else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 2; + else if (isa(PrevDecl)) Kind = 3; Diag(NameLoc, diag::err_tag_reference_conflict) << Kind; Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; // Otherwise it's a declaration. Call out a particularly common // case here. - } else if (isa(PrevDecl)) { + } else if (TypedefNameDecl *TND = dyn_cast(PrevDecl)) { + unsigned Kind = 0; + if (isa(PrevDecl)) Kind = 1; Diag(NameLoc, diag::err_tag_definition_of_typedef) - << Name - << cast(PrevDecl)->getUnderlyingType(); + << Name << Kind << TND->getUnderlyingType(); Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp index 5b3c486fd0..14b0863ab3 100644 --- a/lib/Sema/SemaDeclAttr.cpp +++ b/lib/Sema/SemaDeclAttr.cpp @@ -55,7 +55,7 @@ static const FunctionType *getFunctionType(const Decl *d, Ty = decl->getType(); else if (const FieldDecl *decl = dyn_cast(d)) Ty = decl->getType(); - else if (const TypedefDecl* decl = dyn_cast(d)) + else if (const TypedefNameDecl* decl = dyn_cast(d)) Ty = decl->getUnderlyingType(); else return 0; @@ -101,8 +101,8 @@ static bool isFunctionOrMethodOrBlock(const Decl *d) { /// Return true if the given decl has a declarator that should have /// been processed by Sema::GetTypeForDeclarator. static bool hasDeclarator(const Decl *d) { - // In some sense, TypedefDecl really *ought* to be a DeclaratorDecl. - return isa(d) || isa(d) || isa(d); + // In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl. + return isa(d) || isa(d) || isa(d); } /// hasFunctionProto - Return true if the given decl has a argument @@ -202,7 +202,7 @@ static inline bool isCFStringType(QualType T, ASTContext &Ctx) { static void HandleExtVectorTypeAttr(Scope *scope, Decl *d, const AttributeList &Attr, Sema &S) { - TypedefDecl *tDecl = dyn_cast(d); + TypedefNameDecl *tDecl = dyn_cast(d); if (tDecl == 0) { S.Diag(Attr.getLoc(), diag::err_typecheck_ext_vector_not_typedef); return; @@ -1229,7 +1229,7 @@ static void HandleObjCNSObject(Decl *D, const AttributeList &Attr, Sema &S) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 1; return; } - if (TypedefDecl *TD = dyn_cast(D)) { + if (TypedefNameDecl *TD = dyn_cast(D)) { QualType T = TD->getUnderlyingType(); if (!T->isPointerType() || !T->getAs()->getPointeeType()->isRecordType()) { @@ -1912,7 +1912,7 @@ static void HandleTransparentUnionAttr(Decl *d, const AttributeList &Attr, // Try to find the underlying union declaration. RecordDecl *RD = 0; - TypedefDecl *TD = dyn_cast(d); + TypedefNameDecl *TD = dyn_cast(d); if (TD && TD->getUnderlyingType()->isUnionType()) RD = TD->getUnderlyingType()->getAsUnionType()->getDecl(); else @@ -2103,7 +2103,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { } QualType OldTy; - if (TypedefDecl *TD = dyn_cast(D)) + if (TypedefNameDecl *TD = dyn_cast(D)) OldTy = TD->getUnderlyingType(); else if (ValueDecl *VD = dyn_cast(D)) OldTy = VD->getType(); @@ -2202,7 +2202,7 @@ static void HandleModeAttr(Decl *D, const AttributeList &Attr, Sema &S) { } // Install the new type. - if (TypedefDecl *TD = dyn_cast(D)) { + if (TypedefNameDecl *TD = dyn_cast(D)) { // FIXME: preserve existing source info. TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy)); } else diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 01ce75192a..7d5dc200da 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -3416,9 +3416,9 @@ QualType Sema::CheckDestructorDeclarator(Declarator &D, QualType R, // be used as the identifier in the declarator for a destructor // declaration. QualType DeclaratorType = GetTypeFromParser(D.getName().DestructorName); - if (isa(DeclaratorType)) + if (const TypedefType *TT = DeclaratorType->getAs()) Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name) - << DeclaratorType; + << DeclaratorType << isa(TT->getDecl()); // C++ [class.dtor]p2: // A destructor is used to destroy objects of its class type. A @@ -4051,8 +4051,8 @@ IsEquivalentForUsingDecl(ASTContext &Context, NamedDecl *D1, NamedDecl *D2, return true; } - if (TypedefDecl *TD1 = dyn_cast(D1)) - if (TypedefDecl *TD2 = dyn_cast(D2)) { + if (TypedefNameDecl *TD1 = dyn_cast(D1)) + if (TypedefNameDecl *TD2 = dyn_cast(D2)) { SuppressRedeclaration = true; return Context.hasSameType(TD1->getUnderlyingType(), TD2->getUnderlyingType()); @@ -4651,6 +4651,61 @@ bool Sema::CheckUsingDeclQualifier(SourceLocation UsingLoc, return true; } +Decl *Sema::ActOnAliasDeclaration(Scope *S, + AccessSpecifier AS, + SourceLocation UsingLoc, + UnqualifiedId &Name, + TypeResult Type) { + assert((S->getFlags() & Scope::DeclScope) && + "got alias-declaration outside of declaration scope"); + + if (Type.isInvalid()) + return 0; + + bool Invalid = false; + DeclarationNameInfo NameInfo = GetNameFromUnqualifiedId(Name); + TypeSourceInfo *TInfo = 0; + QualType T = GetTypeFromParser(Type.get(), &TInfo); + + if (DiagnoseClassNameShadow(CurContext, NameInfo)) + return 0; + + if (DiagnoseUnexpandedParameterPack(Name.StartLocation, TInfo, + UPPC_DeclarationType)) + Invalid = true; + + LookupResult Previous(*this, NameInfo, LookupOrdinaryName, ForRedeclaration); + LookupName(Previous, S); + + // Warn about shadowing the name of a template parameter. + if (Previous.isSingleResult() && + Previous.getFoundDecl()->isTemplateParameter()) { + if (DiagnoseTemplateParameterShadow(Name.StartLocation, + Previous.getFoundDecl())) + Invalid = true; + Previous.clear(); + } + + assert(Name.Kind == UnqualifiedId::IK_Identifier && + "name in alias declaration must be an identifier"); + TypeAliasDecl *NewTD = TypeAliasDecl::Create(Context, CurContext, UsingLoc, + Name.StartLocation, + Name.Identifier, TInfo); + + NewTD->setAccess(AS); + + if (Invalid) + NewTD->setInvalidDecl(); + + bool Redeclaration = false; + ActOnTypedefNameDecl(S, CurContext, NewTD, Previous, Redeclaration); + + if (!Redeclaration) + PushOnScopeChains(NewTD, S); + + return NewTD; +} + Decl *Sema::ActOnNamespaceAliasDef(Scope *S, SourceLocation NamespaceLoc, SourceLocation AliasLoc, diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index 0cb9361bdb..4fc1e6912e 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -174,7 +174,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (PrevDecl && SuperClassDecl == 0) { // The previous declaration was not a class decl. Check if we have a // typedef. If we do, get the underlying class type. - if (const TypedefDecl *TDecl = dyn_cast_or_null(PrevDecl)) { + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null(PrevDecl)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->getAs()->getInterface()) @@ -193,7 +194,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, } } - if (!dyn_cast_or_null(PrevDecl)) { + if (!dyn_cast_or_null(PrevDecl)) { if (!SuperClassDecl) Diag(SuperLoc, diag::err_undef_superclass) << SuperName << ClassName << SourceRange(AtInterfaceLoc, ClassLoc); @@ -242,7 +243,8 @@ Decl *Sema::ActOnCompatiblityAlias(SourceLocation AtLoc, // Check for class declaration NamedDecl *CDeclU = LookupSingleName(TUScope, ClassName, ClassLocation, LookupOrdinaryName, ForRedeclaration); - if (const TypedefDecl *TDecl = dyn_cast_or_null(CDeclU)) { + if (const TypedefNameDecl *TDecl = + dyn_cast_or_null(CDeclU)) { QualType T = TDecl->getUnderlyingType(); if (T->isObjCObjectType()) { if (NamedDecl *IDecl = T->getAs()->getInterface()) { @@ -1242,7 +1244,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc, // @class XCElementToggler; // // FIXME: Make an extension? - TypedefDecl *TDD = dyn_cast(PrevDecl); + TypedefNameDecl *TDD = dyn_cast(PrevDecl); if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) { Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i]; Diag(PrevDecl->getLocation(), diag::note_previous_definition); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 80946ead64..d2a3441f4c 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -2469,7 +2469,7 @@ bool Sema::UseArgumentDependentLookup(const CXXScopeSpec &SS, /// were not overloaded, and it doesn't promise that the declaration /// will in fact be used. static bool CheckDeclInExpr(Sema &S, SourceLocation Loc, NamedDecl *D) { - if (isa(D)) { + if (isa(D)) { S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName(); return true; } diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 7bc5904e9a..49e4a87fd1 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -2978,7 +2978,7 @@ bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) { return true; } - if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl()) { + if (!Tag->getDeclName() && !Tag->getTypedefNameForAnonDecl()) { S.Diag(SR.getBegin(), diag::ext_template_arg_unnamed_type) << SR; S.Diag(Tag->getLocation(), diag::note_template_unnamed_type_here); return true; @@ -4374,7 +4374,7 @@ static NamedDecl *getPreviousDecl(NamedDecl *ND) { return FD->getPreviousDeclaration(); if (TagDecl *TD = dyn_cast(ND)) return TD->getPreviousDeclaration(); - if (TypedefDecl *TD = dyn_cast(ND)) + if (TypedefNameDecl *TD = dyn_cast(ND)) return TD->getPreviousDeclaration(); if (FunctionTemplateDecl *FTD = dyn_cast(ND)) return FTD->getPreviousDeclaration(); diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp index 11b98e0af2..3fe5fd5c95 100644 --- a/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -128,7 +128,8 @@ TemplateDeclInstantiator::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { return Inst; } -Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { +Decl *TemplateDeclInstantiator::VisitTypedefNameDecl(TypedefNameDecl *D, + bool IsTypeAlias) { bool Invalid = false; TypeSourceInfo *DI = D->getTypeSourceInfo(); if (DI->getType()->isDependentType() || @@ -144,9 +145,13 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { } // Create the new typedef - TypedefDecl *Typedef - = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(), - D->getLocation(), D->getIdentifier(), DI); + TypedefNameDecl *Typedef; + if (IsTypeAlias) + Typedef = TypeAliasDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); + else + Typedef = TypedefDecl::Create(SemaRef.Context, Owner, D->getLocStart(), + D->getLocation(), D->getIdentifier(), DI); if (Invalid) Typedef->setInvalidDecl(); @@ -154,20 +159,20 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { // tag decl, re-establish that relationship for the new typedef. if (const TagType *oldTagType = D->getUnderlyingType()->getAs()) { TagDecl *oldTag = oldTagType->getDecl(); - if (oldTag->getTypedefForAnonDecl() == D) { + if (oldTag->getTypedefNameForAnonDecl() == D) { TagDecl *newTag = DI->getType()->castAs()->getDecl(); - assert(!newTag->getIdentifier() && !newTag->getTypedefForAnonDecl()); - newTag->setTypedefForAnonDecl(Typedef); + assert(!newTag->getIdentifier() && !newTag->getTypedefNameForAnonDecl()); + newTag->setTypedefNameForAnonDecl(Typedef); } } - if (TypedefDecl *Prev = D->getPreviousDeclaration()) { + if (TypedefNameDecl *Prev = D->getPreviousDeclaration()) { NamedDecl *InstPrev = SemaRef.FindInstantiatedDecl(D->getLocation(), Prev, TemplateArgs); if (!InstPrev) return 0; - Typedef->setPreviousDeclaration(cast(InstPrev)); + Typedef->setPreviousDeclaration(cast(InstPrev)); } SemaRef.InstantiateAttrs(TemplateArgs, D, Typedef); @@ -178,6 +183,14 @@ Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { return Typedef; } +Decl *TemplateDeclInstantiator::VisitTypedefDecl(TypedefDecl *D) { + return VisitTypedefNameDecl(D, /*IsTypeAlias=*/false); +} + +Decl *TemplateDeclInstantiator::VisitTypeAliasDecl(TypeAliasDecl *D) { + return VisitTypedefNameDecl(D, /*IsTypeAlias=*/true); +} + /// \brief Instantiate an initializer, breaking it into separate /// initialization arguments. /// diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index d3408fc6ac..00ac1d63db 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1600,9 +1600,12 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::TemplateTypeArgContext: Error = 7; // Template type argument break; + case Declarator::AliasDeclContext: + Error = 9; // Type alias + break; case Declarator::TypeNameContext: if (!AutoAllowedInTypeName) - Error = 10; // Generic + Error = 11; // Generic break; case Declarator::FileContext: case Declarator::BlockContext: @@ -1616,7 +1619,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // In Objective-C it is an error to use 'auto' on a function declarator. if (D.isFunctionDeclarator()) - Error = 9; + Error = 10; // C++0x [dcl.spec.auto]p2: 'auto' is always fine if the declarator // contains a trailing return type. That is only legal at the outermost @@ -1653,6 +1656,11 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, if (D.getIdentifier()) Name = D.getIdentifier(); + // Does this declaration declare a typedef-name? + bool IsTypedefName = + D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef || + D.getContext() == Declarator::AliasDeclContext; + // Walk the DeclTypeInfo, building the recursive type as we go. // DeclTypeInfos are ordered from the identifier out, which is // opposite of what we want :). @@ -1829,9 +1837,9 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // Exception specs are not allowed in typedefs. Complain, but add it // anyway. - if (FTI.getExceptionSpecType() != EST_None && - D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) - Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef); + if (IsTypedefName && FTI.getExceptionSpecType()) + Diag(FTI.getExceptionSpecLoc(), diag::err_exception_spec_in_typedef) + << (D.getContext() == Declarator::AliasDeclContext); if (!FTI.NumArgs && !FTI.isVariadic && !getLangOptions().CPlusPlus) { // Simple void foo(), where the incoming T is the result type. @@ -2057,8 +2065,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, // declaration. if ((FnTy->getTypeQuals() != 0 || FnTy->getRefQualifier()) && !(D.getContext() == Declarator::TemplateTypeArgContext && - !D.isFunctionDeclarator()) && - D.getDeclSpec().getStorageClassSpec() != DeclSpec::SCS_typedef && + !D.isFunctionDeclarator()) && !IsTypedefName && (FreeFunction || D.getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_static)) { if (D.getContext() == Declarator::TemplateTypeArgContext) { @@ -2196,6 +2203,7 @@ TypeSourceInfo *Sema::GetTypeForDeclarator(Declarator &D, Scope *S, case Declarator::KNRTypeListContext: case Declarator::ObjCPrototypeContext: // FIXME: special diagnostic here? case Declarator::TypeNameContext: + case Declarator::AliasDeclContext: case Declarator::MemberContext: case Declarator::BlockContext: case Declarator::ForContext: @@ -2635,7 +2643,8 @@ TypeResult Sema::ActOnTypeName(Scope *S, Declarator &D) { // A type-specifier-seq shall not define a class or enumeration // unless it appears in the type-id of an alias-declaration // (7.1.3). - if (OwnedTag && OwnedTag->isDefinition()) + if (OwnedTag && OwnedTag->isDefinition() && + D.getContext() != Declarator::AliasDeclContext) Diag(OwnedTag->getLocation(), diag::err_type_defined_in_type_specifier) << Context.getTypeDeclType(OwnedTag); } diff --git a/lib/Sema/TargetAttributesSema.cpp b/lib/Sema/TargetAttributesSema.cpp index c3415cb847..ab697eeed5 100644 --- a/lib/Sema/TargetAttributesSema.cpp +++ b/lib/Sema/TargetAttributesSema.cpp @@ -136,7 +136,7 @@ static void HandleX86ForceAlignArgPointerAttr(Decl *D, if (VD && VD->getType()->isFunctionPointerType()) return; // Also don't warn on function pointer typedefs. - TypedefDecl *TD = dyn_cast(D); + TypedefNameDecl *TD = dyn_cast(D); if (TD && (TD->getUnderlyingType()->isFunctionPointerType() || TD->getUnderlyingType()->isFunctionType())) return; diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h index fadcf264dd..39434c106e 100644 --- a/lib/Sema/TreeTransform.h +++ b/lib/Sema/TreeTransform.h @@ -669,7 +669,7 @@ public: QualType RebuildUnresolvedUsingType(Decl *D); /// \brief Build a new typedef type. - QualType RebuildTypedefType(TypedefDecl *Typedef) { + QualType RebuildTypedefType(TypedefNameDecl *Typedef) { return SemaRef.Context.getTypeDeclType(Typedef); } @@ -851,7 +851,8 @@ public: NamedDecl *SomeDecl = Result.getRepresentativeDecl(); unsigned Kind = 0; if (isa(SomeDecl)) Kind = 1; - else if (isa(SomeDecl)) Kind = 2; + else if (isa(SomeDecl)) Kind = 2; + else if (isa(SomeDecl)) Kind = 3; SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << Kind; SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at); break; @@ -3981,9 +3982,9 @@ template QualType TreeTransform::TransformTypedefType(TypeLocBuilder &TLB, TypedefTypeLoc TL) { const TypedefType *T = TL.getTypePtr(); - TypedefDecl *Typedef - = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), - T->getDecl())); + TypedefNameDecl *Typedef + = cast_or_null(getDerived().TransformDecl(TL.getNameLoc(), + T->getDecl())); if (!Typedef) return QualType(); diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp index 66b4890d2a..fe098c95a7 100644 --- a/lib/Serialization/ASTReader.cpp +++ b/lib/Serialization/ASTReader.cpp @@ -3151,7 +3151,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) { Error("incorrect encoding of typedef type"); return QualType(); } - TypedefDecl *Decl = cast(GetDecl(Record[0])); + TypedefNameDecl *Decl = cast(GetDecl(Record[0])); QualType Canonical = GetType(Record[1]); if (!Canonical.isNull()) Canonical = Context->getCanonicalType(Canonical); @@ -4083,7 +4083,7 @@ void ASTReader::InitializeSema(Sema &S) { // and add them to Sema's vector of such declarations. for (unsigned I = 0, N = ExtVectorDecls.size(); I != N; ++I) SemaObj->ExtVectorDecls.push_back( - cast(GetDecl(ExtVectorDecls[I]))); + cast(GetDecl(ExtVectorDecls[I]))); // FIXME: Do VTable uses and dynamic classes deserialize too much ? // Can we cut them down before writing them ? diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp index 92b387e21a..5b4a64eeb5 100644 --- a/lib/Serialization/ASTReaderDecl.cpp +++ b/lib/Serialization/ASTReaderDecl.cpp @@ -93,6 +93,7 @@ namespace clang { void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); void VisitTypedefDecl(TypedefDecl *TD); + void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); void VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); @@ -240,6 +241,11 @@ void ASTDeclReader::VisitTypedefDecl(TypedefDecl *TD) { TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); } +void ASTDeclReader::VisitTypeAliasDecl(TypeAliasDecl *TD) { + VisitTypeDecl(TD); + TD->setTypeSourceInfo(GetTypeSourceInfo(Record, Idx)); +} + void ASTDeclReader::VisitTagDecl(TagDecl *TD) { VisitTypeDecl(TD); VisitRedeclarable(TD); @@ -251,10 +257,10 @@ void ASTDeclReader::VisitTagDecl(TagDecl *TD) { if (Record[Idx++]) { // hasExtInfo TagDecl::ExtInfo *Info = new (*Reader.getContext()) TagDecl::ExtInfo(); ReadQualifierInfo(*Info, Record, Idx); - TD->TypedefDeclOrQualifier = Info; + TD->TypedefNameDeclOrQualifier = Info; } else - TD->setTypedefForAnonDecl( - cast_or_null(Reader.GetDecl(Record[Idx++]))); + TD->setTypedefNameForAnonDecl( + cast_or_null(Reader.GetDecl(Record[Idx++]))); } void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { @@ -1429,6 +1435,10 @@ Decl *ASTReader::ReadDeclRecord(unsigned Index, DeclID ID) { D = TypedefDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), 0, 0); break; + case DECL_TYPEALIAS: + D = TypeAliasDecl::Create(*Context, 0, SourceLocation(), SourceLocation(), + 0, 0); + break; case DECL_ENUM: D = EnumDecl::Create(*Context, Decl::EmptyShell()); break; diff --git a/lib/Serialization/ASTWriterDecl.cpp b/lib/Serialization/ASTWriterDecl.cpp index c74fe176f3..1306ffda6d 100644 --- a/lib/Serialization/ASTWriterDecl.cpp +++ b/lib/Serialization/ASTWriterDecl.cpp @@ -53,6 +53,7 @@ namespace clang { void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *D); void VisitTypedefDecl(TypedefDecl *D); + void VisitTypeAliasDecl(TypeAliasDecl *D); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); void VisitTagDecl(TagDecl *D); void VisitEnumDecl(EnumDecl *D); @@ -167,6 +168,12 @@ void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { Code = serialization::DECL_TYPEDEF; } +void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { + VisitTypeDecl(D); + Writer.AddTypeSourceInfo(D->getTypeSourceInfo(), Record); + Code = serialization::DECL_TYPEALIAS; +} + void ASTDeclWriter::VisitTagDecl(TagDecl *D) { VisitTypeDecl(D); VisitRedeclarable(D); @@ -179,7 +186,7 @@ void ASTDeclWriter::VisitTagDecl(TagDecl *D) { if (D->hasExtInfo()) Writer.AddQualifierInfo(*D->getExtInfo(), Record); else - Writer.AddDeclRef(D->getTypedefForAnonDecl(), Record); + Writer.AddDeclRef(D->getTypedefNameForAnonDecl(), Record); } void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { diff --git a/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp index 1925131632..e4e5f54770 100644 --- a/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp @@ -176,7 +176,7 @@ static RefKind getTemplateKind(const DeclContext *dc) { } static RefKind getTemplateKind(const TypedefType *tdt) { - const TypedefDecl *td = tdt->getDecl(); + const TypedefNameDecl *td = tdt->getDecl(); RefKind parentKind = getTemplateKind(td->getDeclContext()); if (parentKind == VectorKind) { return llvm::StringSwitch(td->getName()) diff --git a/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp b/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp index 5c999c4096..3d1b5e2d10 100644 --- a/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/LLVMConventionsChecker.cpp @@ -56,7 +56,7 @@ static bool IsStdString(QualType T) { if (!TT) return false; - const TypedefDecl *TD = TT->getDecl(); + const TypedefNameDecl *TD = TT->getDecl(); if (!InNamespace(TD, "std")) return false; diff --git a/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp b/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp new file mode 100644 index 0000000000..751c0df6b8 --- /dev/null +++ b/test/CXX/basic/basic.scope/basic.scope.pdecl/p3.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++0x %s + +// Classes. +namespace Class { + namespace NS { + class C {}; // expected-note {{candidate}} + } + using namespace NS; + class C : C {}; // expected-error {{reference to 'C' is ambiguous}} \ + expected-note {{candidate}} +} + +// Enumerations. +enum E { + EPtrSize = sizeof((E*)0) // ok, E is already declared +}; + +// Alias declarations. clang implements the proposed resolution to N1044. +namespace Alias { + namespace NS { + class C; + } + using namespace NS; + using C = C; // ok, C = B::C + using C = NS::C; // ok, same type +} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp index 64827714a5..c00d4b7023 100644 --- a/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p5.cpp @@ -63,7 +63,7 @@ enum E : auto {}; // expected-error{{'auto' not allowed here}} struct F : auto {}; // expected-error{{expected class name}} template struct G { }; // expected-error{{'auto' not allowed here}} -using A = auto; // expected-error{{expected ';'}} expected-error{{requires a qualified name}} +using A = auto; // expected-error{{'auto' not allowed in type alias}} // FIXME: don't issue the second diagnostic for this error. auto k() -> auto; // expected-error{{'auto' not allowed here}} unexpected-error{{without trailing return type}} diff --git a/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp new file mode 100644 index 0000000000..a51cfbfffc --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.spec/dcl.typedef/p2-0x.cpp @@ -0,0 +1,161 @@ +// RUN: %clang_cc1 -verify -std=c++0x %s + +namespace RedeclAliasTypedef { + typedef int T; + using T = int; + using T = int; + typedef T T; + using T = T; + typedef int T; +} + +namespace IllegalTypeIds { + using A = void(int n = 0); // expected-error {{default arguments can only be specified for parameters in a function declaration}} + using B = inline void(int n); // expected-error {{type name does not allow function specifier}} + using C = virtual void(int n); // expected-error {{type name does not allow function specifier}} + using D = explicit void(int n); // expected-error {{type name does not allow function specifier}} + using E = void(int n) throw(); // expected-error {{exception specifications are not allowed in type aliases}} + // FIXME: this is illegal; we incorrectly accept it for typedefs too. + using F = void(*)(int n) &&; // expected-err + using G = __thread void(int n); // expected-error {{type name does not allow storage class to be specified}} + + using H = void(int n); // ok + using I = void(int n) &&; // ok +} + +namespace IllegalSyntax { + using ::T = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + using operator int = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}} + using typename ::V = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} + using typename ::operator bool = void(int n); // expected-error {{name defined in alias declaration must be an identifier}} +} + +namespace VariableLengthArrays { + using T = int[42]; // ok + + int n = 32; + using T = int[n]; // expected-error {{variable length array declaration not allowed at file scope}} + + const int m = 42; + using U = int[m]; // expected-note {{previous definition}} + using U = int[42]; // ok + using U = int; // expected-error {{type alias redefinition with different types ('int' vs 'int [42]')}} + + void f() { + int n = 42; + goto foo; // expected-error {{goto into protected scope}} + using T = int[n]; // expected-note {{bypasses initialization of VLA type alias}} + foo: ; + } +} + +namespace RedeclFunc { + int f(int, char**); + using T = int; + T f(int, char **); // ok +} + +namespace LookupFilter { + namespace N { struct S; } + using namespace N; + using S = S*; // ok +} + +namespace InFunctions { + template void f0() { + using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} + U u; + } + template void f0(); + + void f1() { + using T = int; + } + void f2() { + using T = int[-1]; // expected-error {{array size is negative}} + } + + template void f3() { // expected-note {{template parameter is declared here}} + using T = int; // expected-error {{declaration of 'T' shadows template parameter}} + } +} + +namespace ClassNameRedecl { + class C0 { + // FIXME: this diagnostic is pretty poor + using C0 = int; // expected-error {{name defined in alias declaration must be an identifier}} + }; + class C1 { + // FIXME: this diagnostic is pretty poor + using C1 = C1; // expected-error {{name defined in alias declaration must be an identifier}} + }; + class C2 { + using C0 = C1; // ok + }; + template class C3 { + using f = T; // expected-error {{declaration type contains unexpanded parameter pack 'T'}} + }; + template class C4 { // expected-note {{template parameter is declared here}} + using T = int; // expected-error {{declaration of 'T' shadows template parameter}} + }; + class C5 { + class c; // expected-note {{previous definition}} + using c = int; // expected-error {{typedef redefinition with different types}} + class d; + using d = d; // ok + }; + class C6 { + class c { using C6 = int; }; // ok + }; +} + +class CtorDtorName { + using X = CtorDtorName; + X(); // expected-error {{expected member name}} + ~X(); // expected-error {{destructor cannot be declared using a type alias}} +}; + +namespace TagName { + using S = struct { int n; }; + using T = class { int n; }; + using U = enum { a, b, c }; + using V = struct V { int n; }; +} + +namespace CWG1044 { + // FIXME: this is terrible. one error is plenty. + using T = T; // expected-error {{type name requires a specifier}} \ + expected-error {{C++ requires a type specifier}} \ + expected-error {{expected ';' after alias declaration}} +} + +namespace StdExample { + template struct pair; + + using handler_t = void (*)(int); + extern handler_t ignore; + extern void (*ignore)(int); + // FIXME: we know we're parsing a type here; don't recover as if we were + // using operator*. + using cell = pair; // expected-error {{use of undeclared identifier 'cell'}} \ + expected-error {{expected expression}} +} + +namespace Access { + class C0 { + using U = int; // expected-note {{declared private here}} + }; + C0::U v; // expected-error {{'U' is a private member}} + class C1 { + public: + using U = int; + }; + C1::U w; // ok +} + +namespace VoidArg { + using V = void; + V f(int); // ok + V g(V); // expected-error {{empty parameter list defined with a type alias of 'void' not allowed}} +} diff --git a/test/FixIt/fixit-cxx0x.cpp b/test/FixIt/fixit-cxx0x.cpp index d8a858d9da..90bf9f5c18 100644 --- a/test/FixIt/fixit-cxx0x.cpp +++ b/test/FixIt/fixit-cxx0x.cpp @@ -14,3 +14,6 @@ void x() { } } +using ::T = void; // expected-error {{name defined in alias declaration must be an identifier}} +using typename U = void; // expected-error {{name defined in alias declaration must be an identifier}} +using typename ::V = void; // expected-error {{name defined in alias declaration must be an identifier}} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index 0aba04a48c..f8ca13aab3 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -272,6 +272,7 @@ public: bool VisitChildren(CXCursor Parent); // Declaration visitors + bool VisitTypeAliasDecl(TypeAliasDecl *D); bool VisitAttributes(Decl *D); bool VisitBlockDecl(BlockDecl *B); bool VisitCXXRecordDecl(CXXRecordDecl *D); @@ -642,6 +643,13 @@ bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) { return false; } +bool CursorVisitor::VisitTypeAliasDecl(TypeAliasDecl *D) { + if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo()) + return Visit(TSInfo->getTypeLoc()); + + return false; +} + bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) { if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo()) return Visit(TSInfo->getTypeLoc()); @@ -1430,7 +1438,7 @@ bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) { } bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) { - return Visit(MakeCursorTypeRef(TL.getTypedefDecl(), TL.getNameLoc(), TU)); + return Visit(MakeCursorTypeRef(TL.getTypedefNameDecl(), TL.getNameLoc(), TU)); } bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) { @@ -3337,6 +3345,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) { return createCXString("UsingDirective"); case CXCursor_UsingDeclaration: return createCXString("UsingDeclaration"); + case CXCursor_TypeAliasDecl: + return createCXString("TypeAliasDecl"); } llvm_unreachable("Unhandled CXCursorKind"); @@ -3877,6 +3887,7 @@ CXCursor clang_getCursorDefinition(CXCursor C) { // declaration and definition. case Decl::Namespace: case Decl::Typedef: + case Decl::TypeAlias: case Decl::TemplateTypeParm: case Decl::EnumConstant: case Decl::Field: diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp index 91bb802dd1..30173d3e7e 100644 --- a/tools/libclang/CIndexUSRs.cpp +++ b/tools/libclang/CIndexUSRs.cpp @@ -431,7 +431,7 @@ void USRGenerator::VisitTagDecl(TagDecl *D) { const unsigned off = Buf.size() - 1; if (EmitDeclName(D)) { - if (const TypedefDecl *TD = D->getTypedefForAnonDecl()) { + if (const TypedefNameDecl *TD = D->getTypedefNameForAnonDecl()) { Buf[off] = 'A'; Out << '@' << TD; }