Laying the basic groundwork for table generating the diagnostics for attribute subjects. This makes some modifications to the way subjects are listed in Attr.td, and updates the attr emitter to handle the new constructs.

I have disabled some attribute subject lines on purpose in Attr.td;
this part is a WIP with the goal being to restore those subjects
incrementally. By commenting them out, it leaves the original behavior
the same as before for those attributes and so those are not
functionality changes.

llvm-svn: 195841
This commit is contained in:
Aaron Ballman 2013-11-27 13:27:02 +00:00
parent e0e31c4a30
commit 74eeeae3d3
5 changed files with 365 additions and 488 deletions

View File

@ -109,11 +109,24 @@ class Accessor<string name, list<Spelling> spellings> {
list<Spelling> Spellings = spellings;
}
class SubjectDiag<bit warn> {
bit Warn = warn;
}
def WarnDiag : SubjectDiag<1>;
def ErrorDiag : SubjectDiag<0>;
class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag,
string customDiag = ""> {
list<AttrSubject> Subjects = subjects;
SubjectDiag Diag = diag;
string CustomDiag = customDiag;
}
class Attr {
// The various ways in which an attribute can be spelled in source
list<Spelling> Spellings;
// The things to which an attribute can appertain
list<AttrSubject> Subjects;
SubjectList Subjects;
// The arguments allowed on an attribute
list<Argument> Args = [];
// Accessors which should be generated for the attribute.
@ -180,7 +193,7 @@ def Alias : Attr {
def Aligned : InheritableAttr {
let Spellings = [GNU<"aligned">, Declspec<"align">, CXX11<"gnu", "aligned">,
Keyword<"alignas">, Keyword<"_Alignas">];
let Subjects = [NonBitField, NormalVar, Tag];
// let Subjects = SubjectList<[NonBitField, NormalVar, Tag]>;
let Args = [AlignedArgument<"Alignment", 1>];
let Accessors = [Accessor<"isGNU", [GNU<"aligned">, CXX11<"gnu","aligned">]>,
Accessor<"isC11", [Keyword<"_Alignas">]>,
@ -201,12 +214,12 @@ def AllocSize : InheritableAttr {
def AlwaysInline : InheritableAttr {
let Spellings = [GNU<"always_inline">, CXX11<"gnu", "always_inline">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def TLSModel : InheritableAttr {
let Spellings = [GNU<"tls_model">, CXX11<"gnu", "tls_model">];
let Subjects = [Var];
let Subjects = SubjectList<[Var], ErrorDiag, "ExpectedTLSVar">;
let Args = [StringArgument<"Model">];
}
@ -246,7 +259,7 @@ def Availability : InheritableAttr {
.Default(llvm::StringRef());
} }];
let HasCustomParsing = 1;
let Subjects = [Named];
// let Subjects = SubjectList<[Named]>;
}
def Blocks : InheritableAttr {
@ -261,13 +274,13 @@ def Bounded : IgnoredAttr {
def CarriesDependency : InheritableParamAttr {
let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">,
CXX11<"std","carries_dependency">];
let Subjects = [ParmVar, Function];
let Subjects = SubjectList<[ParmVar, ObjCMethod, Function], ErrorDiag>;
}
def CDecl : InheritableAttr {
let Spellings = [GNU<"cdecl">, CXX11<"gnu", "cdecl">, Keyword<"__cdecl">,
Keyword<"_cdecl">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
// cf_audited_transfer indicates that the given function has been
@ -276,7 +289,7 @@ def CDecl : InheritableAttr {
// '#pragma clang arc_cf_code_audited' rather than explicitly.
def CFAuditedTransfer : InheritableAttr {
let Spellings = [GNU<"cf_audited_transfer">];
let Subjects = [Function];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
// cf_unknown_transfer is an explicit opt-out of cf_audited_transfer.
@ -284,38 +297,38 @@ def CFAuditedTransfer : InheritableAttr {
// transfer semantics.
def CFUnknownTransfer : InheritableAttr {
let Spellings = [GNU<"cf_unknown_transfer">];
let Subjects = [Function];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
def CFReturnsRetained : InheritableAttr {
let Spellings = [GNU<"cf_returns_retained">];
let Subjects = [ObjCMethod, Function];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
}
def CFReturnsNotRetained : InheritableAttr {
let Spellings = [GNU<"cf_returns_not_retained">];
let Subjects = [ObjCMethod, Function];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
}
def CFConsumed : InheritableParamAttr {
let Spellings = [GNU<"cf_consumed">];
let Subjects = [ParmVar];
let Subjects = SubjectList<[ParmVar]>;
}
def Cleanup : InheritableAttr {
let Spellings = [GNU<"cleanup">, CXX11<"gnu", "cleanup">];
let Args = [FunctionArgument<"FunctionDecl">];
let Subjects = [Var];
let Subjects = SubjectList<[Var]>;
}
def Cold : InheritableAttr {
let Spellings = [GNU<"cold">, CXX11<"gnu", "cold">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def Common : InheritableAttr {
let Spellings = [GNU<"common">, CXX11<"gnu", "common">];
let Subjects = [Var];
let Subjects = SubjectList<[Var]>;
}
def Const : InheritableAttr {
@ -326,27 +339,27 @@ def Const : InheritableAttr {
def Constructor : InheritableAttr {
let Spellings = [GNU<"constructor">, CXX11<"gnu", "constructor">];
let Args = [DefaultIntArgument<"Priority", 65535>];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def CUDAConstant : InheritableAttr {
let Spellings = [GNU<"constant">];
let Subjects = [Var];
let Subjects = SubjectList<[Var]>;
}
def CUDADevice : InheritableAttr {
let Spellings = [GNU<"device">];
let Subjects = [Function, Var];
let Subjects = SubjectList<[Function, Var]>;
}
def CUDAGlobal : InheritableAttr {
let Spellings = [GNU<"global">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def CUDAHost : InheritableAttr {
let Spellings = [GNU<"host">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def CUDALaunchBounds : InheritableAttr {
@ -356,18 +369,18 @@ def CUDALaunchBounds : InheritableAttr {
def CUDAShared : InheritableAttr {
let Spellings = [GNU<"shared">];
let Subjects = [Var];
let Subjects = SubjectList<[Var]>;
}
def C11NoReturn : InheritableAttr {
let Spellings = [Keyword<"_Noreturn">];
let Subjects = [Function];
// let Subjects = SubjectList<[Function], ErrorDiag>;
let SemaHandler = 0;
}
def CXX11NoReturn : InheritableAttr {
let Spellings = [CXX11<"","noreturn">, CXX11<"std","noreturn">];
let Subjects = [Function];
// let Subjects = SubjectList<[Function], ErrorDiag>;
}
def OpenCLKernel : InheritableAttr {
@ -388,25 +401,25 @@ def Deprecated : InheritableAttr {
def Destructor : InheritableAttr {
let Spellings = [GNU<"destructor">, CXX11<"gnu", "destructor">];
let Args = [DefaultIntArgument<"Priority", 65535>];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def ExtVectorType : Attr {
let Spellings = [GNU<"ext_vector_type">];
let Subjects = [TypedefName];
let Subjects = SubjectList<[TypedefName], ErrorDiag>;
let Args = [ExprArgument<"NumElements">];
let ASTNode = 0;
}
def FallThrough : Attr {
let Spellings = [CXX11<"clang", "fallthrough">];
let Subjects = [NullStmt];
// let Subjects = [NullStmt];
}
def FastCall : InheritableAttr {
let Spellings = [GNU<"fastcall">, CXX11<"gnu", "fastcall">,
Keyword<"__fastcall">, Keyword<"_fastcall">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def Final : InheritableAttr {
@ -417,7 +430,7 @@ def Final : InheritableAttr {
def MinSize : InheritableAttr {
let Spellings = [GNU<"minsize">];
let Subjects = [Function, ObjCMethod];
let Subjects = SubjectList<[Function, ObjCMethod], ErrorDiag>;
}
def Format : InheritableAttr {
@ -433,33 +446,33 @@ def FormatArg : InheritableAttr {
def GNUInline : InheritableAttr {
let Spellings = [GNU<"gnu_inline">, CXX11<"gnu", "gnu_inline">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def Hot : InheritableAttr {
let Spellings = [GNU<"hot">, CXX11<"gnu", "hot">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def IBAction : InheritableAttr {
let Spellings = [GNU<"ibaction">];
let Subjects = [ObjCMethod];
// let Subjects = [ObjCMethod];
}
def IBOutlet : InheritableAttr {
let Spellings = [GNU<"iboutlet">];
let Subjects = [ObjCIvar, ObjCProperty];
// let Subjects = [ObjCIvar, ObjCProperty];
}
def IBOutletCollection : InheritableAttr {
let Spellings = [GNU<"iboutletcollection">];
let Args = [TypeArgument<"Interface", 1>];
let Subjects = [ObjCIvar, ObjCProperty];
// let Subjects = [ObjCIvar, ObjCProperty];
}
def Malloc : InheritableAttr {
let Spellings = [GNU<"malloc">, CXX11<"gnu", "malloc">];
let Subjects = [Function];
// let Subjects = [Function];
}
def MaxFieldAlignment : InheritableAttr {
@ -474,7 +487,7 @@ def MayAlias : InheritableAttr {
def MSABI : InheritableAttr {
let Spellings = [GNU<"ms_abi">, CXX11<"gnu", "ms_abi">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def MSP430Interrupt : InheritableAttr, TargetSpecificAttr {
@ -485,7 +498,7 @@ def MSP430Interrupt : InheritableAttr, TargetSpecificAttr {
def Mips16 : InheritableAttr, TargetSpecificAttr {
let Spellings = [GNU<"mips16">, CXX11<"gnu", "mips16">];
let Subjects = [Function];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
def Mode : Attr {
@ -495,7 +508,7 @@ def Mode : Attr {
def Naked : InheritableAttr {
let Spellings = [GNU<"naked">, CXX11<"gnu", "naked">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def NeonPolyVectorType : TypeAttr {
@ -510,12 +523,12 @@ def NeonVectorType : TypeAttr {
def ReturnsTwice : InheritableAttr {
let Spellings = [GNU<"returns_twice">, CXX11<"gnu", "returns_twice">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def NoCommon : InheritableAttr {
let Spellings = [GNU<"nocommon">, CXX11<"gnu", "nocommon">];
let Subjects = [Var];
let Subjects = SubjectList<[Var]>;
}
def NoDebug : InheritableAttr {
@ -524,12 +537,12 @@ def NoDebug : InheritableAttr {
def NoInline : InheritableAttr {
let Spellings = [GNU<"noinline">, CXX11<"gnu", "noinline">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def NoMips16 : InheritableAttr, TargetSpecificAttr {
let Spellings = [GNU<"nomips16">, CXX11<"gnu", "nomips16">];
let Subjects = [Function];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
def NonNull : InheritableAttr {
@ -553,7 +566,7 @@ def NoReturn : InheritableAttr {
def NoInstrumentFunction : InheritableAttr {
let Spellings = [GNU<"no_instrument_function">,
CXX11<"gnu", "no_instrument_function">];
let Subjects = [Function];
let Subjects = SubjectList<[Function]>;
}
def NoThrow : InheritableAttr {
@ -562,55 +575,55 @@ def NoThrow : InheritableAttr {
def NSBridged : InheritableAttr {
let Spellings = [GNU<"ns_bridged">];
let Subjects = [Record];
// let Subjects = SubjectList<[Record], ErrorDiag>;
let Args = [IdentifierArgument<"BridgedType", 1>];
}
def ObjCBridge : InheritableAttr {
let Spellings = [GNU<"objc_bridge">];
let Subjects = [Record];
// let Subjects = SubjectList<[Record], ErrorDiag>;
let Args = [IdentifierArgument<"BridgedType">];
}
def ObjCBridgeMutable : InheritableAttr {
let Spellings = [GNU<"objc_bridge_mutable">];
let Subjects = [Record];
// let Subjects = SubjectList<[Record], ErrorDiag>;
let Args = [IdentifierArgument<"BridgedType">];
}
def NSReturnsRetained : InheritableAttr {
let Spellings = [GNU<"ns_returns_retained">];
let Subjects = [ObjCMethod, Function];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
}
def NSReturnsNotRetained : InheritableAttr {
let Spellings = [GNU<"ns_returns_not_retained">];
let Subjects = [ObjCMethod, Function];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
}
def NSReturnsAutoreleased : InheritableAttr {
let Spellings = [GNU<"ns_returns_autoreleased">];
let Subjects = [ObjCMethod, Function];
// let Subjects = SubjectList<[ObjCMethod, ObjCProperty, Function]>;
}
def NSConsumesSelf : InheritableAttr {
let Spellings = [GNU<"ns_consumes_self">];
let Subjects = [ObjCMethod];
let Subjects = SubjectList<[ObjCMethod]>;
}
def NSConsumed : InheritableParamAttr {
let Spellings = [GNU<"ns_consumed">];
let Subjects = [ParmVar];
let Subjects = SubjectList<[ParmVar]>;
}
def ObjCException : InheritableAttr {
let Spellings = [GNU<"objc_exception">];
let Subjects = [ObjCInterface];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
}
def ObjCMethodFamily : InheritableAttr {
let Spellings = [GNU<"objc_method_family">];
let Subjects = [ObjCMethod];
let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
let Args = [EnumArgument<"Family", "FamilyKind",
["none", "alloc", "copy", "init", "mutableCopy", "new"],
["OMF_None", "OMF_alloc", "OMF_copy", "OMF_init",
@ -623,33 +636,33 @@ def ObjCNSObject : InheritableAttr {
def ObjCPreciseLifetime : InheritableAttr {
let Spellings = [GNU<"objc_precise_lifetime">];
let Subjects = [Var];
let Subjects = SubjectList<[Var], ErrorDiag>;
}
def ObjCReturnsInnerPointer : InheritableAttr {
let Spellings = [GNU<"objc_returns_inner_pointer">];
let Subjects = [ObjCMethod, ObjCProperty];
let Subjects = SubjectList<[ObjCMethod, ObjCProperty], ErrorDiag>;
}
def ObjCRequiresSuper : InheritableAttr {
let Spellings = [GNU<"objc_requires_super">];
let Subjects = [ObjCMethod];
let Subjects = SubjectList<[ObjCMethod], ErrorDiag>;
}
def ObjCRootClass : InheritableAttr {
let Spellings = [GNU<"objc_root_class">];
let Subjects = [ObjCInterface];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
}
def ObjCSuppressProtocol : InheritableAttr {
let Spellings = [GNU<"objc_suppress_protocol_methods">];
let Subjects = [ObjCInterface];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Args = [IdentifierArgument<"Protocol">];
}
def Overloadable : Attr {
let Spellings = [GNU<"overloadable">];
let Subjects = [Function];
let Subjects = SubjectList<[Function], ErrorDiag>;
}
def Override : InheritableAttr {
@ -676,17 +689,17 @@ def Ownership : InheritableAttr {
def Packed : InheritableAttr {
let Spellings = [GNU<"packed">, CXX11<"gnu", "packed">];
let Subjects = [Tag, Field];
// let Subjects = [Tag, Field];
}
def PnaclCall : InheritableAttr {
let Spellings = [GNU<"pnaclcall">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def IntelOclBicc : InheritableAttr {
let Spellings = [GNU<"intel_ocl_bicc">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def Pcs : InheritableAttr {
@ -694,7 +707,7 @@ def Pcs : InheritableAttr {
let Args = [EnumArgument<"PCS", "PCSType",
["aapcs", "aapcs-vfp"],
["AAPCS", "AAPCS_VFP"]>];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def Pure : InheritableAttr {
@ -722,7 +735,7 @@ def WorkGroupSizeHint : InheritableAttr {
def InitPriority : InheritableAttr {
let Spellings = [GNU<"init_priority">];
let Args = [UnsignedArgument<"Priority">];
let Subjects = [Var];
// let Subjects = [Var];
}
def Section : InheritableAttr {
@ -734,34 +747,34 @@ def Sentinel : InheritableAttr {
let Spellings = [GNU<"sentinel">, CXX11<"gnu", "sentinel">];
let Args = [DefaultIntArgument<"Sentinel", 0>,
DefaultIntArgument<"NullPos", 0>];
let Subjects = [Function, ObjCMethod, Block, Var];
// let Subjects = SubjectList<[Function, ObjCMethod, Block, Var]>;
}
def StdCall : InheritableAttr {
let Spellings = [GNU<"stdcall">, CXX11<"gnu", "stdcall">,
Keyword<"__stdcall">, Keyword<"_stdcall">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def SysVABI : InheritableAttr {
let Spellings = [GNU<"sysv_abi">, CXX11<"gnu", "sysv_abi">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def ThisCall : InheritableAttr {
let Spellings = [GNU<"thiscall">, CXX11<"gnu", "thiscall">,
Keyword<"__thiscall">, Keyword<"_thiscall">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def Pascal : InheritableAttr {
let Spellings = [GNU<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">];
let Subjects = [Function, ObjCMethod];
// let Subjects = [Function, ObjCMethod];
}
def TransparentUnion : InheritableAttr {
let Spellings = [GNU<"transparent_union">, CXX11<"gnu", "transparent_union">];
let Subjects = [Record, TypedefName];
// let Subjects = SubjectList<[Record, TypedefName]>;
}
def Unavailable : InheritableAttr {
@ -771,7 +784,7 @@ def Unavailable : InheritableAttr {
def ArcWeakrefUnavailable : InheritableAttr {
let Spellings = [GNU<"objc_arc_weak_reference_unavailable">];
let Subjects = [ObjCInterface];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
}
def ObjCGC : TypeAttr {
@ -787,7 +800,7 @@ def ObjCOwnership : InheritableAttr {
def ObjCRequiresPropertyDefs : InheritableAttr {
let Spellings = [GNU<"objc_requires_property_definitions">];
let Subjects = [ObjCInterface];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
}
def Unused : InheritableAttr {
@ -801,7 +814,7 @@ def Used : InheritableAttr {
def Uuid : InheritableAttr {
let Spellings = [GNU<"uuid">];
let Args = [StringArgument<"Guid">];
let Subjects = [CXXRecord];
// let Subjects = SubjectList<[CXXRecord]>;
}
def VectorSize : TypeAttr {
@ -828,17 +841,17 @@ def TypeVisibility : InheritableAttr {
let Args = [EnumArgument<"Visibility", "VisibilityType",
["default", "hidden", "internal", "protected"],
["Default", "Hidden", "Hidden", "Protected"]>];
let Subjects = [Tag, ObjCInterface, Namespace];
// let Subjects = [Tag, ObjCInterface, Namespace];
}
def VecReturn : InheritableAttr {
let Spellings = [GNU<"vecreturn">];
let Subjects = [CXXRecord];
let Subjects = SubjectList<[CXXRecord], ErrorDiag>;
}
def WarnUnused : InheritableAttr {
let Spellings = [GNU<"warn_unused">];
let Subjects = [Record];
// let Subjects = [Record];
}
def WarnUnusedResult : InheritableAttr {
@ -849,7 +862,7 @@ def WarnUnusedResult : InheritableAttr {
def Weak : InheritableAttr {
let Spellings = [GNU<"weak">, CXX11<"gnu", "weak">];
let Subjects = [Var, Function, CXXRecord];
// let Subjects = SubjectList<[Var, Function, CXXRecord]>;
}
def WeakImport : InheritableAttr {
@ -860,7 +873,7 @@ def WeakRef : InheritableAttr {
let Spellings = [GNU<"weakref">, CXX11<"gnu", "weakref">];
// A WeakRef that has an argument is treated as being an AliasAttr
let Args = [StringArgument<"Aliasee", 1>];
let Subjects = [Var, Function];
let Subjects = SubjectList<[Var, Function], ErrorDiag>;
}
def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr {
@ -873,46 +886,46 @@ def NoSanitizeAddress : InheritableAttr {
GNU<"no_sanitize_address">,
CXX11<"gnu", "no_address_safety_analysis">,
CXX11<"gnu", "no_sanitize_address">];
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate], ErrorDiag>;
}
// Attribute to disable ThreadSanitizer checks.
def NoSanitizeThread : InheritableAttr {
let Spellings = [GNU<"no_sanitize_thread">];
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate], ErrorDiag>;
}
// Attribute to disable MemorySanitizer checks.
def NoSanitizeMemory : InheritableAttr {
let Spellings = [GNU<"no_sanitize_memory">];
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate], ErrorDiag>;
}
// C/C++ Thread safety attributes (e.g. for deadlock, data race checking)
def GuardedVar : InheritableAttr {
let Spellings = [GNU<"guarded_var">];
let Subjects = [Field, Var];
let Subjects = SubjectList<[Field, Var]>;
}
def PtGuardedVar : InheritableAttr {
let Spellings = [GNU<"pt_guarded_var">];
let Subjects = [Field, Var];
let Subjects = SubjectList<[Field, Var]>;
}
def Lockable : InheritableAttr {
let Spellings = [GNU<"lockable">];
let Subjects = [Record];
let Subjects = SubjectList<[Record]>;
}
def ScopedLockable : InheritableAttr {
let Spellings = [GNU<"scoped_lockable">];
let Subjects = [Record];
let Subjects = SubjectList<[Record]>;
}
def NoThreadSafetyAnalysis : InheritableAttr {
let Spellings = [GNU<"no_thread_safety_analysis">];
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def GuardedBy : InheritableAttr {
@ -920,7 +933,7 @@ def GuardedBy : InheritableAttr {
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Field, Var];
let Subjects = SubjectList<[Field, Var]>;
}
def PtGuardedBy : InheritableAttr {
@ -928,7 +941,7 @@ def PtGuardedBy : InheritableAttr {
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Field, Var];
let Subjects = SubjectList<[Field, Var]>;
}
def AcquiredAfter : InheritableAttr {
@ -936,7 +949,7 @@ def AcquiredAfter : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Field, Var];
let Subjects = SubjectList<[Field, Var]>;
}
def AcquiredBefore : InheritableAttr {
@ -944,7 +957,7 @@ def AcquiredBefore : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Field, Var];
let Subjects = SubjectList<[Field, Var]>;
}
def ExclusiveLockFunction : InheritableAttr {
@ -952,7 +965,7 @@ def ExclusiveLockFunction : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def SharedLockFunction : InheritableAttr {
@ -960,7 +973,7 @@ def SharedLockFunction : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def AssertExclusiveLock : InheritableAttr {
@ -968,7 +981,7 @@ def AssertExclusiveLock : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def AssertSharedLock : InheritableAttr {
@ -976,7 +989,7 @@ def AssertSharedLock : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
// The first argument is an integer or boolean value specifying the return value
@ -986,7 +999,7 @@ def ExclusiveTrylockFunction : InheritableAttr {
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
// The first argument is an integer or boolean value specifying the return value
@ -996,7 +1009,7 @@ def SharedTrylockFunction : InheritableAttr {
let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def UnlockFunction : InheritableAttr {
@ -1004,7 +1017,7 @@ def UnlockFunction : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def LockReturned : InheritableAttr {
@ -1012,7 +1025,7 @@ def LockReturned : InheritableAttr {
let Args = [ExprArgument<"Arg">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def LocksExcluded : InheritableAttr {
@ -1020,7 +1033,7 @@ def LocksExcluded : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def ExclusiveLocksRequired : InheritableAttr {
@ -1028,7 +1041,7 @@ def ExclusiveLocksRequired : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
def SharedLocksRequired : InheritableAttr {
@ -1036,14 +1049,14 @@ def SharedLocksRequired : InheritableAttr {
let Args = [VariadicExprArgument<"Args">];
let LateParsed = 1;
let TemplateDependent = 1;
let Subjects = [Function, FunctionTemplate];
let Subjects = SubjectList<[Function, FunctionTemplate]>;
}
// C/C++ consumed attributes.
def Consumable : InheritableAttr {
let Spellings = [GNU<"consumable">];
let Subjects = [CXXRecord];
let Subjects = SubjectList<[CXXRecord]>;
let Args = [EnumArgument<"DefaultState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
["Unknown", "Consumed", "Unconsumed"]>];
@ -1051,7 +1064,7 @@ def Consumable : InheritableAttr {
def CallableWhen : InheritableAttr {
let Spellings = [GNU<"callable_when">];
let Subjects = [CXXMethod];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [VariadicEnumArgument<"CallableState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
["Unknown", "Consumed", "Unconsumed"]>];
@ -1059,7 +1072,7 @@ def CallableWhen : InheritableAttr {
def ParamTypestate : InheritableAttr {
let Spellings = [GNU<"param_typestate">];
let Subjects = [ParmVar];
let Subjects = SubjectList<[ParmVar]>;
let Args = [EnumArgument<"ParamState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
["Unknown", "Consumed", "Unconsumed"]>];
@ -1067,7 +1080,7 @@ def ParamTypestate : InheritableAttr {
def ReturnTypestate : InheritableAttr {
let Spellings = [GNU<"return_typestate">];
let Subjects = [Function, ParmVar];
let Subjects = SubjectList<[Function, ParmVar]>;
let Args = [EnumArgument<"State", "ConsumedState",
["unknown", "consumed", "unconsumed"],
["Unknown", "Consumed", "Unconsumed"]>];
@ -1075,7 +1088,7 @@ def ReturnTypestate : InheritableAttr {
def SetTypestate : InheritableAttr {
let Spellings = [GNU<"set_typestate">];
let Subjects = [CXXMethod];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [EnumArgument<"NewState", "ConsumedState",
["unknown", "consumed", "unconsumed"],
["Unknown", "Consumed", "Unconsumed"]>];
@ -1083,7 +1096,7 @@ def SetTypestate : InheritableAttr {
def TestTypestate : InheritableAttr {
let Spellings = [GNU<"test_typestate">];
let Subjects = [CXXMethod];
let Subjects = SubjectList<[CXXMethod]>;
let Args = [EnumArgument<"TestState", "ConsumedState",
["consumed", "unconsumed"],
["Consumed", "Unconsumed"]>];
@ -1107,7 +1120,7 @@ def TypeTagForDatatype : InheritableAttr {
TypeArgument<"MatchingCType">,
BoolArgument<"LayoutCompatible">,
BoolArgument<"MustBeNull">];
let Subjects = [Var];
// let Subjects = SubjectList<[Var], ErrorDiag>;
let HasCustomParsing = 1;
}
@ -1119,7 +1132,7 @@ def MsProperty : IgnoredAttr {
def MsStruct : InheritableAttr {
let Spellings = [GNU<"ms_struct">, CXX11<"gnu", "ms_struct">];
let Subjects = [Record];
let Subjects = SubjectList<[Record]>;
}
def DLLExport : InheritableAttr, TargetSpecificAttr {

View File

@ -467,6 +467,7 @@ public:
bool hasCustomParsing() const;
unsigned getMinArgs() const;
unsigned getMaxArgs() const;
bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const;
};
/// A factory, from which one makes pools, from which one creates
@ -831,6 +832,35 @@ enum AttributeArgumentNType {
AANT_ArgumentIdentifier
};
/// These constants match the enumerated choices of
/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
enum AttributeDeclKind {
ExpectedFunction,
ExpectedUnion,
ExpectedVariableOrFunction,
ExpectedFunctionOrMethod,
ExpectedParameter,
ExpectedFunctionMethodOrBlock,
ExpectedFunctionMethodOrClass,
ExpectedFunctionMethodOrParameter,
ExpectedClass,
ExpectedVariable,
ExpectedMethod,
ExpectedVariableFunctionOrLabel,
ExpectedFieldOrGlobalVar,
ExpectedStruct,
ExpectedVariableFunctionOrTag,
ExpectedTLSVar,
ExpectedVariableOrField,
ExpectedVariableFieldOrTag,
ExpectedTypeOrNamespace,
ExpectedObjectiveCInterface,
ExpectedMethodOrProperty,
ExpectedStructOrUnion,
ExpectedStructOrUnionOrClass,
ExpectedType
};
} // end namespace clang
#endif

View File

@ -12,8 +12,11 @@
//===----------------------------------------------------------------------===//
#include "clang/Sema/AttributeList.h"
#include "clang/Sema/SemaInternal.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/Basic/IdentifierTable.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringSwitch.h"
@ -149,6 +152,9 @@ struct ParsedAttrInfo {
unsigned NumArgs : 4;
unsigned OptArgs : 4;
unsigned HasCustomParsing : 1;
bool (*DiagAppertainsToDecl)(Sema &S, const AttributeList &Attr,
const Decl *);
};
namespace {
@ -170,3 +176,7 @@ unsigned AttributeList::getMaxArgs() const {
bool AttributeList::hasCustomParsing() const {
return getInfo(*this).HasCustomParsing;
}
bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
}

View File

@ -32,35 +32,6 @@
using namespace clang;
using namespace sema;
/// These constants match the enumerated choices of
/// warn_attribute_wrong_decl_type and err_attribute_wrong_decl_type.
enum AttributeDeclKind {
ExpectedFunction,
ExpectedUnion,
ExpectedVariableOrFunction,
ExpectedFunctionOrMethod,
ExpectedParameter,
ExpectedFunctionMethodOrBlock,
ExpectedFunctionMethodOrClass,
ExpectedFunctionMethodOrParameter,
ExpectedClass,
ExpectedVariable,
ExpectedMethod,
ExpectedVariableFunctionOrLabel,
ExpectedFieldOrGlobalVar,
ExpectedStruct,
ExpectedVariableFunctionOrTag,
ExpectedTLSVar,
ExpectedVariableOrField,
ExpectedVariableFieldOrTag,
ExpectedTypeOrNamespace,
ExpectedObjectiveCInterface,
ExpectedMethodOrProperty,
ExpectedStructOrUnion,
ExpectedStructOrUnionOrClass,
ExpectedType
};
namespace AttributeLangSupport {
enum LANG {
C,
@ -362,12 +333,10 @@ bool Sema::checkStringLiteralArgumentAttr(const AttributeList &Attr,
/// \return true if the Decl is a field or potentially shared global variable
///
static bool mayBeSharedVariable(const Decl *D) {
if (isa<FieldDecl>(D))
return true;
if (const VarDecl *vd = dyn_cast<VarDecl>(D))
return vd->hasGlobalStorage() && !vd->getTLSKind();
return false;
return true;
}
/// \brief Check if the passed-in expression is of type int or bool.
@ -673,24 +642,12 @@ static void handleScopedLockableAttr(Sema &S, Decl *D,
static void handleNoThreadSafetyAnalysis(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
D->addAttr(::new (S.Context) NoThreadSafetyAnalysisAttr(Attr.getRange(),
S.Context));
}
static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
D->addAttr(::new (S.Context)
NoSanitizeAddressAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -698,24 +655,12 @@ static void handleNoSanitizeAddressAttr(Sema &S, Decl *D,
static void handleNoSanitizeMemory(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
D->addAttr(::new (S.Context) NoSanitizeMemoryAttr(Attr.getRange(),
S.Context));
}
static void handleNoSanitizeThread(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
D->addAttr(::new (S.Context) NoSanitizeThreadAttr(Attr.getRange(),
S.Context));
}
@ -783,14 +728,6 @@ static bool checkLockFunAttrCommon(Sema &S, Decl *D,
const AttributeList &Attr,
SmallVectorImpl<Expr *> &Args) {
// zero or more arguments ok
// check that the attribute is applied to a function
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return false;
}
// check that all arguments are lockable objects
checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
@ -858,12 +795,6 @@ static bool checkTryLockFunAttrCommon(Sema &S, Decl *D,
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return false;
}
if (!isIntOrBool(Attr.getArgAsExpr(0))) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
<< Attr.getName() << 1 << AANT_ArgumentIntOrBool;
@ -908,12 +839,6 @@ static bool checkLocksRequiredCommon(Sema &S, Decl *D,
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return false;
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return false;
}
// check that all arguments are lockable objects
checkAttrArgsAreLockableObjs(S, D, Attr, Args);
if (Args.empty())
@ -951,13 +876,6 @@ static void handleSharedLocksRequiredAttr(Sema &S, Decl *D,
static void handleUnlockFunAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
// zero or more arguments ok
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
checkAttrArgsAreLockableObjs(S, D, Attr, Args, 0, /*ParamIdxOk=*/true);
@ -971,12 +889,6 @@ static void handleUnlockFunAttr(Sema &S, Decl *D,
static void handleLockReturnedAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
// check that the argument is lockable object
SmallVector<Expr*, 1> Args;
checkAttrArgsAreLockableObjs(S, D, Attr, Args);
@ -994,12 +906,6 @@ static void handleLocksExcludedAttr(Sema &S, Decl *D,
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return;
if (!isa<FunctionDecl>(D) && !isa<FunctionTemplateDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
// check that all arguments are lockable objects
SmallVector<Expr*, 1> Args;
checkAttrArgsAreLockableObjs(S, D, Attr, Args);
@ -1029,12 +935,6 @@ static void handleConsumableAttr(Sema &S, Decl *D, const AttributeList &Attr) {
<< Attr.getName() << AANT_ArgumentIdentifier;
return;
}
if (!isa<CXXRecordDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedClass;
return;
}
D->addAttr(::new (S.Context)
ConsumableAttr(Attr.getRange(), S.Context, DefaultState,
@ -1063,12 +963,6 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeAtLeastNumArgs(S, Attr, 1))
return;
if (!isa<CXXMethodDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedMethod;
return;
}
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@ -1101,13 +995,7 @@ static void handleCallableWhenAttr(Sema &S, Decl *D,
static void handleParamTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 1)) return;
if (!isa<ParmVarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedParameter;
return;
}
ParamTypestateAttr::ConsumedState ParamState;
if (Attr.isArgIdent(0)) {
@ -1148,12 +1036,6 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 1)) return;
if (!(isa<FunctionDecl>(D) || isa<ParmVarDecl>(D))) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedFunctionMethodOrParameter;
return;
}
ReturnTypestateAttr::ConsumedState ReturnState;
if (Attr.isArgIdent(0)) {
@ -1204,12 +1086,6 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D,
static void handleSetTypestateAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 1))
return;
if (!isa<CXXMethodDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedMethod;
return;
}
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@ -1239,12 +1115,6 @@ static void handleTestTypestateAttr(Sema &S, Decl *D,
if (!checkAttributeNumArgs(S, Attr, 1))
return;
if (!isa<CXXMethodDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedMethod;
return;
}
if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
return;
@ -1270,17 +1140,8 @@ static void handleTestTypestateAttr(Sema &S, Decl *D,
static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
if (TD == 0) {
// __attribute__((ext_vector_type(N))) can only be applied to typedefs
// and type-ids.
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type) <<
Attr.getName() << ExpectedType;
return;
}
// Remember this typedef decl, we will need it later for diagnostics.
S.ExtVectorDecls.push_back(TD);
S.ExtVectorDecls.push_back(cast<TypedefNameDecl>(D));
}
static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@ -1303,13 +1164,8 @@ static void handlePackedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleMsStructAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (RecordDecl *RD = dyn_cast<RecordDecl>(D))
RD->addAttr(::new (S.Context)
MsStructAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedStructOrUnionOrClass;
D->addAttr(::new (S.Context) MsStructAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleIBAction(Sema &S, Decl *D, const AttributeList &Attr) {
@ -1645,12 +1501,6 @@ static void handleWeakRefAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
if (!isa<VarDecl>(D) && !isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariableOrFunction;
return;
}
NamedDecl *nd = cast<NamedDecl>(D);
// gcc rejects
@ -1724,24 +1574,12 @@ static void handleAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleMinSizeAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!isa<FunctionDecl>(D) && !isa<ObjCMethodDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionOrMethod;
return;
}
D->addAttr(::new (S.Context)
MinSizeAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
if (D->hasAttr<HotAttr>()) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< Attr.getName() << "hot";
@ -1753,12 +1591,6 @@ static void handleColdAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
if (D->hasAttr<ColdAttr>()) {
S.Diag(Attr.getLoc(), diag::err_attributes_are_not_compatible)
<< Attr.getName() << "cold";
@ -1770,12 +1602,6 @@ static void handleHotAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
NakedAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -1783,12 +1609,6 @@ static void handleNakedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleAlwaysInlineAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
AlwaysInlineAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -1802,7 +1622,7 @@ static void handleTLSModelAttr(Sema &S, Decl *D,
if (!S.checkStringLiteralArgumentAttr(Attr, 0, Model, &LiteralLoc))
return;
if (!isa<VarDecl>(D) || !cast<VarDecl>(D)->getTLSKind()) {
if (!cast<VarDecl>(D)->getTLSKind()) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedTLSVar;
return;
@ -1841,13 +1661,8 @@ static void handleMayAliasAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleNoCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (isa<VarDecl>(D))
D->addAttr(::new (S.Context)
NoCommonAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
D->addAttr(::new (S.Context) NoCommonAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
@ -1857,13 +1672,8 @@ static void handleCommonAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
if (isa<VarDecl>(D))
D->addAttr(::new (S.Context)
CommonAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
else
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
D->addAttr(::new (S.Context) CommonAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleNoReturnAttr(Sema &S, Decl *D, const AttributeList &attr) {
@ -1955,12 +1765,6 @@ static void handleVecReturnAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return result; // This will be returned in a register
}
*/
if (!isa<RecordDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedClass;
return;
}
if (D->getAttr<VecReturnAttr>()) {
S.Diag(Attr.getLoc(), diag::err_repeat_attribute) << "vecreturn";
return;
@ -2003,10 +1807,6 @@ static void handleDependencyAttr(Sema &S, Scope *Scope, Decl *D,
diag::err_carries_dependency_param_not_function_decl);
return;
}
} else if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunctionMethodOrParameter;
return;
}
D->addAttr(::new (S.Context) CarriesDependencyAttr(
@ -2029,12 +1829,6 @@ static void handleUnusedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleReturnsTwiceAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
ReturnsTwiceAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -2069,12 +1863,6 @@ static void handleConstructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
ConstructorAttr(Attr.getRange(), S.Context, priority,
Attr.getAttributeSpellingListIndex()));
@ -2092,12 +1880,6 @@ static void handleDestructorAttr(Sema &S, Decl *D, const AttributeList &Attr) {
!checkUInt32Argument(S, Attr, Attr.getArgAsExpr(0), priority))
return;
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
DestructorAttr(Attr.getRange(), S.Context, priority,
Attr.getAttributeSpellingListIndex()));
@ -2123,11 +1905,6 @@ static void handleAttrWithMessage(Sema &S, Decl *D,
static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedObjectiveCInterface;
return;
}
D->addAttr(::new (S.Context)
ArcWeakrefUnavailableAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -2135,12 +1912,6 @@ static void handleArcWeakrefUnavailableAttr(Sema &S, Decl *D,
static void handleObjCRootClassAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedObjectiveCInterface;
return;
}
D->addAttr(::new (S.Context)
ObjCRootClassAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -2148,12 +1919,6 @@ static void handleObjCRootClassAttr(Sema &S, Decl *D,
static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedObjectiveCInterface;
return;
}
IdentifierLoc *Parm = Attr.isArgIdent(0) ? Attr.getArgAsIdent(0) : 0;
if (!Parm) {
@ -2169,12 +1934,6 @@ static void handleObjCSuppresProtocolAttr(Sema &S, Decl *D,
static void handleObjCRequiresPropertyDefsAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<ObjCInterfaceDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedObjectiveCInterface;
return;
}
D->addAttr(::new (S.Context)
ObjCRequiresPropertyDefsAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -2485,13 +2244,7 @@ static void handleVisibilityAttr(Sema &S, Decl *D, const AttributeList &Attr,
static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
const AttributeList &Attr) {
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(decl);
if (!method) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< ExpectedMethod;
return;
}
ObjCMethodDecl *method = cast<ObjCMethodDecl>(decl);
if (!Attr.isArgIdent(0)) {
S.Diag(Attr.getLoc(), diag::err_attribute_argument_n_type)
<< Attr.getName() << 1 << AANT_ArgumentIdentifier;
@ -2520,13 +2273,6 @@ static void handleObjCMethodFamilyAttr(Sema &S, Decl *decl,
static void handleObjCExceptionAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
ObjCInterfaceDecl *OCI = dyn_cast<ObjCInterfaceDecl>(D);
if (OCI == 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedObjectiveCInterface;
return;
}
D->addAttr(::new (S.Context)
ObjCExceptionAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -2563,12 +2309,6 @@ static void handleObjCNSObject(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleOverloadableAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
OverloadableAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -2910,8 +2650,8 @@ static void handlePureAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleCleanupAttr(Sema &S, Decl *D, const AttributeList &Attr) {
VarDecl *VD = dyn_cast<VarDecl>(D);
if (!VD || !VD->hasLocalStorage()) {
VarDecl *VD = cast<VarDecl>(D);
if (!VD->hasLocalStorage()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_ignored) << Attr.getName();
return;
}
@ -3636,25 +3376,12 @@ static void handleNoDebugAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleNoInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
NoInlineAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
D->addAttr(::new (S.Context) NoInlineAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
}
static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
NoInstrumentFunctionAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -3662,12 +3389,6 @@ static void handleNoInstrumentFunctionAttr(Sema &S, Decl *D,
static void handleConstantAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
if (!isa<VarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
return;
}
D->addAttr(::new (S.Context)
CUDAConstantAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -3685,12 +3406,6 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
return;
}
if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariableOrFunction;
return;
}
D->addAttr(::new (S.Context)
CUDADeviceAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -3701,12 +3416,6 @@ static void handleDeviceAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
FunctionDecl *FD = cast<FunctionDecl>(D);
if (!FD->getResultType()->isVoidType()) {
TypeLoc TL = FD->getTypeSourceInfo()->getTypeLoc().IgnoreParens();
@ -3732,12 +3441,6 @@ static void handleGlobalAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
D->addAttr(::new (S.Context)
CUDAHostAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -3748,12 +3451,6 @@ static void handleHostAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
if (S.LangOpts.CUDA) {
if (!isa<VarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedVariable;
return;
}
D->addAttr(::new (S.Context)
CUDASharedAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -3763,13 +3460,7 @@ static void handleSharedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
}
static void handleGNUInlineAttr(Sema &S, Decl *D, const AttributeList &Attr) {
FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);
if (Fn == 0) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
<< Attr.getName() << ExpectedFunction;
return;
}
FunctionDecl *Fn = cast<FunctionDecl>(D);
if (!Fn->isInlineSpecified()) {
S.Diag(Attr.getLoc(), diag::warn_gnu_inline_attribute_requires_inline);
return;
@ -4123,14 +3814,9 @@ static bool isValidSubjectOfCFAttribute(Sema &S, QualType type) {
}
static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
ParmVarDecl *param = dyn_cast<ParmVarDecl>(D);
if (!param) {
S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
<< Attr.getRange() << Attr.getName() << ExpectedParameter;
return;
}
ParmVarDecl *param = cast<ParmVarDecl>(D);
bool typeOK, cf;
if (Attr.getKind() == AttributeList::AT_NSConsumed) {
typeOK = isValidSubjectOfNSAttribute(S, param->getType());
cf = false;
@ -4157,12 +3843,6 @@ static void handleNSConsumedAttr(Sema &S, Decl *D, const AttributeList &Attr) {
static void handleNSConsumesSelfAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<ObjCMethodDecl>(D)) {
S.Diag(D->getLocStart(), diag::warn_attribute_wrong_decl_type)
<< Attr.getRange() << Attr.getName() << ExpectedMethod;
return;
}
D->addAttr(::new (S.Context)
NSConsumesSelfAttr(Attr.getRange(), S.Context,
Attr.getAttributeSpellingListIndex()));
@ -4251,27 +3931,17 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
SourceLocation loc = attr.getLoc();
QualType resultType;
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
if (!method) {
ObjCPropertyDecl *property = dyn_cast<ObjCPropertyDecl>(D);
if (!property) {
S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
<< SourceRange(loc, loc) << attr.getName() << ExpectedMethodOrProperty;
return;
}
resultType = property->getType();
}
if (isa<ObjCMethodDecl>(D))
resultType = cast<ObjCMethodDecl>(D)->getResultType();
else
// Check that the method returns a normal pointer.
resultType = method->getResultType();
resultType = cast<ObjCPropertyDecl>(D)->getType();
if (!resultType->isReferenceType() &&
(!resultType->isPointerType() || resultType->isObjCRetainableType())) {
S.Diag(D->getLocStart(), diag::warn_ns_attribute_wrong_return_type)
<< SourceRange(loc)
<< attr.getName() << (method ? EP_ObjCMethod : EP_ObjCProperty)
<< attr.getName()
<< (isa<ObjCMethodDecl>(D) ? EP_ObjCMethod : EP_ObjCProperty)
<< /*non-retainable pointer*/ 2;
// Drop the attribute.
@ -4286,13 +3956,8 @@ static void handleObjCReturnsInnerPointerAttr(Sema &S, Decl *D,
static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
const AttributeList &attr) {
SourceLocation loc = attr.getLoc();
ObjCMethodDecl *method = dyn_cast<ObjCMethodDecl>(D);
ObjCMethodDecl *method = cast<ObjCMethodDecl>(D);
if (!method) {
S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
<< SourceRange(loc, loc) << attr.getName() << ExpectedMethod;
return;
}
DeclContext *DC = method->getDeclContext();
if (const ObjCProtocolDecl *PDecl = dyn_cast_or_null<ObjCProtocolDecl>(DC)) {
S.Diag(D->getLocStart(), diag::warn_objc_requires_super_protocol)
@ -4313,12 +3978,6 @@ static void handleObjCRequiresSuperAttr(Sema &S, Decl *D,
/// Handle cf_audited_transfer and cf_unknown_transfer.
static void handleCFTransferAttr(Sema &S, Decl *D, const AttributeList &A) {
if (!isa<FunctionDecl>(D)) {
S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
<< A.getRange() << A.getName() << ExpectedFunction;
return;
}
bool IsAudited = (A.getKind() == AttributeList::AT_CFAuditedTransfer);
// Check whether there's a conflicting attribute already present.
@ -4433,12 +4092,6 @@ static void handleObjCOwnershipAttr(Sema &S, Decl *D,
static void handleObjCPreciseLifetimeAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!isa<VarDecl>(D) && !isa<FieldDecl>(D)) {
S.Diag(D->getLocStart(), diag::err_attribute_wrong_decl_type)
<< Attr.getRange() << Attr.getName() << ExpectedVariable;
return;
}
ValueDecl *vd = cast<ValueDecl>(D);
QualType type = vd->getType();
@ -4611,6 +4264,11 @@ static bool handleCommonAttributeFeatures(Sema &S, Scope *scope, Decl *D,
if (Attr.getMinArgs() == Attr.getMaxArgs() &&
!checkAttributeNumArgs(S, Attr, Attr.getMinArgs()))
return true;
// Check whether the attribute appertains to the given subject.
if (!Attr.diagnoseAppertainsTo(S, D))
return true;
return false;
}

View File

@ -17,8 +17,10 @@
#include "llvm/TableGen/Record.h"
#include "llvm/TableGen/StringMatcher.h"
#include "llvm/TableGen/TableGenBackend.h"
#include "llvm/TableGen/Error.h"
#include <algorithm>
#include <cctype>
#include <sstream>
using namespace llvm;
@ -1676,7 +1678,7 @@ void EmitClangAttrParsedAttrList(RecordKeeper &Records, raw_ostream &OS) {
}
}
static void emitArgInfo(const Record &R, raw_ostream &OS) {
static void emitArgInfo(const Record &R, std::stringstream &OS) {
// This function will count the number of arguments specified for the
// attribute and emit the number of required arguments followed by the
// number of optional arguments.
@ -1690,27 +1692,191 @@ static void emitArgInfo(const Record &R, raw_ostream &OS) {
OS << ArgCount << ", " << OptCount;
}
static void GenerateDefaultAppertainsTo(raw_ostream &OS) {
OS << "static bool DefaultAppertainsTo(Sema &, const AttributeList &,";
OS << "const Decl *) {\n";
OS << " return true;\n";
OS << "}\n\n";
}
static std::string CalculateDiagnostic(const Record &S) {
// If the SubjectList object has a custom diagnostic associated with it,
// return that directly.
std::string CustomDiag = S.getValueAsString("CustomDiag");
if (!CustomDiag.empty())
return CustomDiag;
// Given the list of subjects, determine what diagnostic best fits.
enum {
Func = 1U << 0,
Var = 1U << 1,
ObjCMethod = 1U << 2,
Param = 1U << 3,
Class = 1U << 4,
Struct = 1U << 5,
Type = 1U << 6,
ObjCIVar = 1U << 7,
ObjCProp = 1U << 8,
ObjCInterface = 1U << 9,
Block = 1U << 10,
Namespace = 1U << 11,
FuncTemplate = 1U << 12,
Field = 1U << 13,
CXXMethod = 1U << 14
};
uint32_t SubMask = 0;
std::vector<Record *> Subjects = S.getValueAsListOfDefs("Subjects");
for (std::vector<Record *>::const_iterator I = Subjects.begin(),
E = Subjects.end(); I != E; ++I) {
uint32_t V = StringSwitch<uint32_t>((*I)->getName())
.Case("Function", Func)
.Case("Var", Var)
.Case("ObjCMethod", ObjCMethod)
.Case("ParmVar", Param)
.Case("TypedefName", Type)
.Case("ObjCIvar", ObjCIVar)
.Case("ObjCProperty", ObjCProp)
.Case("Record", Struct)
.Case("ObjCInterface", ObjCInterface)
.Case("Block", Block)
.Case("CXXRecord", Class)
.Case("Namespace", Namespace)
.Case("FunctionTemplate", FuncTemplate)
.Case("Field", Field)
.Case("CXXMethod", CXXMethod)
.Default(0);
if (!V) {
// Something wasn't in our mapping, so be helpful and let the developer
// know about it.
PrintFatalError((*I)->getLoc(), "Unknown subject type: " +
(*I)->getName());
return "";
}
SubMask |= V;
}
switch (SubMask) {
// For the simple cases where there's only a single entry in the mask, we
// don't have to resort to bit fiddling.
case Func: return "ExpectedFunction";
case Var: return "ExpectedVariable";
case Param: return "ExpectedParameter";
case Class: return "ExpectedClass";
case CXXMethod:
// FIXME: Currently, this maps to ExpectedMethod based on existing code,
// but should map to something a bit more accurate at some point.
case ObjCMethod: return "ExpectedMethod";
case Type: return "ExpectedType";
case ObjCInterface: return "ExpectedObjectiveCInterface";
// FIXME: This could be checking lang opts to remove class.
case Struct: return "ExpectedStructOrUnionOrClass";
case Func | ObjCMethod | Block: return "ExpectedFunctionMethodOrBlock";
case Func | ObjCMethod | Class: return "ExpectedFunctionMethodOrClass";
case Func | Param:
case Func | ObjCMethod | Param: return "ExpectedFunctionMethodOrParameter";
case Func | FuncTemplate:
case Func | ObjCMethod: return "ExpectedFunctionOrMethod";
case Func | Var: return "ExpectedVariableOrFunction";
case ObjCMethod | ObjCProp: return "ExpectedMethodOrProperty";
case Field | Var: return "ExpectedFieldOrGlobalVar";
}
PrintFatalError(S.getLoc(),
"Could not deduce diagnostic argument for Attr subjects");
return "";
}
static std::string GenerateAppertainsTo(const Record &Attr, raw_ostream &OS) {
// If the attribute does not contain a Subjects definition, then use the
// default appertainsTo logic.
if (Attr.isValueUnset("Subjects"))
return "DefaultAppertainsTo";
const Record *SubjectObj = Attr.getValueAsDef("Subjects");
std::vector<Record*> Subjects = SubjectObj->getValueAsListOfDefs("Subjects");
// If the list of subjects is empty, it is assumed that the attribute
// appertains to everything.
if (Subjects.empty())
return "DefaultAppertainsTo";
// If any of the subjects are a SubsetSubject derivative, bail out for now
// as though it was using custom parsing.
bool HasSubsetSubject = false;
bool Warn = SubjectObj->getValueAsDef("Diag")->getValueAsBit("Warn");
// Otherwise, generate an appertainsTo check specific to this attribute which
// checks all of the given subjects against the Decl passed in. Return the
// name of that check to the caller.
std::string FnName = Attr.getName() + "AppertainsTo";
std::stringstream SS;
SS << "static bool " << FnName << "(Sema &S, const AttributeList &Attr, ";
SS << "const Decl *D) {\n";
SS << " if (";
for (std::vector<Record *>::const_iterator I = Subjects.begin(),
E = Subjects.end(); I != E; ++I) {
if ((*I)->isSubClassOf("SubsetSubject"))
HasSubsetSubject = true;
SS << "!isa<" << (*I)->getName() << "Decl>(D)";
if (I + 1 != E)
SS << " && ";
}
SS << ") {\n";
SS << " S.Diag(Attr.getLoc(), diag::";
SS << (Warn ? "warn_attribute_wrong_decl_type" :
"err_attribute_wrong_decl_type");
SS << ")\n";
SS << " << Attr.getName() << ";
SS << CalculateDiagnostic(*SubjectObj) << ";\n";
SS << " return false;\n";
SS << " }\n";
SS << " return true;\n";
SS << "}\n\n";
if (HasSubsetSubject)
return "DefaultAppertainsTo";
OS << SS.str();
return FnName;
}
/// Emits the parsed attribute helpers
void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
emitSourceFileHeader("Parsed attribute helpers", OS);
ParsedAttrMap Attrs = getParsedAttrList(Records);
OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
// Generate the default appertainsTo diagnostic method.
GenerateDefaultAppertainsTo(OS);
// Generate the appertainsTo diagnostic methods and write their names into
// another mapping. At the same time, generate the AttrInfoMap object
// contents. Due to the reliance on generated code, use separate streams so
// that code will not be interleaved.
std::stringstream SS;
for (ParsedAttrMap::iterator I = Attrs.begin(), E = Attrs.end(); I != E;
++I) {
// We need to generate struct instances based off ParsedAttrInfo from
// AttributeList.cpp.
OS << " { ";
emitArgInfo(*I->second, OS);
OS << ", " << I->second->getValueAsBit("HasCustomParsing");
OS << " }";
SS << " { ";
emitArgInfo(*I->second, SS);
SS << ", " << I->second->getValueAsBit("HasCustomParsing");
SS << ", " << GenerateAppertainsTo(*I->second, OS);
SS << " }";
if (I + 1 != E)
OS << ",";
OS << " // AT_" << I->first << "\n";
SS << ",";
SS << " // AT_" << I->first << "\n";
}
OS << "static const ParsedAttrInfo AttrInfoMap[AttributeList::UnknownAttribute + 1] = {\n";
OS << SS.str();
OS << "};\n\n";
}