]> granicus.if.org Git - clang/commitdiff
Moving the documentation for the type safety checking attributes into AttrDocs. If...
authorAaron Ballman <aaron@aaronballman.com>
Fri, 21 Feb 2014 14:14:04 +0000 (14:14 +0000)
committerAaron Ballman <aaron@aaronballman.com>
Fri, 21 Feb 2014 14:14:04 +0000 (14:14 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@201851 91177308-0d34-0410-b5e6-96231b3b80d8

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

index ef301f5dc5abbb8acbe4ddd3386d65c89ecae9f9..fd84adc5daa718829c675236d8b1722de4d0c22c 100644 (file)
@@ -659,3 +659,154 @@ Use ``__attribute__((test_typestate(tested_state)))`` to indicate that a method
 returns true if the object is in the specified state..\r
 \r
 \r
+Type Safety Checking\r
+====================\r
+Clang supports additional attributes to enable checking type safety properties\r
+that can't be enforced by the C type system.  Use cases include:\r
+\r
+* MPI library implementations, where these attributes enable checking that\r
+  the buffer type matches the passed ``MPI_Datatype``;\r
+* for HDF5 library there is a similar use case to MPI;\r
+* checking types of variadic functions' arguments for functions like\r
+  ``fcntl()`` and ``ioctl()``.\r
+\r
+You can detect support for these attributes with ``__has_attribute()``.  For\r
+example:\r
+\r
+.. code-block:: c++\r
+\r
+  #if defined(__has_attribute)\r
+  #  if __has_attribute(argument_with_type_tag) && \\r
+        __has_attribute(pointer_with_type_tag) && \\r
+        __has_attribute(type_tag_for_datatype)\r
+  #    define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx)))\r
+  /* ... other macros ...  */\r
+  #  endif\r
+  #endif\r
+\r
+  #if !defined(ATTR_MPI_PWT)\r
+  # define ATTR_MPI_PWT(buffer_idx, type_idx)\r
+  #endif\r
+\r
+  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)\r
+      ATTR_MPI_PWT(1,3);\r
+\r
+argument_with_type_tag\r
+----------------------\r
+.. csv-table:: Supported Syntaxes\r
+   :header: "GNU", "C++11", "__declspec", "Keyword"\r
+\r
+   "X","","",""\r
+\r
+Use ``__attribute__((argument_with_type_tag(arg_kind, arg_idx,\r
+type_tag_idx)))`` on a function declaration to specify that the function\r
+accepts a type tag that determines the type of some other argument.\r
+``arg_kind`` is an identifier that should be used when annotating all\r
+applicable type tags.\r
+\r
+This attribute is primarily useful for checking arguments of variadic functions\r
+(``pointer_with_type_tag`` can be used in most non-variadic cases).\r
+\r
+For example:\r
+\r
+.. code-block:: c++\r
+\r
+  int fcntl(int fd, int cmd, ...)\r
+      __attribute__(( argument_with_type_tag(fcntl,3,2) ));\r
+\r
+\r
+pointer_with_type_tag\r
+---------------------\r
+.. csv-table:: Supported Syntaxes\r
+   :header: "GNU", "C++11", "__declspec", "Keyword"\r
+\r
+   "X","","",""\r
+\r
+Use ``__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx, type_tag_idx)))``\r
+on a function declaration to specify that the function accepts a type tag that\r
+determines the pointee type of some other pointer argument.\r
+\r
+For example:\r
+\r
+.. code-block:: c++\r
+\r
+  int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)\r
+      __attribute__(( pointer_with_type_tag(mpi,1,3) ));\r
+\r
+\r
+type_tag_for_datatype\r
+---------------------\r
+.. csv-table:: Supported Syntaxes\r
+   :header: "GNU", "C++11", "__declspec", "Keyword"\r
+\r
+   "X","","",""\r
+\r
+Clang supports annotating type tags of two forms.\r
+\r
+* **Type tag that is an expression containing a reference to some declared\r
+  identifier.** Use ``__attribute__((type_tag_for_datatype(kind, type)))`` on a\r
+  declaration with that identifier:\r
+\r
+  .. code-block:: c++\r
+\r
+    extern struct mpi_datatype mpi_datatype_int\r
+        __attribute__(( type_tag_for_datatype(mpi,int) ));\r
+    #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)\r
+\r
+* **Type tag that is an integral literal.** Introduce a ``static const``\r
+  variable with a corresponding initializer value and attach\r
+  ``__attribute__((type_tag_for_datatype(kind, type)))`` on that declaration,\r
+  for example:\r
+\r
+  .. code-block:: c++\r
+\r
+    #define MPI_INT ((MPI_Datatype) 42)\r
+    static const MPI_Datatype mpi_datatype_int\r
+        __attribute__(( type_tag_for_datatype(mpi,int) )) = 42\r
+\r
+The attribute also accepts an optional third argument that determines how the\r
+expression is compared to the type tag.  There are two supported flags:\r
+\r
+* ``layout_compatible`` will cause types to be compared according to\r
+  layout-compatibility rules (C++11 [class.mem] p 17, 18).  This is\r
+  implemented to support annotating types like ``MPI_DOUBLE_INT``.\r
+\r
+  For example:\r
+\r
+  .. code-block:: c++\r
+\r
+    /* In mpi.h */\r
+    struct internal_mpi_double_int { double d; int i; };\r
+    extern struct mpi_datatype mpi_datatype_double_int\r
+        __attribute__(( type_tag_for_datatype(mpi, struct internal_mpi_double_int, layout_compatible) ));\r
+\r
+    #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)\r
+\r
+    /* In user code */\r
+    struct my_pair { double a; int b; };\r
+    struct my_pair *buffer;\r
+    MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ...  */); // no warning\r
+\r
+    struct my_int_pair { int a; int b; }\r
+    struct my_int_pair *buffer2;\r
+    MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ...  */); // warning: actual buffer element\r
+                                                      // type 'struct my_int_pair'\r
+                                                      // doesn't match specified MPI_Datatype\r
+\r
+* ``must_be_null`` specifies that the expression should be a null pointer\r
+  constant, for example:\r
+\r
+  .. code-block:: c++\r
+\r
+    /* In mpi.h */\r
+    extern struct mpi_datatype mpi_datatype_null\r
+        __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));\r
+\r
+    #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)\r
+\r
+    /* In user code */\r
+    MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ...  */); // warning: MPI_DATATYPE_NULL\r
+                                                        // was specified but buffer\r
+                                                        // is not a null pointer\r
+\r
+\r
index 9474bf2069fde6189a1a34cdde9e3f9e94e6e08f..13aae3443953b4ab81142c102b22975f0224610a 100644 (file)
@@ -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
 ======================
 
index 5c597bf99c6e8411da920625f854af5599f62b6e..a23254164d3613f155b49631acc8939c0b11729d 100644 (file)
@@ -1555,7 +1555,7 @@ def ArgumentWithTypeTag : InheritableAttr {
               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
index 37ffee1c75a9b6343f9f152c05dd3a3a20940964..bf7bd4d3e99a162881870fad40ea18a040b3afc2 100644 (file)
@@ -576,7 +576,7 @@ def NoSanitizeAddressDocs : Documentation {
   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 memory should not be inserted
 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
+  }];
+}
index 8f65d910858669a89274886523444d3a6946a198..3b4955755e1f895c20503bb22593af7f633d6cf7 100644 (file)
@@ -2693,6 +2693,7 @@ static void WriteDocumentation(const DocumentationData &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 DocumentationData &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) {