Index: include/clang/Basic/Attr.td
===================================================================
--- include/clang/Basic/Attr.td	(revision 199817)
+++ include/clang/Basic/Attr.td	(working copy)
@@ -74,12 +74,6 @@
                                        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 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 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 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 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 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 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,13 +516,13 @@
 }
 
 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]>;
 }
@@ -529,7 +529,7 @@
 
 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 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 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,7 +572,7 @@
 }
 
 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">;
@@ -579,12 +579,12 @@
 }
 
 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 Malloc : InheritableAttr {
-  let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">];
+  let Spellings = [GCC<"malloc">];
 //  let Subjects = [Function];
 }
 
@@ -623,11 +623,12 @@
 }
 
 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 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 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 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 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 Overloadable : Attr {
   let Spellings = [GNU<"overloadable">];
-  let Subjects = SubjectList<[FunctionDefinition], ErrorDiag>;
+  let Subjects = SubjectList<[Function], ErrorDiag>;
 }
 
 def Override : InheritableAttr { 
@@ -852,7 +849,7 @@
 }
 
 def Packed : InheritableAttr {
-  let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">];
+  let Spellings = [GCC<"packed">];
 //  let Subjects = [Tag, Field];
 }
 
@@ -867,7 +864,7 @@
 }
 
 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 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 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,7 +911,7 @@
 }
 
 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]>;
@@ -921,19 +918,18 @@
 }
 
 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 TransparentUnion : InheritableAttr {
-  let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">];
+  let Spellings = [GCC<"transparent_union">];
 //  let Subjects = SubjectList<[Record, TypedefName]>;
 }
 
@@ -974,7 +970,7 @@
 }
 
 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">;
@@ -981,7 +977,7 @@
 }
 
 def Used : InheritableAttr {
-  let Spellings = [GNU<"used">, CXX11<"gnu", "used">];
+  let Spellings = [GCC<"used">];
 }
 
 def Uuid : InheritableAttr {
@@ -992,7 +988,7 @@
 }
 
 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 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 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 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 @@
 
 // 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 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 @@
   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 @@
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def AssertExclusiveLock : InheritableAttr {
@@ -1180,7 +1173,7 @@
   let LateParsed = 1;
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def AssertSharedLock : InheritableAttr {
@@ -1189,7 +1182,7 @@
   let LateParsed = 1;
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 // The first argument is an integer or boolean value specifying the return value
@@ -1201,7 +1194,7 @@
   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
@@ -1213,7 +1206,7 @@
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def UnlockFunction : InheritableAttr {
@@ -1223,7 +1216,7 @@
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def LockReturned : InheritableAttr {
@@ -1232,7 +1225,7 @@
   let LateParsed = 1;
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def LocksExcluded : InheritableAttr {
@@ -1242,7 +1235,7 @@
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def ExclusiveLocksRequired : InheritableAttr {
@@ -1252,7 +1245,7 @@
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 def SharedLocksRequired : InheritableAttr {
@@ -1262,7 +1255,7 @@
   let TemplateDependent = 1;
   let ParseArgumentsAsUnevaluated = 1;
   let DuplicatesAllowedWhileMerging = 1;
-  let Subjects = SubjectList<[FunctionDefinition, FunctionTemplate]>;
+  let Subjects = SubjectList<[Function, FunctionTemplate]>;
 }
 
 // C/C++ consumed attributes.
@@ -1354,19 +1347,17 @@
 }
 
 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.
 }
Index: include/clang/Sema/AttributeList.h
===================================================================
--- include/clang/Sema/AttributeList.h	(revision 200041)
+++ include/clang/Sema/AttributeList.h	(working copy)
@@ -494,7 +494,7 @@
   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
Index: lib/Parse/ParseDecl.cpp
===================================================================
--- lib/Parse/ParseDecl.cpp	(revision 199817)
+++ lib/Parse/ParseDecl.cpp	(working copy)
@@ -1143,7 +1143,7 @@
 
   const AttributeList *AL = Attrs.getList();
   if (OnDefinition && AL && !AL->isCXX11Attribute() &&
-      !AL->canAppearOnFunctionDefinition())
+      AL->isKnownToGCC())
     Diag(Tok, diag::warn_attribute_on_function_definition)
       << &LA.AttrName;
 
Index: lib/Parse/Parser.cpp
===================================================================
--- lib/Parse/Parser.cpp	(revision 199817)
+++ lib/Parse/Parser.cpp	(working copy)
@@ -1055,7 +1055,7 @@
   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();
Index: lib/Sema/AttributeList.cpp
===================================================================
--- lib/Sema/AttributeList.cpp	(revision 200041)
+++ lib/Sema/AttributeList.cpp	(working copy)
@@ -150,7 +150,7 @@
   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 @@
   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 {
Index: utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- utils/TableGen/ClangAttrEmitter.cpp	(revision 200041)
+++ utils/TableGen/ClangAttrEmitter.cpp	(working copy)
@@ -26,6 +26,63 @@
 
 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")) {
+    if (V == "CXX11")
+      NS = Spelling.getValueAsString("Namespace");
+    bool Unset;
+    K = Spelling.getValueAsBitOrUnset("KnownToGCC", Unset);
+  }
+  FlattenedSpelling(const FlattenedSpelling &RHS) : V(RHS.V), N(RHS.N),
+    NS(RHS.NS), K(RHS.K) {}
+
+  FlattenedSpelling& operator=(const FlattenedSpelling &RHS) {
+    if (&RHS != this) {
+      V = RHS.V;
+      N = RHS.N;
+      NS = RHS.NS;
+      K = RHS.K;
+    }
+    return *this;
+  }
+
+  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 +1037,7 @@
 }
 
 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 +1052,7 @@
 
   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 +1061,7 @@
 
 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 +1083,8 @@
     // 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 +1092,7 @@
     } 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 +1139,18 @@
 }
 
 /// \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 +1165,15 @@
        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 +1182,14 @@
   }
 }
 
-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 +1198,7 @@
 
 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 +1207,14 @@
   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 +1303,7 @@
 
     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 +1478,12 @@
       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 +1503,12 @@
       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 +1531,12 @@
       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 +1778,10 @@
     } 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 +1800,19 @@
   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 +1917,14 @@
     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 +2084,6 @@
 
     uint32_t V = StringSwitch<uint32_t>(Name)
                    .Case("Function", Func)
-                   .Case("FunctionDefinition", Func)
                    .Case("Var", Var)
                    .Case("ObjCMethod", ObjCMethod)
                    .Case("ParmVar", Param)
@@ -2120,8 +2159,6 @@
   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 +2402,7 @@
   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 +2423,13 @@
   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 +2471,7 @@
     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 +2523,15 @@
       } 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 +2588,7 @@
     // 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";
 
