diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 858df3ae214a..1830a144b7a8 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -29,7 +29,7 @@ class SubsetSubject code CheckCode = check; } -// This is the type of a variable which C++0x defines [[aligned()]] as being +// This is the type of a variable which C++11 defines [[aligned()]] as being // a possible subject. def NormalVar : SubsetSubjectgetStorageClass() != VarDecl::Register && @@ -136,12 +136,12 @@ def AddressSpace : Attr { } def Alias : InheritableAttr { - let Spellings = [GNU<"alias">]; + let Spellings = [GNU<"alias">, CXX11<"gnu", "alias">]; let Args = [StringArgument<"Aliasee">]; } def Aligned : InheritableAttr { - let Spellings = [GNU<"aligned">, GNU<"align">]; + let Spellings = [GNU<"aligned">, GNU<"align">, CXX11<"gnu", "aligned">]; let Subjects = [NonBitField, NormalVar, Tag]; let Args = [AlignedArgument<"Alignment">, BoolArgument<"IsMSDeclSpec">]; } @@ -152,16 +152,16 @@ def AlignMac68k : InheritableAttr { } def AllocSize : Attr { - let Spellings = [GNU<"alloc_size">]; + let Spellings = [GNU<"alloc_size">, CXX11<"gnu", "alloc_size">]; let Args = [VariadicUnsignedArgument<"Args">]; } def AlwaysInline : InheritableAttr { - let Spellings = [GNU<"always_inline">]; + let Spellings = [GNU<"always_inline">, CXX11<"gnu", "always_inline">]; } def TLSModel : InheritableAttr { - let Spellings = [GNU<"tls_model">]; + let Spellings = [GNU<"tls_model">, CXX11<"gnu", "tls_model">]; let Subjects = [Var]; let Args = [StringArgument<"Model">]; } @@ -214,7 +214,7 @@ def CarriesDependency : InheritableParamAttr { } def CDecl : InheritableAttr { - let Spellings = [GNU<"cdecl">, GNU<"__cdecl">]; + let Spellings = [GNU<"cdecl">, GNU<"__cdecl">, CXX11<"gnu", "cdecl">]; } // cf_audited_transfer indicates that the given function has been @@ -250,24 +250,24 @@ def CFConsumed : InheritableParamAttr { } def Cleanup : InheritableAttr { - let Spellings = [GNU<"cleanup">]; + let Spellings = [GNU<"cleanup">, CXX11<"gnu", "cleanup">]; let Args = [FunctionArgument<"FunctionDecl">]; } def Cold : InheritableAttr { - let Spellings = [GNU<"cold">]; + let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">]; } def Common : InheritableAttr { - let Spellings = [GNU<"common">]; + let Spellings = [GNU<"common">, CXX11<"gnu", "common">]; } def Const : InheritableAttr { - let Spellings = [GNU<"const">, GNU<"__const">]; + let Spellings = [GNU<"const">, GNU<"__const">, CXX11<"gnu", "const">]; } def Constructor : InheritableAttr { - let Spellings = [GNU<"constructor">]; + let Spellings = [GNU<"constructor">, CXX11<"gnu", "constructor">]; let Args = [IntArgument<"Priority">]; } @@ -307,12 +307,12 @@ def OpenCLImageAccess : Attr { } def Deprecated : InheritableAttr { - let Spellings = [GNU<"deprecated">]; + let Spellings = [GNU<"deprecated">, CXX11<"gnu", "deprecated">]; let Args = [StringArgument<"Message">]; } def Destructor : InheritableAttr { - let Spellings = [GNU<"destructor">]; + let Spellings = [GNU<"destructor">, CXX11<"gnu", "destructor">]; let Args = [IntArgument<"Priority">]; } @@ -323,12 +323,13 @@ def ExtVectorType : Attr { } def FallThrough : Attr { - let Spellings = [CXX11<"clang","fallthrough">]; + let Spellings = [CXX11<"clang", "fallthrough">]; let Subjects = [NullStmt]; } def FastCall : InheritableAttr { - let Spellings = [GNU<"fastcall">, GNU<"__fastcall">]; + let Spellings = [GNU<"fastcall">, GNU<"__fastcall">, + CXX11<"gnu", "fastcall">]; } def Final : InheritableAttr { @@ -342,22 +343,22 @@ def MinSize : InheritableAttr { } def Format : InheritableAttr { - let Spellings = [GNU<"format">]; + let Spellings = [GNU<"format">, CXX11<"gnu", "format">]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">, IntArgument<"FirstArg">]; } def FormatArg : InheritableAttr { - let Spellings = [GNU<"format_arg">]; + let Spellings = [GNU<"format_arg">, CXX11<"gnu", "format_arg">]; let Args = [IntArgument<"FormatIdx">]; } def GNUInline : InheritableAttr { - let Spellings = [GNU<"gnu_inline">]; + let Spellings = [GNU<"gnu_inline">, CXX11<"gnu", "gnu_inline">]; } def Hot : InheritableAttr { - let Spellings = [GNU<"hot">]; + let Spellings = [GNU<"hot">, CXX11<"gnu", "hot">]; } def IBAction : InheritableAttr { @@ -374,7 +375,7 @@ def IBOutletCollection : InheritableAttr { } def Malloc : InheritableAttr { - let Spellings = [GNU<"malloc">]; + let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">]; } def MaxFieldAlignment : InheritableAttr { @@ -384,7 +385,7 @@ def MaxFieldAlignment : InheritableAttr { } def MayAlias : InheritableAttr { - let Spellings = [GNU<"may_alias">]; + let Spellings = [GNU<"may_alias">, CXX11<"gnu", "may_alias">]; } def MSP430Interrupt : InheritableAttr { @@ -404,13 +405,13 @@ def MBlazeSaveVolatiles : InheritableAttr { } def Mode : Attr { - let Spellings = [GNU<"mode">]; + let Spellings = [GNU<"mode">, CXX11<"gnu", "mode">]; let Args = [IdentifierArgument<"Mode">]; let ASTNode = 0; } def Naked : InheritableAttr { - let Spellings = [GNU<"naked">]; + let Spellings = [GNU<"naked">, CXX11<"gnu", "naked">]; } def NeonPolyVectorType : Attr { @@ -426,11 +427,11 @@ def NeonVectorType : Attr { } def ReturnsTwice : InheritableAttr { - let Spellings = [GNU<"returns_twice">]; + let Spellings = [GNU<"returns_twice">, CXX11<"gnu", "returns_twice">]; } def NoCommon : InheritableAttr { - let Spellings = [GNU<"nocommon">]; + let Spellings = [GNU<"nocommon">, CXX11<"gnu", "nocommon">]; } def NoDebug : InheritableAttr { @@ -438,11 +439,11 @@ def NoDebug : InheritableAttr { } def NoInline : InheritableAttr { - let Spellings = [GNU<"noinline">]; + let Spellings = [GNU<"noinline">, CXX11<"gnu", "noinline">]; } def NonNull : InheritableAttr { - let Spellings = [GNU<"nonnull">]; + let Spellings = [GNU<"nonnull">, CXX11<"gnu", "nonnull">]; let Args = [VariadicUnsignedArgument<"Args">]; let AdditionalMembers = [{bool isNonNull(unsigned idx) const { @@ -455,19 +456,20 @@ def NonNull : InheritableAttr { } def NoReturn : InheritableAttr { - let Spellings = [GNU<"noreturn">, CXX11<"","noreturn">, - CXX11<"std","noreturn">]; + let Spellings = [GNU<"noreturn">, CXX11<"gnu", "noreturn">, + CXX11<"", "noreturn">, CXX11<"std", "noreturn">]; // FIXME: Does GCC allow this on the function instead? let Subjects = [Function]; } def NoInstrumentFunction : InheritableAttr { - let Spellings = [GNU<"no_instrument_function">]; + let Spellings = [GNU<"no_instrument_function">, + CXX11<"gnu", "no_instrument_function">]; let Subjects = [Function]; } def NoThrow : InheritableAttr { - let Spellings = [GNU<"nothrow">]; + let Spellings = [GNU<"nothrow">, CXX11<"gnu", "nothrow">]; } def NSBridged : InheritableAttr { @@ -558,7 +560,7 @@ def Ownership : InheritableAttr { } def Packed : InheritableAttr { - let Spellings = [GNU<"packed">]; + let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">]; } def PnaclCall : InheritableAttr { @@ -570,18 +572,18 @@ def IntelOclBicc : InheritableAttr { } def Pcs : InheritableAttr { - let Spellings = [GNU<"pcs">]; + let Spellings = [GNU<"pcs">, CXX11<"gnu", "pcs">]; let Args = [EnumArgument<"PCS", "PCSType", ["aapcs", "aapcs-vfp"], ["AAPCS", "AAPCS_VFP"]>]; } def Pure : InheritableAttr { - let Spellings = [GNU<"pure">]; + let Spellings = [GNU<"pure">, CXX11<"gnu", "pure">]; } def Regparm : InheritableAttr { - let Spellings = [GNU<"regparm">]; + let Spellings = [GNU<"regparm">, CXX11<"gnu", "regparm">]; let Args = [UnsignedArgument<"NumParams">]; } @@ -604,22 +606,23 @@ def InitPriority : InheritableAttr { } def Section : InheritableAttr { - let Spellings = [GNU<"section">]; + let Spellings = [GNU<"section">, CXX11<"gnu", "section">]; let Args = [StringArgument<"Name">]; } def Sentinel : InheritableAttr { - let Spellings = [GNU<"sentinel">]; + let Spellings = [GNU<"sentinel">, CXX11<"gnu", "sentinel">]; let Args = [DefaultIntArgument<"Sentinel", 0>, DefaultIntArgument<"NullPos", 0>]; } def StdCall : InheritableAttr { - let Spellings = [GNU<"stdcall">, GNU<"__stdcall">]; + let Spellings = [GNU<"stdcall">, GNU<"__stdcall">, CXX11<"gnu", "stdcall">]; } def ThisCall : InheritableAttr { - let Spellings = [GNU<"thiscall">, GNU<"__thiscall">]; + let Spellings = [GNU<"thiscall">, GNU<"__thiscall">, + CXX11<"gnu", "thiscall">]; } def Pascal : InheritableAttr { @@ -627,7 +630,7 @@ def Pascal : InheritableAttr { } def TransparentUnion : InheritableAttr { - let Spellings = [GNU<"transparent_union">]; + let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">]; } def Unavailable : InheritableAttr { @@ -658,11 +661,11 @@ def ObjCRequiresPropertyDefs : InheritableAttr { } def Unused : InheritableAttr { - let Spellings = [GNU<"unused">]; + let Spellings = [GNU<"unused">, CXX11<"gnu", "unused">]; } def Used : InheritableAttr { - let Spellings = [GNU<"used">]; + let Spellings = [GNU<"used">, CXX11<"gnu", "used">]; } def Uuid : InheritableAttr { @@ -672,7 +675,7 @@ def Uuid : InheritableAttr { } def VectorSize : Attr { - let Spellings = [GNU<"vector_size">]; + let Spellings = [GNU<"vector_size">, CXX11<"gnu", "vector_size">]; let Args = [ExprArgument<"NumBytes">]; let ASTNode = 0; } @@ -686,7 +689,7 @@ def VecTypeHint : Attr { def Visibility : InheritableAttr { let Clone = 0; - let Spellings = [GNU<"visibility">]; + let Spellings = [GNU<"visibility">, CXX11<"gnu", "visibility">]; let Args = [EnumArgument<"Visibility", "VisibilityType", ["default", "hidden", "internal", "protected"], ["Default", "Hidden", "Hidden", "Protected"]>]; @@ -698,11 +701,13 @@ def VecReturn : InheritableAttr { } def WarnUnusedResult : InheritableAttr { - let Spellings = [GNU<"warn_unused_result">, CXX11<"clang","warn_unused_result">]; + let Spellings = [GNU<"warn_unused_result">, + CXX11<"clang", "warn_unused_result">, + CXX11<"gnu", "warn_unused_result">]; } def Weak : InheritableAttr { - let Spellings = [GNU<"weak">]; + let Spellings = [GNU<"weak">, CXX11<"gnu", "weak">]; } def WeakImport : InheritableAttr { @@ -710,7 +715,7 @@ def WeakImport : InheritableAttr { } def WeakRef : InheritableAttr { - let Spellings = [GNU<"weakref">]; + let Spellings = [GNU<"weakref">, CXX11<"gnu", "weakref">]; } def X86ForceAlignArgPointer : InheritableAttr { diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f61e31c7d9b1..3ea9df4d76c2 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1761,6 +1761,9 @@ def warn_attribute_after_definition_ignored : Warning< InGroup; def warn_unknown_attribute_ignored : Warning< "unknown attribute %0 ignored">, InGroup; +def warn_cxx11_gnu_attribute_on_type : Warning< + "attribute %0 ignored, because it cannot be applied to a type">, + InGroup; def warn_unhandled_ms_attribute_ignored : Warning< "__declspec attribute %0 is not supported">, InGroup; diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp index 930d98d44ac2..3b1dac348e83 100644 --- a/clang/lib/Sema/SemaType.cpp +++ b/clang/lib/Sema/SemaType.cpp @@ -270,8 +270,18 @@ static void moveAttrFromListToList(AttributeList &attr, spliceAttrIntoList(attr, toList); } +/// The location of a type attribute. +enum TypeAttrLocation { + /// The attribute is in the decl-specifier-seq. + TAL_DeclSpec, + /// The attribute is part of a DeclaratorChunk. + TAL_DeclChunk, + /// The attribute is immediately after the declaration's name. + TAL_DeclName +}; + static void processTypeAttrs(TypeProcessingState &state, - QualType &type, bool isDeclSpec, + QualType &type, TypeAttrLocation TAL, AttributeList *attrs); static bool handleFunctionTypeAttr(TypeProcessingState &state, @@ -963,7 +973,7 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) { // list of type attributes to be temporarily saved while the type // attributes are pushed around. if (AttributeList *attrs = DS.getAttributes().getList()) - processTypeAttrs(state, Result, true, attrs); + processTypeAttrs(state, Result, TAL_DeclSpec, attrs); // Apply const/volatile/restrict qualifiers to T. if (unsigned TypeQuals = DS.getTypeQualifiers()) { @@ -1859,7 +1869,7 @@ static QualType GetDeclSpecTypeForDeclarator(TypeProcessingState &state, // "void" instead. T = SemaRef.Context.VoidTy; if (AttributeList *attrs = D.getDeclSpec().getAttributes().getList()) - processTypeAttrs(state, T, true, attrs); + processTypeAttrs(state, T, TAL_DeclSpec, attrs); break; case UnqualifiedId::IK_ConversionFunctionId: @@ -2665,7 +2675,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // See if there are any attributes on this declarator chunk. if (AttributeList *attrs = const_cast(DeclType.getAttrs())) - processTypeAttrs(state, T, false, attrs); + processTypeAttrs(state, T, TAL_DeclChunk, attrs); } if (LangOpts.CPlusPlus && T->isFunctionType()) { @@ -2753,7 +2763,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state, // Apply any undistributed attributes from the declarator. if (!T.isNull()) if (AttributeList *attrs = D.getAttributes()) - processTypeAttrs(state, T, false, attrs); + processTypeAttrs(state, T, TAL_DeclName, attrs); // Diagnose any ignored type attributes. if (!T.isNull()) state.diagnoseIgnoredTypeAttrs(T); @@ -4150,7 +4160,7 @@ static void HandleNeonVectorTypeAttr(QualType& CurType, } static void processTypeAttrs(TypeProcessingState &state, QualType &type, - bool isDeclSpec, AttributeList *attrs) { + TypeAttrLocation TAL, AttributeList *attrs) { // Scan through and apply attributes to this type where it makes sense. Some // attributes (such as __address_space__, __vector_size__, etc) apply to the // type, but others can be present in the type specifiers even though they @@ -4165,6 +4175,20 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, if (attr.isInvalid()) continue; + // [[gnu::...]] attributes are treated as declaration attributes, so may + // not appertain to a DeclaratorChunk, even if we handle them as type + // attributes. + // FIXME: All other C++11 type attributes may *only* appertain to a type, + // and should only be considered here if they appertain to a + // DeclaratorChunk. + if (attr.isCXX11Attribute() && TAL == TAL_DeclChunk && + attr.getScopeName() && attr.getScopeName()->isStr("gnu")) { + state.getSema().Diag(attr.getLoc(), + diag::warn_cxx11_gnu_attribute_on_type) + << attr.getName(); + continue; + } + // If this is an attribute we can handle, do so now, // otherwise, add it to the FnAttrs list for rechaining. switch (attr.getKind()) { @@ -4225,7 +4249,7 @@ static void processTypeAttrs(TypeProcessingState &state, QualType &type, // Never process function type attributes as part of the // declaration-specifiers. - if (isDeclSpec) + if (TAL == TAL_DeclSpec) distributeFunctionTypeAttrFromDeclSpec(state, attr, type); // Otherwise, handle the possible delays. diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp index a1268a811834..dac159a03f49 100644 --- a/clang/test/Parser/cxx0x-attributes.cpp +++ b/clang/test/Parser/cxx0x-attributes.cpp @@ -247,14 +247,18 @@ enum class __attribute__((visibility("hidden"))) SecretKeepers { enum class [[]] EvenMoreSecrets {}; namespace arguments { - // FIXME: remove the sema warnings after migrating existing gnu attributes to c++11 syntax. - void f(const char*, ...) [[gnu::format(printf, 1, 2)]]; // expected-warning {{unknown attribute 'format' ignored}} + void f[[gnu::format(printf, 1, 2)]](const char*, ...); void g() [[unknown::foo(currently arguments of attributes from unknown namespace other than 'gnu' namespace are ignored... blah...)]]; // expected-warning {{unknown attribute 'foo' ignored}} } -// forbid attributes on decl specifiers +// Forbid attributes on decl specifiers. unsigned [[gnu::used]] static int [[gnu::unused]] v1; // expected-warning {{attribute 'unused' ignored, because it is not attached to a declaration}} \ expected-error {{an attribute list cannot appear here}} typedef [[gnu::used]] unsigned long [[gnu::unused]] v2; // expected-warning {{attribute 'unused' ignored, because it is not attached to a declaration}} \ expected-error {{an attribute list cannot appear here}} int [[carries_dependency]] foo(int [[carries_dependency]] x); // expected-warning 2{{attribute 'carries_dependency' ignored, because it is not attached to a declaration}} + +// Forbid [[gnu::...]] attributes on declarator chunks. +int *[[gnu::unused]] v3; // expected-warning {{attribute 'unused' ignored}} +int v4[2][[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}} +int v5()[[gnu::unused]]; // expected-warning {{attribute 'unused' ignored}}