Is there a static_assert replacement which satisfies the C99 standard? - c++

I have been trying to implement a method similar to static_assert which is defined in the C++11 standard. The main problem is how does the C++ compiler write the text message being passed to static_assert as a const char*? I can get the compiler to write a message like A_is_not_POD. This is what I have:
#define MY_STATIC_ASSERT(condition, name) \
typedef char name[(condition) ? 1 : -1];
But it would be quite nice to get the compiler to write something like "Error: A is not POD." Any suggestions?

Not sure i understand question, but C11 have _Static_assert(condition, errmessage). In C99 this functionality was missing but, depending on compiler, it could be possible to emulate. E.g. for gcc (unfortulately clang doesn't support attribute(error))
#define MY_STATIC_ASSERT(cnd, descr) ({ \
extern int __attribute__ ((error("static assert failed: (" #cnd ") (" #descr ")"))) \
compile_time_check(void); \
((cnd) ? 0 : compile_time_check()), 0; \
})

In the c99 standard there is no "official" way to perform a static assertion in your C++ compiler.
"The main problem is how does the C++ compiler write the text message being passed to static_assert as a const char*?"
The C++ compiler detects an error in the code and prints out an appropriate error message based on a standard list of messages it has for each error that is known it can encounter. In c99, the compiler doesn't know what a "static assert error" is, so you need to cause some other error.
However, because creating static asserts with a c99 compiler is kind of a hack, it is not capable of printing out a nice error message exactly how you want.
For your example,
#define MY_STATIC_ASSERT(condition, name) \
typedef char name[(condition) ? 1 : -1];
MY_STATIC_ASSERT(false, my_error_msg)
will trigger the "error: size of array ‘my_error_msg’ is negative" message in the gcc compiler (and should a similar message in other compilers, you hope!). Giving the array an error message for the name was a way to print out your own info. There are various other techniques/hacks you can do on purpose such as bad templates, enums link
Note: you can provide custom compiler messages prior to C++11 using pre-processor macros such as #error or #pragma. However pre-process time is not the same as compile-time! The the pre-processor has a limited ability to evaluate many expressions and keywords such as "if", "sizeof", "return" and so on have no meaning to the pre-processor, only the compiler. link with some overview

Related

What are "extern char condition tricks"?

I was reading the GCC documentation on C and C++ function attributes. In the description of the error and warning attributes, the documentation casually mentions the following "trick":
error ("message")
warning ("message")
If the error or warning attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, an error or warning (respectively) that includes message is diagnosed. This is useful for compile-time checking, especially together with __builtin_constant_p and inline functions where checking the inline function arguments is not possible through extern char [(condition) ? 1 : -1]; tricks.
While it is possible to leave the function undefined and thus invoke a link failure (to define the function with a message in .gnu.warning* section), when using these attributes the problem is diagnosed earlier and with exact location of the call even in presence of inline functions or when not emitting debugging information.
There's no further explanation. Perhaps it's obvious to programmers immersed in the environment, but it's not at all obvious to me, and I could not find any explanation online. What is this technique and when might I use it?
I believe the premise is to have a compile time assert functionality. Suppose that you wrote
extern char a[(condition) ? 1 : -1];
If condition is true, nothing happens and the line compiles to nothing. The extern makes sure that a doesn't use any memory. However, if condition is false, a is declared as an array of negative length, and you get a compile time error.
You probably wrap it in a macro and have something similar to static_assert
#define STATIC_ASSERT(condition) extern char a[(condition) ? 1 : -1]

Generating a preprocessor error if a define is used

Is it possible with the C++ preprocessor to emit an #error if a particular #define is used? Something like this:
#define this_must_not_be_used #error You shouldn't use that.
In C++11,
#define this_must_not_be_used static_assert(false, "You shouldn't use that.");
In C11,
#define _Static_assert(0, "You shouldn't use that.");
For C before C11 or C++ before C++11, you'll have to think up some other invalid expression that contains a string that will show up in the error message. I'm thinking along the lines of
#define this_must_not_be_used ("You shouldn't use that",)
There is no standard way of defining a macro in such a way that its use, wherever it is, will give you a compilation error, especially not one that gives a clear and useful error message. For all you know, the code that uses it might just be stringizing its result, or it might be part of an assert condition that gets removed by the preprocessor.
For most practical purposes, putting something that cannot possibly be part of a valid C (or C++) program will be good enough.
Some implementations do have implementation-specific methods of achieving exactly what you ask for, though. For instance, with GCC, you can use
#pragma GCC poison this_should_not_be_used
where its subsequent use, no matter how it ends up used, will give:
error: attempt to use poisoned "this_should_not_be_used"
You may want to look at your own compiler's documentation to see if it has anything similar. You can also use conditional macro definitions, so that with GCC you use this approach, with your compiler you use your compiler's approach, and with an unknown compiler you fall back to the standard method of providing a macro definition that will probably lead to a difficult-to-read error message.
Do you mean something like follows:
#ifdef this_must_not_be_used
#error "You shouln't use that."
#endif

How can I invoke a compile-time error via a C++ macro?

The idea is to cause a compile-time error with an error message if a certain macro is invoked. Can this be done? How?
#ifdef RUBBISH_COMPILER
# define alignof(T) // what here?
#endif
const std::size_t = alignof(some_type); // invocation, causing compilation error
The invocation shall produce a sensible error message like
alignof() not available with this compiler.
In C++11,
#define DONT_INVOKE_ME static_assert(false, "Don't invoke this macro");
Historically, it was easy to cause an error, but trickier to get a message into the output. One simple trick was to create an invalid declaration, with the message in the declared name:
#define DONT_INVOKE_ME char dont_invoke_this_macro[-1];
This isn't perfect, as you can't use freeform text for the message - it must be a valid identifier. There were fancier tricks (such as those used by Boost's static assert), but they're only of historical interest these days.

What other hidden variables (pre-defined using macros) do I have access to in g++?

note: I am using g++ version 4.3.4
So I was learning about assert statements and came across a homebrew assert macro that uses that variables __LINE__ and __FILE__ which (cleverly) give the line number and the file name from where they were called -- in this case, from where the assertation failed. These are epic pieces of information to have!
I was able to infer that the variable __FUNCTION__ will give you the function name that you are inside of... amazing!! However, when assert.h is at work, you also get the arguments to the function (i.e. function: int main(int, char**) and all I can do currently is get the function name...
Generally speaking, where can I learn more about these wonderful hidden variables and get a complete list of all of them?
p.s. I guess I understand now why you aren't supposed to use variable names starting with __
Generally speaking, you can find out anything you want about a language by reading its standards document and/or lone implementation's documentation. In the case of C++, this would currently be ISO/IEC 14882:2003, the 2003 C++ standard. I don't have a copy, but I do have the C99 standard (ISO/IEC 9899:1990), which also lists (in §6.10.8) the magic macros __DATE__ and __TIME__, which expand to strings containing the date & time of the enclosing source file's compilation. (Also, instead of __FUNCTION__, C99 has __func__ (§6.4.2.2); is the former standard C++ or a compile extension?)
EDIT: The only list of these special names for GCC/G++ that I can find is this section of the GCC manual, which describes __func__, __FUNCTION__, and __PRETTY_FUNCTION__.
As far as getting the function arguments, you can try using __PRETTY_FUNCTION__ instead of __FUNCTION__. More information is available here: http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
As far as a list of pre-defined macros, you can find a lot of them if you hunt around in here: http://gcc.gnu.org/onlinedocs/cpp/Predefined-Macros.html#Predefined-Macros
I cannot say with certainty that the list referenced above is complete. The reason I say this is that __PRETTY_FUNCTION__ cannot be found under the list of predefined macros... why this is, I cannot say.

__attribute__((format(printf, 1, 2))) for MSVC?

With GCC, I can specify __attribute__((format(printf, 1, 2))) , telling the compiler that this function takes vararg parameters that are printf format specifiers.
This is very helpful in the cases where I wrap e.g. the vsprintf function family. I can have
extern void log_error(const char *format, ...) __attribute__((format(printf, 1, 2)));
And whenever I call this function, gcc will check that the types and number of arguments conform to the given format specifiers as it would for printf, and issue a warning if not.
Does the Microsoft C/C++ compiler have anything similar ?
Using SAL Annotations you can use _Printf_format_string_ (as of VS2k8 or VS2k10) or __format_string (for VS2k5):
#undef FORMAT_STRING
#if _MSC_VER >= 1400
# include <sal.h>
# if _MSC_VER > 1400
# define FORMAT_STRING(p) _Printf_format_string_ p
# else
# define FORMAT_STRING(p) __format_string p
# endif /* FORMAT_STRING */
#else
# define FORMAT_STRING(p) p
#endif /* _MSC_VER */
/* use /analyze or _USE_ATTRIBUTES_FOR_SAL for checking */
extern void log_error(FORMAT_STRING(const char* format), ...);
As previously mentioned by #RustyX printf format checking is now supported by default as of VC2015. That is without a /analyze static analysis pass. Regrettably there is not yet a mechanism for marking user-defined wrapper functions.
This suggest the obvious workaround of calling printf. That is defining a macro which invokes both the user-defined function as well as the printf itself. The latter on a dead path to be optimized out.
This has the added benefit of achieving some level of portability to other compilers.
int printf_wrapper_(const char *format, ...);
#define printf_wrapper(...) \
(printf || printf(__VA_ARGS__), printf_wrapper_(__VA_ARGS__))
The drawback is that VC2015 performs some rudimentary dead-code elimination prior to the format check, testing only the remaining live code.
Thus sizeof or constant conditional expressions will fail. As a rule of thumb if a debug build emits run-time code then you will get the warning, though later passes in release builds may still kill the call.
Alas this makes it something of a moving target liable to change in future compiler versions. Albeit a relatively benign one.
While GCC checks format specifiers when -Wformat is enabled, VC++ has no such checking, even for standard functions so there is no equivalent to this __attribute__ because there is no equivalent to -Wformat.
I think Microsoft's emphasis on C++ (evidenced by maintaining ISO compliance for C++ while only supporting C89) may be in part the reason why VC++ does not have format specifier checking; in C++ using <iostream> format specifiers are unnecessary.
There is an interesting article on the subject on Code Project:
"Using C++ Templates for Startup Validation"
by Alexander Gorobets
http://www.codeproject.com/KB/cpp/ValidateprintfFunction.aspx
I've modified it so that I have a macro PRINTF_VALIDATE(format, ...) that logs all format errors at program statup (there's no need to actually execute the code). It produces something like this:
test.cpp(147) : error : 'printf' format character 'f' at position 1 does not match parameter type INT
test.cpp(147) : error : 'printf' too many arguments (3 instead of 2)
One can use it for example like this:
#define LOG(fmt, ...) do { PRINTF_VALIDATE(fmt, __VA_ARGS__); WriteLog(fmt, __VA_ARGS__); } while(0)
This is not as useful as compiler support, but it works on Visual Studio 2005...
Workaround for MSVS, GCC and clang:
"If you’re using a macro to call your printf-like functions, you can use a helper-macro to get compile time format checks like this:
#define CHECK_FORMAT(...) \
do { \
char const dummy = sizeof(printf(__VA_ARGS__)); \
(void)dummy; \
} while (false)
#define MY_FMT(...) \
do { \
CHECK_FORMAT(__VA_ARGS__); \
MyFormatFunc(__FILE__, __LINE__, __VA_ARGS__); \
} while (false)
https://godbolt.org/z/38PaG5fx6
The printf call in the sizeof isn’t evaluated so it doesn’t generate code, but current versions of MSVC, GCC and Clang will still do the format-string check so you get the warning. The local dummy variable is also optimized away with -O2."
Source