35

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?
a3f
  • 8,517
  • 1
  • 41
  • 46
Steven Smethurst
  • 4,495
  • 15
  • 55
  • 92

4 Answers4

43

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
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • 19
    Any C compiler conforming to C99 or later *must* support `__func__`; in that sense, it's not an optional feature. So one way to tell that `__func__` is supported is by checking `__STDC_VERSION__ >= 199901L`. (Though a pre-C99 or non-conforming compiler could support it as an extension.) – Keith Thompson Mar 08 '13 at 23:59
  • 5
    @KeithThompson I was assuming C++. But the main point was that it's not a macro. – Luchian Grigore Mar 09 '13 at 00:00
  • 6
    Ah, good point; the OP didn't add a tag for the language. The C++ standard didn't mandate `__func__` until 2011. It's probably a common extension for pre-C++11 compilers. – Keith Thompson Mar 09 '13 at 00:04
17

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

Jean Davy
  • 2,062
  • 1
  • 19
  • 24
11

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.

nonsensickle
  • 4,438
  • 2
  • 34
  • 61
  • 2
    _I would like to add that the `__FUNCTION__` macro is defined for both GCC and MSVC._ the documentation quote explicitly states that this is **not** a macro. – Antonin Décimo Apr 12 '20 at 09:38
7

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
Community
  • 1
  • 1
alexfontaine
  • 113
  • 5