Replicating the behavior of __PRETTY_FUNCTION__ in C++ - c++

Where in GCC is the behavior of C++’s __PRETTY_FUNCTION__ defined? I want to replicate its functionality in Visual Studio.
It’s my understanding that I could replace __PRETTY_FUNCTION__ with either __FUNCTION__ or __FUNCSIG__,¹ but that, then, I’d lose the ability to compile the code on macOS.
How do include __PRETTY_FUNCTION__’s functionality in code that I want to be able to compile in, say, both Visual Studio and Xcode.
Apologies if the answer to my question is in the text I’m linking to or in the resources it mentions.

Define your own macro that refers to __FUNCTION__ or __PRETTY_FUNCTION__ based on your compiler:
#ifdef _MSC_VER
#define MY_FUNCTION_MACRO __FUNCTION__ // or __FUNCSIG__
#else
#define MY_FUNCTION_MACRO __PRETTY_FUNCTION__
#endif
And then use MY_FUNCTION_MACRO throughout your cross-patform code.
Note that MY_FUNCTION_MACRO will still produce different strings from between VC++ and GCC/Clang. This is unavoidable and gets you as close as you can get.
For example:
int main()
{
std::cout << MY_FUNCTION_MACRO << std::endl;
}
will produce "main" when using __FUNCTION__ or "int __cdecl main(void)" when using __FUNCSIG__ in VC++, whereas __PRETTY_FUNCTION__ produces "int main()" in GCC/Clang.

I was wondering about this myself, found your post, and did some more digging. Here's some answers and more that I discovered...
Where in GCC is the behavior of C++’s __PRETTY_FUNCTION__ defined?
A recursive search for __PRETTY_FUNCTION__ within the gcc source code mirrored on github suggested that its behavior is mostly defined through DECL_PRETTY_FUNCTION_P in gcc/cp/pt.cc. This in turn sees to cp_make_fname_decl being invoked from gcc/cp/decl.cc. And that builds a declaration for __PRETTY_FUNCTION__.
Currently - as of my reading of this code and experience using __PRETTY_FUNCTION__ - gcc provides a locally scoped, read only, constant expression, character array type of value.
I.e., by its naming convention, __PRETTY_FUNCTION__ may look like a macro (that's what I'd assumed), but by its current implementation (in gcc), it's instead a locally scoped, character array.
How do I include __PRETTY_FUNCTION__’s functionality in code that I want to be able to compile in, say, both Visual Studio and Xcode?
Xcode by default I understand is using an Apple version of clang. Clang is more similar to gcc with respect to this question, than to msvc. So if by Xcode, you mean to use the default compiler, that'd be clang which similarly supports __PRETTY_FUNCTION__.
With this in mind, I like cscrimage's answer using __FUNCSIG__ for msvc and __PRETTY_FUNCTION__ otherwise:
#ifdef _MSC_VER
#define MY_FUNCTION_MACRO __FUNCSIG__
#else
#define MY_FUNCTION_MACRO __PRETTY_FUNCTION__
#endif
What To Expect
Using the abort sort of code within a function such as the following demonstrates the formats of these values for different compilers:
template <typename T> std::string Name()
{
#if defined(__clang__) || defined(__GNUC__)
return std::string {__PRETTY_FUNCTION__};
#elif defined(_MSC_VER)
return std::string {__FUNCSIG__};
#else
return "not supported by compiler";
#endif
}
template <typename T> struct Other {};
using F = Other<int>;
A statement like:
std::cout << Name<F>() << '\n';
On gcc 12.2 yields:
std::string Name() [with T = Other<int>; std::string = std::__cxx11::basic_string<char>]
And on msvc 19.22 yields:
class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Name<struct Other<int>>(void)
That's pretty compiler dependent and clang is slightly different from gcc as well.
Normalizing The Values
We could however use something like std::regex_replace with compiler dependent std::regex values to parse these into a more similar format between these compilers. I didn't find any documentation from gcc nor msvc that guaranteed what this format will be so I wouldn't expect it to stay the same between all releases of compilers either.
In my case (that got me to dig into this), I was particularly concerned about stringifying types and built on these techniques using the template type parameter as the value I intended to return from the replacement. Here's that code as an example that accounts for differences between msvc, clang, and gcc:
template <typename T>
std::string Name()
{
// Ideally return string unique to the type T...
#if defined(_MSC_VER)
// template <typename T> string Name() { return string{__FUNCSIG__}; }
// enum class Fruit {APPLE, PEAR};
// std::cout << Name<Fruit>() << '\n';
// produces:
// class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __cdecl Name<enum Fruit>(void)
return std::regex_replace(__FUNCSIG__, std::regex(".* __cdecl [^<]+<(.*)>\\(void\\)"), "$1");
#elif defined(__clang__)
// template <typename T> string Name() { return string{__PRETTY_FUNCTION__}; }
// enum class Fruit {APPLE, PEAR};
// std::cout << Name<Fruit>() << '\n';
// produces: std::string Name() [T = Fruit]
return std::regex_replace(__PRETTY_FUNCTION__, std::regex(".*T = (.*)\\].*"), "$1");
#elif defined(__GNUC__)
// template <typename T> string Name() { return string{__PRETTY_FUNCTION__}; }
// enum class Fruit {APPLE, PEAR};
// std::cout << Name<Fruit>() << '\n';
// produces: std::string Name() [with T = Fruit; std::string = std::__cxx11::basic_string<char>]
return std::regex_replace(__PRETTY_FUNCTION__, std::regex(".*T = (.*);.*"), "$1");
#else
return {}; // not unique but maybe still helpful at avoiding compiler issues
#endif
}
template <typename T> struct Other {};
using F = Other<int>;
int main()
{
std::cout << Name<F>() << '\n';
}
With that, on gcc 12.2 and clang trunk we get Other<int>, and on msvc 19.22 we get struct Other<int> - see the full code at godbolt. This was close enough for my purposes.
Regular expressions for instead returning a commonly formatted function signature looks more involved (depending of course on exactly how common a format one wants) but I don't see why that couldn't be done also.
Some Alternatives
If you can use boost, you may want to look into BOOST_CURRENT_FUNCTION or boost::core::demangle depending on whether you just want code to pick the variable for you to use on your platforms or whether you're more interested in re-using code that's already been written to give you the formatting. And if you have RTTI enabled, you can use something like boost::core::demangle(typeid(T).name()). I notice however that for functions, this will strip off the function name and just provide a readable function signature for it. It also seems like demangle used between clang and msvc isn't returning a completely platform independent signature for the function either.
Or, if you can use C++20 or newer and it's the function signature and name you're wanting, std::source_location::function_name looks interesting. It's implementation defined too however.

