coles.david at gmail.com
2014-May-06 13:39 UTC
[LLVMdev] Compile time checks and GCC's '__warning__' attribute
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL:
<http://lists.llvm.org/pipermail/llvm-dev/attachments/20140506/0d08175a/attachment.html>
Richard Smith
2014-May-06 20:15 UTC
[LLVMdev] Compile time checks and GCC's '__warning__' attribute
[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>