clang and gcc implement __PRETTY_FUNCTION__ differently

Hi,
Here is one difference between clang and gcc which makes some of our software fail when built with clang.
is this something you would consider fixing?

Thanks,

–kcc

% cat pretty.cc
#include <stdio.h>
template
const char foo() {
return PRETTY_FUNCTION;
}
int main() {
printf("%s\n", foo());
}
% g++ pretty.cc && ./a.out
const char
foo() [with T = int]
% ~/llvm/build/Release+Asserts/bin/clang++ pretty.cc && ./a.out
const char *foo()

I’m of two minds here. I think it would be great to include the template arguments for the instantiation into the pretty name… But I’m really worried about trying to chase the exact formatting used by GCC.

From what I can tell, this is the format used in their diagnostic printing. I would expect that to change on the GCC end as well, so it seems that any code depending on this is just a time bomb…

Hi,
Here is one difference between clang and gcc which makes some of our
software fail when built with clang.
is this something you would consider fixing?

No, we are not going to change the placement of the * in "const char *foo".

-Eli

Hi,
Here is one difference between clang and gcc which makes some of our
software fail when built with clang.
is this something you would consider fixing?

No, we are not going to change the placement of the * in “const char *foo”.

That’s not about ‘*’, but about “[with T = int]”
I don’t think that there is any standard that exactly defines how PRETTY_FUNCTION behaves, but having
[with T = int]" might be useful.

(But yes, our code that relies on this is … )

–kcc

> Hi,
> Here is one difference between clang and gcc which makes some of our
> software fail when built with clang.
> is this something you would consider fixing?

No, we are not going to change the placement of the * in "const char
*foo".

That's not about '*', but about "[with T = int]"
I don't think that there is any standard that exactly defines
how __PRETTY_FUNCTION__ behaves, but having
[with T = int]" might be useful.

Yes, it seems like it would be useful.

(But yes, our code that relies on this is ... )

Yes.

-Eli

This gets more interesting if the template is actually used by the
function. Changing it to foo(T x) and adjusting the call, the result is:

clang:
const char *foo(int)

gcc:
const char* foo(T) [with T = int]

I don't think the GCC output is really better.

Joerg

It's worth noting that clang's output is actually ambiguous in some
cases at the moment: you can't tell the difference between "void
f(int)" and "template<typename T> void f(T)" with T=int.

-Eli

I think Clang’s output should be improved… and I’ll actually be glad if it doesn’t match the GCC output just so that people are slightly less likely to try parsing this stuff… madness… ;]

Right. For this reason, I like GCC's output better (except that the '*' is in the wrong place <g>).

  - Doug

Here’s something I coded to try things out. Should we print function parameter types the way we do right now or should we do it like gcc (printing template parameter names instead of real type names)?

gcc:
const char* foo(T) [with T = int]

msvc:
const char *__cdecl foo(int)

clang:
const char *foo(int)

clang + patch:
const char* foo(int) [T = int]

potential formatting (gcc msvc hybrid):
const char *foo<T = int>(T)

What do you think?

pretty_function.patch (968 Bytes)

Either form is fine with me, but please make sure to eliminate unused
templates from the output. That's my biggest issue with GCC.

Joerg

Here’s something I coded to try things out. Should we print function parameter types the way we do right now or should we do it like gcc (printing template parameter names instead of real type names)?

gcc:
const char* foo(T) [with T = int]

msvc:
const char *__cdecl foo(int)

clang:
const char *foo(int)

clang + patch:
const char* foo(int) [T = int]

This form is ambiguous. You don’t know which argument use the template type.

For example, if foo were declared like that:
int foo(T x, int y);

you will get:
int foo(int x, int y) [T = int]

potential formatting (gcc msvc hybrid):
const char *foo<T = int>(T)

What do you think?

#include <stdio.h>
template
const char *foo() {
return PRETTY_FUNCTION;
}
int main() {
printf("%s\n", foo());
}

This gets more interesting if the template is actually used by the
function. Changing it to foo(T x) and adjusting the call, the result is:

clang:
const char *foo(int)

gcc:
const char* foo(T) [with T = int]

I don’t think the GCC output is really better.

It’s worth noting that clang’s output is actually ambiguous in some
cases at the moment: you can’t tell the difference between “void
f(int)” and “template void f(T)” with T=int.

Right. For this reason, I like GCC’s output better (except that the ‘*’ is in the wrong place ).

  • Doug

cfe-dev mailing list
cfe-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

<pretty_function.patch>_______________________________________________
cfe-dev mailing list
cfe-dev@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev

– Jean-Daniel

Joerg what do you exactly mean by unused templates?

Go back to the starting point of this thread.

Joerg

I’m just not sure about the exact meaning.

T is definitely unused

template
const char *foo() {
return PRETTY_FUNCTION;
}

But what about

template
const char *foo() {
T t();
std::cout << t;

return PRETTY_FUNCTION;
}

I’m just not familiar with the term unused template parameter. Does it mean not showing up in the function parameter list, not showing up anywhere inside function body or something else?

That's not valid, is it? E.g. the function doesn't result in
non-conflicting specialisations, does it?

Joerg

You’re right, the example was stupid. I’m just trying to understand what unused template actually means and more importantly how to check if it’s used or not?

Unused in the sense that no parameter (and the return type) are derived
from the template parameter.

Joerg

You're right, the example was stupid. I'm just trying to understand what
unused template actually means and more importantly how to check if it's used
or not?

Your example looked reasonable to me (apart from "T t();", which declares a
function...). That's one of the cases in which __PRETTY_FUNCTION__ is
currently ambiguous.

Here’s something I coded to try things out. Should we print function parameter types the way we do right now or should we do it like gcc (printing template parameter names instead of real type names)?

I’d prefer to print the template parameter names.

gcc:
const char* foo(T) [with T = int]

msvc:
const char *__cdecl foo(int)

clang:
const char *foo(int)

clang + patch:
const char* foo(int) [T = int]

Definitely an improvement. I still like GCC’s best.

potential formatting (gcc msvc hybrid):
const char *foo<T = int>(T)

What do you think?

Thanks for working on this!