neither gcc nor clang are compliant with standard c++

Neither GCC nor Clang are compliant with standard C++

Neither GCC nor Clang are compliant with standard C++ GCC 和 Clang 均不符合 C++ 标准

2026-07-08 2026年7月8日

In C++, function types have a “language linkage” associated with them: this is either “C++”, “C”, or some other implementation-defined language. And 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. 在 C++ 中,函数类型关联着一种“语言链接”(language linkage):即“C++”、“C”或其他由实现定义的语言。标准非常明确地指出,即使两个函数类型在其他方面完全相同,只要它们的语言链接不同,它们就是不同的类型。其设计初衷是某些实现可能对 C++ 函数和 C 函数使用不同的调用约定,因此它们不能混用。

GCC and Clang, however, just don’t store language linkage information with the type. So two functions with different language linkages can be identical: 然而,GCC 和 Clang 并没有在类型中存储语言链接信息。因此,两个具有不同语言链接的函数可能会被视为相同:

#include <type_traits>

extern "C" using c_func = void ();

// This static assertion should fail, but it doesn't
// 这个静态断言本应失败,但实际上并没有
static_assert(std::is_same<c_func, void ()>::value);

This can also cause erroneous compilation failures when overloading a function which takes in 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. 上述代码本应能够编译通过,但 GCC 和 Clang 都认为参数列表是相同的,从而违反了“单一定义规则”(One Definition Rule)。

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. 依我之见,这不应归咎于 GCC 或 Clang,而应归咎于标准。也就是说,标准本身是有问题的,应该进行更新,将此行为改为由实现定义。GCC 和 Clang 无法改变其行为,因为这将导致破坏性的 ABI 变更(修饰名中的 extern "C" 函数类型编码方式会发生变化)。而且它们也没有理由做出这种改变:据我所知,在几乎所有平台上,C 和 C++ 的调用约定都是相同的。