Compile time checks and GCC's '__warning__' attribute

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Compile time checks and GCC's '__warning__' attribute

coles.david@gmail.com
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.

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.

Cheers,
David

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
Reply | Threaded
Open this post in threaded view
|

Re: Compile time checks and GCC's '__warning__' attribute

Richard Smith-33
[Moving from llvmdev to cfe-dev]

On Tue, May 6, 2014 at 6:39 AM, [hidden email] <[hidden email]> 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.

_______________________________________________
LLVM Developers mailing list
[hidden email]         http://llvm.cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev