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.
Related
First of all, it is important to say that the code will be a mess, I know that and there is a reason behind the messy code, but I prefer not to specify why to avoid going off track.
This snippet of code decrypts a pointer:
//LLUNGO is long long
//PLLUNGO is long long pointer
//SCANVELOCE is __fastcall
LLUNGO SCANVELOCE DecryptPointer(PPTR_SECRET _pSecret, PLLUNGO _OldPointer)
{
_OldPointer = (PLLUNGO) PTR_ENCRYPTION_ALGORITHM(*_OldPointer, _pSecret->Segreto);
INTERO Reference = GetReferenceToPtr(_pSecret, _OldPointer);
if (PTR_BAD_REFERENCE(Reference))
QUICK_PRINT("Bad reference error.\n");
return PTR_ENCRYPTION_ALGORITHM((LLUNGO)_pSecret->Riferimenti[Reference], _pSecret->Segreto);
}
using the following macros:
#define PTR_ENCRYPTION_ALGORITHM(PTR, KEY) (~(PTR ^ KEY))
#define PTR_BAD_REFERENCE(PTR) ((-1) == (PTR))
Now the problem is when I use the macro stated below, for some reason even if I am using the right arguments it is still throwing me this error:
no instance of overloaded function "DecryptPointer" corresponds to the
arguments.
Consider that NBYTE is BYTE and REGISTRA is the register keyword.
NBYTE SCANVELOCE MFINIT(LLUNGO _FuncAddr, PMUTILATE_FUNCTION _Function)
{
if (!_FuncAddr || !_Function)
return FALSO;
SELF_PTR_DECRYPTION( _FuncAddr ); //error thrown here
SELF_PTR_DECRYPTION( _Function ); //and here too!
for (REGISTRA PNBYTE Current = (PNBYTE)_FuncAddr; ; Current--)
{
if (MF_PUSH_EBP == *Current)
{
_Function->Inizio = (LLUNGO)Current;
break;
}
}
And the SELF_PTR_DECRYPTION macro + everything else necessary for the DecryptPointer function to work:
(PTR_SECRET being a struct)
#define SELF_PTR_DECRYPTION(X) ((X) = (PTR_DECRYPTION(X)))
#define PTR_DECRYPTION(X) DecryptPointer(&PTR_SECRET_NAME, X)
#define PTR_SECRET_NAME g_PTR_SECRET
INIT(PTR_SECRET PTR_SECRET_NAME);
Again sorry for the stupidly messy code, I'm struggling too, just like everyone reading this probably will, but again there is a reason behind the mess.
The solution has been found in the comments by #yano:
you've taken me straight to macro hell. If I'm following correctly,
_FuncAddr in the SELF_PTR_DECRYPTION( _FuncAddr ); call ends up being the 2nd argument to DecryptPointer, which expects a PLLUNGO type.
However, _FuncAddr is a LLUNGO type. And if its complaining about "no
overloaded function" it sounds like you're using a C++ compiler, not
C.
Many thanks, and sorry for the absolute mess of code I presented here.
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 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.
I am writing code in embedded c(in Kiel4) comparing String in buffer AtRes with C003 and it will assigned to uc EVENTbuf like
else if(ucEVENTBuf=tmMisc_strnstr((INT8C *)AtRes,"C003,",4))
now I am getting warning
assignment in condition
how to overcome thise warnning.
Thank you
Your compiler is interprething the if statemente as follows:
if( ucEVENTBuf=1 ) // or whatever
which is an assignement. As other people said it is usually sufficient to put other parentesis around:
if( (ucEVENTBuf=1) ) // or whatever
but if also this doesn't work for you, you may try this:
else if((ucEVENTBuf=tmMisc_strnstr((INT8C *)AtRes,"C003,",4))!=0) /* <<<<< ask explicitely to compare against 0 */
A common error when programming C in the old days was to accidentally use assignment instead of comparison:
if (x = 3)
So compilers started warning about this. But if you really mean to assign and use the result as a boolean expression, you can. Some compilers will not warn if you add parentheses:
if ((x = 3))
If that isn't enough on your system, you can try to make it more explicit:
if (!!(x = 3))
Try to replace
else if(ucEVENTBuf=tmMisc_strnstr((INT8C *)AtRes,"C003,",4))
with
else if((ucEVENTBuf=tmMisc_strnstr((INT8C *)AtRes,"C003,",4)))
Or with
else if((ucEVENTBuf=tmMisc_strnstr((INT8C *)AtRes,"C003,",4)) != NULL)
If your compiler still gives you the same warning (it should not), then try this
else {
ucEVENTBuf=tmMisc_strnstr((INT8C *)AtRes,"C003,",4);
if (ucEVENTBuf != NULL) {
}
}
You may need do other changes to the structure of your code.
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.