[LLVMdev] Compile time checks and GCC's '__warning__' attribute

Richard Smith richard at metafoo.co.uk
Tue May 6 13:15:51 PDT 2014


[Moving from llvmdev to cfe-dev]

On Tue, May 6, 2014 at 6:39 AM, coles.david at gmail.com <coles.david at gmail.com
> wrote:

> Hi,
>
> I've been trying to implement some basic compile time checks such as using
> "__builtin_object_size" to verify certain preconditions (such as ensuring a
> function that is passed a byte array contains a minimum number of bytes).
> This turned out to be a little tricker than expected as "_Static_assert"
> and similar mechanisms can't be used since "__builtin_object_size" can't be
> used as a integral constant expression.
>

__builtin_object_size can be used as a constant expression in some cases
(essentially, when its operand is a constant expression).

Most GCC code I've looked at uses the "__warning__" or "__error__"
> attributes to declare trap functions that if not eliminated via dead-code
> elimination will generate a compiler warning or error (big improvement over
> just a runtime abort). For example:
>
>     size_t d_len = __builtin_object_size(d, 0);
>     if (__builtin_constant_p(copy_amount) && (copy_amount > d_len)) {
>          // declared with __attribute__((__error__("memcpy called with
> size bigger than destination")));
>         __memcpy_dest_size_error();
>     }
>
> Sadly neither of these attributes are currently supported in Clang. Is
> this a reasonable feature request or does Clang have some better mechanism?
> (Perhaps the Static Analyzer?)
>
> I notice that Clang supports both the "deprecated" and "unavailable"
> attributes, but these serve a slightly different purpose of warning or
> preventing a user from calling certain functions.
>
> Probably the most promising option appears to be Clang 3.5's new
> "enable_if" function attribute that could be used to make the function
> unavailable if it violates certain preconditions.
>

enable_if should do the job here; it's designed for exactly this sort of
check. Something like:

void *memcpy(void *dest, const void *src, size_t n)
  __attribute__((enable_if(__builtin_object_size(dest, 0) < n, "selected if
dest is too small"),
                 unavailable("dest of memcpy is smaller than size of buffer
to copy"),
                 overloadable));
void *memcpy(void *dest, const void *src, size_t n)
  __attribute__((enable_if(__builtin_object_size(src, 0) < n, "selected if
src is too small"),
                 unavailable("src of memcpy is smaller than size of buffer
to copy"),
                 overloadable));
void *memcpy(void *dest, const void *src, size_t n) asm("memcpy")
  __attribute__((overloadable));

... should work.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20140506/478719f6/attachment.html>


More information about the llvm-dev mailing list