[clang] fa0320d - Add ParsedAttrInfo::handleDeclAttribute
John Brawn via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 23 06:25:18 PDT 2020
Author: John Brawn
Date: 2020-03-23T13:23:11Z
New Revision: fa0320dd8d5aa6ea920ac78224d5044398ba50b4
URL: https://github.com/llvm/llvm-project/commit/fa0320dd8d5aa6ea920ac78224d5044398ba50b4
DIFF: https://github.com/llvm/llvm-project/commit/fa0320dd8d5aa6ea920ac78224d5044398ba50b4.diff
LOG: Add ParsedAttrInfo::handleDeclAttribute
This makes it possible for plugin attributes to actually do something, and also
removes a lot of boilerplate for simple attributes in SemaDeclAttr.cpp.
Differential Revision: https://reviews.llvm.org/D31342
Added:
Modified:
clang/docs/ClangPlugins.rst
clang/docs/InternalsManual.rst
clang/include/clang/Basic/Attr.td
clang/include/clang/Sema/ParsedAttr.h
clang/lib/Sema/ParsedAttr.cpp
clang/lib/Sema/SemaDeclAttr.cpp
clang/utils/TableGen/ClangAttrEmitter.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangPlugins.rst b/clang/docs/ClangPlugins.rst
index 23e037e197c9..7e33ea33c0df 100644
--- a/clang/docs/ClangPlugins.rst
+++ b/clang/docs/ClangPlugins.rst
@@ -63,6 +63,53 @@ registering it using ``PragmaHandlerRegistry::Add<>``:
static PragmaHandlerRegistry::Add<ExamplePragmaHandler> 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() {
+ Spellings.push_back({ParsedAttr::AS_GNU,"example"});
+ }
+ AttrHandling handleDeclAttribute(Sema &S, Decl *D,
+ const ParsedAttr &Attr) const override {
+ // Handle the attribute
+ return AttributeApplied;
+ }
+ };
+
+ static ParsedAttrInfoRegistry::Add<ExampleAttrInfo> Z("example_attr","example attribute description");
+
+The members of ``ParsedAttrInfo`` that a plugin attribute must define are:
+
+ * ``Spellings``, which must be populated with every `Spelling
+ </doxygen/structclang_1_1ParsedAttrInfo_1_1Spelling.html>`_ of the
+ attribute, each of which consists of an attribute syntax and how the
+ attribute name is spelled for that syntax. If the syntax allows a scope then
+ the spelling must be "scope::attr" if a scope is present or "::attr" if not.
+ * ``handleDeclAttribute``, which is the function that applies the attribute to
+ a declaration. It is responsible for checking that the attribute's arguments
+ are valid, and typically applies the attribute by adding an ``Attr`` to the
+ ``Decl``. It returns either ``AttributeApplied``, to indicate that the
+ attribute was successfully applied, or ``AttributeNotApplied`` if it wasn't.
+
+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
=======================
diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst
index 3681675a3244..09aec6df69f2 100644
--- a/clang/docs/InternalsManual.rst
+++ b/clang/docs/InternalsManual.rst
@@ -2455,6 +2455,9 @@ Attributes that do not require custom semantic handling should set the
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
diff erent targets. For instance, the ARM and MSP430 targets both have an
attribute spelled ``GNU<"interrupt">``, but with
diff erent parsing and semantic
@@ -2481,12 +2484,11 @@ Boilerplate
All semantic processing of declaration attributes happens in `lib/Sema/SemaDeclAttr.cpp
<https://github.com/llvm/llvm-project/blob/master/clang/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<YourAttr>(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
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 10ed63d7ccae..c8c35cbe5b70 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -513,6 +513,8 @@ class Attr {
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
@@ -681,6 +683,7 @@ def Artificial : InheritableAttr {
let Spellings = [GCC<"artificial">];
let Subjects = SubjectList<[InlineFunction]>;
let Documentation = [ArtificialDocs];
+ let SimpleHandler = 1;
}
def XRayInstrument : InheritableAttr {
@@ -692,6 +695,7 @@ def XRayInstrument : InheritableAttr {
Accessor<"neverXRayInstrument",
[Clang<"xray_never_instrument">]>];
let Documentation = [XRayDocs];
+ let SimpleHandler = 1;
}
def XRayLogArgs : InheritableAttr {
@@ -948,6 +952,7 @@ def OSConsumesThis : InheritableAttr {
let Spellings = [Clang<"os_consumes_this">];
let Subjects = SubjectList<[NonStaticCXXMethod]>;
let Documentation = [RetainBehaviorDocs];
+ let SimpleHandler = 1;
}
def Cleanup : InheritableAttr {
@@ -972,6 +977,7 @@ def Common : InheritableAttr {
def Const : InheritableAttr {
let Spellings = [GCC<"const">, GCC<"__const">];
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def ConstInit : InheritableAttr {
@@ -983,6 +989,7 @@ def ConstInit : InheritableAttr {
let Accessors = [Accessor<"isConstinit", [Keyword<"constinit">]>];
let Documentation = [ConstInitDocs];
let LangOpts = [CPlusPlus];
+ let SimpleHandler = 1;
}
def Constructor : InheritableAttr {
@@ -1113,6 +1120,7 @@ def CXX11NoReturn : InheritableAttr {
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
@@ -1121,6 +1129,7 @@ def OpenCLKernel : InheritableAttr {
let Spellings = [Keyword<"__kernel">, Keyword<"kernel">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def OpenCLUnrollHint : InheritableAttr {
@@ -1190,6 +1199,7 @@ def RenderScriptKernel : Attr {
let Subjects = SubjectList<[Function]>;
let Documentation = [RenderScriptKernelAttributeDocs];
let LangOpts = [RenderScript];
+ let SimpleHandler = 1;
}
def Deprecated : InheritableAttr {
@@ -1214,6 +1224,7 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Spellings = [Declspec<"empty_bases">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [EmptyBasesDocs];
+ let SimpleHandler = 1;
}
def AllocSize : InheritableAttr {
@@ -1285,6 +1296,7 @@ def FlagEnum : InheritableAttr {
let Spellings = [Clang<"flag_enum">];
let Subjects = SubjectList<[Enum]>;
let Documentation = [FlagEnumDocs];
+ let SimpleHandler = 1;
}
def EnumExtensibility : InheritableAttr {
@@ -1299,6 +1311,7 @@ def Flatten : InheritableAttr {
let Spellings = [GCC<"flatten">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [FlattenDocs];
+ let SimpleHandler = 1;
}
def Format : InheritableAttr {
@@ -1344,6 +1357,7 @@ def IBAction : InheritableAttr {
// 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 {
@@ -1384,6 +1398,7 @@ def LifetimeBound : DeclOrTypeAttr {
let Subjects = SubjectList<[ParmVar, ImplicitObjectParameter], ErrorDiag>;
let Documentation = [LifetimeBoundDocs];
let LangOpts = [CPlusPlus];
+ let SimpleHandler = 1;
}
def TrivialABI : InheritableAttr {
@@ -1393,6 +1408,7 @@ def TrivialABI : InheritableAttr {
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [TrivialABIDocs];
let LangOpts = [CPlusPlus];
+ let SimpleHandler = 1;
}
def MaxFieldAlignment : InheritableAttr {
@@ -1407,6 +1423,7 @@ def MayAlias : InheritableAttr {
// 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 {
@@ -1512,12 +1529,14 @@ def NoUniqueAddress : InheritableAttr, TargetSpecificAttr<TargetItaniumCXXABI> {
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 {
@@ -1530,12 +1549,14 @@ def NoAlias : InheritableAttr {
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 {
@@ -1548,30 +1569,35 @@ def NoDuplicate : InheritableAttr {
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<TargetMips32> {
let Spellings = [GCC<"nomips16">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> {
let Spellings = [GCC<"nomicromips">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [MicroMipsDocs];
+ let SimpleHandler = 1;
}
def RISCVInterrupt : InheritableAttr, TargetSpecificAttr<TargetRISCV> {
@@ -1666,6 +1692,7 @@ def NoSplitStack : InheritableAttr {
let Spellings = [GCC<"no_split_stack">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [NoSplitStackDocs];
+ let SimpleHandler = 1;
}
def NonNull : InheritableParamAttr {
@@ -1763,6 +1790,7 @@ def NoInstrumentFunction : InheritableAttr {
let Spellings = [GCC<"no_instrument_function">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def NotTailCalled : InheritableAttr {
@@ -1775,6 +1803,7 @@ def NoStackProtector : InheritableAttr {
let Spellings = [Clang<"no_stack_protector">];
let Subjects = SubjectList<[Function]>;
let Documentation = [NoStackProtectorDocs];
+ let SimpleHandler = 1;
}
def NoThrow : InheritableAttr {
@@ -1837,6 +1866,7 @@ def NSConsumesSelf : InheritableAttr {
let Spellings = [Clang<"ns_consumes_self">];
let Subjects = SubjectList<[ObjCMethod]>;
let Documentation = [RetainBehaviorDocs];
+ let SimpleHandler = 1;
}
def NSConsumed : InheritableParamAttr {
@@ -1849,6 +1879,7 @@ def ObjCException : InheritableAttr {
let Spellings = [Clang<"objc_exception">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def ObjCMethodFamily : InheritableAttr {
@@ -1893,6 +1924,7 @@ def ObjCRootClass : InheritableAttr {
let Spellings = [Clang<"objc_root_class">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def ObjCNonLazyClass : Attr {
@@ -1900,12 +1932,14 @@ def ObjCNonLazyClass : Attr {
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 {
@@ -1945,6 +1979,7 @@ def ObjCRuntimeVisible : Attr {
let Spellings = [Clang<"objc_runtime_visible">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [ObjCRuntimeVisibleDocs];
+ let SimpleHandler = 1;
}
def ObjCClassStub : Attr {
@@ -1952,6 +1987,7 @@ def ObjCClassStub : Attr {
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [ObjCClassStubDocs];
let LangOpts = [ObjCNonFragileRuntime];
+ let SimpleHandler = 1;
}
def ObjCBoxable : Attr {
@@ -1970,6 +2006,7 @@ def Overloadable : Attr {
let Spellings = [Clang<"overloadable">];
let Subjects = SubjectList<[Function], ErrorDiag>;
let Documentation = [OverloadableDocs];
+ let SimpleHandler = 1;
}
def Override : InheritableAttr {
@@ -2027,6 +2064,7 @@ def AArch64VectorPcs: DeclOrTypeAttr {
def Pure : InheritableAttr {
let Spellings = [GCC<"pure">];
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def Regparm : TypeAttr {
@@ -2350,6 +2388,7 @@ def ArcWeakrefUnavailable : InheritableAttr {
let Spellings = [Clang<"objc_arc_weak_reference_unavailable">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def ObjCGC : TypeAttr {
@@ -2368,6 +2407,7 @@ def ObjCRequiresPropertyDefs : InheritableAttr {
let Spellings = [Clang<"objc_requires_property_definitions">];
let Subjects = SubjectList<[ObjCInterface], ErrorDiag>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def Unused : InheritableAttr {
@@ -2382,6 +2422,7 @@ def Used : InheritableAttr {
let Spellings = [GCC<"used">];
let Subjects = SubjectList<[NonLocalVar, Function, ObjCMethod]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def Uuid : InheritableAttr {
@@ -2443,6 +2484,7 @@ def WarnUnused : InheritableAttr {
let Spellings = [GCC<"warn_unused">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def WarnUnusedResult : InheritableAttr {
@@ -2465,6 +2507,7 @@ def Weak : InheritableAttr {
let Spellings = [GCC<"weak">];
let Subjects = SubjectList<[Var, Function, CXXRecord]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def WeakImport : InheritableAttr {
@@ -2484,6 +2527,7 @@ def LTOVisibilityPublic : InheritableAttr {
let Spellings = [Clang<"lto_visibility_public">];
let Subjects = SubjectList<[Record]>;
let Documentation = [LTOVisibilityDocs];
+ let SimpleHandler = 1;
}
def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr<TargetAnyX86> {
@@ -2500,6 +2544,7 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr,
TargetSpecificAttr<TargetAnyX86> {
let Spellings = [GCC<"no_caller_saved_registers">];
let Documentation = [AnyX86NoCallerSavedRegistersDocs];
+ let SimpleHandler = 1;
}
def AnyX86NoCfCheck : DeclOrTypeAttr, TargetSpecificAttr<TargetAnyX86>{
@@ -2551,6 +2596,7 @@ def CFICanonicalJumpTable : InheritableAttr {
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)
@@ -2563,6 +2609,7 @@ def GuardedVar : InheritableAttr {
let Spellings = [Clang<"guarded_var", 0>];
let Subjects = SubjectList<[Field, SharedVar]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def PtGuardedVar : InheritableAttr {
@@ -2582,6 +2629,7 @@ def ScopedLockable : InheritableAttr {
let Spellings = [Clang<"scoped_lockable", 0>];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def Capability : InheritableAttr {
@@ -2678,6 +2726,7 @@ def NoThreadSafetyAnalysis : InheritableAttr {
let Spellings = [Clang<"no_thread_safety_analysis">];
let Subjects = SubjectList<[Function]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def GuardedBy : InheritableAttr {
@@ -2814,6 +2863,7 @@ def ConsumableAutoCast : InheritableAttr {
let Spellings = [Clang<"consumable_auto_cast_state", 0>];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def ConsumableSetOnRead : InheritableAttr {
@@ -2823,6 +2873,7 @@ def ConsumableSetOnRead : InheritableAttr {
let Spellings = [Clang<"consumable_set_state_on_read", 0>];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def CallableWhen : InheritableAttr {
@@ -2929,6 +2980,7 @@ def MSNoVTable : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> {
let Spellings = [Declspec<"novtable">];
let Subjects = SubjectList<[CXXRecord]>;
let Documentation = [MSNoVTableDocs];
+ let SimpleHandler = 1;
}
def : IgnoredAttr {
@@ -2954,6 +3006,7 @@ def MSStruct : InheritableAttr {
let Spellings = [GCC<"ms_struct">];
let Subjects = SubjectList<[Record]>;
let Documentation = [Undocumented];
+ let SimpleHandler = 1;
}
def DLLExport : InheritableAttr, TargetSpecificAttr<TargetWindows> {
@@ -3002,6 +3055,7 @@ def DLLImportStaticLocal : InheritableAttr, TargetSpecificAttr<TargetWindows> {
def SelectAny : InheritableAttr {
let Spellings = [Declspec<"selectany">, GCC<"selectany">];
let Documentation = [SelectAnyDocs];
+ let SimpleHandler = 1;
}
def Thread : Attr {
@@ -3277,12 +3331,14 @@ def ExcludeFromExplicitInstantiation : InheritableAttr {
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 {
diff --git a/clang/include/clang/Sema/ParsedAttr.h b/clang/include/clang/Sema/ParsedAttr.h
index 4894e689475a..439e54084109 100644
--- a/clang/include/clang/Sema/ParsedAttr.h
+++ b/clang/include/clang/Sema/ParsedAttr.h
@@ -68,7 +68,7 @@ struct ParsedAttrInfo {
std::vector<Spelling> Spellings;
ParsedAttrInfo(AttributeCommonInfo::Kind AttrKind =
- AttributeCommonInfo::UnknownAttribute)
+ AttributeCommonInfo::NoSemaHandlerAttribute)
: AttrKind(AttrKind), NumArgs(0), OptArgs(0), HasCustomParsing(0),
IsTargetSpecific(0), IsType(0), IsStmt(0), IsKnownToGCC(0),
IsSupportedByPragmaAttribute(0) {}
@@ -99,6 +99,18 @@ struct ParsedAttrInfo {
llvm::SmallVectorImpl<std::pair<attr::SubjectMatchRule, bool>> &Rules,
const LangOptions &LangOpts) const {
}
+ enum AttrHandling {
+ NotHandled,
+ AttributeApplied,
+ AttributeNotApplied
+ };
+ /// If this ParsedAttrInfo knows how to handle this ParsedAttr applied to this
+ /// Decl then do so and return either AttributeApplied if it was applied or
+ /// AttributeNotApplied if it wasn't. Otherwise return NotHandled.
+ virtual AttrHandling handleDeclAttribute(Sema &S, Decl *D,
+ const ParsedAttr &Attr) const {
+ return NotHandled;
+ }
static const ParsedAttrInfo &get(const AttributeCommonInfo &A);
};
diff --git a/clang/lib/Sema/ParsedAttr.cpp b/clang/lib/Sema/ParsedAttr.cpp
index fa7b59de3e31..6d96ea96cd37 100644
--- a/clang/lib/Sema/ParsedAttr.cpp
+++ b/clang/lib/Sema/ParsedAttr.cpp
@@ -140,7 +140,8 @@ const ParsedAttrInfo &ParsedAttrInfo::get(const AttributeCommonInfo &A) {
return *Ptr;
// If we failed to find a match then return a default ParsedAttrInfo.
- static ParsedAttrInfo DefaultParsedAttrInfo;
+ static ParsedAttrInfo DefaultParsedAttrInfo(
+ AttributeCommonInfo::UnknownAttribute);
return DefaultParsedAttrInfo;
}
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index 393fdcb479d5..5ea5103c3000 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -6747,6 +6747,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
switch (AL.getKind()) {
default:
+ if (AL.getInfo().handleDeclAttribute(S, D, AL) != ParsedAttrInfo::NotHandled)
+ break;
if (!AL.isStmtAttr()) {
// Type attributes are handled elsewhere; silently move on.
assert(AL.isTypeAttr() && "Non-type attribute not handled");
@@ -6769,15 +6771,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleSimpleAttributeWithExclusions<Mips16Attr, MicroMipsAttr,
MipsInterruptAttr>(S, D, AL);
break;
- case ParsedAttr::AT_NoMips16:
- handleSimpleAttribute<NoMips16Attr>(S, D, AL);
- break;
case ParsedAttr::AT_MicroMips:
handleSimpleAttributeWithExclusions<MicroMipsAttr, Mips16Attr>(S, D, AL);
break;
- case ParsedAttr::AT_NoMicroMips:
- handleSimpleAttribute<NoMicroMipsAttr>(S, D, AL);
- break;
case ParsedAttr::AT_MipsLongCall:
handleSimpleAttributeWithExclusions<MipsLongCallAttr, MipsShortCallAttr>(
S, D, AL);
@@ -6813,9 +6809,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_WebAssemblyImportName:
handleWebAssemblyImportNameAttr(S, D, AL);
break;
- case ParsedAttr::AT_IBAction:
- handleSimpleAttribute<IBActionAttr>(S, D, AL);
- break;
case ParsedAttr::AT_IBOutlet:
handleIBOutlet(S, D, AL);
break;
@@ -6840,9 +6833,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_AlwaysInline:
handleAlwaysInlineAttr(S, D, AL);
break;
- case ParsedAttr::AT_Artificial:
- handleSimpleAttribute<ArtificialAttr>(S, D, AL);
- break;
case ParsedAttr::AT_AnalyzerNoReturn:
handleAnalyzerNoReturnAttr(S, D, AL);
break;
@@ -6874,9 +6864,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Constructor:
handleConstructorAttr(S, D, AL);
break;
- case ParsedAttr::AT_CXX11NoReturn:
- handleSimpleAttribute<CXX11NoReturnAttr>(S, D, AL);
- break;
case ParsedAttr::AT_Deprecated:
handleDeprecatedAttr(S, D, AL);
break;
@@ -6904,15 +6891,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_OptimizeNone:
handleOptimizeNoneAttr(S, D, AL);
break;
- case ParsedAttr::AT_FlagEnum:
- handleSimpleAttribute<FlagEnumAttr>(S, D, AL);
- break;
case ParsedAttr::AT_EnumExtensibility:
handleEnumExtensibilityAttr(S, D, AL);
break;
- case ParsedAttr::AT_Flatten:
- handleSimpleAttribute<FlattenAttr>(S, D, AL);
- break;
case ParsedAttr::AT_SYCLKernel:
handleSYCLKernelAttr(S, D, AL);
break;
@@ -6948,27 +6929,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Restrict:
handleRestrictAttr(S, D, AL);
break;
- case ParsedAttr::AT_LifetimeBound:
- handleSimpleAttribute<LifetimeBoundAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MayAlias:
- handleSimpleAttribute<MayAliasAttr>(S, D, AL);
- break;
case ParsedAttr::AT_Mode:
handleModeAttr(S, D, AL);
break;
- case ParsedAttr::AT_NoAlias:
- handleSimpleAttribute<NoAliasAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoCommon:
- handleSimpleAttribute<NoCommonAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoSplitStack:
- handleSimpleAttribute<NoSplitStackAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoUniqueAddress:
- handleSimpleAttribute<NoUniqueAddressAttr>(S, D, AL);
- break;
case ParsedAttr::AT_NonNull:
if (auto *PVD = dyn_cast<ParmVarDecl>(D))
handleNonNullAttrParameter(S, PVD, AL);
@@ -6987,9 +6950,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_AllocAlign:
handleAllocAlignAttr(S, D, AL);
break;
- case ParsedAttr::AT_Overloadable:
- handleSimpleAttribute<OverloadableAttr>(S, D, AL);
- break;
case ParsedAttr::AT_Ownership:
handleOwnershipAttr(S, D, AL);
break;
@@ -7045,9 +7005,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_ObjCRuntimeName:
handleObjCRuntimeName(S, D, AL);
break;
- case ParsedAttr::AT_ObjCRuntimeVisible:
- handleSimpleAttribute<ObjCRuntimeVisibleAttr>(S, D, AL);
- break;
case ParsedAttr::AT_ObjCBoxable:
handleObjCBoxable(S, D, AL);
break;
@@ -7065,12 +7022,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
S.AddXConsumedAttr(D, AL, parsedAttrToRetainOwnershipKind(AL),
/*IsTemplateInstantiation=*/false);
break;
- case ParsedAttr::AT_NSConsumesSelf:
- handleSimpleAttribute<NSConsumesSelfAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_OSConsumesThis:
- handleSimpleAttribute<OSConsumesThisAttr>(S, D, AL);
- break;
case ParsedAttr::AT_OSReturnsRetainedOnZero:
handleSimpleAttributeOrDiagnose<OSReturnsRetainedOnZeroAttr>(
S, D, AL, isValidOSObjectOutParameter(D),
@@ -7104,9 +7055,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_VecTypeHint:
handleVecTypeHint(S, D, AL);
break;
- case ParsedAttr::AT_ConstInit:
- handleSimpleAttribute<ConstInitAttr>(S, D, AL);
- break;
case ParsedAttr::AT_InitPriority:
handleInitPriorityAttr(S, D, AL);
break;
@@ -7137,12 +7085,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Unavailable:
handleAttrWithMessage<UnavailableAttr>(S, D, AL);
break;
- case ParsedAttr::AT_ArcWeakrefUnavailable:
- handleSimpleAttribute<ArcWeakrefUnavailableAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCRootClass:
- handleSimpleAttribute<ObjCRootClassAttr>(S, D, AL);
- break;
case ParsedAttr::AT_ObjCDirect:
handleObjCDirectAttr(S, D, AL);
break;
@@ -7150,27 +7092,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleObjCDirectMembersAttr(S, D, AL);
handleSimpleAttribute<ObjCDirectMembersAttr>(S, D, AL);
break;
- case ParsedAttr::AT_ObjCNonLazyClass:
- handleSimpleAttribute<ObjCNonLazyClassAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCSubclassingRestricted:
- handleSimpleAttribute<ObjCSubclassingRestrictedAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ObjCClassStub:
- handleSimpleAttribute<ObjCClassStubAttr>(S, D, AL);
- break;
case ParsedAttr::AT_ObjCExplicitProtocolImpl:
handleObjCSuppresProtocolAttr(S, D, AL);
break;
- case ParsedAttr::AT_ObjCRequiresPropertyDefs:
- handleSimpleAttribute<ObjCRequiresPropertyDefsAttr>(S, D, AL);
- break;
case ParsedAttr::AT_Unused:
handleUnusedAttr(S, D, AL);
break;
- case ParsedAttr::AT_ReturnsTwice:
- handleSimpleAttribute<ReturnsTwiceAttr>(S, D, AL);
- break;
case ParsedAttr::AT_NotTailCalled:
handleSimpleAttributeWithExclusions<NotTailCalledAttr, AlwaysInlineAttr>(
S, D, AL);
@@ -7179,24 +7106,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handleSimpleAttributeWithExclusions<DisableTailCallsAttr, NakedAttr>(S, D,
AL);
break;
- case ParsedAttr::AT_Used:
- handleSimpleAttribute<UsedAttr>(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<WarnUnusedAttr>(S, D, AL);
- break;
case ParsedAttr::AT_WarnUnusedResult:
handleWarnUnusedResult(S, D, AL);
break;
- case ParsedAttr::AT_Weak:
- handleSimpleAttribute<WeakAttr>(S, D, AL);
- break;
case ParsedAttr::AT_WeakRef:
handleWeakRefAttr(S, D, AL);
break;
@@ -7206,9 +7124,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_TransparentUnion:
handleTransparentUnionAttr(S, D, AL);
break;
- case ParsedAttr::AT_ObjCException:
- handleSimpleAttribute<ObjCExceptionAttr>(S, D, AL);
- break;
case ParsedAttr::AT_ObjCMethodFamily:
handleObjCMethodFamilyAttr(S, D, AL);
break;
@@ -7224,37 +7139,12 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Sentinel:
handleSentinelAttr(S, D, AL);
break;
- case ParsedAttr::AT_Const:
- handleSimpleAttribute<ConstAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Pure:
- handleSimpleAttribute<PureAttr>(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<NoDuplicateAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_Convergent:
- handleSimpleAttribute<ConvergentAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoInline:
- handleSimpleAttribute<NoInlineAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoInstrumentFunction: // Interacts with -pg.
- handleSimpleAttribute<NoInstrumentFunctionAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_NoStackProtector:
- // Interacts with -fstack-protector options.
- handleSimpleAttribute<NoStackProtectorAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_CFICanonicalJumpTable:
- handleSimpleAttribute<CFICanonicalJumpTableAttr>(S, D, AL);
- break;
case ParsedAttr::AT_StdCall:
case ParsedAttr::AT_CDecl:
case ParsedAttr::AT_FastCall:
@@ -7279,9 +7169,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Pointer:
handleLifetimeCategoryAttr(S, D, AL);
break;
- case ParsedAttr::AT_OpenCLKernel:
- handleSimpleAttribute<OpenCLKernelAttr>(S, D, AL);
- break;
case ParsedAttr::AT_OpenCLAccess:
handleOpenCLAccessAttr(S, D, AL);
break;
@@ -7300,38 +7187,17 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_InternalLinkage:
handleInternalLinkageAttr(S, D, AL);
break;
- case ParsedAttr::AT_ExcludeFromExplicitInstantiation:
- handleSimpleAttribute<ExcludeFromExplicitInstantiationAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_LTOVisibilityPublic:
- handleSimpleAttribute<LTOVisibilityPublicAttr>(S, D, AL);
- break;
// Microsoft attributes:
- case ParsedAttr::AT_EmptyBases:
- handleSimpleAttribute<EmptyBasesAttr>(S, D, AL);
- break;
case ParsedAttr::AT_LayoutVersion:
handleLayoutVersion(S, D, AL);
break;
- case ParsedAttr::AT_TrivialABI:
- handleSimpleAttribute<TrivialABIAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MSNoVTable:
- handleSimpleAttribute<MSNoVTableAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_MSStruct:
- handleSimpleAttribute<MSStructAttr>(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<SelectAnyAttr>(S, D, AL);
- break;
case ParsedAttr::AT_Thread:
handleDeclspecThreadAttr(S, D, AL);
break;
@@ -7350,24 +7216,15 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_AssertSharedLock:
handleAssertSharedLockAttr(S, D, AL);
break;
- case ParsedAttr::AT_GuardedVar:
- handleSimpleAttribute<GuardedVarAttr>(S, D, AL);
- break;
case ParsedAttr::AT_PtGuardedVar:
handlePtGuardedVarAttr(S, D, AL);
break;
- case ParsedAttr::AT_ScopedLockable:
- handleSimpleAttribute<ScopedLockableAttr>(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<NoThreadSafetyAnalysisAttr>(S, D, AL);
- break;
case ParsedAttr::AT_GuardedBy:
handleGuardedByAttr(S, D, AL);
break;
@@ -7419,12 +7276,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_Consumable:
handleConsumableAttr(S, D, AL);
break;
- case ParsedAttr::AT_ConsumableAutoCast:
- handleSimpleAttribute<ConsumableAutoCastAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_ConsumableSetOnRead:
- handleSimpleAttribute<ConsumableSetOnReadAttr>(S, D, AL);
- break;
case ParsedAttr::AT_CallableWhen:
handleCallableWhenAttr(S, D, AL);
break;
@@ -7448,16 +7299,8 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_TypeTagForDatatype:
handleTypeTagForDatatypeAttr(S, D, AL);
break;
- case ParsedAttr::AT_AnyX86NoCallerSavedRegisters:
- handleSimpleAttribute<AnyX86NoCallerSavedRegistersAttr>(S, D, AL);
- break;
- case ParsedAttr::AT_RenderScriptKernel:
- handleSimpleAttribute<RenderScriptKernelAttr>(S, D, AL);
- break;
+
// XRay attributes.
- case ParsedAttr::AT_XRayInstrument:
- handleSimpleAttribute<XRayInstrumentAttr>(S, D, AL);
- break;
case ParsedAttr::AT_XRayLogArgs:
handleXRayLogArgsAttr(S, D, AL);
break;
@@ -7466,11 +7309,6 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
handlePatchableFunctionEntryAttr(S, D, AL);
break;
- // Move semantics attribute.
- case ParsedAttr::AT_Reinitializes:
- handleSimpleAttribute<ReinitializesAttr>(S, D, AL);
- break;
-
case ParsedAttr::AT_AlwaysDestroy:
case ParsedAttr::AT_NoDestroy:
handleDestroyAttr(S, D, AL);
diff --git a/clang/utils/TableGen/ClangAttrEmitter.cpp b/clang/utils/TableGen/ClangAttrEmitter.cpp
index 601f186086ec..f640c9eecaee 100644
--- a/clang/utils/TableGen/ClangAttrEmitter.cpp
+++ b/clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -3661,6 +3661,20 @@ static void GenerateSpellingIndexToSemanticSpelling(const Record &Attr,
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 AttrHandling 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 AttributeApplied;\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.
@@ -3742,6 +3756,7 @@ void EmitClangAttrParsedAttrImpl(RecordKeeper &Records, raw_ostream &OS) {
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
More information about the cfe-commits
mailing list