30
votes

I am attempting to build a debug log message function that records the file, line, and function of of where the log message was called from.

#define DEBUG_PANIC(p) CLogging::Debuglogf( "Debug marker (%s) - ::%s() in file: %s(%d)", p, __func__ , __FILE__, __LINE__ );

The above code works on some compilers but not all. My code needs to be cross compatible with GCC as well as Microsoft Visual studios. I have added the below defines to help with compatibility.

#ifndef __FUNCTION_NAME__
    #if defined __func__ 
        // Undeclared 
        #define __FUNCTION_NAME__   __func__ 
    #elif defined __FUNCTION__ 
        // Undeclared
        #define __FUNCTION_NAME__   __FUNCTION__  
    #elif defined __PRETTY_FUNCTION__
        // Undeclared
        #define __FUNCTION_NAME__   __PRETTY_FUNCTION__
    #else
        // Declared
        #define __FUNCTION_NAME__   "N/A"   
    #endif // __func__ 

#endif // __FUNCTION_NAME__

#define DEBUG_PANIC(p) CLogging::Debuglogf( "Debug marker (%s) - ::%s() in file: %s(%d)", p, __FUNCTION_NAME__, __FILE__, __LINE__ );

The problem with the above code snippet is that it is the #else macro is active on all compilers while the other macros are not. in other words #if defined __func__ is false on compilers where __func__ is a predefined macro.

My question is

  • How do I create a cross compiler macro to find the function name ?
  • How can I tell if a __func__ can be used?
4
Are you writing C or C++? - Keith Thompson
@KeithThompson Sorry I forgot to add that to the question, Yes C++ - Steven Smethurst

4 Answers

34
votes

You're assuming __func__ is a macro, but it's not. It's a conditionally-supported predefined identifier, so you can't check it with #if defined or #ifdef.

If the compilers have no way of telling you whether this is supported (they could via a _FUNC_SUPPORTED or something, I'm not saying they actually are doing this), you'll have to check the compiler instead of the actual identifier.

Something along the lines:

#ifndef __FUNCTION_NAME__
    #ifdef WIN32   //WINDOWS
        #define __FUNCTION_NAME__   __FUNCTION__  
    #else          //*NIX
        #define __FUNCTION_NAME__   __func__ 
    #endif
#endif
16
votes

As often Boost is THE cross platform solution with BOOST_CURRENT_FUNCTION defined in <boost/current_function.hpp>.

9
votes

I would like to add that the __FUNCTION__ macro is defined for both GCC and MSVC. Though non-standard, it is available on both compilers.

GCC Standard Predefined Macros quote:

C99 introduces __func__, and GCC has provided __FUNCTION__ for a long time. Both of these are strings containing the name of the current function (there are slight semantic differences; see the GCC manual). Neither of them is a macro; the preprocessor does not know the name of the current function. They tend to be useful in conjunction with __FILE__ and __LINE__, though.

MSVC Predefined Macros quote:

__FUNCTION__

Valid only in a function. Defines the undecorated name of the enclosing function as a string literal.

__FUNCTION__ is not expanded if you use the /EP or /P compiler option.

See __FUNCDNAME__ for an example.

So using __FUNCTION__ would be ok, since both compilers implement it. Though you may not get the same results on both compilers but that might be acceptable in some situations.

7
votes

they are neither preprocessor macros, like __FILE__ and __LINE__, nor variables.

Taken from the following link:

http://gcc.gnu.org/onlinedocs/gcc-3.2/gcc/Function-Names.html

Also, please check out this other question that was answered that is similar to yours:

How to check if __PRETTY_FUNCTION__ can be used?

Example:

#ifdef _MSC_VER // Visual Studio
    #define FUNCTION_NAME __FUNCTION__
#endif