Index: clang/docs/ClangPlugins.rst =================================================================== --- clang/docs/ClangPlugins.rst +++ clang/docs/ClangPlugins.rst @@ -63,6 +63,46 @@ static PragmaHandlerRegistry::Add Y("example_pragma","example pragma description"); +Defining attributes +=================== + +Plugins can define attributes by declaring a ``ParsedAttrInfo`` and registering +it using ``ParsedAttrInfoRegister::Add<>``: + +.. code-block:: c++ + + class ExampleAttrInfo : public ParsedAttrInfo { + public: + ExampleAttrInfo() { + AttrKind = ParsedAttr::NoSemaHandlerAttribute; + Spellings.push_back({ParsedAttr::AS_GNU,"example"}); + } + virtual bool handleDeclAttribute(Sema &S, Decl *D, + const ParsedAttr &Attr) const { + // Handle the attribute + } + }; + + static ParsedAttrInfoRegistry::Add Z("example_attr","example attribute description"); + +The members of ``ParsedAttrInfo`` that a plugin attribute must define are: + * ``AttrKind``, which must be set to ``ParsedAttr::NoSemaHandlerAttribute``. + * ``Spellings``, which must be populated with the attribute syntaxes that are + allowed and how the attribute name is spelled for each syntax. + * ``handleDeclAttribute``, which is the function that applies the attribute to + a declaration. + +The members of ``ParsedAttrInfo`` that may need to be defined, depending on the +attribute, are: + * ``NumArgs`` and ``OptArgs``, which set the number of required and optional + arguments to the attribute. + * ``diagAppertainsToDecl``, which checks if the attribute has been used on the + right kind of declaration and issues a diagnostic if not. + * ``diagLangOpts``, which checks if the attribute is permitted for the current + language mode and issues a diagnostic if not. + * ``existsInTarget``, which checks if the attribute is permitted for the given + target. + Putting it all together ======================= Index: clang/docs/InternalsManual.rst =================================================================== --- clang/docs/InternalsManual.rst +++ clang/docs/InternalsManual.rst @@ -2455,6 +2455,9 @@ attributes are assumed to use a semantic handler by default. Attributes without a semantic handler are not given a parsed attribute ``Kind`` enumerator. +"Simple" attributes, that require no custom semantic processing aside from what +is automatically provided, should set the ``SimpleHandler`` field to ``1``. + Target-specific attributes may share a spelling with other attributes in different targets. For instance, the ARM and MSP430 targets both have an attribute spelled ``GNU<"interrupt">``, but with different parsing and semantic @@ -2481,12 +2484,11 @@ All semantic processing of declaration attributes happens in `lib/Sema/SemaDeclAttr.cpp `_, and generally starts in the ``ProcessDeclAttribute()`` function. If the -attribute is a "simple" attribute -- meaning that it requires no custom semantic -processing aside from what is automatically provided, add a call to -``handleSimpleAttribute(S, D, Attr);`` to the switch statement. -Otherwise, write a new ``handleYourAttr()`` function, and add that to the switch -statement. Please do not implement handling logic directly in the ``case`` for -the attribute. +attribute has the ``SimpleHandler`` field set to ``1`` then the function to +process the attribute will be automatically generated, and nothing needs to be +done here. Otherwise, write a new ``handleYourAttr()`` function, and add that to +the switch statement. Please do not implement handling logic directly in the +``case`` for the attribute. Unless otherwise specified by the attribute definition, common semantic checking of the parsed attribute is handled automatically. This includes diagnosing Index: clang/include/clang/Basic/Attr.td =================================================================== --- clang/include/clang/Basic/Attr.td +++ clang/include/clang/Basic/Attr.td @@ -510,6 +510,8 @@ bit ASTNode = 1; // Set to true for attributes which have handler in Sema. bit SemaHandler = 1; + // Set to true if this attribute doesn't need custom handling in Sema. + bit SimpleHandler = 0; // Set to true for attributes that are completely ignored. bit Ignored = 0; // Set to true if the attribute's parsing does not match its semantic @@ -678,6 +680,7 @@ let Spellings = [GCC<"artificial">]; let Subjects = SubjectList<[InlineFunction], WarnDiag>; let Documentation = [ArtificialDocs]; + let SimpleHandler = 1; } def XRayInstrument : InheritableAttr { @@ -689,6 +692,7 @@ Accessor<"neverXRayInstrument", [Clang<"xray_never_instrument">]>]; let Documentation = [XRayDocs]; + let SimpleHandler = 1; } def XRayLogArgs : InheritableAttr { @@ -945,6 +949,7 @@ let Spellings = [Clang<"os_consumes_this">]; let Subjects = SubjectList<[NonStaticCXXMethod]>; let Documentation = [RetainBehaviorDocs]; + let SimpleHandler = 1; } def Cleanup : InheritableAttr { @@ -969,6 +974,7 @@ def Const : InheritableAttr { let Spellings = [GCC<"const">, GCC<"__const">]; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def ConstInit : InheritableAttr { @@ -980,6 +986,7 @@ let Accessors = [Accessor<"isConstinit", [Keyword<"constinit">]>]; let Documentation = [ConstInitDocs]; let LangOpts = [CPlusPlus]; + let SimpleHandler = 1; } def Constructor : InheritableAttr { @@ -1110,6 +1117,7 @@ let Spellings = [CXX11<"", "noreturn", 200809>]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [CXX11NoReturnDocs]; + let SimpleHandler = 1; } // Similar to CUDA, OpenCL attributes do not receive a [[]] spelling because @@ -1118,6 +1126,7 @@ let Spellings = [Keyword<"__kernel">, Keyword<"kernel">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def OpenCLUnrollHint : InheritableAttr { @@ -1187,6 +1196,7 @@ let Subjects = SubjectList<[Function]>; let Documentation = [RenderScriptKernelAttributeDocs]; let LangOpts = [RenderScript]; + let SimpleHandler = 1; } def Deprecated : InheritableAttr { @@ -1211,6 +1221,7 @@ let Spellings = [Declspec<"empty_bases">]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [EmptyBasesDocs]; + let SimpleHandler = 1; } def AllocSize : InheritableAttr { @@ -1282,6 +1293,7 @@ let Spellings = [Clang<"flag_enum">]; let Subjects = SubjectList<[Enum]>; let Documentation = [FlagEnumDocs]; + let SimpleHandler = 1; } def EnumExtensibility : InheritableAttr { @@ -1296,6 +1308,7 @@ let Spellings = [GCC<"flatten">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [FlattenDocs]; + let SimpleHandler = 1; } def Format : InheritableAttr { @@ -1341,6 +1354,7 @@ // of the compiler. However, this node needs to exist in the AST because // external tools rely on it. let Documentation = [Undocumented]; + let SimpleHandler = 1; } def IBOutlet : InheritableAttr { @@ -1381,6 +1395,7 @@ let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>; let Documentation = [LifetimeBoundDocs]; let LangOpts = [CPlusPlus]; + let SimpleHandler = 1; } def TrivialABI : InheritableAttr { @@ -1390,6 +1405,7 @@ let Subjects = SubjectList<[CXXRecord]>; let Documentation = [TrivialABIDocs]; let LangOpts = [CPlusPlus]; + let SimpleHandler = 1; } def MaxFieldAlignment : InheritableAttr { @@ -1404,6 +1420,7 @@ // FIXME: this is a type attribute in GCC, but a declaration attribute here. let Spellings = [GCC<"may_alias">]; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def MIGServerRoutine : InheritableAttr { @@ -1509,12 +1526,14 @@ let Spellings = [CXX11<"", "no_unique_address", 201803>]; let Subjects = SubjectList<[NonBitField], ErrorDiag>; let Documentation = [NoUniqueAddressDocs]; + let SimpleHandler = 1; } def ReturnsTwice : InheritableAttr { let Spellings = [GCC<"returns_twice">]; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def DisableTailCalls : InheritableAttr { @@ -1527,12 +1546,14 @@ let Spellings = [Declspec<"noalias">]; let Subjects = SubjectList<[Function]>; let Documentation = [NoAliasDocs]; + let SimpleHandler = 1; } def NoCommon : InheritableAttr { let Spellings = [GCC<"nocommon">]; let Subjects = SubjectList<[Var]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def NoDebug : InheritableAttr { @@ -1545,30 +1566,35 @@ let Spellings = [Clang<"noduplicate">]; let Subjects = SubjectList<[Function]>; let Documentation = [NoDuplicateDocs]; + let SimpleHandler = 1; } def Convergent : InheritableAttr { let Spellings = [Clang<"convergent">]; let Subjects = SubjectList<[Function]>; let Documentation = [ConvergentDocs]; + let SimpleHandler = 1; } def NoInline : InheritableAttr { let Spellings = [GCC<"noinline">, Declspec<"noinline">]; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def NoMips16 : InheritableAttr, TargetSpecificAttr { let Spellings = [GCC<"nomips16">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def NoMicroMips : InheritableAttr, TargetSpecificAttr { let Spellings = [GCC<"nomicromips">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [MicroMipsDocs]; + let SimpleHandler = 1; } def RISCVInterrupt : InheritableAttr, TargetSpecificAttr { @@ -1663,6 +1689,7 @@ let Spellings = [GCC<"no_split_stack">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [NoSplitStackDocs]; + let SimpleHandler = 1; } def NonNull : InheritableParamAttr { @@ -1760,6 +1787,7 @@ let Spellings = [GCC<"no_instrument_function">]; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def NotTailCalled : InheritableAttr { @@ -1772,6 +1800,7 @@ let Spellings = [Clang<"no_stack_protector">]; let Subjects = SubjectList<[Function]>; let Documentation = [NoStackProtectorDocs]; + let SimpleHandler = 1; } def NoThrow : InheritableAttr { @@ -1834,6 +1863,7 @@ let Spellings = [Clang<"ns_consumes_self">]; let Subjects = SubjectList<[ObjCMethod]>; let Documentation = [RetainBehaviorDocs]; + let SimpleHandler = 1; } def NSConsumed : InheritableParamAttr { @@ -1846,6 +1876,7 @@ let Spellings = [Clang<"objc_exception">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def ObjCMethodFamily : InheritableAttr { @@ -1890,6 +1921,7 @@ let Spellings = [Clang<"objc_root_class">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def ObjCNonLazyClass : Attr { @@ -1897,12 +1929,14 @@ let Subjects = SubjectList<[ObjCInterface, ObjCImpl], ErrorDiag>; let LangOpts = [ObjC]; let Documentation = [ObjCNonLazyClassDocs]; + let SimpleHandler = 1; } def ObjCSubclassingRestricted : InheritableAttr { let Spellings = [Clang<"objc_subclassing_restricted">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [ObjCSubclassingRestrictedDocs]; + let SimpleHandler = 1; } def ObjCExplicitProtocolImpl : InheritableAttr { @@ -1942,6 +1976,7 @@ let Spellings = [Clang<"objc_runtime_visible">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [ObjCRuntimeVisibleDocs]; + let SimpleHandler = 1; } def ObjCClassStub : Attr { @@ -1949,6 +1984,7 @@ let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [ObjCClassStubDocs]; let LangOpts = [ObjCNonFragileRuntime]; + let SimpleHandler = 1; } def ObjCBoxable : Attr { @@ -1967,6 +2003,7 @@ let Spellings = [Clang<"overloadable">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [OverloadableDocs]; + let SimpleHandler = 1; } def Override : InheritableAttr { @@ -2024,6 +2061,7 @@ def Pure : InheritableAttr { let Spellings = [GCC<"pure">]; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def Regparm : TypeAttr { @@ -2347,6 +2385,7 @@ let Spellings = [Clang<"objc_arc_weak_reference_unavailable">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def ObjCGC : TypeAttr { @@ -2365,6 +2404,7 @@ let Spellings = [Clang<"objc_requires_property_definitions">]; let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def Unused : InheritableAttr { @@ -2379,6 +2419,7 @@ let Spellings = [GCC<"used">]; let Subjects = SubjectList<[NonLocalVar, Function, ObjCMethod]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def Uuid : InheritableAttr { @@ -2440,6 +2481,7 @@ let Spellings = [GCC<"warn_unused">]; let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def WarnUnusedResult : InheritableAttr { @@ -2462,6 +2504,7 @@ let Spellings = [GCC<"weak">]; let Subjects = SubjectList<[Var, Function, CXXRecord]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def WeakImport : InheritableAttr { @@ -2481,6 +2524,7 @@ let Spellings = [Clang<"lto_visibility_public">]; let Subjects = SubjectList<[Record]>; let Documentation = [LTOVisibilityDocs]; + let SimpleHandler = 1; } def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr { @@ -2497,6 +2541,7 @@ TargetSpecificAttr { let Spellings = [GCC<"no_caller_saved_registers">]; let Documentation = [AnyX86NoCallerSavedRegistersDocs]; + let SimpleHandler = 1; } def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr{ @@ -2548,6 +2593,7 @@ let Spellings = [Clang<"cfi_canonical_jump_table">]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [CFICanonicalJumpTableDocs]; + let SimpleHandler = 1; } // C/C++ Thread safety attributes (e.g. for deadlock, data race checking) @@ -2560,6 +2606,7 @@ let Spellings = [Clang<"guarded_var", 0>]; let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def PtGuardedVar : InheritableAttr { @@ -2579,6 +2626,7 @@ let Spellings = [Clang<"scoped_lockable", 0>]; let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def Capability : InheritableAttr { @@ -2675,6 +2723,7 @@ let Spellings = [Clang<"no_thread_safety_analysis">]; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def GuardedBy : InheritableAttr { @@ -2811,6 +2860,7 @@ let Spellings = [Clang<"consumable_auto_cast_state", 0>]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def ConsumableSetOnRead : InheritableAttr { @@ -2820,6 +2870,7 @@ let Spellings = [Clang<"consumable_set_state_on_read", 0>]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def CallableWhen : InheritableAttr { @@ -2926,6 +2977,7 @@ let Spellings = [Declspec<"novtable">]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [MSNoVTableDocs]; + let SimpleHandler = 1; } def : IgnoredAttr { @@ -2951,6 +3003,7 @@ let Spellings = [GCC<"ms_struct">]; let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; + let SimpleHandler = 1; } def DLLExport : InheritableAttr, TargetSpecificAttr { @@ -2999,6 +3052,7 @@ def SelectAny : InheritableAttr { let Spellings = [Declspec<"selectany">, GCC<"selectany">]; let Documentation = [SelectAnyDocs]; + let SimpleHandler = 1; } def Thread : Attr { @@ -3392,12 +3446,14 @@ let Subjects = SubjectList<[Var, Function, CXXRecord]>; let Documentation = [ExcludeFromExplicitInstantiationDocs]; let MeaningfulToClassTemplateDefinition = 1; + let SimpleHandler = 1; } def Reinitializes : InheritableAttr { let Spellings = [Clang<"reinitializes", 0>]; let Subjects = SubjectList<[NonStaticNonConstCXXMethod], ErrorDiag>; let Documentation = [ReinitializesDocs]; + let SimpleHandler = 1; } def NoDestroy : InheritableAttr { Index: clang/include/clang/Sema/ParsedAttr.h =================================================================== --- clang/include/clang/Sema/ParsedAttr.h +++ clang/include/clang/Sema/ParsedAttr.h @@ -99,6 +99,12 @@ llvm::SmallVectorImpl> &Rules, const LangOptions &LangOpts) const { } + /// If this ParsedAttrInfo knows how to apply an attribute to a decl then do + /// so and return true. If not return false. + virtual bool handleDeclAttribute(Sema &S, Decl *D, + const ParsedAttr &Attr) const { + return false; + } static const ParsedAttrInfo &get(const AttributeCommonInfo &A); }; Index: clang/lib/Sema/SemaDeclAttr.cpp =================================================================== --- clang/lib/Sema/SemaDeclAttr.cpp +++ clang/lib/Sema/SemaDeclAttr.cpp @@ -6694,6 +6694,8 @@ switch (AL.getKind()) { default: + if (AL.getInfo().handleDeclAttribute(S, D, AL)) + break; if (!AL.isStmtAttr()) { // Type attributes are handled elsewhere; silently move on. assert(AL.isTypeAttr() && "Non-type attribute not handled"); @@ -6716,15 +6718,9 @@ handleSimpleAttributeWithExclusions(S, D, AL); break; - case ParsedAttr::AT_NoMips16: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_MicroMips: handleSimpleAttributeWithExclusions(S, D, AL); break; - case ParsedAttr::AT_NoMicroMips: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_MipsLongCall: handleSimpleAttributeWithExclusions( S, D, AL); @@ -6760,9 +6756,6 @@ case ParsedAttr::AT_WebAssemblyImportName: handleWebAssemblyImportNameAttr(S, D, AL); break; - case ParsedAttr::AT_IBAction: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_IBOutlet: handleIBOutlet(S, D, AL); break; @@ -6787,9 +6780,6 @@ case ParsedAttr::AT_AlwaysInline: handleAlwaysInlineAttr(S, D, AL); break; - case ParsedAttr::AT_Artificial: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_AnalyzerNoReturn: handleAnalyzerNoReturnAttr(S, D, AL); break; @@ -6821,9 +6811,6 @@ case ParsedAttr::AT_Constructor: handleConstructorAttr(S, D, AL); break; - case ParsedAttr::AT_CXX11NoReturn: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Deprecated: handleDeprecatedAttr(S, D, AL); break; @@ -6851,15 +6838,9 @@ case ParsedAttr::AT_OptimizeNone: handleOptimizeNoneAttr(S, D, AL); break; - case ParsedAttr::AT_FlagEnum: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_EnumExtensibility: handleEnumExtensibilityAttr(S, D, AL); break; - case ParsedAttr::AT_Flatten: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_SYCLKernel: handleSYCLKernelAttr(S, D, AL); break; @@ -6895,27 +6876,9 @@ case ParsedAttr::AT_Restrict: handleRestrictAttr(S, D, AL); break; - case ParsedAttr::AT_LifetimeBound: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_MayAlias: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Mode: handleModeAttr(S, D, AL); break; - case ParsedAttr::AT_NoAlias: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_NoCommon: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_NoSplitStack: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_NoUniqueAddress: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_NonNull: if (auto *PVD = dyn_cast(D)) handleNonNullAttrParameter(S, PVD, AL); @@ -6934,9 +6897,6 @@ case ParsedAttr::AT_AllocAlign: handleAllocAlignAttr(S, D, AL); break; - case ParsedAttr::AT_Overloadable: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Ownership: handleOwnershipAttr(S, D, AL); break; @@ -6992,9 +6952,6 @@ case ParsedAttr::AT_ObjCRuntimeName: handleObjCRuntimeName(S, D, AL); break; - case ParsedAttr::AT_ObjCRuntimeVisible: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_ObjCBoxable: handleObjCBoxable(S, D, AL); break; @@ -7012,12 +6969,6 @@ S.AddXConsumedAttr(D, AL, parsedAttrToRetainOwnershipKind(AL), /*IsTemplateInstantiation=*/false); break; - case ParsedAttr::AT_NSConsumesSelf: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_OSConsumesThis: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_OSReturnsRetainedOnZero: handleSimpleAttributeOrDiagnose( S, D, AL, isValidOSObjectOutParameter(D), @@ -7051,9 +7002,6 @@ case ParsedAttr::AT_VecTypeHint: handleVecTypeHint(S, D, AL); break; - case ParsedAttr::AT_ConstInit: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_InitPriority: handleInitPriorityAttr(S, D, AL); break; @@ -7084,12 +7032,6 @@ case ParsedAttr::AT_Unavailable: handleAttrWithMessage(S, D, AL); break; - case ParsedAttr::AT_ArcWeakrefUnavailable: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_ObjCRootClass: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_ObjCDirect: handleObjCDirectAttr(S, D, AL); break; @@ -7097,27 +7039,12 @@ handleObjCDirectMembersAttr(S, D, AL); handleSimpleAttribute(S, D, AL); break; - case ParsedAttr::AT_ObjCNonLazyClass: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_ObjCSubclassingRestricted: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_ObjCClassStub: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_ObjCExplicitProtocolImpl: handleObjCSuppresProtocolAttr(S, D, AL); break; - case ParsedAttr::AT_ObjCRequiresPropertyDefs: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Unused: handleUnusedAttr(S, D, AL); break; - case ParsedAttr::AT_ReturnsTwice: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_NotTailCalled: handleSimpleAttributeWithExclusions( S, D, AL); @@ -7126,24 +7053,15 @@ handleSimpleAttributeWithExclusions(S, D, AL); break; - case ParsedAttr::AT_Used: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Visibility: handleVisibilityAttr(S, D, AL, false); break; case ParsedAttr::AT_TypeVisibility: handleVisibilityAttr(S, D, AL, true); break; - case ParsedAttr::AT_WarnUnused: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_WarnUnusedResult: handleWarnUnusedResult(S, D, AL); break; - case ParsedAttr::AT_Weak: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_WeakRef: handleWeakRefAttr(S, D, AL); break; @@ -7153,9 +7071,6 @@ case ParsedAttr::AT_TransparentUnion: handleTransparentUnionAttr(S, D, AL); break; - case ParsedAttr::AT_ObjCException: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_ObjCMethodFamily: handleObjCMethodFamilyAttr(S, D, AL); break; @@ -7171,37 +7086,12 @@ case ParsedAttr::AT_Sentinel: handleSentinelAttr(S, D, AL); break; - case ParsedAttr::AT_Const: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_Pure: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Cleanup: handleCleanupAttr(S, D, AL); break; case ParsedAttr::AT_NoDebug: handleNoDebugAttr(S, D, AL); break; - case ParsedAttr::AT_NoDuplicate: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_Convergent: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_NoInline: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_NoInstrumentFunction: // Interacts with -pg. - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_NoStackProtector: - // Interacts with -fstack-protector options. - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_CFICanonicalJumpTable: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_StdCall: case ParsedAttr::AT_CDecl: case ParsedAttr::AT_FastCall: @@ -7226,9 +7116,6 @@ case ParsedAttr::AT_Pointer: handleLifetimeCategoryAttr(S, D, AL); break; - case ParsedAttr::AT_OpenCLKernel: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_OpenCLAccess: handleOpenCLAccessAttr(S, D, AL); break; @@ -7247,38 +7134,17 @@ case ParsedAttr::AT_InternalLinkage: handleInternalLinkageAttr(S, D, AL); break; - case ParsedAttr::AT_ExcludeFromExplicitInstantiation: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_LTOVisibilityPublic: - handleSimpleAttribute(S, D, AL); - break; // Microsoft attributes: - case ParsedAttr::AT_EmptyBases: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_LayoutVersion: handleLayoutVersion(S, D, AL); break; - case ParsedAttr::AT_TrivialABI: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_MSNoVTable: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_MSStruct: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Uuid: handleUuidAttr(S, D, AL); break; case ParsedAttr::AT_MSInheritance: handleMSInheritanceAttr(S, D, AL); break; - case ParsedAttr::AT_SelectAny: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_Thread: handleDeclspecThreadAttr(S, D, AL); break; @@ -7297,24 +7163,15 @@ case ParsedAttr::AT_AssertSharedLock: handleAssertSharedLockAttr(S, D, AL); break; - case ParsedAttr::AT_GuardedVar: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_PtGuardedVar: handlePtGuardedVarAttr(S, D, AL); break; - case ParsedAttr::AT_ScopedLockable: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_NoSanitize: handleNoSanitizeAttr(S, D, AL); break; case ParsedAttr::AT_NoSanitizeSpecific: handleNoSanitizeSpecificAttr(S, D, AL); break; - case ParsedAttr::AT_NoThreadSafetyAnalysis: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_GuardedBy: handleGuardedByAttr(S, D, AL); break; @@ -7366,12 +7223,6 @@ case ParsedAttr::AT_Consumable: handleConsumableAttr(S, D, AL); break; - case ParsedAttr::AT_ConsumableAutoCast: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_ConsumableSetOnRead: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_CallableWhen: handleCallableWhenAttr(S, D, AL); break; @@ -7395,16 +7246,8 @@ case ParsedAttr::AT_TypeTagForDatatype: handleTypeTagForDatatypeAttr(S, D, AL); break; - case ParsedAttr::AT_AnyX86NoCallerSavedRegisters: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_RenderScriptKernel: - handleSimpleAttribute(S, D, AL); - break; + // XRay attributes. - case ParsedAttr::AT_XRayInstrument: - handleSimpleAttribute(S, D, AL); - break; case ParsedAttr::AT_XRayLogArgs: handleXRayLogArgsAttr(S, D, AL); break; @@ -7413,11 +7256,6 @@ handlePatchableFunctionEntryAttr(S, D, AL); break; - // Move semantics attribute. - case ParsedAttr::AT_Reinitializes: - handleSimpleAttribute(S, D, AL); - break; - case ParsedAttr::AT_AlwaysDestroy: case ParsedAttr::AT_NoDestroy: handleDestroyAttr(S, D, AL); Index: clang/utils/TableGen/ClangAttrEmitter.cpp =================================================================== --- clang/utils/TableGen/ClangAttrEmitter.cpp +++ clang/utils/TableGen/ClangAttrEmitter.cpp @@ -3583,6 +3583,20 @@ OS << "}\n\n"; } +static void GenerateHandleDeclAttribute(const Record &Attr, raw_ostream &OS) { + // Only generate if Attr can be handled simply. + if (!Attr.getValueAsBit("SimpleHandler")) + return; + + // Generate a function which just converts from ParsedAttr to the Attr type. + OS << "virtual bool handleDeclAttribute(Sema &S, Decl *D,"; + OS << "const ParsedAttr &Attr) const {\n"; + OS << " D->addAttr(::new (S.Context) " << Attr.getName(); + OS << "Attr(S.Context, Attr));\n"; + OS << " return true;\n"; + OS << "}\n\n"; +} + static bool IsKnownToGCC(const Record &Attr) { // Look at the spellings for this subject; if there are any spellings which // claim to be known to GCC, the attribute is known to GCC. @@ -3664,6 +3678,7 @@ GenerateTargetRequirements(Attr, Dupes, OS); GenerateSpellingIndexToSemanticSpelling(Attr, OS); PragmaAttributeSupport.generateStrictConformsTo(*I->second, OS); + GenerateHandleDeclAttribute(Attr, OS); OS << "static const ParsedAttrInfo" << I->first << " Instance;\n"; OS << "};\n"; OS << "const ParsedAttrInfo" << I->first << " ParsedAttrInfo" << I->first