r200252 - Add a new attribute meta-spelling called "GCC" -- it widens into being a GNU spelling, and a CXX11 spelling with the namespace "gnu". It also sets a bit on the spelling certifying that it is known to GCC. From this, we can warn about the extension appropriately. As a consequence, the FunctionDefinition functionality is completely removed.

Aaron Ballman aaron at aaronballman.com
Mon Jan 27 14:10:05 PST 2014


Author: aaronballman
Date: Mon Jan 27 16:10:04 2014
New Revision: 200252

URL: http://llvm.org/viewvc/llvm-project?rev=200252&view=rev
Log:
Add a new attribute meta-spelling called "GCC" -- it widens into being a GNU spelling, and a CXX11 spelling with the namespace "gnu". It also sets a bit on the spelling certifying that it is known to GCC. From this, we can warn about the extension appropriately. As a consequence, the FunctionDefinition functionality is completely removed.

Replacing the functionality from r199676, which didn't solve the problem as elegantly.

Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Sema/AttributeList.h
    cfe/trunk/lib/Parse/ParseDecl.cpp
    cfe/trunk/lib/Parse/Parser.cpp
    cfe/trunk/lib/Sema/AttributeList.cpp
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=200252&r1=200251&r2=200252&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Mon Jan 27 16:10:04 2014
@@ -74,12 +74,6 @@ def HasFunctionProto : SubsetSubject<Dec
                                        isa<ObjCMethodDecl>(S) ||
                                        isa<BlockDecl>(S)}]>;
 
-// This is a fake Decl node that represents a function definition as well as a
-// function declaration. This can be used for attributes which are allowed to
-// appear on the definition of a function that's been late parsed. It is
-// treated and diagnosed the same as a FunctionDecl.
-def FunctionDefinition : DDecl<Function, 1>;
-
 // A single argument to an attribute
 class Argument<string name, bit optional> {
   string Name = name;
@@ -132,6 +126,7 @@ class VariadicEnumArgument<string name,
 class Spelling<string name, string variety> {
   string Name = name;
   string Variety = variety;
+  bit KnownToGCC;
 }
 
 class GNU<string name> : Spelling<name, "GNU">;
@@ -141,6 +136,13 @@ class CXX11<string namespace, string nam
 }
 class Keyword<string name> : Spelling<name, "Keyword">;
 
+// The GCC spelling implies GNU<name, "GNU"> and CXX11<"gnu", name> and also
+// sets KnownToGCC to 1. This spelling should be used for any GCC-compatible
+// attributes.
+class GCC<string name> : Spelling<name, "GCC"> {
+  let KnownToGCC = 1;
+}
+
 class Accessor<string name, list<Spelling> spellings> {
   string Name = name;
   list<Spelling> Spellings = spellings;
@@ -270,16 +272,16 @@ def AddressSpace : TypeAttr {
 }
 
 def Alias : Attr {
-  let Spellings = [GNU<"alias">, CXX11<"gnu", "alias">];
+  let Spellings = [GCC<"alias">];
   let Args = [StringArgument<"Aliasee">];
 }
 
 def Aligned : InheritableAttr {
-  let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">,
-                   Keyword<"alignas">, Keyword<"_Alignas">];
+  let Spellings = [GCC<"aligned">, Declspec<"align">, Keyword<"alignas">,
+                   Keyword<"_Alignas">];
 //  let Subjects = SubjectList<[NonBitField, NormalVar, Tag]>;
   let Args = [AlignedArgument<"Alignment", 1>];
-  let Accessors = [Accessor<"isGNU", [GNU<"aligned">, CXX11<"gnu","aligned">]>,
+  let Accessors = [Accessor<"isGNU", [GCC<"aligned">]>,
                    Accessor<"isC11", [Keyword<"_Alignas">]>,
                    Accessor<"isAlignas", [Keyword<"alignas">,
                                           Keyword<"_Alignas">]>,
@@ -293,12 +295,12 @@ def AlignMac68k : InheritableAttr {
 }
 
 def AlwaysInline : InheritableAttr {
-  let Spellings = [GNU<"always_inline">, CXX11<"gnu", "always_inline">];
+  let Spellings = [GCC<"always_inline">];
   let Subjects = SubjectList<[Function]>;
 }
 
 def TLSModel : InheritableAttr {
-  let Spellings = [GNU<"tls_model">, CXX11<"gnu", "tls_model">];
+  let Spellings = [GCC<"tls_model">];
   let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">;
   let Args = [StringArgument<"Model">];
 }
@@ -363,8 +365,7 @@ def CarriesDependency : InheritableParam
 }
 
 def CDecl : InheritableAttr {
-  let Spellings = [GNU<"cdecl">, CXX11<"gnu", "cdecl">, Keyword<"__cdecl">,
-                   Keyword<"_cdecl">];
+  let Spellings = [GCC<"cdecl">, Keyword<"__cdecl">, Keyword<"_cdecl">];
 //  let Subjects = [Function, ObjCMethod];
 }
 
@@ -401,28 +402,27 @@ def CFConsumed : InheritableParamAttr {
 }
 
 def Cleanup : InheritableAttr {
-  let Spellings = [GNU<"cleanup">, CXX11<"gnu", "cleanup">];
+  let Spellings = [GCC<"cleanup">];
   let Args = [FunctionArgument<"FunctionDecl">];
   let Subjects = SubjectList<[Var]>;
 }
 
 def Cold : InheritableAttr {
-  let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">];
+  let Spellings = [GCC<"cold">];
   let Subjects = SubjectList<[Function]>;
 }
 
 def Common : InheritableAttr {
-  let Spellings = [GNU<"common">, CXX11<"gnu", "common">];
+  let Spellings = [GCC<"common">];
   let Subjects = SubjectList<[Var]>;
 }
 
 def Const : InheritableAttr {
-  let Spellings = [GNU<"const">, GNU<"__const">,
-                   CXX11<"gnu", "const">, CXX11<"gnu", "__const">];
+  let Spellings = [GCC<"const">, GCC<"__const">];
 }
 
 def Constructor : InheritableAttr {
-  let Spellings = [GNU<"constructor">, CXX11<"gnu", "constructor">];
+  let Spellings = [GCC<"constructor">];
   let Args = [DefaultIntArgument<"Priority", 65535>];
   let Subjects = SubjectList<[Function]>;
 }
@@ -516,20 +516,20 @@ def OpenCLConstantAddressSpace : TypeAtt
 }
 
 def Deprecated : InheritableAttr {
-  let Spellings = [GNU<"deprecated">, Declspec<"deprecated">,
-                   CXX11<"gnu", "deprecated">, CXX11<"","deprecated">];
+  let Spellings = [GCC<"deprecated">, Declspec<"deprecated">,
+                   CXX11<"","deprecated">];
   let Args = [StringArgument<"Message", 1>];
 }
 
 def Destructor : InheritableAttr {
-  let Spellings = [GNU<"destructor">, CXX11<"gnu", "destructor">];
+  let Spellings = [GCC<"destructor">];
   let Args = [DefaultIntArgument<"Priority", 65535>];
   let Subjects = SubjectList<[Function]>;
 }
 
 def EnableIf : InheritableAttr {
   let Spellings = [GNU<"enable_if">];
-  let Subjects = SubjectList<[FunctionDefinition]>;
+  let Subjects = SubjectList<[Function]>;
   let Args = [ExprArgument<"Cond">, StringArgument<"Message">];
   let TemplateDependent = 1;
 }
@@ -547,8 +547,8 @@ def FallThrough : Attr {
 }
 
 def FastCall : InheritableAttr {
-  let Spellings = [GNU<"fastcall">, CXX11<"gnu", "fastcall">,
-                   Keyword<"__fastcall">, Keyword<"_fastcall">];
+  let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">,
+                   Keyword<"_fastcall">];
 //  let Subjects = [Function, ObjCMethod];
 }
 
