Hacker News

Neither GCC nor Clang are compliant with standard C++

Language Linkage and Type Identity

In C++, function types have a "language linkage" associated with them: this is either "C++", "C", or some other implementation-defined language. The standard very explicitly states that "Two function types with different language linkages are distinct types even if they are otherwise identical." The idea is that some implementations may have different calling conventions for C++ functions than for C functions, so they can't be intermixed.

GCC and Clang, however, just don't store language linkage information with the type. So two functions with different language linkages can be identical:

#include <type_traits>
extern "C" using c_func = void ();

// this static assertion should fail, but it doesn't
static_assert(std::is_same_v<c_func, void()>);

Erroneous Overload Resolution

This can also cause erroneous compilation failures when overloading a function which takes a function pointer parameter:

extern "C" using c_func = void ();
void f(c_func *) {}
void f(void (*)()) {}

The above code should compile, but GCC and Clang both think that the parameter lists are identical and thus this violates the One Definition Rule.

Who Is at Fault?

IMO the blame here doesn't lie on GCC or Clang; it lies on the standard. That is, the standard is wrong and should be updated to make this implementation-defined. GCC and Clang can't change their behavior because that would be a breaking ABI change (extern "C" function types in mangled names would be encoded differently). And they have no reason to make this change: the calling conventions for C and C++ are identical on, as far as I can tell, pretty much every platform.

Comments

No comments yet. Start the discussion.