[cfe-commits] r172382 - in /cfe/trunk: include/clang/Basic/Attr.td include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaType.cpp test/Parser/cxx0x-attributes.cpp

Richard Smith richard-llvm at metafoo.co.uk
Sun Jan 13 23:53:02 PST 2013


Author: rsmith
Date: Mon Jan 14 01:53:01 2013
New Revision: 172382

URL: http://llvm.org/viewvc/llvm-project?rev=172382&view=rev
Log:
Accept [[gnu::*]] for all __attribute__((*))s which are:
 1) Supported by Clang, and
 2) Supported by GCC, and
 3) Documented in GCC's manual.

g++ allows its C++11-style attributes to appertain only to the entity being
declared, and never to a type (even for a type attribute), so we do the same.

Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/SemaType.cpp
    cfe/trunk/test/Parser/cxx0x-attributes.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=172382&r1=172381&r2=172382&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Mon Jan 14 01:53:01 2013
@@ -29,7 +29,7 @@
   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 : SubsetSubject<Var, "non-register, non-parameter variable",
                               [{S->getStorageClass() != VarDecl::Register &&
@@ -136,12 +136,12 @@
 }
 
 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 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 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 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 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 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 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 Malloc : InheritableAttr {
-  let Spellings = [GNU<"malloc">];
+  let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">];
 }
 
 def MaxFieldAlignment : InheritableAttr {
@@ -384,7 +385,7 @@
 }
 
 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 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 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 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 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 Packed : InheritableAttr {
-  let Spellings = [GNU<"packed">];
+  let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">];
 }
 
 def PnaclCall : InheritableAttr {
@@ -570,18 +572,18 @@
 }
 
 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 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 TransparentUnion : InheritableAttr {
-  let Spellings = [GNU<"transparent_union">];
+  let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">];
 }
 
 def Unavailable : InheritableAttr {
@@ -658,11 +661,11 @@
 }
 
 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 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 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 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 WeakRef : InheritableAttr {
-  let Spellings = [GNU<"weakref">];
+  let Spellings = [GNU<"weakref">, CXX11<"gnu", "weakref">];
 }
 
 def X86ForceAlignArgPointer : InheritableAttr {

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=172382&r1=172381&r2=172382&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Jan 14 01:53:01 2013
@@ -1761,6 +1761,9 @@
    InGroup<IgnoredAttributes>;
 def warn_unknown_attribute_ignored : Warning<
   "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
+def warn_cxx11_gnu_attribute_on_type : Warning<
+  "attribute %0 ignored, because it cannot be applied to a type">,
+  InGroup<IgnoredAttributes>;
 def warn_unhandled_ms_attribute_ignored : Warning<
   "__declspec attribute %0 is not supported">, 
   InGroup<IgnoredAttributes>;

Modified: cfe/trunk/lib/Sema/SemaType.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=172382&r1=172381&r2=172382&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaType.cpp (original)
+++ cfe/trunk/lib/Sema/SemaType.cpp Mon Jan 14 01:53:01 2013
@@ -270,8 +270,18 @@
   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 @@
   // 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 @@
     // "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 @@
 
     // See if there are any attributes on this declarator chunk.
     if (AttributeList *attrs = const_cast<AttributeList*>(DeclType.getAttrs()))
-      processTypeAttrs(state, T, false, attrs);
+      processTypeAttrs(state, T, TAL_DeclChunk, attrs);
   }
 
   if (LangOpts.CPlusPlus && T->isFunctionType()) {
@@ -2753,7 +2763,7 @@
   // 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 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 @@
     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 @@
 
       // 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.

Modified: cfe/trunk/test/Parser/cxx0x-attributes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Parser/cxx0x-attributes.cpp?rev=172382&r1=172381&r2=172382&view=diff
==============================================================================
--- cfe/trunk/test/Parser/cxx0x-attributes.cpp (original)
+++ cfe/trunk/test/Parser/cxx0x-attributes.cpp Mon Jan 14 01:53:01 2013
@@ -247,14 +247,18 @@
 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}}





More information about the cfe-commits mailing list