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>