Seems that __attribute__((noreturn))
and probably some other attributes, form part of the function type as far as C++ language semantics are concerned - but not as far as name mangling (at least on itanium) is concerned.
So, for instance:
template<typename T>
struct t1 { };
void f() __attribute__((noreturn));
void g();
t1<decltype(f)> v1;
t1<decltype(g)> v2;
Produces two distinct types in the DWARF representation and at the language level like this:
void f1(decltype(f));
void f2() {
f1(g); // fails to compile: error: no matching function for call to 'f1'
// note: candidate function not viable: no known conversion from 'void ()' to 'decltype(f) *' (aka 'void (*)() __attribute__((noreturn))') for 1st argument
}
(the inverse would be OK - a noreturn function type is implicitly convertible to an un-attributed (possibly-but-not-necessarily noreturning) function type)
But try to /define/ (declarations are OK) two overloads, and at least on Itanium, that’s not possible:
nrt2.cpp:8:6: error: definition with same mangled name '_Z2f1PFvvE' as another definition
void f1(decltype(g)) { }
^
nrt2.cpp:7:6: note: previous definition is here
void f1(decltype(f)) { }
^
I guess the answer is we should model this as we do today, as separate types. It does present a slight wrinkle for the Simplified Template Names work - since we don’t encode “noreturn” in a function type - so that’s probably an issue we should fix (seems there is a DWARF attribute, DW_AT_noreturn
we can use for it - would need to add that to the DISubroutineType, etc) - though I’m not planning on doing that right away.
For now I’ll just not simplify templates that include parameters that have the noreturn attribute.