зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
98a57868d6
Коммит
162e1c1b48
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1995,17 +1995,21 @@ public:
|
|||
};
|
||||
|
||||
|
||||
class TypedefDecl : public TypeDecl, public Redeclarable<TypedefDecl> {
|
||||
/// Base class for declarations which introduce a typedef-name.
|
||||
class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> {
|
||||
/// 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<TypedefDecl> 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<TypedefNameDecl> 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<TagDecl> {
|
||||
|
@ -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<TypedefDecl*, ExtInfo*> TypedefDeclOrQualifier;
|
||||
/// a typedef or alias, it points to the TypedefNameDecl (used for mangling);
|
||||
/// otherwise, it is a null (TypedefNameDecl) pointer.
|
||||
llvm::PointerUnion<TypedefNameDecl*, ExtInfo*> TypedefNameDeclOrQualifier;
|
||||
|
||||
bool hasExtInfo() const { return TypedefDeclOrQualifier.is<ExtInfo*>(); }
|
||||
ExtInfo *getExtInfo() { return TypedefDeclOrQualifier.get<ExtInfo*>(); }
|
||||
bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is<ExtInfo*>(); }
|
||||
ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get<ExtInfo*>(); }
|
||||
const ExtInfo *getExtInfo() const {
|
||||
return TypedefDeclOrQualifier.get<ExtInfo*>();
|
||||
return TypedefNameDeclOrQualifier.get<ExtInfo*>();
|
||||
}
|
||||
|
||||
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<TypedefDecl*>();
|
||||
TypedefNameDecl *getTypedefNameForAnonDecl() const {
|
||||
return hasExtInfo() ? 0 : TypedefNameDeclOrQualifier.get<TypedefNameDecl*>();
|
||||
}
|
||||
|
||||
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.
|
||||
|
|
|
@ -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 T> class A : public B<T> { using typename B<T>::foo; };
|
||||
|
|
|
@ -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<TypedefDecl*>(D)) {
|
||||
Decl(const_cast<TypedefNameDecl*>(D)) {
|
||||
assert(!isa<TypedefType>(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;
|
||||
|
|
|
@ -527,7 +527,7 @@ class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
|||
TypedefTypeLoc,
|
||||
TypedefType> {
|
||||
public:
|
||||
TypedefDecl *getTypedefDecl() const {
|
||||
TypedefNameDecl *getTypedefNameDecl() const {
|
||||
return getTypePtr()->getDecl();
|
||||
}
|
||||
};
|
||||
|
|
|
@ -17,7 +17,9 @@ def Named : Decl<1>;
|
|||
def NamespaceAlias : DDecl<Named>;
|
||||
def Label : DDecl<Named>;
|
||||
def Type : DDecl<Named, 1>;
|
||||
def Typedef : DDecl<Type>;
|
||||
def TypedefName : DDecl<Type, 1>;
|
||||
def Typedef : DDecl<TypedefName>;
|
||||
def TypeAlias : DDecl<TypedefName>;
|
||||
def UnresolvedUsingTypename : DDecl<Type>;
|
||||
def Tag : DDecl<Type, 1>, DeclContext;
|
||||
def Enum : DDecl<Tag>;
|
||||
|
|
|
@ -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<CXX0x>;
|
||||
|
||||
// C++0x alias-declaration
|
||||
def ext_alias_declaration : ExtWarn<
|
||||
"alias declarations accepted as a C++0x extension">, InGroup<CXX0x>;
|
||||
def err_alias_declaration_not_identifier : Error<
|
||||
"name defined in alias declaration must be an identifier">;
|
||||
|
||||
// C++0x override control
|
||||
def ext_override_control_keyword : Extension<
|
||||
"'%0' keyword accepted as a C++0x extension">, InGroup<CXX0x>;
|
||||
|
|
|
@ -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<
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<TypedefDecl*, 24> ExtVectorDecls;
|
||||
llvm::SmallVector<TypedefNameDecl*, 24> ExtVectorDecls;
|
||||
|
||||
/// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes.
|
||||
llvm::OwningPtr<CXXFieldCollector> 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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -907,7 +907,7 @@ ASTContext::getTypeInfo(const Type *T) const {
|
|||
return getTypeInfo(cast<ParenType>(T)->getInnerType().getTypePtr());
|
||||
|
||||
case Type::Typedef: {
|
||||
const TypedefDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
||||
const TypedefNameDecl *Typedef = cast<TypedefType>(T)->getDecl();
|
||||
std::pair<uint64_t, unsigned> 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<TypedefDecl>(Decl))
|
||||
if (const TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Decl))
|
||||
return getTypedefType(Typedef);
|
||||
|
||||
assert(!isa<TemplateTypeParmDecl>(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<TypedefType>(Ty)) {
|
||||
if (TypedefDecl *TD = TDT->getDecl())
|
||||
if (TypedefNameDecl *TD = TDT->getDecl())
|
||||
if (TD->getAttr<ObjCNSObjectAttr>())
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -100,7 +100,7 @@ break; \
|
|||
// Don't desugar through the primary typedef of an anonymous type.
|
||||
if (const TagType *UTT = Underlying->getAs<TagType>())
|
||||
if (const TypedefType *QTT = dyn_cast<TypedefType>(QT))
|
||||
if (UTT->getDecl()->getTypedefForAnonDecl() == QTT->getDecl())
|
||||
if (UTT->getDecl()->getTypedefNameForAnonDecl() == QTT->getDecl())
|
||||
break;
|
||||
|
||||
// Record that we actually looked through an opaque type here.
|
||||
|
|
|
@ -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<RecordDecl>(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<EnumDecl>(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<TypedefDecl>(D1)) {
|
||||
if (TypedefDecl *Typedef2 = dyn_cast<TypedefDecl>(D2)) {
|
||||
} else if (TypedefNameDecl *Typedef1 = dyn_cast<TypedefNameDecl>(D1)) {
|
||||
if (TypedefNameDecl *Typedef2 = dyn_cast<TypedefNameDecl>(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<TypedefDecl>(Importer.Import(T->getDecl()));
|
||||
TypedefNameDecl *ToDecl
|
||||
= dyn_cast_or_null<TypedefNameDecl>(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<TypedefDecl>(*Lookup.first)) {
|
||||
if (TypedefNameDecl *FoundTypedef =
|
||||
dyn_cast<TypedefNameDecl>(*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<TypedefDecl>(Found)) {
|
||||
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
|
||||
if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
|
||||
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<TypedefDecl>(Found)) {
|
||||
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Found)) {
|
||||
if (const TagType *Tag = Typedef->getUnderlyingType()->getAs<TagType>())
|
||||
Found = Tag->getDecl();
|
||||
}
|
||||
|
@ -3997,19 +4015,19 @@ Decl *ASTImporter::Import(Decl *FromD) {
|
|||
|
||||
if (TagDecl *FromTag = dyn_cast<TagDecl>(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<TypedefDecl>(FromD)) {
|
||||
} else if (TypedefNameDecl *FromTypedef = dyn_cast<TypedefNameDecl>(FromD)) {
|
||||
// When we've finished transforming a typedef, see whether it was the
|
||||
// typedef for an anonymous tag.
|
||||
for (llvm::SmallVector<TagDecl *, 4>::iterator
|
||||
FromTag = AnonTagsWithPendingTypedefs.begin(),
|
||||
FromTagEnd = AnonTagsWithPendingTypedefs.end();
|
||||
FromTag != FromTagEnd; ++FromTag) {
|
||||
if ((*FromTag)->getTypedefForAnonDecl() == FromTypedef) {
|
||||
if ((*FromTag)->getTypedefNameForAnonDecl() == FromTypedef) {
|
||||
if (TagDecl *ToTag = cast_or_null<TagDecl>(Import(*FromTag))) {
|
||||
// We found the typedef for an anonymous tag; link them.
|
||||
ToTag->setTypedefForAnonDecl(cast<TypedefDecl>(ToD));
|
||||
ToTag->setTypedefNameForAnonDecl(cast<TypedefNameDecl>(ToD));
|
||||
AnonTagsWithPendingTypedefs.erase(FromTag);
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -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<TypedefDecl>(*Path.Decls.first) ||
|
||||
if (isa<TypedefNameDecl>(*Path.Decls.first) ||
|
||||
(*Path.Decls.first)->isInIdentifierNamespace(IDNS_Tag))
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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<TagDecl>(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<VarDecl>(D) ||
|
||||
isa<FieldDecl>(D) ||
|
||||
(isa<TagDecl>(D) &&
|
||||
(D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
|
||||
(D->getDeclName() || cast<TagDecl>(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<Type*>(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,
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<TypedefDecl>(D))
|
||||
if (TypedefNameDecl* TDD = dyn_cast<TypedefNameDecl>(D))
|
||||
return TDD->getUnderlyingType();
|
||||
if (ValueDecl* VD = dyn_cast<ValueDecl>(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()) {
|
||||
|
|
|
@ -543,12 +543,20 @@ struct XMLDumper : public XMLDeclVisitor<XMLDumper>,
|
|||
|
||||
// TypedefDecl
|
||||
void visitTypedefDeclAttrs(TypedefDecl *D) {
|
||||
visitRedeclarableAttrs(D);
|
||||
visitRedeclarableAttrs<TypedefNameDecl>(D);
|
||||
}
|
||||
void visitTypedefDeclChildren(TypedefDecl *D) {
|
||||
dispatch(D->getTypeSourceInfo()->getTypeLoc());
|
||||
}
|
||||
|
||||
// TypeAliasDecl
|
||||
void visitTypeAliasDeclAttrs(TypeAliasDecl *D) {
|
||||
visitRedeclarableAttrs<TypedefNameDecl>(D);
|
||||
}
|
||||
void visitTypeAliasDeclChildren(TypeAliasDecl *D) {
|
||||
dispatch(D->getTypeSourceInfo()->getTypeLoc());
|
||||
}
|
||||
|
||||
// TagDecl
|
||||
void visitTagDeclAttrs(TagDecl *D) {
|
||||
visitRedeclarableAttrs(D);
|
||||
|
|
|
@ -748,7 +748,7 @@ void CXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
|
|||
|
||||
// We must have an anonymous struct.
|
||||
const TagDecl *TD = cast<TagDecl>(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() &&
|
||||
|
|
|
@ -314,7 +314,7 @@ MicrosoftCXXNameMangler::mangleUnqualifiedName(const NamedDecl *ND,
|
|||
|
||||
// We must have an anonymous struct.
|
||||
const TagDecl *TD = cast<TagDecl>(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() &&
|
||||
|
|
|
@ -236,6 +236,9 @@ void StmtDumper::DumpDeclarator(Decl *D) {
|
|||
if (TypedefDecl *localType = dyn_cast<TypedefDecl>(D)) {
|
||||
OS << "\"typedef " << localType->getUnderlyingType().getAsString()
|
||||
<< ' ' << localType << '"';
|
||||
} else if (TypeAliasDecl *localType = dyn_cast<TypeAliasDecl>(D)) {
|
||||
OS << "\"using " << localType << " = "
|
||||
<< localType->getUnderlyingType().getAsString() << '"';
|
||||
} else if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) {
|
||||
OS << "\"";
|
||||
// Emit storage class for vardecls.
|
||||
|
|
|
@ -98,7 +98,7 @@ bool StmtIteratorBase::HandleDecl(Decl* D) {
|
|||
if (VD->getInit())
|
||||
return true;
|
||||
}
|
||||
else if (TypedefDecl* TD = dyn_cast<TypedefDecl>(D)) {
|
||||
else if (TypedefNameDecl* TD = dyn_cast<TypedefNameDecl>(D)) {
|
||||
if (const VariableArrayType* VAPtr =
|
||||
FindVA(TD->getUnderlyingType().getTypePtr())) {
|
||||
setVAPtr(VAPtr);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -546,7 +546,7 @@ void TypePrinter::AppendScope(DeclContext *DC, std::string &Buffer) {
|
|||
Buffer += Spec->getIdentifier()->getName();
|
||||
Buffer += TemplateArgsStr;
|
||||
} else if (TagDecl *Tag = dyn_cast<TagDecl>(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 {
|
||||
|
|
|
@ -91,8 +91,9 @@ void CodeGenFunction::EmitDecl(const Decl &D) {
|
|||
return EmitVarDecl(VD);
|
||||
}
|
||||
|
||||
case Decl::Typedef: { // typedef int X;
|
||||
const TypedefDecl &TD = cast<TypedefDecl>(D);
|
||||
case Decl::Typedef: // typedef int X;
|
||||
case Decl::TypeAlias: { // using X = int; [C++0x]
|
||||
const TypedefNameDecl &TD = cast<TypedefNameDecl>(D);
|
||||
QualType Ty = TD.getUnderlyingType();
|
||||
|
||||
if (Ty->isVariablyModifiedType())
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -335,8 +335,9 @@ void DeclContextPrinter::PrintDeclContext(const DeclContext* DC,
|
|||
Out << "<field> " << FD << '\n';
|
||||
break;
|
||||
}
|
||||
case Decl::Typedef: {
|
||||
TypedefDecl* TD = cast<TypedefDecl>(*I);
|
||||
case Decl::Typedef:
|
||||
case Decl::TypeAlias: {
|
||||
TypedefNameDecl* TD = cast<TypedefNameDecl>(*I);
|
||||
Out << "<typedef> " << TD << '\n';
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -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())));
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -4953,7 +4953,7 @@ void RewriteObjC::RewriteBlockPointerDecl(NamedDecl *ND) {
|
|||
QualType DeclT;
|
||||
if (VarDecl *VD = dyn_cast<VarDecl>(ND))
|
||||
DeclT = VD->getType();
|
||||
else if (TypedefDecl *TDD = dyn_cast<TypedefDecl>(ND))
|
||||
else if (TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(ND))
|
||||
DeclT = TDD->getUnderlyingType();
|
||||
else if (FieldDecl *FD = dyn_cast<FieldDecl>(ND))
|
||||
DeclT = FD->getType();
|
||||
|
@ -5736,7 +5736,7 @@ Stmt *RewriteObjC::RewriteFunctionBodyOrGlobalInitializer(Stmt *S) {
|
|||
RewriteTypeOfDecl(VD);
|
||||
}
|
||||
}
|
||||
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
|
||||
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(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<TypedefDecl>(D)) {
|
||||
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
|
||||
if (isTopLevelBlockPointerType(TD->getUnderlyingType()))
|
||||
RewriteBlockPointerDecl(TD);
|
||||
else if (TD->getUnderlyingType()->isFunctionPointerType())
|
||||
|
|
|
@ -149,6 +149,11 @@ static std::pair<unsigned,unsigned>
|
|||
return std::make_pair((unsigned) diag::note_protected_by_vla_typedef, 0);
|
||||
}
|
||||
|
||||
if (const TypeAliasDecl *TD = dyn_cast<TypeAliasDecl>(D)) {
|
||||
if (TD->getUnderlyingType()->isVariablyModifiedType())
|
||||
return std::make_pair((unsigned) diag::note_protected_by_vla_type_alias, 0);
|
||||
}
|
||||
|
||||
return std::make_pair(0U, 0U);
|
||||
}
|
||||
|
||||
|
|
|
@ -1011,16 +1011,16 @@ static void DiagnoseAccessPath(Sema &S,
|
|||
// Find an original declaration.
|
||||
while (D->isOutOfLine()) {
|
||||
NamedDecl *PrevDecl = 0;
|
||||
if (isa<VarDecl>(D))
|
||||
PrevDecl = cast<VarDecl>(D)->getPreviousDeclaration();
|
||||
else if (isa<FunctionDecl>(D))
|
||||
PrevDecl = cast<FunctionDecl>(D)->getPreviousDeclaration();
|
||||
else if (isa<TypedefDecl>(D))
|
||||
PrevDecl = cast<TypedefDecl>(D)->getPreviousDeclaration();
|
||||
else if (isa<TagDecl>(D)) {
|
||||
if (VarDecl *VD = dyn_cast<VarDecl>(D))
|
||||
PrevDecl = VD->getPreviousDeclaration();
|
||||
else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
|
||||
PrevDecl = FD->getPreviousDeclaration();
|
||||
else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(D))
|
||||
PrevDecl = TND->getPreviousDeclaration();
|
||||
else if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
|
||||
if (isa<RecordDecl>(D) && cast<RecordDecl>(D)->isInjectedClassName())
|
||||
break;
|
||||
PrevDecl = cast<TagDecl>(D)->getPreviousDeclaration();
|
||||
PrevDecl = TD->getPreviousDeclaration();
|
||||
}
|
||||
if (!PrevDecl) break;
|
||||
D = PrevDecl;
|
||||
|
|
|
@ -255,7 +255,7 @@ bool Sema::isAcceptableNestedNameSpecifier(NamedDecl *SD) {
|
|||
QualType T = Context.getTypeDeclType(cast<TypeDecl>(SD));
|
||||
if (T->isDependentType())
|
||||
return true;
|
||||
else if (TypedefDecl *TD = dyn_cast<TypedefDecl>(SD)) {
|
||||
else if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(SD)) {
|
||||
if (TD->getUnderlyingType()->isRecordType() ||
|
||||
(Context.getLangOptions().CPlusPlus0x &&
|
||||
TD->getUnderlyingType()->isEnumeralType()))
|
||||
|
@ -549,7 +549,7 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S,
|
|||
} else if (isa<RecordDecl>(SD)) {
|
||||
RecordTypeLoc RecordTL = TLB.push<RecordTypeLoc>(T);
|
||||
RecordTL.setNameLoc(IdentifierLoc);
|
||||
} else if (isa<TypedefDecl>(SD)) {
|
||||
} else if (isa<TypedefNameDecl>(SD)) {
|
||||
TypedefTypeLoc TypedefTL = TLB.push<TypedefTypeLoc>(T);
|
||||
TypedefTL.setNameLoc(IdentifierLoc);
|
||||
} else if (isa<EnumDecl>(SD)) {
|
||||
|
|
|
@ -2964,9 +2964,9 @@ void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
|
|||
if (const EnumType *SourceEnum = Source->getAs<EnumType>())
|
||||
if (const EnumType *TargetEnum = Target->getAs<EnumType>())
|
||||
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;
|
||||
|
|
|
@ -1837,7 +1837,7 @@ static const char *GetCompletionTypeString(QualType T,
|
|||
// Anonymous tag types are constant strings.
|
||||
if (const TagType *TagT = dyn_cast<TagType>(T))
|
||||
if (TagDecl *Tag = TagT->getDecl())
|
||||
if (!Tag->getIdentifier() && !Tag->getTypedefForAnonDecl()) {
|
||||
if (!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl()) {
|
||||
switch (Tag->getTagKind()) {
|
||||
case TTK_Struct: return "struct <anonymous>";
|
||||
case TTK_Class: return "class <anonymous>";
|
||||
|
@ -1940,7 +1940,7 @@ static std::string FormatFunctionParameter(ASTContext &Context,
|
|||
// Look through typedefs.
|
||||
if (TypedefTypeLoc *TypedefTL = dyn_cast<TypedefTypeLoc>(&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;
|
||||
|
|
|
@ -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<TypedefDecl>(Old))
|
||||
if (TypedefNameDecl *OldTypedef = dyn_cast<TypedefNameDecl>(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<TypeAliasDecl>(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<TypedefDecl>(Old))
|
||||
New->setPreviousDeclaration(cast<TypedefDecl>(Old));
|
||||
if (TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(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<TypedefDecl >(Old))
|
||||
if (!isa<TypedefNameDecl>(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<CXXRecordDecl>(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<CXXRecordDecl>(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<TypedefType>())
|
||||
IsTypeAlias = isa<TypeAliasDecl>(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<ParmVarDecl>(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<TypedefDecl>(PrevDecl)) {
|
||||
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(PrevDecl)) {
|
||||
if (const TagType *TT = TD->getUnderlyingType()->getAs<TagType>()) {
|
||||
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<TypedefDecl>(PrevDecl)) Kind = 1;
|
||||
else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
|
||||
else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
|
||||
else if (isa<ClassTemplateDecl>(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<TypedefDecl>(PrevDecl)) Kind = 1;
|
||||
else if (isa<ClassTemplateDecl>(PrevDecl)) Kind = 2;
|
||||
else if (isa<TypeAliasDecl>(PrevDecl)) Kind = 2;
|
||||
else if (isa<ClassTemplateDecl>(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<TypedefDecl>(PrevDecl)) {
|
||||
} else if (TypedefNameDecl *TND = dyn_cast<TypedefNameDecl>(PrevDecl)) {
|
||||
unsigned Kind = 0;
|
||||
if (isa<TypeAliasDecl>(PrevDecl)) Kind = 1;
|
||||
Diag(NameLoc, diag::err_tag_definition_of_typedef)
|
||||
<< Name
|
||||
<< cast<TypedefDecl>(PrevDecl)->getUnderlyingType();
|
||||
<< Name << Kind << TND->getUnderlyingType();
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl;
|
||||
Invalid = true;
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ static const FunctionType *getFunctionType(const Decl *d,
|
|||
Ty = decl->getType();
|
||||
else if (const FieldDecl *decl = dyn_cast<FieldDecl>(d))
|
||||
Ty = decl->getType();
|
||||
else if (const TypedefDecl* decl = dyn_cast<TypedefDecl>(d))
|
||||
else if (const TypedefNameDecl* decl = dyn_cast<TypedefNameDecl>(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<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefDecl>(d);
|
||||
// In some sense, TypedefNameDecl really *ought* to be a DeclaratorDecl.
|
||||
return isa<DeclaratorDecl>(d) || isa<BlockDecl>(d) || isa<TypedefNameDecl>(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<TypedefDecl>(d);
|
||||
TypedefNameDecl *tDecl = dyn_cast<TypedefNameDecl>(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<TypedefDecl>(D)) {
|
||||
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
|
||||
QualType T = TD->getUnderlyingType();
|
||||
if (!T->isPointerType() ||
|
||||
!T->getAs<PointerType>()->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<TypedefDecl>(d);
|
||||
TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(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<TypedefDecl>(D))
|
||||
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D))
|
||||
OldTy = TD->getUnderlyingType();
|
||||
else if (ValueDecl *VD = dyn_cast<ValueDecl>(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<TypedefDecl>(D)) {
|
||||
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) {
|
||||
// FIXME: preserve existing source info.
|
||||
TD->setTypeSourceInfo(S.Context.getTrivialTypeSourceInfo(NewTy));
|
||||
} else
|
||||
|
|
|
@ -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<TypedefType>(DeclaratorType))
|
||||
if (const TypedefType *TT = DeclaratorType->getAs<TypedefType>())
|
||||
Diag(D.getIdentifierLoc(), diag::err_destructor_typedef_name)
|
||||
<< DeclaratorType;
|
||||
<< DeclaratorType << isa<TypeAliasDecl>(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<TypedefDecl>(D1))
|
||||
if (TypedefDecl *TD2 = dyn_cast<TypedefDecl>(D2)) {
|
||||
if (TypedefNameDecl *TD1 = dyn_cast<TypedefNameDecl>(D1))
|
||||
if (TypedefNameDecl *TD2 = dyn_cast<TypedefNameDecl>(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,
|
||||
|
|
|
@ -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<TypedefDecl>(PrevDecl)) {
|
||||
if (const TypedefNameDecl *TDecl =
|
||||
dyn_cast_or_null<TypedefNameDecl>(PrevDecl)) {
|
||||
QualType T = TDecl->getUnderlyingType();
|
||||
if (T->isObjCObjectType()) {
|
||||
if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface())
|
||||
|
@ -193,7 +194,7 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc,
|
|||
}
|
||||
}
|
||||
|
||||
if (!dyn_cast_or_null<TypedefDecl>(PrevDecl)) {
|
||||
if (!dyn_cast_or_null<TypedefNameDecl>(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<TypedefDecl>(CDeclU)) {
|
||||
if (const TypedefNameDecl *TDecl =
|
||||
dyn_cast_or_null<TypedefNameDecl>(CDeclU)) {
|
||||
QualType T = TDecl->getUnderlyingType();
|
||||
if (T->isObjCObjectType()) {
|
||||
if (NamedDecl *IDecl = T->getAs<ObjCObjectType>()->getInterface()) {
|
||||
|
@ -1242,7 +1244,7 @@ Sema::ActOnForwardClassDeclaration(SourceLocation AtClassLoc,
|
|||
// @class XCElementToggler;
|
||||
//
|
||||
// FIXME: Make an extension?
|
||||
TypedefDecl *TDD = dyn_cast<TypedefDecl>(PrevDecl);
|
||||
TypedefNameDecl *TDD = dyn_cast<TypedefNameDecl>(PrevDecl);
|
||||
if (!TDD || !TDD->getUnderlyingType()->isObjCObjectType()) {
|
||||
Diag(AtClassLoc, diag::err_redefinition_different_kind) << IdentList[i];
|
||||
Diag(PrevDecl->getLocation(), diag::note_previous_definition);
|
||||
|
|
|
@ -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<TypedefDecl>(D)) {
|
||||
if (isa<TypedefNameDecl>(D)) {
|
||||
S.Diag(Loc, diag::err_unexpected_typedef) << D->getDeclName();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -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<TagDecl>(ND))
|
||||
return TD->getPreviousDeclaration();
|
||||
if (TypedefDecl *TD = dyn_cast<TypedefDecl>(ND))
|
||||
if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(ND))
|
||||
return TD->getPreviousDeclaration();
|
||||
if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND))
|
||||
return FTD->getPreviousDeclaration();
|
||||
|
|
|
@ -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<TagType>()) {
|
||||
TagDecl *oldTag = oldTagType->getDecl();
|
||||
if (oldTag->getTypedefForAnonDecl() == D) {
|
||||
if (oldTag->getTypedefNameForAnonDecl() == D) {
|
||||
TagDecl *newTag = DI->getType()->castAs<TagType>()->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<TypedefDecl>(InstPrev));
|
||||
Typedef->setPreviousDeclaration(cast<TypedefNameDecl>(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.
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<TypedefDecl>(D);
|
||||
TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
|
||||
if (TD && (TD->getUnderlyingType()->isFunctionPointerType() ||
|
||||
TD->getUnderlyingType()->isFunctionType()))
|
||||
return;
|
||||
|
|
|
@ -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<TypedefDecl>(SomeDecl)) Kind = 1;
|
||||
else if (isa<ClassTemplateDecl>(SomeDecl)) Kind = 2;
|
||||
else if (isa<TypeAliasDecl>(SomeDecl)) Kind = 2;
|
||||
else if (isa<ClassTemplateDecl>(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<typename Derived>
|
|||
QualType TreeTransform<Derived>::TransformTypedefType(TypeLocBuilder &TLB,
|
||||
TypedefTypeLoc TL) {
|
||||
const TypedefType *T = TL.getTypePtr();
|
||||
TypedefDecl *Typedef
|
||||
= cast_or_null<TypedefDecl>(getDerived().TransformDecl(TL.getNameLoc(),
|
||||
T->getDecl()));
|
||||
TypedefNameDecl *Typedef
|
||||
= cast_or_null<TypedefNameDecl>(getDerived().TransformDecl(TL.getNameLoc(),
|
||||
T->getDecl()));
|
||||
if (!Typedef)
|
||||
return QualType();
|
||||
|
||||
|
|
|
@ -3151,7 +3151,7 @@ QualType ASTReader::ReadTypeRecord(unsigned Index) {
|
|||
Error("incorrect encoding of typedef type");
|
||||
return QualType();
|
||||
}
|
||||
TypedefDecl *Decl = cast<TypedefDecl>(GetDecl(Record[0]));
|
||||
TypedefNameDecl *Decl = cast<TypedefNameDecl>(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<TypedefDecl>(GetDecl(ExtVectorDecls[I])));
|
||||
cast<TypedefNameDecl>(GetDecl(ExtVectorDecls[I])));
|
||||
|
||||
// FIXME: Do VTable uses and dynamic classes deserialize too much ?
|
||||
// Can we cut them down before writing them ?
|
||||
|
|
|
@ -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<TypedefDecl>(Reader.GetDecl(Record[Idx++])));
|
||||
TD->setTypedefNameForAnonDecl(
|
||||
cast_or_null<TypedefNameDecl>(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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<RefKind>(td->getName())
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
}
|
|
@ -63,7 +63,7 @@ enum E : auto {}; // expected-error{{'auto' not allowed here}}
|
|||
struct F : auto {}; // expected-error{{expected class name}}
|
||||
template<typename T = auto> 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}}
|
||||
|
|
|
@ -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<typename...T> void f0() {
|
||||
using U = T*; // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
|
||||
U u;
|
||||
}
|
||||
template void f0<int, char>();
|
||||
|
||||
void f1() {
|
||||
using T = int;
|
||||
}
|
||||
void f2() {
|
||||
using T = int[-1]; // expected-error {{array size is negative}}
|
||||
}
|
||||
|
||||
template<typename...T> 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<typename...T> class C3 {
|
||||
using f = T; // expected-error {{declaration type contains unexpanded parameter pack 'T'}}
|
||||
};
|
||||
template<typename T> 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<typename T, typename U> 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<void*, cell*>; // 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}}
|
||||
}
|
|
@ -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}}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче