r201851 - Moving the documentation for the type safety checking attributes into AttrDocs. If a custom heading is provided, do not automatically generate the alternate spelling list. This is necessary because some attributes have distinct semantic spellings and meanings, but use the same semantic attribute internally. Such attributes should have multiple elements in their documentation list, but not show all spellings. At some point, it would be nice to have a way to attach the documentation element to a ...

Aaron Ballman aaron at aaronballman.com
Fri Feb 21 06:14:05 PST 2014


Author: aaronballman
Date: Fri Feb 21 08:14:04 2014
New Revision: 201851

URL: http://llvm.org/viewvc/llvm-project?rev=201851&view=rev
Log:
Moving the documentation for the type safety checking attributes into AttrDocs. If a custom heading is provided, do not automatically generate the alternate spelling list. This is necessary because some attributes have distinct semantic spellings and meanings, but use the same semantic attribute internally. Such attributes should have multiple elements in their documentation list, but not show all spellings. At some point, it would be nice to have a way to attach the documentation element to a specific spelling for these cases.

Modified:
    cfe/trunk/docs/AttributeReference.rst
    cfe/trunk/docs/LanguageExtensions.rst
    cfe/trunk/include/clang/Basic/Attr.td
    cfe/trunk/include/clang/Basic/AttrDocs.td
    cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp

Modified: cfe/trunk/docs/AttributeReference.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/AttributeReference.rst?rev=201851&r1=201850&r2=201851&view=diff
==============================================================================
--- cfe/trunk/docs/AttributeReference.rst (original)
+++ cfe/trunk/docs/AttributeReference.rst Fri Feb 21 08:14:04 2014
@@ -659,3 +659,154 @@ Use ``__attribute__((test_typestate(test
 returns true if the object is in the specified state..
 
 
+Type Safety Checking
+====================
+Clang supports additional attributes to enable checking type safety properties
+that can't be enforced by the C type system.  Use cases include:
+
+* MPI library implementations, where these attributes enable checking that
+  the buffer type matches the passed ``MPI_Datatype``;
+* for HDF5 library there is a similar use case to MPI;
+* checking types of variadic functions' arguments for functions like
+  ``fcntl()`` and ``ioctl()``.
+
+You can detect support for these attributes with ``__has_attribute()``.  For
+example:
+
+.. code-block:: c++
+
+  #if defined(__has_attribute)
+  #  if __has_attribute(argument_with_type_tag) && \
+        __has_attribute(pointer_with_type_tag) && \
+        __has_attribute(type_tag_for_datatype)
+  #    define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx)))
+  /* ... other macros ...  */
+  #  endif
+  #endif
+
+  #if !defined(ATTR_MPI_PWT)
+  # define ATTR_MPI_PWT(buffer_idx, type_idx)
+  #endif
+
+  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
+      ATTR_MPI_PWT(1,3);
+
+argument_with_type_tag
+----------------------
+.. csv-table:: Supported Syntaxes
+   :header: "GNU", "C++11", "__declspec", "Keyword"
+
+   "X","","",""
+
+Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx,
+type_tag_idx)))`` on a function declaration to specify that the function
+accepts a type tag that determines the type of some other argument.
+``arg_kind`` is an identifier that should be used when annotating all
+applicable type tags.
+
+This attribute is primarily useful for checking arguments of variadic functions
+(``pointer_with_type_tag`` can be used in most non-variadic cases).
+
+For example:
+
+.. code-block:: c++
+
+  int fcntl(int fd, int cmd, ...)
+      __attribute__(( argument_with_type_tag(fcntl,3,2) ));
+
+
+pointer_with_type_tag
+---------------------
+.. csv-table:: Supported Syntaxes
+   :header: "GNU", "C++11", "__declspec", "Keyword"
+
+   "X","","",""
+
+Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))``
+on a function declaration to specify that the function accepts a type tag that
+determines the pointee type of some other pointer argument.
+
+For example:
+
+.. code-block:: c++
+
+  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
+      __attribute__(( pointer_with_type_tag(mpi,1,3) ));
+
+
+type_tag_for_datatype
+---------------------
+.. csv-table:: Supported Syntaxes
+   :header: "GNU", "C++11", "__declspec", "Keyword"
+
+   "X","","",""
+
+Clang supports annotating type tags of two forms.
+
+* **Type tag that is an expression containing a reference to some declared
+  identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a
+  declaration with that identifier:
+
+  .. code-block:: c++
+
+    extern struct mpi_datatype mpi_datatype_int
+        __attribute__(( type_tag_for_datatype(mpi,int) ));
+    #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
+
+* **Type tag that is an integral literal.** Introduce a ``static const``
+  variable with a corresponding initializer value and attach
+  ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration,
+  for example:
+
+  .. code-block:: c++
+
+    #define MPI_INT ((MPI_Datatype) 42)
+    static const MPI_Datatype mpi_datatype_int
+        __attribute__(( type_tag_for_datatype(mpi,int) )) = 42
+
+The attribute also accepts an optional third argument that determines how the
+expression is compared to the type tag.  There are two supported flags:
+
+* ``layout_compatible`` will cause types to be compared according to
+  layout-compatibility rules (C++11 [class.mem] p 17, 18).  This is
+  implemented to support annotating types like ``MPI_DOUBLE_INT``.
+
+  For example:
+
+  .. code-block:: c++
+
+    /* In mpi.h */
+    struct internal_mpi_double_int { double d; int i; };
+    extern struct mpi_datatype mpi_datatype_double_int
+        __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) ));
+
+    #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
+
+    /* In user code */
+    struct my_pair { double a; int b; };
+    struct my_pair *buffer;
+    MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ...  */); // no warning
+
+    struct my_int_pair { int a; int b; }
+    struct my_int_pair *buffer2;
+    MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ...  */); // warning: actual buffer element
+                                                      // type 'struct my_int_pair'
+                                                      // doesn't match specified MPI_Datatype
+
+* ``must_be_null`` specifies that the expression should be a null pointer
+  constant, for example:
+
+  .. code-block:: c++
+
+    /* In mpi.h */
+    extern struct mpi_datatype mpi_datatype_null
+        __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
+
+    #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
+
+    /* In user code */
+    MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ...  */); // warning: MPI_DATATYPE_NULL
+                                                        // was specified but buffer
+                                                        // is not a null pointer
+
+

Modified: cfe/trunk/docs/LanguageExtensions.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/LanguageExtensions.rst?rev=201851&r1=201850&r2=201851&view=diff
==============================================================================
--- cfe/trunk/docs/LanguageExtensions.rst (original)
+++ cfe/trunk/docs/LanguageExtensions.rst Fri Feb 21 08:14:04 2014
@@ -1648,158 +1648,6 @@ with :doc:`ThreadSanitizer`.
 Use ``__has_feature(memory_sanitizer)`` to check if the code is being built
 with :doc:`MemorySanitizer`.
 
-Thread Safety Analysis
-======================
-
-Clang Thread Safety Analysis is a C++ language extension which warns about
-potential race conditions in code.  The analysis works very much like a type
-system for multi-threaded programs.  In addition to declaring the *type* of
-data (e.g. ``int``, ``float``, etc.), the programmer can (optionally) declare
-how access to that data is controlled in a multi-threaded environment.  The
-compiler will then issue warnings whenever code fails to follow obey the
-declared requirements.
-
-The complete list of thread safety attributes, along with examples and
-frequently asked questions, can be found in the main documentation: see 
-:doc:`ThreadSafetyAnalysis`.
-
-Type Safety Checking
-====================
-
-Clang supports additional attributes to enable checking type safety properties
-that can't be enforced by the C type system.  Use cases include:
-
-* MPI library implementations, where these attributes enable checking that
-  the buffer type matches the passed ``MPI_Datatype``;
-* for HDF5 library there is a similar use case to MPI;
-* checking types of variadic functions' arguments for functions like
-  ``fcntl()`` and ``ioctl()``.
-
-You can detect support for these attributes with ``__has_attribute()``.  For
-example:
-
-.. code-block:: c++
-
-  #if defined(__has_attribute)
-  #  if __has_attribute(argument_with_type_tag) && \
-        __has_attribute(pointer_with_type_tag) && \
-        __has_attribute(type_tag_for_datatype)
-  #    define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx)))
-  /* ... other macros ...  */
-  #  endif
-  #endif
-
-  #if !defined(ATTR_MPI_PWT)
-  # define ATTR_MPI_PWT(buffer_idx, type_idx)
-  #endif
-
-  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
-      ATTR_MPI_PWT(1,3);
-
-``argument_with_type_tag(...)``
--------------------------------
-
-Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx,
-type_tag_idx)))`` on a function declaration to specify that the function
-accepts a type tag that determines the type of some other argument.
-``arg_kind`` is an identifier that should be used when annotating all
-applicable type tags.
-
-This attribute is primarily useful for checking arguments of variadic functions
-(``pointer_with_type_tag`` can be used in most non-variadic cases).
-
-For example:
-
-.. code-block:: c++
-
-  int fcntl(int fd, int cmd, ...)
-      __attribute__(( argument_with_type_tag(fcntl,3,2) ));
-
-``pointer_with_type_tag(...)``
-------------------------------
-
-Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))``
-on a function declaration to specify that the function accepts a type tag that
-determines the pointee type of some other pointer argument.
-
-For example:
-
-.. code-block:: c++
-
-  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
-      __attribute__(( pointer_with_type_tag(mpi,1,3) ));
-
-``type_tag_for_datatype(...)``
-------------------------------
-
-Clang supports annotating type tags of two forms.
-
-* **Type tag that is an expression containing a reference to some declared
-  identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a
-  declaration with that identifier:
-
-  .. code-block:: c++
-
-    extern struct mpi_datatype mpi_datatype_int
-        __attribute__(( type_tag_for_datatype(mpi,int) ));
-    #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
-
-* **Type tag that is an integral literal.** Introduce a ``static const``
-  variable with a corresponding initializer value and attach
-  ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration,
-  for example:
-
-  .. code-block:: c++
-
-    #define MPI_INT ((MPI_Datatype) 42)
-    static const MPI_Datatype mpi_datatype_int
-        __attribute__(( type_tag_for_datatype(mpi,int) )) = 42
-
-The attribute also accepts an optional third argument that determines how the
-expression is compared to the type tag.  There are two supported flags:
-
-* ``layout_compatible`` will cause types to be compared according to
-  layout-compatibility rules (C++11 [class.mem] p 17, 18).  This is
-  implemented to support annotating types like ``MPI_DOUBLE_INT``.
-
-  For example:
-
-  .. code-block:: c++
-
-    /* In mpi.h */
-    struct internal_mpi_double_int { double d; int i; };
-    extern struct mpi_datatype mpi_datatype_double_int
-        __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) ));
-
-    #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
-
-    /* In user code */
-    struct my_pair { double a; int b; };
-    struct my_pair *buffer;
-    MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ...  */); // no warning
-
-    struct my_int_pair { int a; int b; }
-    struct my_int_pair *buffer2;
-    MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ...  */); // warning: actual buffer element
-                                                      // type 'struct my_int_pair'
-                                                      // doesn't match specified MPI_Datatype
-
-* ``must_be_null`` specifies that the expression should be a null pointer
-  constant, for example:
-
-  .. code-block:: c++
-
-    /* In mpi.h */
-    extern struct mpi_datatype mpi_datatype_null
-        __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
-
-    #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
-
-    /* In user code */
-    MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ...  */); // warning: MPI_DATATYPE_NULL
-                                                        // was specified but buffer
-                                                        // is not a null pointer
-
 Format String Checking
 ======================
 

Modified: cfe/trunk/include/clang/Basic/Attr.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=201851&r1=201850&r2=201851&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Attr.td (original)
+++ cfe/trunk/include/clang/Basic/Attr.td Fri Feb 21 08:14:04 2014
@@ -1555,7 +1555,7 @@ def ArgumentWithTypeTag : InheritableAtt
               UnsignedArgument<"TypeTagIdx">,
               BoolArgument<"IsPointer">];
   let HasCustomParsing = 1;
-  let Documentation = [Undocumented];
+  let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs];
 }
 
 def TypeTagForDatatype : InheritableAttr {
@@ -1566,7 +1566,7 @@ def TypeTagForDatatype : InheritableAttr
               BoolArgument<"MustBeNull">];
 //  let Subjects = SubjectList<[Var], ErrorDiag>;
   let HasCustomParsing = 1;
-  let Documentation = [Undocumented];
+  let Documentation = [TypeTagForDatatypeDocs];
 }
 
 // Microsoft-related attributes

Modified: cfe/trunk/include/clang/Basic/AttrDocs.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/AttrDocs.td?rev=201851&r1=201850&r2=201851&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/AttrDocs.td (original)
+++ cfe/trunk/include/clang/Basic/AttrDocs.td Fri Feb 21 08:14:04 2014
@@ -576,7 +576,7 @@ def NoSanitizeAddressDocs : Documentatio
   let Category = DocCatFunction;
   // This function has multiple distinct spellings, and so it requires a custom
   // heading to be specified. The most common spelling is sufficient.