@@ -564,7 +564,7 @@ def MinSize : InheritableAttr {
 }
 
 def Format : InheritableAttr {
-  let Spellings = [GNU<"format">, CXX11<"gnu", "format">];
+  let Spellings = [GCC<"format">];
   let Args = [IdentifierArgument<"Type">, IntArgument<"FormatIdx">,
               IntArgument<"FirstArg">];
   let Subjects = SubjectList<[ObjCMethod, Block, HasFunctionProto], WarnDiag,
@@ -572,19 +572,19 @@ def Format : InheritableAttr {
 }
 
 def FormatArg : InheritableAttr {
-  let Spellings = [GNU<"format_arg">, CXX11<"gnu", "format_arg">];
+  let Spellings = [GCC<"format_arg">];
   let Args = [IntArgument<"FormatIdx">];
   let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag,
                              "ExpectedFunction">;
 }
 
 def GNUInline : InheritableAttr {
-  let Spellings = [GNU<"gnu_inline">, CXX11<"gnu", "gnu_inline">];
+  let Spellings = [GCC<"gnu_inline">];
   let Subjects = SubjectList<[Function]>;
 }
 
 def Hot : InheritableAttr {
-  let Spellings = [GNU<"hot">, CXX11<"gnu", "hot">];
+  let Spellings = [GCC<"hot">];
   let Subjects = SubjectList<[Function]>;
   // An AST node is created for this attribute, but not actually used beyond
   // semantic checking for mutual exclusion with the Cold attribute.
@@ -611,7 +611,7 @@ def IBOutletCollection : InheritableAttr
 }
 
 def Malloc : InheritableAttr {
-  let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">];
+  let Spellings = [GCC<"malloc">];
 //  let Subjects = [Function];
 }
 
@@ -623,11 +623,12 @@ def MaxFieldAlignment : InheritableAttr
 }
 
 def MayAlias : InheritableAttr {
-  let Spellings = [GNU<"may_alias">, CXX11<"gnu", "may_alias">];
+  // FIXME: this is a type attribute in GCC, but a declaration attribute here.
+  let Spellings = [GCC<"may_alias">];
 }
 
 def MSABI : InheritableAttr {
-  let Spellings = [GNU<"ms_abi">, CXX11<"gnu", "ms_abi">];
+  let Spellings = [GCC<"ms_abi">];
 //  let Subjects = [Function, ObjCMethod];
 }
 
@@ -641,17 +642,17 @@ def MSP430Interrupt : InheritableAttr, T
 }
 
 def Mips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
-  let Spellings = [GNU<"mips16">, CXX11<"gnu", "mips16">];
+  let Spellings = [GCC<"mips16">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
 }
 
 def Mode : Attr {
-  let Spellings = [GNU<"mode">, CXX11<"gnu", "mode">];
+  let Spellings = [GCC<"mode">];
   let Args = [IdentifierArgument<"Mode">];
 }
 
 def Naked : InheritableAttr {
-  let Spellings = [GNU<"naked">, CXX11<"gnu", "naked">, Declspec<"naked">];
+  let Spellings = [GCC<"naked">, Declspec<"naked">];
   let Subjects = SubjectList<[Function]>;
 }
 
@@ -666,12 +667,12 @@ def NeonVectorType : TypeAttr {
 }
 
 def ReturnsTwice : InheritableAttr {
-  let Spellings = [GNU<"returns_twice">, CXX11<"gnu", "returns_twice">];
+  let Spellings = [GCC<"returns_twice">];
   let Subjects = SubjectList<[Function]>;
 }
 
 def NoCommon : InheritableAttr {
-  let Spellings = [GNU<"nocommon">, CXX11<"gnu", "nocommon">];
+  let Spellings = [GCC<"nocommon">];
   let Subjects = SubjectList<[Var]>;
 }
 
@@ -680,18 +681,17 @@ def NoDebug : InheritableAttr {
 }
 
 def NoInline : InheritableAttr {
-  let Spellings = [GNU<"noinline">, CXX11<"gnu", "noinline">,
-                   Declspec<"noinline">];
+  let Spellings = [GCC<"noinline">, Declspec<"noinline">];
   let Subjects = SubjectList<[Function]>;
 }
 
 def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> {
-  let Spellings = [GNU<"nomips16">, CXX11<"gnu", "nomips16">];
+  let Spellings = [GCC<"nomips16">];
   let Subjects = SubjectList<[Function], ErrorDiag>;
 }
 
 def NonNull : InheritableAttr {
-  let Spellings = [GNU<"nonnull">, CXX11<"gnu", "nonnull">];
+  let Spellings = [GCC<"nonnull">];
   let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag,
                              "ExpectedFunctionMethodOrParameter">;
   let Args = [VariadicUnsignedArgument<"Args">];
@@ -706,26 +706,23 @@ def NonNull : InheritableAttr {
 }
 
 def ReturnsNonNull : InheritableAttr {
-  let Spellings = [GNU<"returns_nonnull">, CXX11<"gnu", "returns_nonnull">];
+  let Spellings = [GCC<"returns_nonnull">];
   let Subjects = SubjectList<[ObjCMethod, HasFunctionProto], WarnDiag,
                              "ExpectedFunctionOrMethod">;
 }
 
 def NoReturn : InheritableAttr {
-  let Spellings = [GNU<"noreturn">, CXX11<"gnu", "noreturn">,
-                   Declspec<"noreturn">];
+  let Spellings = [GCC<"noreturn">, Declspec<"noreturn">];
   // FIXME: Does GCC allow this on the function instead?
 }
 
 def NoInstrumentFunction : InheritableAttr {
-  let Spellings = [GNU<"no_instrument_function">,
-                   CXX11<"gnu", "no_instrument_function">];
+  let Spellings = [GCC<"no_instrument_function">];
   let Subjects = SubjectList<[Function]>;
 }
 
 def NoThrow : InheritableAttr {
-  let Spellings = [GNU<"nothrow">, CXX11<"gnu", "nothrow">,
-                   Declspec<"nothrow">];
+  let Spellings = [GCC<"nothrow">, Declspec<"nothrow">];
 }
 
 def ObjCBridge : InheritableAttr {
@@ -825,7 +822,7 @@ def ObjCDesignatedInitializer : Attr {
 
 def Overloadable : Attr {
   let Spellings = [GNU<"overloadable">];
-  let Subjects = SubjectList<[FunctionDefinition], ErrorDiag>;
+  let Subjects = SubjectList<[Function], ErrorDiag>;
 }
 
 def Override : InheritableAttr { 
@@ -852,7 +849,7 @@ def Ownership : InheritableAttr {
 }
 
 def Packed : InheritableAttr {
-  let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">];
+  let Spellings = [GCC<"packed">];
 //  let Subjects = [Tag, Field];
 }
 
@@ -867,7 +864,7 @@ def IntelOclBicc : InheritableAttr {
 }
 
 def Pcs : InheritableAttr {
-  let Spellings = [GNU<"pcs">, CXX11<"gnu", "pcs">];
+  let Spellings = [GCC<"pcs">];
   let Args = [EnumArgument<"PCS", "PCSType",
                            ["aapcs", "aapcs-vfp"],
                            ["AAPCS", "AAPCS_VFP"]>];
@@ -875,11 +872,11 @@ def Pcs : InheritableAttr {
 }
 
 def Pure : InheritableAttr {
-  let Spellings = [GNU<"pure">, CXX11<"gnu", "pure">];
+  let Spellings = [GCC<"pure">];
 }
 
 def Regparm : TypeAttr {
-  let Spellings = [GNU<"regparm">, CXX11<"gnu", "regparm">];
+  let Spellings = [GCC<"regparm">];
   let Args = [UnsignedArgument<"NumParams">];
   let ASTNode = 0;
 }
@@ -906,7 +903,7 @@ def InitPriority : InheritableAttr {
 }
 
 def Section : InheritableAttr {
-  let Spellings = [GNU<"section">, CXX11<"gnu", "section">];
+  let Spellings = [GCC<"section">];
   let Args = [StringArgument<"Name">];
   let Subjects = SubjectList<[Function, GlobalVar, 
                               ObjCMethod, ObjCProperty], ErrorDiag,
@@ -914,26 +911,25 @@ def Section : InheritableAttr {
 }
 
 def Sentinel : InheritableAttr {
-  let Spellings = [GNU<"sentinel">, CXX11<"gnu", "sentinel">];
+  let Spellings = [GCC<"sentinel">];
   let Args = [DefaultIntArgument<"Sentinel", 0>,
               DefaultIntArgument<"NullPos", 0>];
 //  let Subjects = SubjectList<[Function, ObjCMethod, Block, Var]>;
 }
 
 def StdCall : InheritableAttr {
-  let Spellings = [GNU<"stdcall">, CXX11<"gnu", "stdcall">,
-                   Keyword<"__stdcall">, Keyword<"_stdcall">];
+  let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">];
 //  let Subjects = [Function, ObjCMethod];
 }
 
 def SysVABI : InheritableAttr {
-  let Spellings = [GNU<"sysv_abi">, CXX11<"gnu", "sysv_abi">];
+  let Spellings = [GCC<"sysv_abi">];
 //  let Subjects = [Function, ObjCMethod];
 }
 
 def ThisCall : InheritableAttr {
-  let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">,
-                   Keyword<"__thiscall">, Keyword<"_thiscall">];
+  let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">,
+                   Keyword<"_thiscall">];
 //  let Subjects = [Function, ObjCMethod];
 }
 
@@ -943,7 +939,7 @@ def Pascal : InheritableAttr {
 }
 
 def TransparentUnion : InheritableAttr {
-  let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">];
+  let Spellings = [GCC<"transparent_union">];
 //  let Subjects = SubjectList<[Record, TypedefName]>;
 }
 
@@ -974,14 +970,14 @@ def ObjCRequiresPropertyDefs : Inheritab
 }
 
 def Unused : InheritableAttr {
-  let Spellings = [GNU<"unused">, CXX11<"gnu", "unused">];
+  let Spellings = [GCC<"unused">];
   let Subjects = SubjectList<[Var, ObjCIvar, Type, Label, Field, ObjCMethod,
                               FunctionLike], WarnDiag,
                              "ExpectedVariableFunctionOrLabel">;
 }
 
 def Used : InheritableAttr {
-  let Spellings = [GNU<"used">, CXX11<"gnu", "used">];
+  let Spellings = [GCC<"used">];
 }
 
 def Uuid : InheritableAttr {
@@ -992,7 +988,7 @@ def Uuid : InheritableAttr {
 }
 
 def VectorSize : TypeAttr {
-  let Spellings = [GNU<"vector_size">, CXX11<"gnu", "vector_size">];
+  let Spellings = [GCC<"vector_size">];
   let Args = [ExprArgument<"NumBytes">];
 }
 
@@ -1004,7 +1000,7 @@ def VecTypeHint : InheritableAttr {
 
 def Visibility : InheritableAttr {
   let Clone = 0;
-  let Spellings = [GNU<"visibility">, CXX11<"gnu", "visibility">];
+  let Spellings = [GCC<"visibility">];
   let Args = [EnumArgument<"Visibility", "VisibilityType",
                            ["default", "hidden", "internal", "protected"],
                            ["Default", "Hidden", "Hidden", "Protected"]>];
@@ -1030,15 +1026,14 @@ def WarnUnused : InheritableAttr {
 }
 
 def WarnUnusedResult : InheritableAttr {
-  let Spellings = [GNU<"warn_unused_result">,
-                   CXX11<"clang", "warn_unused_result">,
-                   CXX11<"gnu", "warn_unused_result">];
+  let Spellings = [GCC<"warn_unused_result">,
+                   CXX11<"clang", "warn_unused_result">];
   let Subjects = SubjectList<[ObjCMethod, CXXRecord, FunctionLike], WarnDiag,
                              "ExpectedFunctionMethodOrClass">;
 }
 
 def Weak : InheritableAttr {
-  let Spellings = [GNU<"weak">, CXX11<"gnu", "weak">];
+  let Spellings = [GCC<"weak">];
   let Subjects = SubjectList<[Var, Function, CXXRecord]>;
 }
 
@@ -1047,7 +1042,7 @@ def WeakImport : InheritableAttr {
 }
 
 def WeakRef : InheritableAttr {
-  let Spellings = [GNU<"weakref">, CXX11<"gnu", "weakref">];
+  let Spellings = [GCC<"weakref">];
   // A WeakRef that has an argument is treated as being an AliasAttr
   let Args = [StringArgument<"Aliasee", 1>];
   let Subjects = SubjectList<[Var, Function], ErrorDiag>;
@@ -1062,10 +1057,8 @@ def X86ForceAlignArgPointer : Inheritabl
 
 // Attribute to disable AddressSanitizer (or equivalent) checks.
 def NoSanitizeAddress : InheritableAttr {
-  let Spellings = [GNU<"no_address_safety_analysis">,
-                   GNU<"no_sanitize_address">,
-                   CXX11<"gnu", "no_address_safety_analysis">,
-                   CXX11<"gnu", "no_sanitize_address">];
+  let Spellings = [GCC<"no_address_safety_analysis">,
+                   GCC<"no_sanitize_address">];
   let Subjects = SubjectList<[Function, FunctionTemplate], ErrorDiag>;
 }
 
@@ -1107,7 +1100,7 @@ def ScopedLockable : InheritableAttr {
 
 def NoThreadSafetyAnalysis : InheritableAttr {
   let Spellings = [GNU<"no_thread_safety_analysis">];
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def GuardedBy : InheritableAttr {
@@ -1161,7 +1154,7 @@ def ExclusiveLockFunction : InheritableA
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def SharedLockFunction : InheritableAttr {
@@ -1171,7 +1164,7 @@ def SharedLockFunction : InheritableAttr
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def AssertExclusiveLock : InheritableAttr {
@@ -1181,7 +1174,7 @@ def AssertExclusiveLock : InheritableAtt
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def AssertSharedLock : InheritableAttr {
@@ -1191,7 +1184,7 @@ def AssertSharedLock : InheritableAttr {
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 // The first argument is an integer or boolean value specifying the return value
@@ -1203,7 +1196,7 @@ def ExclusiveTrylockFunction : Inheritab
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 // The first argument is an integer or boolean value specifying the return value
@@ -1215,7 +1208,7 @@ def SharedTrylockFunction : InheritableA
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def UnlockFunction : InheritableAttr {
@@ -1225,7 +1218,7 @@ def UnlockFunction : InheritableAttr {
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def LockReturned : InheritableAttr {
@@ -1234,7 +1227,7 @@ def LockReturned : InheritableAttr {
   let LateParsed = 1;
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def LocksExcluded : InheritableAttr {
@@ -1244,7 +1237,7 @@ def LocksExcluded : InheritableAttr {
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def ExclusiveLocksRequired : InheritableAttr {
@@ -1254,7 +1247,7 @@ def ExclusiveLocksRequired : Inheritable
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def SharedLocksRequired : InheritableAttr {
@@ -1264,7 +1257,7 @@ def SharedLocksRequired : InheritableAtt
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 // C/C++ consumed attributes.
@@ -1356,19 +1349,17 @@ def MsProperty : IgnoredAttr {
 }
 
 def MsStruct : InheritableAttr {
-  let Spellings = [GNU<"ms_struct">, CXX11<"gnu", "ms_struct">];
+  let Spellings = [GCC<"ms_struct">];
   let Subjects = SubjectList<[Record]>;
 }
 
 def DLLExport : InheritableAttr, TargetSpecificAttr<TargetX86Win> {
-  let Spellings = [Declspec<"dllexport">, GNU<"dllexport">,
-                   CXX11<"gnu", "dllexport">];
+  let Spellings = [Declspec<"dllexport">, GCC<"dllexport">];
   let Subjects = SubjectList<[Function, Var]>;
 }
 
 def DLLImport : InheritableAttr, TargetSpecificAttr<TargetX86Win> {
-  let Spellings = [Declspec<"dllimport">, GNU<"dllimport">,
-                   CXX11<"gnu", "dllimport">];
+  let Spellings = [Declspec<"dllimport">, GCC<"dllimport">];
   // Technically, the subjects for DllImport are Function and Var, but there is
   // custom semantic handling required when MicrosoftExt is true.
 }

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=200252&r1=200251&r2=200252&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Mon Jan 27 16:10:04 2014
@@ -494,7 +494,7 @@ public:
   bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
   bool diagnoseLangOpts(class Sema &S) const;
   bool existsInTarget(llvm::Triple T) const;
-  bool canAppearOnFunctionDefinition() const;
+  bool isKnownToGCC() const;
 
   /// \brief If the parsed attribute has a semantic equivalent, and it would
   /// have a semantic Spelling enumeration (due to having semantically-distinct

Modified: cfe/trunk/lib/Parse/ParseDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?rev=200252&r1=200251&r2=200252&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/ParseDecl.cpp (original)
+++ cfe/trunk/lib/Parse/ParseDecl.cpp Mon Jan 27 16:10:04 2014
@@ -1143,7 +1143,7 @@ void Parser::ParseLexedAttribute(LatePar
 
   const AttributeList *AL = Attrs.getList();
   if (OnDefinition && AL && !AL->isCXX11Attribute() &&
-      !AL->canAppearOnFunctionDefinition())
+      AL->isKnownToGCC())
     Diag(Tok, diag::warn_attribute_on_function_definition)
       << &LA.AttrName;
 

Modified: cfe/trunk/lib/Parse/Parser.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/Parser.cpp?rev=200252&r1=200251&r2=200252&view=diff
==============================================================================
--- cfe/trunk/lib/Parse/Parser.cpp (original)
+++ cfe/trunk/lib/Parse/Parser.cpp Mon Jan 27 16:10:04 2014
@@ -1055,7 +1055,7 @@ Decl *Parser::ParseFunctionDefinition(Pa
   if (Tok.isNot(tok::equal)) {
     AttributeList *DtorAttrs = D.getAttributes();
     while (DtorAttrs) {
-      if (!DtorAttrs->canAppearOnFunctionDefinition() &&
+      if (DtorAttrs->isKnownToGCC() &&
           !DtorAttrs->isCXX11Attribute()) {
         Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
           << DtorAttrs->getName();

Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=200252&r1=200251&r2=200252&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Mon Jan 27 16:10:04 2014
@@ -150,7 +150,7 @@ struct ParsedAttrInfo {
   unsigned HasCustomParsing : 1;
   unsigned IsTargetSpecific : 1;
   unsigned IsType : 1;
-  unsigned CanAppearOnFuncDef : 1;
+  unsigned IsKnownToGCC : 1;
 
   bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
                                const Decl *);
@@ -199,8 +199,8 @@ bool AttributeList::existsInTarget(llvm:
   return getInfo(*this).ExistsInTarget(T);
 }
 
-bool AttributeList::canAppearOnFunctionDefinition() const {
-  return getInfo(*this).CanAppearOnFuncDef;
+bool AttributeList::isKnownToGCC() const {
+  return getInfo(*this).IsKnownToGCC;
 }
 
 unsigned AttributeList::getSemanticSpelling() const {

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=200252&r1=200251&r2=200252&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Mon Jan 27 16:10:04 2014
@@ -26,6 +26,54 @@
 
 using namespace llvm;
 
+class FlattenedSpelling {
+  std::string V, N, NS;
+  bool K;
+
+public:
+  FlattenedSpelling(const std::string &Variety, const std::string &Name,
+                    const std::string &Namespace, bool KnownToGCC) :
+    V(Variety), N(Name), NS(Namespace), K(KnownToGCC) {}
+  explicit FlattenedSpelling(const Record &Spelling) :
+    V(Spelling.getValueAsString("Variety")),
+    N(Spelling.getValueAsString("Name")) {
+
+    assert(V != "GCC" && "Given a GCC spelling, which means this hasn't been"
+           "flattened!");
+    if (V == "CXX11")
+      NS = Spelling.getValueAsString("Namespace");
+    bool Unset;
+    K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
+  }
+
+  const std::string &variety() const { return V; }
+  const std::string &name() const { return N; }
+  const std::string &nameSpace() const { return NS; }
+  bool knownToGCC() const { return K; }
+};
+
+std::vector<FlattenedSpelling> GetFlattenedSpellings(const Record &Attr) {
+  std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
+  std::vector<FlattenedSpelling> Ret;
+
+  for (std::vector<Record *>::const_iterator I = Spellings.begin(),
+       E = Spellings.end(); I != E; ++I) {
+    const Record &Spelling = **I;
+
+    if (Spelling.getValueAsString("Variety") == "GCC") {
+      // Gin up two new spelling objects to add into the list.
+      Ret.push_back(FlattenedSpelling("GNU", Spelling.getValueAsString("Name"),
+                                      "", true));
+      Ret.push_back(FlattenedSpelling("CXX11",
+                                      Spelling.getValueAsString("Name"),
+                                      "gnu", true));
+    } else
+      Ret.push_back(FlattenedSpelling(Spelling));
+  }
+
+  return Ret;
+}
+
 static std::string ReadPCHRecord(StringRef type) {
   return StringSwitch<std::string>(type)
     .EndsWith("Decl *", "GetLocalDeclAs<" 
@@ -980,7 +1028,7 @@ static void writeAvailabilityValue(raw_o
 }
 
 static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
-  std::vector<Record *> Spellings = R.getValueAsListOfDefs("Spellings");
+  std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
 
   OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
   if (Spellings.empty()) {
@@ -995,7 +1043,7 @@ static void writeGetSpellingFunction(Rec
 
   for (unsigned I = 0; I < Spellings.size(); ++I)
     OS << "  case " << I << ":\n"
-          "    return \"" << Spellings[I]->getValueAsString("Name") << "\";\n";
+          "    return \"" << Spellings[I].name() << "\";\n";
   // End of the switch statement.
   OS << "  }\n";
   // End of the getSpelling function.
@@ -1004,7 +1052,7 @@ static void writeGetSpellingFunction(Rec
 
 static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
                                      raw_ostream &OS) {
-  std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
+  std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
 
   OS << "void " << R.getName() << "Attr::printPretty("
     << "raw_ostream &OS, const PrintingPolicy &Policy) const {\n";
@@ -1026,8 +1074,8 @@ static void writePrettyPrintFunction(Rec
     // The actual spelling of the name and namespace (if applicable)
     // of an attribute without considering prefix and suffix.
     llvm::SmallString<64> Spelling;
-    std::string Name = Spellings[I]->getValueAsString("Name");
-    std::string Variety = Spellings[I]->getValueAsString("Variety");
+    std::string Name = Spellings[I].name();
+    std::string Variety = Spellings[I].variety();
 
     if (Variety == "GNU") {
       Prefix = " __attribute__((";
@@ -1035,7 +1083,7 @@ static void writePrettyPrintFunction(Rec
     } else if (Variety == "CXX11") {
       Prefix = " [[";
       Suffix = "]]";
-      std::string Namespace = Spellings[I]->getValueAsString("Namespace");
+      std::string Namespace = Spellings[I].nameSpace();
       if (Namespace != "") {
         Spelling += Namespace;
         Spelling += "::";
@@ -1082,19 +1130,18 @@ static void writePrettyPrintFunction(Rec
 }
 
 /// \brief Return the index of a spelling in a spelling list.
-static unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList,
-                                     const Record &Spelling) {
+static unsigned
+getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
+                     const FlattenedSpelling &Spelling) {
   assert(SpellingList.size() && "Spelling list is empty!");
 
   for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
-    Record *S = SpellingList[Index];
-    if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety"))
+    const FlattenedSpelling &S = SpellingList[Index];
+    if (S.variety() != Spelling.variety())
       continue;
-    if (S->getValueAsString("Variety") == "CXX11" &&
-        S->getValueAsString("Namespace") !=
-        Spelling.getValueAsString("Namespace"))
+    if (S.nameSpace() != Spelling.nameSpace())
       continue;
-    if (S->getValueAsString("Name") != Spelling.getValueAsString("Name"))
+    if (S.name() != Spelling.name())
       continue;
 
     return Index;
@@ -1109,15 +1156,15 @@ static void writeAttrAccessorDefinition(
        E = Accessors.end(); I != E; ++I) {
     Record *Accessor = *I;
     std::string Name = Accessor->getValueAsString("Name");
-    std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs(
-      "Spellings");
-    std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings");
+    std::vector<FlattenedSpelling> Spellings = 
+      GetFlattenedSpellings(*Accessor);
+    std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
     assert(SpellingList.size() &&
            "Attribute with empty spelling list can't have accessors!");
 
     OS << "  bool " << Name << "() const { return SpellingListIndex == ";
     for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
-      OS << getSpellingListIndex(SpellingList, *Spellings[Index]);
+      OS << getSpellingListIndex(SpellingList, Spellings[Index]);
       if (Index != Spellings.size() -1)
         OS << " ||\n    SpellingListIndex == ";
       else
@@ -1126,14 +1173,14 @@ static void writeAttrAccessorDefinition(
   }
 }
 
-static bool SpellingNamesAreCommon(const std::vector<Record *>& Spellings) {
+static bool
+SpellingNamesAreCommon(const std::vector<FlattenedSpelling>& Spellings) {
   assert(!Spellings.empty() && "An empty list of spellings was provided");
   std::string FirstName = NormalizeNameForSpellingComparison(
-    Spellings.front()->getValueAsString("Name"));
-  for (std::vector<Record *>::const_iterator I = llvm::next(Spellings.begin()),
-       E = Spellings.end(); I != E; ++I) {
-    std::string Name = NormalizeNameForSpellingComparison(
-      (*I)->getValueAsString("Name"));
+    Spellings.front().name());
+  for (std::vector<FlattenedSpelling>::const_iterator
+       I = llvm::next(Spellings.begin()), E = Spellings.end(); I != E; ++I) {
+    std::string Name = NormalizeNameForSpellingComparison(I->name());
     if (Name != FirstName)
       return false;
   }
@@ -1142,7 +1189,7 @@ static bool SpellingNamesAreCommon(const
 
 typedef std::map<unsigned, std::string> SemanticSpellingMap;
 static std::string
-CreateSemanticSpellings(const std::vector<Record *> &Spellings,
+CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
                         SemanticSpellingMap &Map) {
   // The enumerants are automatically generated based on the variety,
   // namespace (if present) and name for each attribute spelling. However,
@@ -1151,17 +1198,14 @@ CreateSemanticSpellings(const std::vecto
   std::string Ret("  enum Spelling {\n");
   std::set<std::string> Uniques;
   unsigned Idx = 0;
-  for (std::vector<Record *>::const_iterator I = Spellings.begin(),
+  for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
         E = Spellings.end(); I != E; ++I, ++Idx) {
-    const Record &S = **I;
-    std::string Variety = S.getValueAsString("Variety");
-    std::string Spelling = S.getValueAsString("Name");
-    std::string Namespace = "";
+    const FlattenedSpelling &S = *I;
+    std::string Variety = S.variety();
+    std::string Spelling = S.name();
+    std::string Namespace = S.nameSpace();
     std::string EnumName = "";
 
-    if (Variety == "CXX11")
-      Namespace = S.getValueAsString("Namespace");
-
     EnumName += (Variety + "_");
     if (!Namespace.empty())
       EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
@@ -1250,7 +1294,7 @@ void EmitClangAttrClass(RecordKeeper &Re
 
     OS << "\npublic:\n";
 
-    std::vector<Record *> Spellings = R.getValueAsListOfDefs("Spellings");
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
 
     // If there are zero or one spellings, all spelling-related functionality
     // can be elided. If all of the spellings share the same name, the spelling
@@ -1425,13 +1469,12 @@ void EmitClangAttrTypeArgList(RecordKeep
       continue;
 
     // All these spellings take a single type argument.
-    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
     std::set<std::string> Emitted;
-    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
+    for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
          E = Spellings.end(); I != E; ++I) {
-      if (Emitted.insert((*I)->getValueAsString("Name")).second)
-        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
-           << "true" << ")\n";
+      if (Emitted.insert(I->name()).second)
+        OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
     }
   }
 }
@@ -1451,13 +1494,12 @@ void EmitClangAttrArgContextList(RecordK
       continue;
 
     // All these spellings take are parsed unevaluated.
-    std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
     std::set<std::string> Emitted;
-    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
+    for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
          E = Spellings.end(); I != E; ++I) {
-      if (Emitted.insert((*I)->getValueAsString("Name")).second)
-        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
-        << "true" << ")\n";
+      if (Emitted.insert(I->name()).second)
+        OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
     }
 
   }
@@ -1480,13 +1522,12 @@ void EmitClangAttrIdentifierArgList(Reco
       continue;
 
     // All these spellings take an identifier argument.
-    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
     std::set<std::string> Emitted;
-    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
+    for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
          E = Spellings.end(); I != E; ++I) {
-      if (Emitted.insert((*I)->getValueAsString("Name")).second)
-        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
-           << "true" << ")\n";
+      if (Emitted.insert(I->name()).second)
+        OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
     }
   }
 }
@@ -1728,12 +1769,10 @@ void EmitClangAttrSpellingList(RecordKee
     } else
       Test = "true";
 
-    std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
-    for (std::vector<Record*>::const_iterator I = Spellings.begin(),
-         E = Spellings.end(); I != E; ++I) {
-      OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " << Test;
-      OS << ")\n";
-    }
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
+    for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
+         E = Spellings.end(); I != E; ++I)
+      OS << ".Case(\"" << I->name() << "\", " << Test << ")\n";
   }
 
 }
@@ -1752,25 +1791,19 @@ void EmitClangAttrSpellingListIndex(Reco
   for (ParsedAttrMap::const_iterator I = Attrs.begin(), E = Attrs.end();
        I != E; ++I) {
     Record &R = *I->second;
-    std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings");
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
     OS << "  case AT_" << I->first << ": {\n";
     for (unsigned I = 0; I < Spellings.size(); ++ I) {
-      SmallString<16> Namespace;
-      if (Spellings[I]->getValueAsString("Variety") == "CXX11")
-        Namespace = Spellings[I]->getValueAsString("Namespace");
-      else
-        Namespace = "";
-
       OS << "    if (Name == \""
-        << Spellings[I]->getValueAsString("Name") << "\" && "
+        << Spellings[I].name() << "\" && "
         << "SyntaxUsed == "
-        << StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety"))
+        << StringSwitch<unsigned>(Spellings[I].variety())
           .Case("GNU", 0)
           .Case("CXX11", 1)
           .Case("Declspec", 2)
           .Case("Keyword", 3)
           .Default(0)
-        << " && Scope == \"" << Namespace << "\")\n"
+        << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
         << "        return " << I << ";\n";
     }
 
@@ -1875,16 +1908,14 @@ void EmitClangAttrLateParsedList(RecordK
     bool LateParsed = Attr.getValueAsBit("LateParsed");
 
     if (LateParsed) {
-      std::vector<Record*> Spellings =
-        Attr.getValueAsListOfDefs("Spellings");
+      std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
 
       // FIXME: Handle non-GNU attributes
-      for (std::vector<Record*>::const_iterator I = Spellings.begin(),
-           E = Spellings.end(); I != E; ++I) {
-        if ((*I)->getValueAsString("Variety") != "GNU")
+      for (std::vector<FlattenedSpelling>::const_iterator
+           I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
+        if (I->variety() != "GNU")
           continue;
-        OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", "
-           << LateParsed << ")\n";
+        OS << ".Case(\"" << I->name() << "\", " << LateParsed << ")\n";
       }
     }
   }
@@ -2044,7 +2075,6 @@ static std::string CalculateDiagnostic(c
 
     uint32_t V = StringSwitch<uint32_t>(Name)
                    .Case("Function", Func)
-                   .Case("FunctionDefinition", Func)
                    .Case("Var", Var)
                    .Case("ObjCMethod", ObjCMethod)
                    .Case("ParmVar", Param)
@@ -2120,8 +2150,6 @@ static std::string GetSubjectWithSuffix(
   std::string B = R->getName();
   if (B == "DeclBase")
     return "Decl";
-  else if (B == "FunctionDefinition")
-    return "FunctionDecl";
   return B + "Decl";
 }
 static std::string GenerateCustomAppertainsTo(const Record &Subject,
@@ -2365,7 +2393,7 @@ static std::string GenerateSpellingIndex
   if (!Attr.getValueAsBit("ASTNode"))
     return "defaultSpellingIndexToSemanticSpelling";
 
-  std::vector<Record *> Spellings = Attr.getValueAsListOfDefs("Spellings");
+  std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
 
   // If there are zero or one spellings, or all of the spellings share the same
   // name, we can also bail out early.
@@ -2386,19 +2414,13 @@ static std::string GenerateSpellingIndex
   return Name;
 }
 
-static bool CanAppearOnFuncDef(const Record &Attr) {
-  // Look at the subjects this function appertains to; if a FunctionDefinition
-  // appears in the list, then this attribute can appear on a function
-  // definition.
-  if (Attr.isValueUnset("Subjects"))
-    return false;
-
-  std::vector<Record *> Subjects = Attr.getValueAsDef("Subjects")->
-                                        getValueAsListOfDefs("Subjects");
-  for (std::vector<Record *>::const_iterator I = Subjects.begin(),
-       E = Subjects.end(); I != E; ++I) {
-    const Record &Subject = **I;
-    if (Subject.getName() == "FunctionDefinition")
+static bool IsKnownToGCC(const Record &Attr) {
+  // Look at the spellings for this subject; if there are any spellings which
+  // claim to be known to GCC, the attribute is known to GCC.
+  std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
+  for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
+       E = Spellings.end(); I != E; ++I) {
+    if (I->knownToGCC())
       return true;
   }
   return false;
@@ -2440,7 +2462,7 @@ void EmitClangAttrParsedAttrImpl(RecordK
     SS << ", " << I->second->getValueAsBit("HasCustomParsing");
     SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
     SS << ", " << I->second->isSubClassOf("TypeAttr");
-    SS << ", " << CanAppearOnFuncDef(*I->second);
+    SS << ", " << IsKnownToGCC(*I->second);
     SS << ", " << GenerateAppertainsTo(*I->second, OS);
     SS << ", " << GenerateLangOptRequirements(*I->second, OS);
     SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
@@ -2492,15 +2514,15 @@ void EmitClangAttrParsedAttrKinds(Record
       } else
         AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
 
-      std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings");
-      for (std::vector<Record*>::const_iterator I = Spellings.begin(),
-           E = Spellings.end(); I != E; ++I) {
-        std::string RawSpelling = (*I)->getValueAsString("Name");
+      std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
+      for (std::vector<FlattenedSpelling>::const_iterator
+           I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
+        std::string RawSpelling = I->name();
         std::vector<StringMatcher::StringPair> *Matches = 0;
-        std::string Spelling, Variety = (*I)->getValueAsString("Variety");
+        std::string Spelling, Variety = I->variety();
         if (Variety == "CXX11") {
           Matches = &CXX11;
-          Spelling += (*I)->getValueAsString("Namespace");
+          Spelling += I->nameSpace();
           Spelling += "::";
         } else if (Variety == "GNU")
           Matches = &GNU;
@@ -2557,7 +2579,7 @@ void EmitClangAttrDump(RecordKeeper &Rec
     // If the attribute has a semantically-meaningful name (which is determined
     // by whether there is a Spelling enumeration for it), then write out the
     // spelling used for the attribute.
-    std::vector<Record *> Spellings = R.getValueAsListOfDefs("Spellings");
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
     if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
       OS << "    OS << \" \" << A->getSpelling();\n";
 





More information about the cfe-commits mailing list