Related

using __FUNCSIG__ in a macro expands it to be empty

I am using an API which return int error codes and I decided to build a wrapper error class :
class Error
{
...
public:
Error(int ErrC, const char* UserMessage, const char* FileName, int LineNumber, const char* Function);
char * GetFunction();
...
}
I decided to venture into the world of macros and create a macro to instantiate the class for me :
#define API_ERROR(Code,MSG) API::Error(Code,MSG,__FILE__,__LINE__,__FUNCSIG__)
I then defined a Test function that is called by main
void TestFunc()
{
API::Error Error = API_ERROR(0,"Hello");
std::cout << Error.GetFunction();
}
Using the compiler option to output the post pre-processing results (Properties->C/C++->Preprocessor->Preprocess to a file) yielded
void TestFunc()
{
API::Error Error = API::Error(o,"Hello","...\\main.cpp",30,);
std::cout << Error.GetFunction();
}
I think this does not work because __FUNCSIG__ is only defined inside functions.
I have also tried
#define EMPTY()
#define DEFER(...) __VA_ARGS__ EMPTY()
#define API_ERROR(Code,MSG) API::Error(Code,MSG,__FILE__,__LINE__,DEFER(__FUNCSIG__))
But I think I misunderstood the author of the post.
Is there a way to make this work ?
I am using Visual Studio 2019 Community with the default MSVC++ compiler.
From this VS2019 predefined macro reference
The __FUNCSIG__ macro isn't expanded if you use the /EP or /P compiler option.
[Emphasis mine]
If you preprocess your source then the /EP or /P flags would be set, and the macro won't be expanded. It will only be expanded when actually building your source.
The __FUNCSIG__ macro will probably not be expanded by the preprocessor because it doesn't really know anything about C++ symbols. It might not even be a true preprocessor macro, and could be "expanded" (or replaced) at a later stage in compilation when C++ symbols are known.

How does libc++'s std::is_literal_type work?

This is the same situation for std::is_literal_type and std::is_standard_layout.
The implementation of std::is_literal_type in libc++ is
template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_literal_type
#ifdef _LIBCPP_IS_LITERAL
: public integral_constant<bool, _LIBCPP_IS_LITERAL(_Tp)>
#else
: integral_constant<bool, is_scalar<typename remove_all_extents<_Tp>::type>::value ||
is_reference<typename remove_all_extents<_Tp>::type>::value>
#endif
{};
There is no _LIBCPP_IS_LITERAL, so the code will be
template <typename T> struct is_literal_type : integral_constant<bool,
is_scalar<typename remove_all_extents<T>::type>::value or
is_reference<typename remove_all_extents<T>::type>::value> {};
I wrote a demo:
#include <iostream>
using namespace std;
struct s {
int a;
char b;
long c;
};
int main(int argc, char *argv[]) {
cout << boolalpha;
cout << is_scalar_v<typename remove_all_extents<s>::type> << endl;
cout << is_reference_v<typename remove_all_extents<s>::type> << endl;
}
The result is false and false. But the result of is_literal_type_v<s> is true.
Could anyone explain how std::is_literal_type works?
is_literal_type is a "magic" C++ library thing. It cannot be implemented in C++ as the language currently stands (with static reflection, it should be possible, but that's C++23 at the soonest). It is implemented by using compiler-specific intrinsic tools, not by using C++ directly. _LIBCPP_IS_LITERAL is probably a macro defined by the compiler (hence it appearing undefined) which represents that particular compiler intrinsic.
As such, you really shouldn't look too closely at the implementation of this or many of the other type traits.
I imagine the version where _LIBCPP_IS_LITERAL is not defined is for compatibility with older versions of the compiler that did not expose the necessary intrinsic. So the library implementation does the best that it can without compiler support.
To add to the previous answer by #NicolBolas: It is probably wrong that _LIBCPP_IS_LITERAL is not set. Have a look at __config.h:
#if defined(_LIBCPP_COMPILER_CLANG)
[...]
#if __has_feature(is_literal)
#define _LIBCPP_IS_LITERAL(T) __is_literal(T)
#endif
[...]
#elif defined(_LIBCPP_COMPILER_GCC)
[...]
#if _GNUC_VER >= 407
[...]
#define _LIBCPP_IS_LITERAL(T) __is_literal_type(T)
[...]
#endif
Therefore the macro will be set if you are compiling with a recent enough Clang or GCC and in either case it will use a compiler intrinsic. __is_literal for Clang or __is_literal_type for GCC.
Both intrinsics are documented:
From https://clang.llvm.org/docs/LanguageExtensions.html:
__is_literal(type): Determines whether the given type is a literal type
From https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html:
__is_literal_type (type)
If type is a literal type ([basic.types]) the trait is true, else it is false. Requires: type shall be a complete type, (possibly cv-qualified) void, or an array of unknown bound.
You should not use these intrinsics directly though, because as you can see they are not portable. They are defined for the standard library developers.

Visual C++ equivalent of __FILE__ , __LINE__ and __PRETTY_FUNCTION__

GCC compiler gives me the following macros:
__FILE__ so that I can print out the file name + directory.
__LINE__ so that I can print out the line number of where I'm printing from.
__PRETTY_FUNCTION__ so that I can print out the pretty function name
Does Visual C++ have the equivalent of these macros? A side question is, are these standard for C++ compilers?
In VS2008, this:
struct A
{
bool Test(int iDummyArg)
{
const char *szFile = __FILE__;
int iLine = __LINE__;
const char *szFunc = __FUNCTION__; // Func name
const char *szFunD = __FUNCDNAME__; // Decorated
const char *szFunS = __FUNCSIG__; // Signature
printf("%s\n", szFile);
printf("%d\n", iLine);
printf("%s\n", szFunc);
printf("%s\n", szFunD);
printf("%s\n", szFunS);
return true;
}
};
int wmain(int argc, TCHAR *lpszArgv[])
{
A a;
a.Test(10);
}
will print this:
c:\source\test_projects\blah\blah.cpp
14
A::Test
?Test#A##QAE_NH#Z
bool __thiscall A::Test(int)
(The line number is "wrong" since there was really some extra stuff at the top of my file.)
__FILE__ and __LINE__ are standard, and I'm rather certain Microsoft compilers have essentially always had them.
__PRETTY_FUNCTION__ is a gcc feature.
For more portability in getting the current function name, you can try BOOST_CURRENT_FUNCTION.
Yes Visual C++ has them or an equivalent. See the responses here:
What's the difference between __PRETTY_FUNCTION__, __FUNCTION__, __func__?
function-func/4384860#4384860
Also note that despite the upper case used, they aren't macros. They're variables.
I know that MSVC offers __FILE__ and __LINE__, both of which are Standard macros. They also offer __FUNCTION__, which I believe is what you're looking for,
__FILE__ and __LINE__ are standard since C89. __PRETTY_FUNCTION__ is a GCCism. __func__ is a C99ism which (unlike GCCisms) may well be available in Visual C++; it is not precisely the same as __PRETTY_FUNCTION__ but it may be close enough for your purposes.
Yes, Microsoft Visual Studio has __FILE__ and __LINE__. Here are more MSVC macros.
Both are ANSI C++.
MSVC has __FUNCTION__, which is Microsoft-specific.
Using c++14 with constexpr you can use this: WHERE macro.
Based on usage of:
__PRETTY_FUNCTION__
__LINE__
#include "string/ConstexprString.hpp"
#define S1(x) #x
#define S2(x) S1(x)
// WHERE - const char* const should be used as temporary value
#define WHERE (string::make(__PRETTY_FUNCTION__) + ":" + string::make(S2(__LINE__))).get()
// It is safe to store e.g. `constexpr auto where = WHERE_STR;`
#define WHERE_STR (string::make(__PRETTY_FUNCTION__) + ":" + string::make(S2(__LINE__)))
Example usage:
// Called: void (anonymous namespace)::exampleUseCaseWhere(int):18
std::cout << "Called: " << WHERE << std::endl;
Full & running example here
See:
src/acme/where.hpp
src/string/ConstexprString.hpp
src/acme/where_test.cpp

How to find out if this preprocessor macro exists?

I want to know how to find out if the preprocessor macro __PRETTY_FUNCTION__ can be used with a given compiler (As it is supposed to be non-standard). How do I check this in a header file? What I want to do is something like:
#ifndef __PRETTY_FUNCTION__
#define __PRETTY_FUNCTION__ __func__
#endif
But, I'm guessing what happens is the preprocessor defines the macro in place for each function so I wonder whether there's any meaning to __PRETTY_FUNCTION__ (Unlike __FILE__ or __LINE__) outside a function. Is this true or can I just use the code above? If not, how do I check for it?
EDIT: I tried it. __PRETTY_FUNCTION__ is undefined outside a function (I didn't check inside a class). So there has to be another way.
EDIT2: Actually a simple hack would be to do this :):
void Dummy()
{
#ifndef __PRETTY_FUNCTION__
#define __PRETTY_FUNCTION__ __func__
#endif
}
The other method is to check for compiler as was suggested by others.
You probably have to know which compiler you're using. For GCC (the GNU Compiler Collection), you'd probably test:
#ifdef __GNUG__
...use __PRETTY_FUNCTION__
#endif
You might check the compiler version if you know which one introduced the feature and you are in any danger of having your code compiled with an older version.
The GCC (4.4.1) manual says:
In C, __PRETTY_FUNCTION__ is yet another name for __func__. However, in C++, __PRETTY_FUNCTION__ contains the type signature of the function as well as its bare name.
For example, this program:
extern "C" {
extern int printf (char *, ...);
}
class a {
public:
void sub (int i)
{
printf ("__FUNCTION__ = %s\n", __FUNCTION__);
printf ("__PRETTY_FUNCTION__ = %s\n", __PRETTY_FUNCTION__);
}
};
int
main (void)
{
a ax;
ax.sub (0);
return 0;
}
gives this output:
__FUNCTION__ = sub
__PRETTY_FUNCTION__ = void a::sub(int)
These identifiers are not preprocessor macros. In GCC 3.3 and earlier, in C only, __FUNCTION__ and __PRETTY_FUNCTION__ were treated as string literals; they could be used
to initialize char arrays, and they could be concatenated with other string literals. GCC
3.4 and later treat them as variables, like __func__. In C++, __FUNCTION__ and __PRETTY_
FUNCTION__ have always been variables.

Macro / keyword which can be used to print out method name?

__FILE__ and __LINE__ are well known. There is a __func__ since C99.
#include <iostream>
struct Foo {
void Do(){ std::cout << __func__ << std::endl; }
};
int main()
{
std::cout << __func__ << std::endl;
Foo foo; foo.Do();
return 0;
}
will output
main
Do
Is there any macro / keyword that would output method name like Foo::Do?
Boost has a special utility macro called BOOST_CURRENT_FUNCTION that hides the differences between the compiler implementations.
Following it's implementation we see that there are several macros depending on compiler:
__PRETTY_FUNCTION__ -- GCC, MetroWerks, Digital Mars, ICC, MinGW
__FUNCSIG__ -- MSVC
__FUNCTION__ -- Intel and IBM
__FUNC__ -- Borland
__func__ -- ANSI C99
On GCC you can use __FUNCTION__ and
__PRETTY_FUNCTION__.
On MSVC you can use __FUNCSIG__ and __FUNCTION__.
There's no such macro in standard C++, and that includes the draft C++0x standard I looked at. It would complicate compilation, since parsing (necessary to determine what a function is) comes after preprocessing, and I suspect that's why there's nothing in the standard.
The __func__ you're using is nonstandard, although it apparently works on your compiler.
Not in Standard C++ (and __func__ is not part of C++). Your implementation may have such a feature though - which compiler are you using?
See "Predefined Macros (C/C++)" for a complete list supported by MS Visual Studio.
This might be useful:
http://gcc.gnu.org/onlinedocs/gcc/Function-Names.html
#include"stdio.h"
#include"stdlib.h"
int main()
{
printf("line number is %d .. func name is %s, file name is %s",__LINE__,__PRETTY_FUNCTION__,__FILE__);
return 0;
}
This is how to print line number, function name and file name in gcc.