diff options
| -rw-r--r-- | clang/include/clang/Basic/Attr.td | 175 | ||||
| -rw-r--r-- | clang/include/clang/Sema/AttributeList.h | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Parse/Parser.cpp | 2 | ||||
| -rw-r--r-- | clang/lib/Sema/AttributeList.cpp | 6 | ||||
| -rw-r--r-- | clang/utils/TableGen/ClangAttrEmitter.cpp | 216 | 
6 files changed, 208 insertions, 195 deletions
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 9e23afcca36..a704f3bea31 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -74,12 +74,6 @@ def HasFunctionProto : SubsetSubject<DeclBase,                                         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, string type, list<string> values,  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 name> : Spelling<name, "CXX11"> {  }  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 : InheritableParamAttr {  }  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 : TypeAttr {  }  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, TargetSpecificAttr<TargetMSP430> {  }  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 : InheritableAttr {  }  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 : InheritableAttr, TargetSpecificAttr<TargetX86> {  // 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 : InheritableAttr {    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 : InheritableAttr {    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 : 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 @@ -1215,7 +1208,7 @@ def SharedTrylockFunction : InheritableAttr {    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 : InheritableAttr {    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 : InheritableAttr {    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.  } diff --git a/clang/include/clang/Sema/AttributeList.h b/clang/include/clang/Sema/AttributeList.h index 79630f730a8..8b686331085 100644 --- a/clang/include/clang/Sema/AttributeList.h +++ b/clang/include/clang/Sema/AttributeList.h @@ -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 diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index f6435f9eeaf..c295c766065 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1143,7 +1143,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,    const AttributeList *AL = Attrs.getList();    if (OnDefinition && AL && !AL->isCXX11Attribute() && -      !AL->canAppearOnFunctionDefinition()) +      AL->isKnownToGCC())      Diag(Tok, diag::warn_attribute_on_function_definition)        << &LA.AttrName; diff --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp index abd34fd650e..efa6a1bb592 100644 --- a/clang/lib/Parse/Parser.cpp +++ b/clang/lib/Parse/Parser.cpp @@ -1055,7 +1055,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,    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(); diff --git a/clang/lib/Sema/AttributeList.cpp b/clang/lib/Sema/AttributeList.cpp index aa6f72b2371..7258b37ffe9 100644 --- a/clang/lib/Sema/AttributeList.cpp +++ b/clang/lib/Sema/AttributeList.cpp @@ -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::Triple T) const {    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 { diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp index 6a8c73d3702..4d6f4a77744 100644 --- a/clang/utils/TableGen/ClangAttrEmitter.cpp +++ b/clang/utils/TableGen/ClangAttrEmitter.cpp @@ -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_ostream &OS) {  }  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(Record &R, raw_ostream &OS) {    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(Record &R, raw_ostream &OS) {  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(Record &R, std::vector<Argument*> &Args,      // 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(Record &R, std::vector<Argument*> &Args,      } 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(Record &R, std::vector<Argument*> &Args,  }  /// \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(Record &R, raw_ostream &OS) {         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(Record &R, raw_ostream &OS) {    }  } -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 std::vector<Record *>& Spellings) {  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::vector<Record *> &Spellings,    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 &Records, raw_ostream &OS) {      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(RecordKeeper &Records, raw_ostream &OS) {        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(RecordKeeper &Records, raw_ostream &OS) {        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(RecordKeeper &Records, raw_ostream &OS) {        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(RecordKeeper &Records, raw_ostream &OS) {      } 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(RecordKeeper &Records, raw_ostream &OS) {    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(RecordKeeper &Records, raw_ostream &OS) {      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(const Record &S) {      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(const Record *R) {    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 GenerateSpellingIndexToSemanticSpelling(const Record &Attr,    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 GenerateSpellingIndexToSemanticSpelling(const Record &Attr,    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(RecordKeeper &Records, raw_ostream &OS) {      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(RecordKeeper &Records, raw_ostream &OS) {        } 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 &Records, raw_ostream &OS) {      // 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";  | 

