diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2014-01-27 22:10:04 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2014-01-27 22:10:04 +0000 |
commit | c669cc0d773aa555e59c4b91728e1288e676094d (patch) | |
tree | 308776e8b8db233af85486d72f75cf00172464fc /clang | |
parent | 340e44074b7b2a65228b5572c23aa937993a27b8 (diff) | |
download | bcm5719-llvm-c669cc0d773aa555e59c4b91728e1288e676094d.tar.gz bcm5719-llvm-c669cc0d773aa555e59c4b91728e1288e676094d.zip |
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.
llvm-svn: 200252
Diffstat (limited to 'clang')
-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"; |