Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mangled names for internal linkage functions in extern "C" are different from GCC #88593

Open
MaskRay opened this issue Apr 12, 2024 · 2 comments

Comments

@MaskRay
Copy link
Member

MaskRay commented Apr 12, 2024

This records a name mangling difference with GCC. It's possible that Clang's decision is desired and we should not take any action.
(I saw a relevant issue about this but I cannot find it now.)

extern "C" {
static void f0() {}
static void f0(int) {}
}
  • GCC: error: conflicting declaration of C function ‘void f0(int)’
  • Clang: accepted; names are mangled

C++ https://eel.is/c++draft/dcl.link gives an example:

extern "C" {
  static void f4();             // the name of the function f4 has internal linkage,
                                // so f4 has no language linkage; its type has C language linkage
}

If f4 has no language linkage, it seems to make sense to mangle it. So Clang's choice is probably desired.

GCC's decision allows alias/ifunc attributes with an unmangled name like the following:

extern "C" {
static void f0() {}
void g0() __attribute__((alias("f0")));
}

With Clang, _ZL2f0v is needed. This difference makes such alias/ifunc attributes uses in C++ non-portable. However, this probably does not matter because people rarely use alias/ifunc in C++.

I think certain extensions rely on mangling internal linkage functions in extern "C", e.g. __attribute__((overloadable)).

@llvmbot
Copy link
Collaborator

llvmbot commented Apr 12, 2024

@llvm/issue-subscribers-clang-codegen

Author: Fangrui Song (MaskRay)

This records a name mangling difference with GCC. It's possible that Clang's decision is desired and we should not take any action. (I saw a relevant issue about this but I cannot find it now.)
extern "C" {
static void f0() {}
static void f0(int) {}
}
  • GCC: error: conflicting declaration of C function ‘void f0(int)’
  • Clang: accepted; names are mangled

C++ https://eel.is/c++draft/dcl.link gives an example:

extern "C" {
  static void f4();             // the name of the function f4 has internal linkage,
                                // so f4 has no language linkage; its type has C language linkage
}

If f4 has no language linkage, it seems to make sense to mangle it. So Clang's choice is probably desired.

GCC's decision allows alias/ifunc attributes with an unmangled name: void g4() __attribute__((alias("f4"))).

@pinskia
Copy link

pinskia commented Apr 14, 2024

MaskRay added a commit that referenced this issue Apr 16, 2024
https://reviews.llvm.org/D54188 marked "alias" targets as used in C to
fix -Wunused false positives. This patch extends the approach to handle
mangled names to support global scope names in C++ and the
`overloadable` attribute in C.

In addition, we mark ifunc targets as used to fix #63957.

While our approach has false negatives for namespace scope names, the
majority of alias/ifunc C++ uses (global scope with no overloads) are
handled.

Note: The following function with internal linkage but C language
linkage type is mangled in Clang but not in GCC. This inconsistency
makes alias/ifunc difficult to use in C++ with portability (#88593).
```
extern "C" {
static void f0() {}
// GCC: void g0() __attribute__((alias("_ZL2f0v")));
// Clang: void g0() __attribute__((alias("f0")));
}
```

Pull Request: #87130
MaskRay added a commit that referenced this issue Apr 16, 2024
https://reviews.llvm.org/D54188 marked "alias" targets as used in C to
fix -Wunused false positives. This patch extends the approach to handle
mangled names to support global scope names in C++ and the
`overloadable` attribute in C.

(Note: we should skip `UsingShadowDecl`, which would trigger an
assertion failure in `ItaniumMangleContextImpl::mangleCXXName`.
See regression test added by commit 1c2afba.)

In addition, we mark ifunc targets as used to fix #63957 (temporarily
used by xz; ifunc was removed by
tukaani-project/xz@689ae24)

While our approach has false negatives for namespace scope names, the
majority of alias/ifunc C++ uses (global scope with no overloads) are
handled.

Note: The following function with internal linkage but C language
linkage type is mangled in Clang but not in GCC. This inconsistency
makes alias/ifunc difficult to use in C++ with portability (#88593).
```
extern "C" {
static void f0() {}
// GCC: void g0() __attribute__((alias("_ZL2f0v")));
// Clang: void g0() __attribute__((alias("f0")));
}
```

Pull Request: #87130
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants