diff options
Diffstat (limited to 'docs/LanguageExtensions.html')
-rw-r--r-- | docs/LanguageExtensions.html | 162 |
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) && \ + __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); +</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) &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 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) &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) &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> |