Add support for "type safety" attributes that allow checking that 'void *'
function arguments and arguments for variadic functions are of a particular
type which is determined by some other argument to the same function call.

Usecases include:
* MPI library implementations, where these attributes enable checking that
  buffer type matches the passed MPI_Datatype;
* for HDF5 library there is a similar usecase as MPI;
* checking types of variadic functions' arguments for functions like
  fcntl() and ioctl().


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@162067 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/docs/LanguageExtensions.html b/docs/LanguageExtensions.html
index eac3c69..40477b8 100644
--- a/docs/LanguageExtensions.html
+++ b/docs/LanguageExtensions.html
@@ -142,6 +142,13 @@
     <li><a href="#ts_slr"><tt>shared_locks_required(...)</tt></a></li>   
     </ul>
 </li>
+<li><a href="#type_safety">Type Safety Checking</a>
+  <ul>
+  <li><a href="#argument_with_type_tag"><tt>argument_with_type_tag(...)</tt></a></li>
+  <li><a href="#pointer_with_type_tag"><tt>pointer_with_type_tag(...)</tt></a></li>
+  <li><a href="#type_tag_for_datatype"><tt>type_tag_for_datatype(...)</tt></a></li>
+  </ul>
+</li>
 </ul>
 
 <!-- ======================================================================= -->
@@ -1913,6 +1920,161 @@
 shared locks. Arguments must be lockable type, and there must be at 
 least one argument.</p> 
 
+<!-- ======================================================================= -->
+<h2 id="type_safety">Type Safety Checking</h2>
+<!-- ======================================================================= -->
+
+<p>Clang supports additional attributes to enable checking type safety
+properties that can't be enforced by C type system.  Usecases include:</p>
+<ul>
+<li>MPI library implementations, where these attributes enable checking that
+    buffer type matches the passed <tt>MPI_Datatype</tt>;</li>
+<li>for HDF5 library there is a similar usecase as MPI;</li>
+<li>checking types of variadic functions' arguments for functions like
+    <tt>fcntl()</tt> and <tt>ioctl()</tt>.</li>
+</ul>
+
+<p>You can detect support for these attributes with __has_attribute().  For
+example:</p>
+
+<blockquote>
+<pre>
+#if defined(__has_attribute)
+#  if __has_attribute(argument_with_type_tag) &amp;&amp; \
+      __has_attribute(pointer_with_type_tag) &amp;&amp; \
+      __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);
+</pre>
+</blockquote>
+
+<h3 id="argument_with_type_tag"><tt>argument_with_type_tag(...)</tt></h3>
+
+<p>Use <tt>__attribute__((argument_with_type_tag(arg_kind, arg_idx,
+type_tag_idx)))</tt> on a function declaration to specify that the function
+accepts a type tag that determines the type of some other argument.
+<tt>arg_kind</tt> is an identifier that should be used when annotating all
+applicable type tags.</p>
+
+<p>This attribute is primarily useful for checking arguments of variadic
+functions (<tt>pointer_with_type_tag</tt> can be used in most of non-variadic
+cases).</p>
+
+<p>For example:</p>
+<blockquote>
+<pre>
+int fcntl(int fd, int cmd, ...)
+      __attribute__(( argument_with_type_tag(fcntl,3,2) ));
+</pre>
+</blockquote>
+
+<h3 id="pointer_with_type_tag"><tt>pointer_with_type_tag(...)</tt></h3>
+
+<p>Use <tt>__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx,
+type_tag_idx)))</tt> on a function declaration to specify that the
+function a type tag that determines the pointee type of some other pointer
+argument.</p>
+
+<p>For example:</p>
+<blockquote>
+<pre>
+int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
+    __attribute__(( pointer_with_type_tag(mpi,1,3) ));
+</pre>
+</blockquote>
+
+<h3 id="type_tag_for_datatype"><tt>type_tag_for_datatype(...)</tt></h3>
+
+<p>Clang supports annotating type tags of two forms.</p>
+
+<ul>
+<li><b>Type tag that is an expression containing a reference to some declared
+identifier.</b> Use <tt>__attribute__((type_tag_for_datatype(kind, type)))</tt>
+on a declaration with that identifier:
+
+<blockquote>
+<pre>
+extern struct mpi_datatype mpi_datatype_int
+    __attribute__(( type_tag_for_datatype(mpi,int) ));
+#define MPI_INT ((MPI_Datatype) &amp;mpi_datatype_int)
+</pre>
+</blockquote></li>
+
+<li><b>Type tag that is an integral literal.</b>  Introduce a <tt>static
+const</tt> variable with a corresponding initializer value and attach
+<tt>__attribute__((type_tag_for_datatype(kind, type)))</tt> on that
+declaration, for example:
+
+<blockquote>
+<pre>
+#define MPI_INT ((MPI_Datatype) 42)
+static const MPI_Datatype mpi_datatype_int
+    __attribute__(( type_tag_for_datatype(mpi,int) )) = 42
+</pre>
+</blockquote></li>
+</ul>
+
+<p>The attribute also accepts an optional third argument that determines how
+the expression is compared to the type tag.  There are two supported flags:</p>
+
+<ul><li><tt>layout_compatible</tt> will cause types to be compared according to
+layout-compatibility rules (C++11 [class.mem] p&nbsp;17, 18).  This is
+implemented to support annotating types like <tt>MPI_DOUBLE_INT</tt>.
+
+<p>For example:</p>
+<blockquote>
+<pre>
+/* 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) &amp;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
+</pre>
+</blockquote>
+</li>
+
+<li><tt>must_be_null</tt> specifies that the expression should be a null
+pointer constant, for example:
+
+<blockquote>
+<pre>
+/* 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) &amp;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
+</pre>
+</blockquote>
+</li>
+</ul>
+
 </div>
 </body>
 </html>