r198705 - Updating the documentation about how to add attributes based on the rather extensive refactorings that have happened over the past several months.
aaron at aaronballman.com
Tue Jan 7 12:12:20 PST 2014
Date: Tue Jan 7 14:12:20 2014
New Revision: 198705
Updating the documentation about how to add attributes based on the rather extensive refactorings that have happened over the past several months.
--- cfe/trunk/docs/InternalsManual.rst (original)
+++ cfe/trunk/docs/InternalsManual.rst Tue Jan 7 14:12:20 2014
@@ -1588,47 +1588,146 @@ How to change Clang
How to add an attribute
-To add an attribute, you'll have to add it to the list of attributes, add it to
-the parsing phase, and look for it in the AST scan.
-has a good example of adding a warning attribute.
-(Beware that this hasn't been reviewed/fixed by the people who designed the
-attributes system yet.)
+Attributes in clang come in two forms: parsed form, and semantic form. Both
+forms are represented via a tablegen definition of the attribute, specified in
-First, add your attribute to the `include/clang/Basic/Attr.td file
+First, add your attribute to the `include/clang/Basic/Attr.td
Each attribute gets a ``def`` inheriting from ``Attr`` or one of its
subclasses. ``InheritableAttr`` means that the attribute also applies to
-subsequent declarations of the same name.
+subsequent declarations of the same name. ``InheritableParamAttr`` is similar
+to ``InheritableAttr``, except that the attribute is written on a parameter
+instead of a declaration, type or statement. Attributes inheriting from
+``TypeAttr`` are pure type attributes which generally are not given a
+representation in the AST. Attributes inheriting from ``TargetSpecificAttr``
+are attributes specific to one or more target architectures. An attribute that
+inherits from ``IgnoredAttr`` is parsed, but will generate an ignored attribute
+diagnostic when used. The attribute type may be useful when an attribute is
+supported by another vendor, but not supported by clang.
``Spellings`` lists the strings that can appear in ``__attribute__((here))`` or
-``[[here]]``. All such strings will be synonymous. If you want to allow the
-``[]`` C++11 syntax, you have to define a list of ``Namespaces``, which will
-let users write ``[[namespace::spelling]]``. Using the empty string for a
-namespace will allow users to write just the spelling with no "``::``".
-Attributes which g++-4.8 accepts should also have a
-``CXX11<"gnu", "spelling">`` spelling.
+``[[here]]``. All such strings will be synonymous. Possible ``Spellings``
+are: ``GNU`` (for use with GNU-style __attribute__ spellings), ``Declspec``
+(for use with Microsoft Visual Studio-style __declspec spellings), ``CXX11`
+(for use with C++11-style [[foo]] and [[foo::bar]] spellings), and ``Keyword``
+(for use with attributes that are implemented as keywords, like C++11's
+``override`` or ``final``). If you want to allow the ``[]`` C++11 syntax, you
+have to define a list of ``Namespaces``, which will let users write
+``[[namespace::spelling]]``. Using the empty string for a namespace will allow
+users to write just the spelling with no "``::``". Attributes which g++-4.8
+or later accepts should also have a ``CXX11<"gnu", "spelling">`` spelling.
``Subjects`` restricts what kinds of AST node to which this attribute can
-appertain (roughly, attach).
+appertain (roughly, attach). The subjects are specified via a ``SubjectList``,
+which specify the list of subjects. Additionally, subject-related diagnostics
+can be specified to be warnings or errors, with the default being a warning.
+The diagnostics displayed to the user are automatically determined based on
+the subjects in the list, but a custom diagnostic parameter can also be
+specified in the ``SubjectList``. The diagnostics generated for subject list
+violations are either ``diag::warn_attribute_wrong_decl_type`` or
+``diag::err_attribute_wrong_decl_type``, and the parameter enumeration is
+found in `include/clang/Sema/AttributeList.h
+If you add new Decl nodes to the ``SubjectList``, you may need to update the
+logic used to automatically determine the diagnostic parameter in `utils/TableGen/ClangAttrEmitter.cpp
+Diagnostic checking for attribute subject lists is automated except when
+``HasCustomParsing`` is set to ``1``.
+By default, all subjects in the SubjectList must either be a Decl node defined
+in ``DeclNodes.td``, or a statement node defined in ``StmtNodes.td``. However,
+more complex subjects can be created by creating a ``SubsetSubject`` object.
+Each such object has a base subject which it appertains to (which must be a
+Decl or Stmt node, and not a SubsetSubject node), and some custom code which is
+called when determining whether an attribute appertains to the subject. For
+instance, a ``NonBitField`` SubsetSubject appertains to a ``FieldDecl``, and
+tests whether the given FieldDecl is a bit field. When a SubsetSubject is
+specified in a SubjectList, a custom diagnostic parameter must also be provided.
``Args`` names the arguments the attribute takes, in order. If ``Args`` is
``[StringArgument<"Arg1">, IntArgument<"Arg2">]`` then
-``__attribute__((myattribute("Hello", 3)))`` will be a valid use.
+``__attribute__((myattribute("Hello", 3)))`` will be a valid use. Attribute
+arguments specify both the parsed form and the semantic form of the attribute.
+The previous example shows an attribute which requires two attributes while
+parsing, and the Attr subclass' constructor for the attribute will require a
+string and integer argument.
+Diagnostic checking for argument counts is automated except when
+``HasCustomParsing`` is set to ``1``, or when the attribute uses an optional or
+variadic argument. Diagnostic checking for argument semantics is not automated.
+If the parsed form of the attribute is more complex, or differs from the
+semantic form, the ``HasCustomParsing`` bit can be set to ``1`` for the class,
+and the parsing code in `Parser::ParseGNUAttributeArgs
+can be updated for the special case. Note that this only applies to arguments
+with a GNU spelling -- attributes with a __declspec spelling currently ignore
+this flag and are handled by ``Parser::ParseMicrosoftDeclSpec``.
+Custom accessors can be generated for an attribute based on the spelling list
+for that attribute. For instance, if an attribute has two different spellings:
+'Foo' and 'Bar', accessors can be created:
+``[Accessor<"isFoo", [GNU<"Foo">]>, Accessor<"isBar", [GNU<"Bar">]>]``
+These accessors will be generated on the semantic form of the attribute,
+accepting no arguments and returning a Boolean.
+Attributes which do not require an AST node should set the ``ASTNode`` field to
+``0`` to avoid polluting the AST. Note that anything inheriting from
+``TypeAttr`` or ``IgnoredAttr`` automatically do not generate an AST node. All
+other attributes generate an AST node by default. The AST node is the semantic
+representation of the attribute.
+Attributes which do not require custom semantic handling should set the
+``SemaHandler`` field to ``0``. Note that anything inheriting from
+``IgnoredAttr`` automatically do not get a semantic handler. All other
+attributes are assumed to use a semantic handler by default. Attributes
+without a semantic handler are not given a parsed attribute Kind enumeration.
+The ``LangOpts`` field can be used to specify a list of language options
+required by the attribute. For instance, all of the CUDA-specific attributes
+specify ``[CUDA]`` for the ``LangOpts`` field, and when the CUDA language
+option is not enabled, an "attribute ignored" warning diagnostic is emitted.
+Since language options are not table generated nodes, new language options must
+be created manually and should specify the spelling used by ``LangOptions`` class.
+Target-specific attribute sometimes 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
+requirements. To support this feature, an attribute inheriting from
+``TargetSpecificAttribute`` make specify a ``ParseKind`` field. This field
+should be the same value between all arguments sharing a spelling, and
+corresponds to the parsed attribute's Kind enumeration. This allows attributes
+to share a parsed attribute kind, but have distinct semantic attribute classes.
+For instance, ``AttributeList::AT_Interrupt`` is the shared parsed attribute
+kind, but ARMInterruptAttr and MSP430InterruptAttr are the semantic attributes
+If additional functionality is desired for the semantic form of the attribute,
+the ``AdditionalMembers`` field specifies code to be copied verbatim into the
+semantic attribute class object.
-Write a new ``HandleYourAttr()`` function in `lib/Sema/SemaDeclAttr.cpp
-and add a case to the switch in ``ProcessNonInheritableDeclAttr()`` or
-``ProcessInheritableDeclAttr()`` forwarding to it.
+All semantic processing of declaration attributes happens in `lib/Sema/SemaDeclAttr.cpp
+and generally starts in the ``ProcessDeclAttribute`` function. If your
+attribute is a "simple" attribute -- meaning that it requires no custom
+semantic processing aside from what is automatically provided for you, you can
+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.
If your attribute causes extra warnings to fire, define a ``DiagGroup`` in
@@ -1638,6 +1737,10 @@ only defining one diagnostic, you can sk
``InGroup<DiagGroup<"your-attribute">>`` directly in `DiagnosticSemaKinds.td
+All semantic diagnostics generated for your attribute, including automatically-
+generated ones (such as subjects and argument counts), should have a
+corresponding test case.
The meat of your attribute
More information about the cfe-commits