summaryrefslogtreecommitdiffstats
path: root/docs/LanguageExtensions.html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/LanguageExtensions.html')
-rw-r--r--docs/LanguageExtensions.html162
1 files changed, 162 insertions, 0 deletions
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 @@ declaration to specify that the function must be called while holding the listed
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>
OpenPOWER on IntegriCloud