This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Strange compilier's behaviour with function template, NAN and default parameter

I have got an error message with next code

template< typename Type >
int func( Type as, float fl=NAN );
error:  #109: expression preceding parentheses of apparent call must have (pointer-to-) function type

It seems the problem is with resolving NAN, defined in math.h at line 249

#   define NAN (__ESCAPE__(0f_7FC00000))

There is no problem if no NAN used

template< typename Type >
int func( Type as, float fl=0 );

There is no problem if template not used

int func( int as, float fl=NAN );

There is no problem with GCC.

Compilier version

*** Using Compiler 'V5.05 update 2 (build 169)'

  • Experiments:

    template< typename Type >
    int func( Type as, float fl=(float)(NAN) );  //fail
    
    template< typename Type >
    int func( Type as, float fl=0f_7FC00000 );  // Compiled. No error
    
    template< typename Type >
    int func( Type as, float fl=__ESCAPE__(0f_7FC00000) );  //fail
    

  • The problem appears to be that the C++ compiler does not recognize the (undocumented?) compiler intrinsic __ESCAPE__ early enough in the parsing process to decipher this expression.

  • I've found this thread about __ESCAPE__ http://www.keil.com/forum/9630/
    It seems problem may be solved with declaring

    #define __ESCAPE__(__x)  (__x)
    


    I will test soon.

  • That makes __ESCAPE into a null operation. But the question then is what functionality that gets lost - because ARM must have had some intention with the __ESCAPE() construct.

  • ARM must have had some intention with the __ESCAPE() construct.

    Evidently. But the only description of it that you'll find is very vague about what it actually does. They only tell it's a compiler builtin, and that it's used to hide usages of non-standard features from standard-picky modes of the compiler. I.e. they explain the why, but not the how.

    #define-ing it away is supposed to only be needed for compilers other than ARMCC using ARM's <math.h> or <limits.h>. Why one would do that is beyond my tolerance for utter nonsense. :->

    As it is, this is a failure of ARM's headers to play nice with ARM's compiler. In other words: this a compiler bug worth reporting to support.

  • Ah - so basically it already is a no-op.

    It's expected to be 100% transparent when compiling with the ARM compiler - just "unit expansion" of the argument(s).

    While it's expected to expand to nothing at all for "non-compliant" compilers.

    So with the ARM compiler:

    int func( Type as, float fl=0f_7FC00000 );
    

    And with another compiler:

    int func( Type as, float fl= );
    


    But that would mean that the "=" should have been inside the __ESCAPE__, or the "non-compliant" compilers that doesn't support this 0f_7FC00000 hexadecimal floating-point value will still fail to compile.

    It feels like the __ESCAPE__ construct was a design that failed before it left the drawing board.

  • Ah - so basically it already is a no-op.

    Not quite. ARM wouldn't have to go this far out of their way just to create a no-op. Just writing nothing at all would have the same effect.

    And with another compiler:

    int func( Type as, float fl= );
    

    No. With any other compiler, you get.

    int func( Type as, float fl= __ESCAPE__(0f_7FC00000) );
    

    What that actually turns into depends entirely on what the user of the alien compiler decides to #define __ESCAPE__ as to fix this obvious syntax error.

    But OTOH that alien compiler would surely come with its own <math.h>. So there should never be a need to pull in the one from ARMCC's system include file collection.

    Using another implementation's Standard C Library headers is a Bad Thing, and one should fully expect bad things to happen because of it. As I take it, this macro may be just an elaborate, circuitous way of expressing "Here Be Dragons".

  • So, does anybody have bright idea and better solution than

    #ifdef __CC_ARM
     #undef NAN
     #define NAN  (0f_7FC00000)
    #endif
    

    or even

    #ifdef __CC_ARM
     #undef __ESCAPE__
     #define __ESCAPE__
    #endif
    

    ?

  • So, does anybody have bright idea and better solution than

    The only actual solution to this is for Keil/ARM to find.

    It's ARM's own header file, and ARM's own compiler, so if combining the two in a slightly unusual fashion causes a problem, that's ARM's problem to solve. So have you filed a support request yet?

    Until then, your best bet at a temporary workaround would probably be one of those you showed.

  • Yet another...

    #include <cmath>
    class Cla {
      float h = NAN;  // error:  #65: expected a ";"
    };
    

    What's the f... The medicine is same

    #include <cmath>
    #ifdef __CC_ARM
     // ARM CC bug http://www.keil.com/forum/60227/
     #define __ESCAPE__(__x)  (__x)
    #endif
    

    All files compiled with --cpp11.