r195841 - 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.

Aaron Ballman aaron at aaronballman.com
Wed Nov 27 05:27:03 PST 2013


Author: aaronballman
Date: Wed Nov 27 07:27:02 2013
New Revision: 195841

URL: http://llvm.org/viewvc/llvm-project?rev=195841&view=rev
Log:
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.

Modified:
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Sema/AttributeList.h
    cfe/trunk/lib/Sema/AttributeList.cpp
    cfe/trunk/lib/Sema/SemaDeclAttr.cpp
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=195841&r1=195840&r2=195841&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Wed Nov 27 07:27:02 2013
@@ -109,11 +109,24 @@ class Accessor<string name, list<Spellin
   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, T
 
 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 : InheritableA
   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 : InheritableAtt
   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 : Inheritab
   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 : InheritableA
   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 : Inheritable
   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 : InheritableAtt
   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 {

Modified: cfe/trunk/include/clang/Sema/AttributeList.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?rev=195841&r1=195840&r2=195841&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/AttributeList.h (original)
+++ cfe/trunk/include/clang/Sema/AttributeList.h Wed Nov 27 07:27:02 2013
@@ -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

Modified: cfe/trunk/lib/Sema/AttributeList.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/AttributeList.cpp?rev=195841&r1=195840&r2=195841&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/AttributeList.cpp (original)
+++ cfe/trunk/lib/Sema/AttributeList.cpp Wed Nov 27 07:27:02 2013
@@ -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() con
 bool AttributeList::hasCustomParsing() const {
   return getInfo(*this).HasCustomParsing;
 }
+
+bool AttributeList::diagnoseAppertainsTo(Sema &S, const Decl *D) const {
+  return getInfo(*this).DiagAppertainsToDecl(S, *this, D);
+}

Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=195841&r1=195840&r2=195841&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Wed Nov 27 07:27:02 2013
@@ -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::checkStringLiteralArgumentAtt
 /// \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(Sem
 
 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(
 
 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
                                    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(Se
   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(Sem
   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 handleSharedLocksRequiredAtt
 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,
 
 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
   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
         << 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
                                    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
 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(Se
                                       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(Se
 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
   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
 
 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, De
 }
 
 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, D
     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, Dec
 }
 
 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
 }
 
 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
 }
 
 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, Dec
 
 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,
   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,
 }
 
 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, De
     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,
     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
              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, De
 
 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 &
       !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
       !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 &
 
 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 handleArcWeakrefUnavailableA
 
 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
 
 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 handleObjCSuppresProtocolAtt
 
 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
 
 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(S
 
 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,
 
 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
 }
 
 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, D
 }
 
 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 handleNoInstrumentFunctionAt
 
 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, De
       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, De
 
 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, De
 
 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
 
 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, De
 }
 
 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(
 }
 
 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
 
 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 handleObjCReturnsInnerPointe
   
   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 handleObjCReturnsInnerPointe
 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(
 
 /// 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
 
 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 handleCommonAttributeFeature
   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;
 }
 

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=195841&r1=195840&r2=195841&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Wed Nov 27 07:27:02 2013
@@ -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(RecordK
   }
 }
 
-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,
   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";
 }
 





More information about the cfe-commits mailing list