pdPASS macro doesn't work with GNU C++ 14

fjrg76 wrote on Monday, May 28, 2018:

Hi, while working on a C++ project I noticed something wrong when using the
pdPASS macro:

/home/fjrg76/git/prueba1114lap/freertos10.0.1/inc/projdefs.h:47:27: error:
ISO C++ forbids comparison between pointer and integer [-fpermissive]

#define pdPASS ( pdTRUE )
^
/home/fjrg76/git/prueba1114lap/prueba11/inc/FreeRTOSConfig.h:103:33: note:
in definition of macro ‘configASSERT’
#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS();
for( ;; ); }
^
…/src/prueba11.cpp:112:39: note: in expansion of macro ‘pdPASS

  • configASSERT( myTimer.GetHandle() == pdPASS );*

But if I change pdPASS to pdFAIL, then it compiles:

configASSERT( myTimer.GetHandle() != pdFAIL );

From FreeRTOS/projdefs.h

#define pdFALSE ( ( BaseType_t ) 0 )
#define pdTRUE ( ( BaseType_t ) 1 )

#define pdPASS ( pdTRUE ) // <-- Eclipse IDE has placed an
error mark (X) in this line
#define pdFAIL ( pdFALSE )

From my file prueba11.cpp:

class Timer
{
public:
// …

  • TimerHandle_t GetHandle() const*
  • {*
  •    return this->handle;*
    
  • }*

protected:
TimerHandle_t handle = pdFAIL;
};

class MyTimer:public Timer {//};

int main(void)
{
// …

MyTimer myTimer{ pdMS_TO_TICKS( 100 ), pdTRUE, 0, 7 };
  • configASSERT( myTimer.GetHandle() == pdPASS );*

  • if ( myTimer.GetHandle() != pdPASS ) while(1);*

if( myTimer.Start() == false ) while(1);

vTaskStartScheduler();

return 0 ;

}

Any hints? Of course I can use pdFAIL instead of pdPASS throughout all my
code/project, but this situation (bug?) might be more serious than it
appears. As said, I’m using the GNU C++ 14 compiler under a Linux Box
(maybe it’s not important)


M.I. Fco. Javier Rodríguez G.

richard_damon wrote on Monday, May 28, 2018:

Why are you asserting that GetHandle will return pdPASS? That is almost certainly not true.
Handles are pointers, and pointers having the value of 1 are very rare.
Do you mean that the handle isn’t 0 (NULL)?

davidbrown wrote on Tuesday, May 29, 2018:

Hi,

You are getting this warning because your code is wrong - it is helping
you find a bug.

The only integer constant you can safely compare with a pointer is 0,
because that is a “null pointer constant”. (Note you can’t compare a
pointer to an int that happens to be 0 - you can only compare to the
constant 0.)

What you are trying to do is check that the handle is valid - i.e., it
is non-zero. You do /can/ that by:

configASSERT(myTimer.GetHandle() != pdFAIL);

You /cannot/ do it by asserting that the handle value is pdPASS.

It is almost certainly better, IMHO, to simply assert that the handle is
valid by a conversion to bool:

configASSERT(myTimer.GetHandle());

This is idiomatic C and C++. Adding " != pdFAIL" gives no benefits,
while " == pdPASS" is directly wrong.

I have not looked in the context of projedefs.h or how these macros are
intended to be used. But as a general point, I am always highly
sceptical about using “home-made booleans”. FreeRTOS is designed to
work with pre-C99 C, and thus needs to use them - your code is C++14,
and does not need them. When you need a boolean type, use “bool” - when
you need boolean values, use “true” and “false”. And when you need a
null pointer constant, use nullptr (for C++11 onwards) or NULL (for C).
You can also use 0 directly, but prefer nullptr when you can, NULL when
you can’t. Avoid using cast expressions like you get from the pdFAIL macro.