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
This commit is contained in:
Aaron Ballman 2014-01-27 22:10:04 +00:00
parent 340e44074b
commit c669cc0d77
6 changed files with 208 additions and 195 deletions

View File

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

View File

@ -494,7 +494,7 @@ public:
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
bool diagnoseLangOpts(class Sema &S) const; bool diagnoseLangOpts(class Sema &S) const;
bool existsInTarget(llvm::Triple T) 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 /// \brief If the parsed attribute has a semantic equivalent, and it would
/// have a semantic Spelling enumeration (due to having semantically-distinct /// have a semantic Spelling enumeration (due to having semantically-distinct

View File

@ -1143,7 +1143,7 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
const AttributeList *AL = Attrs.getList(); const AttributeList *AL = Attrs.getList();
if (OnDefinition && AL && !AL->isCXX11Attribute() && if (OnDefinition && AL && !AL->isCXX11Attribute() &&
!AL->canAppearOnFunctionDefinition()) AL->isKnownToGCC())
Diag(Tok, diag::warn_attribute_on_function_definition) Diag(Tok, diag::warn_attribute_on_function_definition)
<< &LA.AttrName; << &LA.AttrName;

View File

@ -1055,7 +1055,7 @@ Decl *Parser::ParseFunctionDefinition(ParsingDeclarator &D,
if (Tok.isNot(tok::equal)) { if (Tok.isNot(tok::equal)) {
AttributeList *DtorAttrs = D.getAttributes(); AttributeList *DtorAttrs = D.getAttributes();
while (DtorAttrs) { while (DtorAttrs) {
if (!DtorAttrs->canAppearOnFunctionDefinition() && if (DtorAttrs->isKnownToGCC() &&
!DtorAttrs->isCXX11Attribute()) { !DtorAttrs->isCXX11Attribute()) {
Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition) Diag(DtorAttrs->getLoc(), diag::warn_attribute_on_function_definition)
<< DtorAttrs->getName(); << DtorAttrs->getName();

View File

@ -150,7 +150,7 @@ struct ParsedAttrInfo {
unsigned HasCustomParsing : 1; unsigned HasCustomParsing : 1;
unsigned IsTargetSpecific : 1; unsigned IsTargetSpecific : 1;
unsigned IsType : 1; unsigned IsType : 1;
unsigned CanAppearOnFuncDef : 1; unsigned IsKnownToGCC : 1;
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr, bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *); const Decl *);
@ -199,8 +199,8 @@ bool AttributeList::existsInTarget(llvm::Triple T) const {
return getInfo(*this).ExistsInTarget(T); return getInfo(*this).ExistsInTarget(T);
} }
bool AttributeList::canAppearOnFunctionDefinition() const { bool AttributeList::isKnownToGCC() const {
return getInfo(*this).CanAppearOnFuncDef; return getInfo(*this).IsKnownToGCC;
} }
unsigned AttributeList::getSemanticSpelling() const { unsigned AttributeList::getSemanticSpelling() const {

View File

@ -26,6 +26,54 @@
using namespace llvm; 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) { static std::string ReadPCHRecord(StringRef type) {
return StringSwitch<std::string>(type) return StringSwitch<std::string>(type)
.EndsWith("Decl *", "GetLocalDeclAs<" .EndsWith("Decl *", "GetLocalDeclAs<"
@ -980,7 +1028,7 @@ static void writeAvailabilityValue(raw_ostream &OS) {
} }
static void writeGetSpellingFunction(Record &R, 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"; OS << "const char *" << R.getName() << "Attr::getSpelling() const {\n";
if (Spellings.empty()) { if (Spellings.empty()) {
@ -995,7 +1043,7 @@ static void writeGetSpellingFunction(Record &R, raw_ostream &OS) {
for (unsigned I = 0; I < Spellings.size(); ++I) for (unsigned I = 0; I < Spellings.size(); ++I)
OS << " case " << I << ":\n" OS << " case " << I << ":\n"
" return \"" << Spellings[I]->getValueAsString("Name") << "\";\n"; " return \"" << Spellings[I].name() << "\";\n";
// End of the switch statement. // End of the switch statement.
OS << " }\n"; OS << " }\n";
// End of the getSpelling function. // 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, static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
raw_ostream &OS) { raw_ostream &OS) {
std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
OS << "void " << R.getName() << "Attr::printPretty(" OS << "void " << R.getName() << "Attr::printPretty("
<< "raw_ostream &OS, const PrintingPolicy &Policy) const {\n"; << "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) // The actual spelling of the name and namespace (if applicable)
// of an attribute without considering prefix and suffix. // of an attribute without considering prefix and suffix.
llvm::SmallString<64> Spelling; llvm::SmallString<64> Spelling;
std::string Name = Spellings[I]->getValueAsString("Name"); std::string Name = Spellings[I].name();
std::string Variety = Spellings[I]->getValueAsString("Variety"); std::string Variety = Spellings[I].variety();
if (Variety == "GNU") { if (Variety == "GNU") {
Prefix = " __attribute__(("; Prefix = " __attribute__((";
@ -1035,7 +1083,7 @@ static void writePrettyPrintFunction(Record &R, std::vector<Argument*> &Args,
} else if (Variety == "CXX11") { } else if (Variety == "CXX11") {
Prefix = " [["; Prefix = " [[";
Suffix = "]]"; Suffix = "]]";
std::string Namespace = Spellings[I]->getValueAsString("Namespace"); std::string Namespace = Spellings[I].nameSpace();
if (Namespace != "") { if (Namespace != "") {
Spelling += Namespace; Spelling += Namespace;
Spelling += "::"; 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. /// \brief Return the index of a spelling in a spelling list.
static unsigned getSpellingListIndex(const std::vector<Record*> &SpellingList, static unsigned
const Record &Spelling) { getSpellingListIndex(const std::vector<FlattenedSpelling> &SpellingList,
const FlattenedSpelling &Spelling) {
assert(SpellingList.size() && "Spelling list is empty!"); assert(SpellingList.size() && "Spelling list is empty!");
for (unsigned Index = 0; Index < SpellingList.size(); ++Index) { for (unsigned Index = 0; Index < SpellingList.size(); ++Index) {
Record *S = SpellingList[Index]; const FlattenedSpelling &S = SpellingList[Index];
if (S->getValueAsString("Variety") != Spelling.getValueAsString("Variety")) if (S.variety() != Spelling.variety())
continue; continue;
if (S->getValueAsString("Variety") == "CXX11" && if (S.nameSpace() != Spelling.nameSpace())
S->getValueAsString("Namespace") !=
Spelling.getValueAsString("Namespace"))
continue; continue;
if (S->getValueAsString("Name") != Spelling.getValueAsString("Name")) if (S.name() != Spelling.name())
continue; continue;
return Index; return Index;
@ -1109,15 +1156,15 @@ static void writeAttrAccessorDefinition(Record &R, raw_ostream &OS) {
E = Accessors.end(); I != E; ++I) { E = Accessors.end(); I != E; ++I) {
Record *Accessor = *I; Record *Accessor = *I;
std::string Name = Accessor->getValueAsString("Name"); std::string Name = Accessor->getValueAsString("Name");
std::vector<Record*> Spellings = Accessor->getValueAsListOfDefs( std::vector<FlattenedSpelling> Spellings =
"Spellings"); GetFlattenedSpellings(*Accessor);
std::vector<Record*> SpellingList = R.getValueAsListOfDefs("Spellings"); std::vector<FlattenedSpelling> SpellingList = GetFlattenedSpellings(R);
assert(SpellingList.size() && assert(SpellingList.size() &&
"Attribute with empty spelling list can't have accessors!"); "Attribute with empty spelling list can't have accessors!");
OS << " bool " << Name << "() const { return SpellingListIndex == "; OS << " bool " << Name << "() const { return SpellingListIndex == ";
for (unsigned Index = 0; Index < Spellings.size(); ++Index) { for (unsigned Index = 0; Index < Spellings.size(); ++Index) {
OS << getSpellingListIndex(SpellingList, *Spellings[Index]); OS << getSpellingListIndex(SpellingList, Spellings[Index]);
if (Index != Spellings.size() -1) if (Index != Spellings.size() -1)
OS << " ||\n SpellingListIndex == "; OS << " ||\n SpellingListIndex == ";
else 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"); assert(!Spellings.empty() && "An empty list of spellings was provided");
std::string FirstName = NormalizeNameForSpellingComparison( std::string FirstName = NormalizeNameForSpellingComparison(
Spellings.front()->getValueAsString("Name")); Spellings.front().name());
for (std::vector<Record *>::const_iterator I = llvm::next(Spellings.begin()), for (std::vector<FlattenedSpelling>::const_iterator
E = Spellings.end(); I != E; ++I) { I = llvm::next(Spellings.begin()), E = Spellings.end(); I != E; ++I) {
std::string Name = NormalizeNameForSpellingComparison( std::string Name = NormalizeNameForSpellingComparison(I->name());
(*I)->getValueAsString("Name"));
if (Name != FirstName) if (Name != FirstName)
return false; return false;
} }
@ -1142,7 +1189,7 @@ static bool SpellingNamesAreCommon(const std::vector<Record *>& Spellings) {
typedef std::map<unsigned, std::string> SemanticSpellingMap; typedef std::map<unsigned, std::string> SemanticSpellingMap;
static std::string static std::string
CreateSemanticSpellings(const std::vector<Record *> &Spellings, CreateSemanticSpellings(const std::vector<FlattenedSpelling> &Spellings,
SemanticSpellingMap &Map) { SemanticSpellingMap &Map) {
// The enumerants are automatically generated based on the variety, // The enumerants are automatically generated based on the variety,
// namespace (if present) and name for each attribute spelling. However, // 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::string Ret(" enum Spelling {\n");
std::set<std::string> Uniques; std::set<std::string> Uniques;
unsigned Idx = 0; 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) { E = Spellings.end(); I != E; ++I, ++Idx) {
const Record &S = **I; const FlattenedSpelling &S = *I;
std::string Variety = S.getValueAsString("Variety"); std::string Variety = S.variety();
std::string Spelling = S.getValueAsString("Name"); std::string Spelling = S.name();
std::string Namespace = ""; std::string Namespace = S.nameSpace();
std::string EnumName = ""; std::string EnumName = "";
if (Variety == "CXX11")
Namespace = S.getValueAsString("Namespace");
EnumName += (Variety + "_"); EnumName += (Variety + "_");
if (!Namespace.empty()) if (!Namespace.empty())
EnumName += (NormalizeNameForSpellingComparison(Namespace).str() + EnumName += (NormalizeNameForSpellingComparison(Namespace).str() +
@ -1250,7 +1294,7 @@ void EmitClangAttrClass(RecordKeeper &Records, raw_ostream &OS) {
OS << "\npublic:\n"; 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 // 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 // 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; continue;
// All these spellings take a single type argument. // 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; 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) { E = Spellings.end(); I != E; ++I) {
if (Emitted.insert((*I)->getValueAsString("Name")).second) if (Emitted.insert(I->name()).second)
OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
<< "true" << ")\n";
} }
} }
} }
@ -1451,13 +1494,12 @@ void EmitClangAttrArgContextList(RecordKeeper &Records, raw_ostream &OS) {
continue; continue;
// All these spellings take are parsed unevaluated. // 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; 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) { E = Spellings.end(); I != E; ++I) {
if (Emitted.insert((*I)->getValueAsString("Name")).second) if (Emitted.insert(I->name()).second)
OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
<< "true" << ")\n";
} }
} }
@ -1480,13 +1522,12 @@ void EmitClangAttrIdentifierArgList(RecordKeeper &Records, raw_ostream &OS) {
continue; continue;
// All these spellings take an identifier argument. // 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; 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) { E = Spellings.end(); I != E; ++I) {
if (Emitted.insert((*I)->getValueAsString("Name")).second) if (Emitted.insert(I->name()).second)
OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " OS << ".Case(\"" << I->name() << "\", " << "true" << ")\n";
<< "true" << ")\n";
} }
} }
} }
@ -1728,12 +1769,10 @@ void EmitClangAttrSpellingList(RecordKeeper &Records, raw_ostream &OS) {
} else } else
Test = "true"; Test = "true";
std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
for (std::vector<Record*>::const_iterator I = Spellings.begin(), for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
E = Spellings.end(); I != E; ++I) { E = Spellings.end(); I != E; ++I)
OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " << Test; OS << ".Case(\"" << I->name() << "\", " << Test << ")\n";
OS << ")\n";
}
} }
} }
@ -1752,25 +1791,19 @@ void EmitClangAttrSpellingListIndex(RecordKeeper &Records, raw_ostream &OS) {
for (ParsedAttrMap::const_iterator I = Attrs.begin(), E = Attrs.end(); for (ParsedAttrMap::const_iterator I = Attrs.begin(), E = Attrs.end();
I != E; ++I) { I != E; ++I) {
Record &R = *I->second; Record &R = *I->second;
std::vector<Record*> Spellings = R.getValueAsListOfDefs("Spellings"); std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
OS << " case AT_" << I->first << ": {\n"; OS << " case AT_" << I->first << ": {\n";
for (unsigned I = 0; I < Spellings.size(); ++ I) { 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 == \"" OS << " if (Name == \""
<< Spellings[I]->getValueAsString("Name") << "\" && " << Spellings[I].name() << "\" && "
<< "SyntaxUsed == " << "SyntaxUsed == "
<< StringSwitch<unsigned>(Spellings[I]->getValueAsString("Variety")) << StringSwitch<unsigned>(Spellings[I].variety())
.Case("GNU", 0) .Case("GNU", 0)
.Case("CXX11", 1) .Case("CXX11", 1)
.Case("Declspec", 2) .Case("Declspec", 2)
.Case("Keyword", 3) .Case("Keyword", 3)
.Default(0) .Default(0)
<< " && Scope == \"" << Namespace << "\")\n" << " && Scope == \"" << Spellings[I].nameSpace() << "\")\n"
<< " return " << I << ";\n"; << " return " << I << ";\n";
} }
@ -1875,16 +1908,14 @@ void EmitClangAttrLateParsedList(RecordKeeper &Records, raw_ostream &OS) {
bool LateParsed = Attr.getValueAsBit("LateParsed"); bool LateParsed = Attr.getValueAsBit("LateParsed");
if (LateParsed) { if (LateParsed) {
std::vector<Record*> Spellings = std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
Attr.getValueAsListOfDefs("Spellings");
// FIXME: Handle non-GNU attributes // FIXME: Handle non-GNU attributes
for (std::vector<Record*>::const_iterator I = Spellings.begin(), for (std::vector<FlattenedSpelling>::const_iterator
E = Spellings.end(); I != E; ++I) { I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
if ((*I)->getValueAsString("Variety") != "GNU") if (I->variety() != "GNU")
continue; continue;
OS << ".Case(\"" << (*I)->getValueAsString("Name") << "\", " OS << ".Case(\"" << I->name() << "\", " << LateParsed << ")\n";
<< LateParsed << ")\n";
} }
} }
} }
@ -2044,7 +2075,6 @@ static std::string CalculateDiagnostic(const Record &S) {
uint32_t V = StringSwitch<uint32_t>(Name) uint32_t V = StringSwitch<uint32_t>(Name)
.Case("Function", Func) .Case("Function", Func)
.Case("FunctionDefinition", Func)
.Case("Var", Var) .Case("Var", Var)
.Case("ObjCMethod", ObjCMethod) .Case("ObjCMethod", ObjCMethod)
.Case("ParmVar", Param) .Case("ParmVar", Param)
@ -2120,8 +2150,6 @@ static std::string GetSubjectWithSuffix(const Record *R) {
std::string B = R->getName(); std::string B = R->getName();
if (B == "DeclBase") if (B == "DeclBase")
return "Decl"; return "Decl";
else if (B == "FunctionDefinition")
return "FunctionDecl";
return B + "Decl"; return B + "Decl";
} }
static std::string GenerateCustomAppertainsTo(const Record &Subject, static std::string GenerateCustomAppertainsTo(const Record &Subject,
@ -2365,7 +2393,7 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
if (!Attr.getValueAsBit("ASTNode")) if (!Attr.getValueAsBit("ASTNode"))
return "defaultSpellingIndexToSemanticSpelling"; 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 // If there are zero or one spellings, or all of the spellings share the same
// name, we can also bail out early. // name, we can also bail out early.
@ -2386,19 +2414,13 @@ static std::string GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
return Name; return Name;
} }
static bool CanAppearOnFuncDef(const Record &Attr) { static bool IsKnownToGCC(const Record &Attr) {
// Look at the subjects this function appertains to; if a FunctionDefinition // Look at the spellings for this subject; if there are any spellings which
// appears in the list, then this attribute can appear on a function // claim to be known to GCC, the attribute is known to GCC.
// definition. std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
if (Attr.isValueUnset("Subjects")) for (std::vector<FlattenedSpelling>::const_iterator I = Spellings.begin(),
return false; E = Spellings.end(); I != E; ++I) {
if (I->knownToGCC())
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")
return true; return true;
} }
return false; return false;
@ -2440,7 +2462,7 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
SS << ", " << I->second->getValueAsBit("HasCustomParsing"); SS << ", " << I->second->getValueAsBit("HasCustomParsing");
SS << ", " << I->second->isSubClassOf("TargetSpecificAttr"); SS << ", " << I->second->isSubClassOf("TargetSpecificAttr");
SS << ", " << I->second->isSubClassOf("TypeAttr"); SS << ", " << I->second->isSubClassOf("TypeAttr");
SS << ", " << CanAppearOnFuncDef(*I->second); SS << ", " << IsKnownToGCC(*I->second);
SS << ", " << GenerateAppertainsTo(*I->second, OS); SS << ", " << GenerateAppertainsTo(*I->second, OS);
SS << ", " << GenerateLangOptRequirements(*I->second, OS); SS << ", " << GenerateLangOptRequirements(*I->second, OS);
SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS); SS << ", " << GenerateTargetRequirements(*I->second, Dupes, OS);
@ -2492,15 +2514,15 @@ void EmitClangAttrParsedAttrKinds(RecordKeeper &Records, raw_ostream &OS) {
} else } else
AttrName = NormalizeAttrName(StringRef(Attr.getName())).str(); AttrName = NormalizeAttrName(StringRef(Attr.getName())).str();
std::vector<Record*> Spellings = Attr.getValueAsListOfDefs("Spellings"); std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(Attr);
for (std::vector<Record*>::const_iterator I = Spellings.begin(), for (std::vector<FlattenedSpelling>::const_iterator
E = Spellings.end(); I != E; ++I) { I = Spellings.begin(), E = Spellings.end(); I != E; ++I) {
std::string RawSpelling = (*I)->getValueAsString("Name"); std::string RawSpelling = I->name();
std::vector<StringMatcher::StringPair> *Matches = 0; std::vector<StringMatcher::StringPair> *Matches = 0;
std::string Spelling, Variety = (*I)->getValueAsString("Variety"); std::string Spelling, Variety = I->variety();
if (Variety == "CXX11") { if (Variety == "CXX11") {
Matches = &CXX11; Matches = &CXX11;
Spelling += (*I)->getValueAsString("Namespace"); Spelling += I->nameSpace();
Spelling += "::"; Spelling += "::";
} else if (Variety == "GNU") } else if (Variety == "GNU")
Matches = &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 // If the attribute has a semantically-meaningful name (which is determined
// by whether there is a Spelling enumeration for it), then write out the // by whether there is a Spelling enumeration for it), then write out the
// spelling used for the attribute. // spelling used for the attribute.
std::vector<Record *> Spellings = R.getValueAsListOfDefs("Spellings"); std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings)) if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
OS << " OS << \" \" << A->getSpelling();\n"; OS << " OS << \" \" << A->getSpelling();\n";