-  let Heading = "no_sanitize_address";
+  let Heading = "no_sanitize_address (no_address_safety_analysis, gnu::no_address_safety_analysis, gnu::no_sanitize_address)";
   let Content = [{
 Use ``__attribute__((no_sanitize_address))`` on a function declaration to
 specify that address safety instrumentation (e.g. AddressSanitizer) should
@@ -603,3 +603,149 @@ specify that checks for uninitialized me
 to avoid false positives in other places.
   }];
 }
+
+def TypeSafetyCat : DocumentationCategory<"Type Safety Checking"> {
+  let Content = [{
+Clang supports additional attributes to enable checking type safety properties
+that can't be enforced by the C type system.  Use cases include:
+
+* MPI library implementations, where these attributes enable checking that
+  the buffer type matches the passed ``MPI_Datatype``;
+* for HDF5 library there is a similar use case to MPI;
+* checking types of variadic functions' arguments for functions like
+  ``fcntl()`` and ``ioctl()``.
+
+You can detect support for these attributes with ``__has_attribute()``.  For
+example:
+
+.. code-block:: c++
+
+  #if defined(__has_attribute)
+  #  if __has_attribute(argument_with_type_tag) && \
+        __has_attribute(pointer_with_type_tag) && \
+        __has_attribute(type_tag_for_datatype)
+  #    define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx)))
+  /* ... other macros ...  */
+  #  endif
+  #endif
+
+  #if !defined(ATTR_MPI_PWT)
+  # define ATTR_MPI_PWT(buffer_idx, type_idx)
+  #endif
+
+  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
+      ATTR_MPI_PWT(1,3);
+  }];
+}
+
+def ArgumentWithTypeTagDocs : Documentation {
+  let Category = TypeSafetyCat;
+  let Heading = "argument_with_type_tag";
+  let Content = [{
+Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx,
+type_tag_idx)))`` on a function declaration to specify that the function
+accepts a type tag that determines the type of some other argument.
+``arg_kind`` is an identifier that should be used when annotating all
+applicable type tags.
+
+This attribute is primarily useful for checking arguments of variadic functions
+(``pointer_with_type_tag`` can be used in most non-variadic cases).
+
+For example:
+
+.. code-block:: c++
+
+  int fcntl(int fd, int cmd, ...)
+      __attribute__(( argument_with_type_tag(fcntl,3,2) ));
+  }];
+}
+
+def PointerWithTypeTagDocs : Documentation {
+  let Category = TypeSafetyCat;
+  let Heading = "pointer_with_type_tag";
+  let Content = [{
+Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))``
+on a function declaration to specify that the function accepts a type tag that
+determines the pointee type of some other pointer argument.
+
+For example:
+
+.. code-block:: c++
+
+  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
+      __attribute__(( pointer_with_type_tag(mpi,1,3) ));
+  }];
+}
+
+def TypeTagForDatatypeDocs : Documentation {
+  let Category = TypeSafetyCat;
+  let Content = [{
+Clang supports annotating type tags of two forms.
+
+* **Type tag that is an expression containing a reference to some declared
+  identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a
+  declaration with that identifier:
+
+  .. code-block:: c++
+
+    extern struct mpi_datatype mpi_datatype_int
+        __attribute__(( type_tag_for_datatype(mpi,int) ));
+    #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
+
+* **Type tag that is an integral literal.** Introduce a ``static const``
+  variable with a corresponding initializer value and attach
+  ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration,
+  for example:
+
+  .. code-block:: c++
+
+    #define MPI_INT ((MPI_Datatype) 42)
+    static const MPI_Datatype mpi_datatype_int
+        __attribute__(( type_tag_for_datatype(mpi,int) )) = 42
+
+The attribute also accepts an optional third argument that determines how the
+expression is compared to the type tag.  There are two supported flags:
+
+* ``layout_compatible`` will cause types to be compared according to
+  layout-compatibility rules (C++11 [class.mem] p 17, 18).  This is
+  implemented to support annotating types like ``MPI_DOUBLE_INT``.
+
+  For example:
+
+  .. code-block:: c++
+
+    /* In mpi.h */
+    struct internal_mpi_double_int { double d; int i; };
+    extern struct mpi_datatype mpi_datatype_double_int
+        __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) ));
+
+    #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
+
+    /* In user code */
+    struct my_pair { double a; int b; };
+    struct my_pair *buffer;
+    MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ...  */); // no warning
+
+    struct my_int_pair { int a; int b; }
+    struct my_int_pair *buffer2;
+    MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ...  */); // warning: actual buffer element
+                                                      // type 'struct my_int_pair'
+                                                      // doesn't match specified MPI_Datatype
+
+* ``must_be_null`` specifies that the expression should be a null pointer
+  constant, for example:
+
+  .. code-block:: c++
+
+    /* In mpi.h */
+    extern struct mpi_datatype mpi_datatype_null
+        __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
+
+    #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
+
+    /* In user code */
+    MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ...  */); // warning: MPI_DATATYPE_NULL
+                                                        // was specified but buffer
+                                                        // is not a null pointer
+  }];
+}

Modified: cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp?rev=201851&r1=201850&r2=201851&view=diff
==============================================================================
--- cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp (original)
+++ cfe/trunk/utils/TableGen/ClangAttrEmitter.cpp Fri Feb 21 08:14:04 2014
@@ -2693,6 +2693,7 @@ static void WriteDocumentation(const Doc
 
   // Determine the heading to be used for this attribute.
   std::string Heading = Doc.Documentation->getValueAsString("Heading");
+  bool CustomHeading = !Heading.empty();
   if (Heading.empty()) {
     // If there's only one spelling, we can simply use that.
     if (Spellings.size() == 1)
@@ -2745,7 +2746,7 @@ static void WriteDocumentation(const Doc
 
   // Print out the heading for the attribute. If there are alternate spellings,
   // then display those after the heading.
-  if (!Names.empty()) {
+  if (!CustomHeading && !Names.empty()) {
     Heading += " (";
     for (std::vector<std::string>::const_iterator I = Names.begin(),
          E = Names.end(); I != E; ++I) {





More information about the cfe-commits mailing list