I'm working on a macro that will support error handling.
#define Try(e, call) ( (e == OK) && ((e = call) != OK) )
It can be used as the expression of an if-statement:
if (Try(err, SomeFunction(foo, bar))) {
// Entered only if err was OK before the if-statement and SomeFunction()
// returned a non-OK value.
}
The function won't be called if err was already non-OK before the if-statement. After the if-statement err will be set to the return value of SomeFunction().
So far so good. However I also want to use the macro without an if-statement:
Try(err, SomeFunction(foo, bar));
In this case GCC gives the following warning:
warning: value computed is not used [-Wunused-value]
And that's what my question is about: how can I rewrite the macro such that GCC won't produce this warning. I know the warning can be disabled with a flag (but I want to keep it enabled for other code) or by casting the result explicitly to void. The following statement code won't produce the warning:
(void) Try(err, SomeFunction(foo, bar));
But it's far from ideal to prefix each Try() with a void cast. Any suggestions?
You can use the ternary operator like this:
( (e == OK) ? ((e = call) != OK) : (e == OK) )
I'd go for something like this
inline
bool notOK(int err) {
return err != OK;
}
#define Try(e, call) ( !notOK(e) && notOK(e = call) )
Usually compilers don't complain about function return values that are not used.
For debugging purposes it might be necessary also to add an "instantiation"
bool notOK(int err);
in a .c file.
Just an idea.
static inline int identity (int x) { return x; }
#define Try(e, call) (identity ((e == OK) && ((e = call) != OK)))
You may want to #define inline __inline__ or #define inline /*nothing*/ for non-gcc compilers.
Related
I often write code which ends up being long sequences something like
int error;
error = do_something();
if (error) {
return error;
}
error = do_something_else(with, some, args);
if (error) {
return error;
}
error = do_something_yet_again();
if (error) {
return error;
}
return 0;
I'm searching for a cleaner way to write this that to some extent avoids the repeated identical checks. So far, I've written an ERROR_OR macro, which works something like
#define ERROR_OR(origerr, newerr) \
({ \
int __error_or_origerr = (origerr); \
(__error_or_origerr != 0) \
? __error_or_origerr \
: (newerr); \
})
which allows the original code to become something like
int error = 0;
error = ERROR_OR(error, do_something());
error = ERROR_OR(error, do_something_else(with, some, args));
error = ERROR_OR(error, do_something_yet_again());
return error;
This is (in my opinion) a little cleaner. It's also less understandable, since the function of the ERROR_PRESERVE macro isn't apparent unless you read its documentation and/or implementation. It also doesn't solve the problem of repetition, just makes it easier to write all the (now implicit) checks on a single line.
What I'd really like to re-write this all as would be the following:
return ERROR_SHORT_CIRCUIT(
do_something(),
do_something_else(with, some, args),
do_something_yet_again()
);
The hypothetical ERROR_SHORT_CIRCUIT macro would
Take a variable number of expressions in its argument list
Evaluate each expression in order
If every expression evaluates to zero, evaluate to zero itself
If any expression evaluates to nonzero, immediately terminate and evaluate to the value of that last expression
This last condition is where my short-circuit diverges from a straightforward use of the || operator -- since this will evaluate to 1 instead of the error value.
My initial attempt at writing this is the following:
#define ERROR_SHORT_CIRCUIT(firsterr, ...) \
({ \
int __error_ss_firsterr = (firsterr); \
(__error_ss_firsterr != ERROR_NONE) \
? __error_ss_firsterr \
: ERROR_SHORT_CIRCUIT(__VA_ARGS__); \
})
This has two obvious problems:
It doesn't handle its base-case (when __VA_ARGS__ is a single value)
C doesn't support recursive macros
I've looked into some recursive macro hacks, but I dislike using that degree of pre-processor magic -- too much room for something to be subtly wrong. I've also considered using real (possibly variadic) functions, but this would require either
giving up the short-circuit behavior
passing the functions in as pointers, and therefore normalizing their signatures
and both of these seem worse than the original, explicit code.
I'm interested to hear advice on the best way to handle this. I'm open to many different approaches, but my ultimate goal is to avoid repetition without hurting readability.
(I suppose it's obvious I'm suffering some envy of the behavior of the || operator in languages like Ruby).
I'd use code like:
if ((error = do_something()) != 0 ||
(error = do_something_else(with, some, args)) != 0 ||
(error = do_something_yet_again()) != 0)
return error;
return 0;
It's fully defined because there are sequence points before each || operator. It doesn't really need a macro. It only runs into problems when you allocate resources or do other operations between function calls, but that is different from what your example code shows. At least 90% of the battle was creating the sequence of do_something_or_other() functions that make it easy to handle the error sequencing.
Another option:
int error = 0;
do {
// Note: extra parens suppress assignment-as-conditional warning
if ((error = do_something())) break;
if ((error = do_something_else())) break;
if ((error = do_yet_another_thing())) break;
error = do_a_final_thing();
} while (0);
return error;
I noticed a strange idiom in openssl source code, here and repeated below:
if ((in == NULL) && (passwds == NULL)) {
if (1) { (* <---- HERE *)
#ifndef OPENSSL_NO_UI
/* build a null-terminated list */
static char *passwds_static[2] = { NULL, NULL };
passwds = passwds_static;
if (in == NULL)
if (EVP_read_pw_string
(passwd_malloc, passwd_malloc_size, "Password: ",
!(passed_salt || in_noverify)) != 0)
goto end;
passwds[0] = passwd_malloc;
} else {
#endif
BIO_printf(bio_err, "password required\n");
goto end;
}
}
It seems that this piece of code is equivalent to:
if ((in == NULL) && (passwds == NULL)) {
#ifndef OPENSSL_NO_UI
/* build a null-terminated list */
static char *passwds_static[2] = { NULL, NULL };
passwds = passwds_static;
if (in == NULL)
if (EVP_read_pw_string
(passwd_malloc, passwd_malloc_size, "Password: ",
!(passed_salt || in_noverify)) != 0)
goto end;
passwds[0] = passwd_malloc;
#else
BIO_printf(bio_err, "password required\n");
goto end;
#endif
}
I ruled out some explanations:
it could be to introduce block scope for passwds_static, but the enclosing if would serve a similar purpose
it could be a construct that through several meaningful transformations becomes meaningless, but that construct is there since the introduction of OPENSSL_NO_UI.
Am I missing something here? What are the advantages of this if (1)? Is this used in other code bases?
Thanks!
After looking at other similar places, I found an explanation:
if (1) { /* This is a trick we use to avoid bit rot.
* at least the "else" part will always be
* compiled.
*/
#ifdef AF_INET6
family = AF_INET6;
} else {
#endif
BIOerr(BIO_F_ACPT_STATE, BIO_R_UNAVAILABLE_IP_FAMILY);
goto exit_loop;
}
In most cases (including their CI I guess), OPENSSL_NO_UI is not defined, so both branches are compiled. If the API one of the branches uses changes, it will be spotted by the compiler, and it can be fixed, without having to test all the compile-time switches.
It is apparently used to remove code that shouldn't be executed, similar to using #ifdef compiler switches. Most often strange things like this is an indication of poor version control more than anything else.
Please note that this is not recommended practice - there should be no source code present that never gets executed in no circumstances. It is better practice to use version control, or if that's not possible use compiler switches, or if that's not possible then "comment out" the code.
the statement:
if(1) {
is to always have a matching opening brace for the closing brace.
I have a compiler warning I would like to get rid off.
warning: the argument to '__builtin_assume' has side effects that will be discarded [-Wassume]
C:\Keil_v5\ARM\ARMCLANG\Bin..\include\assert.h(72): note: expanded from macro 'assert'
define assert(e) ((e) ? (void)0 : _CLIBNS _aeabi_assert(e, _FILE__, _LINE__), (__ARM_PROMISE)((e)?1:0))
The idea is to have no warning when compiled with warning set to "pedantic".
The cause is a recently added pointer check function to my embedded code. The idea is to improve the following:
void foo(int* const val)
{ assert(val != NULL);
/*Use val etc.*/
}
to something along the lines of:
void foo(int* const val)
{ assert(checkPtr(val) == OK);
/*Use val etc.*/
}
This is because automatic variables are not zero intialised. Thus, it is likely that an uninitialised pointer will not be NULL. This is a coding mistake that I would like to detect (not necessarily my own doing), hence the checks. The following is not perfect, but does seem to pick up more pointer errors (not dangling ones unfortunately).
I have the following code in a header file to implement this:
#define INTERNAL_RAM_START ((uintptr_t)0x2000000UL)
#define INTERNAL_RAM_END (INTERNAL_RAM_START + (uintptr_t)0x20000UL)
#define INTERNAL_ROM_START ((uintptr_t)0x8000000UL)
#define INTERNAL_ROM_END (INTERNAL_ROM_START + (uintptr_t)0x100000UL)
typedef enum{OK, NOT_OK}Status_t;
static inline Status_t checkPtr(const void* const ptrToCheck)
{
if(ptr == NULL)
return NOT_OK;
const uintptr_t ptr = (uintptr_t)ptrToCheck;
if((ptr >= INTERNAL_RAM_START) && (ptr < INTERNAL_RAM_END))
return OK;
if((ptr >= INTERNAL_ROM_START) && (ptr < INTERNAL_ROM_END))
return OK;
return NOT_OK
}
I don't have any warnings with ARMCC 5.06 in my code. From what I can see, my checkPtr function does not have any side effects. It does not access any variables other than the pointer that was passed to it.
The documentation suggests that armclang supports the __attribute__ ((pure)) and __attribute__ ((const)) function attributes. These attributes are for functions that don't have any side effect, their return value is based on the input parameters. A pure function can also read global state, while a const function can only examine its function parameters.
Adding one of these attributes to your checkPtr declaration and definition should silence the warning.
The problem is this:
#define do_stuff(ret) ((ret) ? getstuff(ret) : 0)
int var;
do_stuff(&var);
test.h:34:46: warning: the address of 'var' will always evaluate as 'true' [-Waddress]
do_stuff acts as a function that accepts an output-pointer that can be NULL, though, thus the warning is not helpful but annoying.
Is there a way via code to make gcc stop complaining? Maybe an (at least kind of) portable one?
Btw. do_stuff has to be a macro as ret actually gets set in a generic way (here stripped for simplicity).
Edit:
Again, I just want to have the usual output-pointer that can be NULL, but inside a macro instead of a function. The actual code looks like this:
#define retrieve(x, ret) \
( ret ? (*ret = x.buf[0], 1) : 0 )
which gave the warning from above when using it like retrieve(stuff, NULL). Accordingly to Adriano Repetti's answer, I changed it to:
#define retrieve(x, ret) \
( ((void *)ret != NULL) ? (*ret = x.buf[0], 1) : 0 )
which works, but now gives me warning: dereferencing 'void *' pointer as this gets expanded to ( ((void *)NULL != NULL) ? (*NULL = x.buf[0], 1) : 0 ). Is there a way I can get rid of this warning, too?
retrieve has to be a macro because x.buf is of variant type, and so is ret, passing it through a function like in 2501's tip would result in type loss.
Assuming you really can't avoid a macro and considering that I wouldn't disable warnings (even if this particular one isn't dangerous) then I'd cheat compiler with some casts. Code will be portable and no warnings will be emitted:
#define do_stuff(ret) (((uintptr_t)NULL != (uintptr_t)ret) ? getstuff(ret) : 0)
Central point here is simply this: (uintptr_t)NULL != (uintptr_t)ret. I'd suggest to also read this post here on SO. Note that also simply NULL != (void*)ret works.
You can add a dummy function that just returns the pointer, this might silence the compiler:
void* pass( void* a )
{
return a ;
}
#define do_stuff(ret) ( pass(ret) ? getstuff(ret) : 0)
int var;
do_stuff( &var );
GCC's -Waddress command line flag is used to disable this type of warnings. But it's better to write your code without warnings.
I would like to force a functions parameters to accept only specific definitions. For example, consider #define OUTPUT 1, #define INPUT 0 and void restrictedFunction(int parameter); .
How would I force restrictedFunction(int parameter) to accept only OUTPUT or INPUT?
I would also like to take into consideration that another definition may have the same value, for example, #define LEFT 1 and #define RIGHT 0.
So in this case I would like restrictedFunction(int parameter) to be able to accept only OUTPUT and INPUT specifically.
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
void restrictedFunction(IO_Type parameter) { ... }
It doesn't absolutely force the use of the values (the compiler will let someone write restrictedFunction(4)), but it is about as good as you'll get.
If you truly want to force the correct type, then:
typedef enum { INPUT = 0, OUTPUT = 1 } IO_Type;
typedef struct { IO_Type io_type } IO_Param;
void restrictedFunction(IO_Param parameter) { ... }
In C99 or later, you could call that with:
restrictedFunction((IO_Param){ INPUT });
This is a compound literal, creating a structure on the fly. It is not entirely clear that the structure type really buys you very much, but it will force the users to think a little and may improve the diagnostics from the compiler when they use it wrong (but they can probably use restrictedFunction((IO_Param){ 4 }); still).
What this means is that your restrictedFunction() code should be ready to validate the argument:
void restrictedFunction(IO_Type io_type)
{
switch (io_type)
{
case INPUT:
...do input handling...
break;
case OUTPUT:
...do output handling...
break;
default:
assert(io_type != INPUT && io_type != OUTPUT);
...or other error handling...
break;
}
}
You could use an enum.
typedef enum TrafficDirection { INPUT = 0, OUTPUT = 1 } TrafficDirection;
restrictedFunction(TrafficDirection direction);
of course, this isn't perfect. You can still pass any int to it as long as you use a cast.
restrictedFunction((TrafficDirection) 4);
You don't get quite as much protection as you might like, but you can do:
enum func_type { INPUT, OUTPUT };
void restrictedFunction( enum func_type parameter );
You can use a wrapper to validate the argument:
#define restrictedFunction(x) do { \
static_assert((x) == INPUT || (x) == OUTPUT); \
assert(!strcmp(#x, "INPUT") || !strcmp(#x, "OUTPUT")); \
restrictedFunction(x); \
} while(0)
Notes:
This assumes restrictedFunction() returns a void. If it returns a value which you actually use, you'll need something like gcc's compound statement http://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html. Or--better--you can use BUILD_BUG_ON_ZERO (see What is ":-!!" in C code?), which I keep forgetting about, because it doesn't seem to work with C++.
The do ... while(0) is to "swallow the semi-colon"; not really relevant here.
static_assert() is a compile-time assert; there are many variants available. Here is a link to one, https://stackoverflow.com/a/9059896/318716, if you don't have your own handy.
assert() is the standard run-time assert.
With gcc 4.1.2, and my version of static_assert(), you can replace the run-time assert() with a compile-time assert when the two !strcmp()'s are replaced with ==; see example below. I haven't tested this with other compilers.
x is only used once in the macro expansion, since the first four references are only used at compile-time.
When your actually define your function, you'll have to add parentheses to disable the macro expansion, as in:
void (restrictedFunction)(int x){ ... }
Also, if your code has a special case (whose code doesn't?) where you need to call restrictedFunction() with the argument foo, you'll need to write:
(restrictedFunction)(foo);
Here is a complete example, which puts a wrapper around the standard library function exit():
#include <stdlib.h>
#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum{EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
#define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
#define exit(x) do { \
ASSERTM((x) == EXIT_SUCCESS || (x) == EXIT_FAILURE, value); \
ASSERTM(#x == "EXIT_SUCCESS" || #x == "EXIT_FAILURE", symbol); \
exit(x); \
} while(0)
int main(void) {
exit(EXIT_SUCCESS); // good
exit(EXIT_FAILURE); // good
exit(0); // bad
exit(3); // doubly bad
}
If I try to compile it, I get:
gcc foo.c -o foo
foo.c: In function 'main':
foo.c:17: error: enumerator value for 'symbol_ASSERT_line_17' is not an integer constant
foo.c:18: warning: division by zero
foo.c:18: error: enumerator value for 'value_ASSERT_line_18' is not an integer constant
foo.c:18: error: enumerator value for 'symbol_ASSERT_line_18' is not an integer constant