diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2014-01-07 20:12:20 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2014-01-07 20:12:20 +0000 |
commit | 92e28e876d67f8f632dee423eeacde5e9f31227f (patch) | |
tree | c86529b5fda5c5d4be66e3ddf4ed039e60356e15 /clang/docs/InternalsManual.rst | |
parent | 7c81c4a3548915b5b8bd7e4f9b1238f63bd66925 (diff) | |
download | llvm-92e28e876d67f8f632dee423eeacde5e9f31227f.zip llvm-92e28e876d67f8f632dee423eeacde5e9f31227f.tar.gz llvm-92e28e876d67f8f632dee423eeacde5e9f31227f.tar.bz2 |
Updating the documentation about how to add attributes based on the rather extensive refactorings that have happened over the past several months.
llvm-svn: 198705
Diffstat (limited to 'clang/docs/InternalsManual.rst')
-rw-r--r-- | clang/docs/InternalsManual.rst | 145 |
1 files changed, 124 insertions, 21 deletions
diff --git a/clang/docs/InternalsManual.rst b/clang/docs/InternalsManual.rst index 6f55702..40a1a09 100644 --- a/clang/docs/InternalsManual.rst +++ b/clang/docs/InternalsManual.rst @@ -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. -`r124217 <http://llvm.org/viewvc/llvm-project?view=rev&revision=124217>`_ -has a good example of adding a warning attribute. +Attribute Basics +^^^^^^^^^^^^^^^^ -(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 +Attr.td. ``include/clang/Basic/Attr.td`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -First, add your attribute to the `include/clang/Basic/Attr.td file -<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?view=markup>`_. +First, add your attribute to the `include/clang/Basic/Attr.td +<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?view=markup>`_ +file. 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 +<http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/AttributeList.h?view=markup>`_ +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 +<http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?view=markup>`_. + +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 +<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Parse/ParseDecl.cpp?view=markup>`_ +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 +generated. + +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. Boilerplate ^^^^^^^^^^^ -Write a new ``HandleYourAttr()`` function in `lib/Sema/SemaDeclAttr.cpp -<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?view=markup>`_, -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 +<http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?view=markup>`_, +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 `include/clang/Basic/DiagnosticGroups.td @@ -1638,6 +1737,10 @@ only defining one diagnostic, you can skip ``DiagnosticGroups.td`` and use ``InGroup<DiagGroup<"your-attribute">>`` directly in `DiagnosticSemaKinds.td <http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?view=markup>`_ +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 ^^^^^^^^^^^^^^^^^^^^^^^^^^ |