When an alias or ifunc attribute refers to a function name that is
mangled, a diagnostic is emitted to suggest the mangled name as a
replacement for the given function name for every matching name in the
current TU.
Fixes #59164
Differential D143803
[clang][alias|ifunc]: Add a diagnostic for mangled names 0xdc03 on Feb 10 2023, 8:47 PM. Authored by
Details When an alias or ifunc attribute refers to a function name that is Fixes #59164
Diff Detail
Event TimelineComment Actions Note that as it stands currently, this patch cannot be committed because the test clang/test/SemaCXX/externc-ifunc-resolver.cpp fails to run. The contents of the test are as follows: // RUN: %clang_cc1 -emit-llvm-only -triple x86_64-linux-gnu -verify %s extern "C" { __attribute__((used)) static void *resolve_foo() { return 0; } namespace NS { __attribute__((used)) static void *resolve_foo() { return 0; } } // namespace NS // FIXME: This diagnostic is pretty confusing, the issue is that the existence // of the two functions suppresses the 'alias' creation, and thus the ifunc // resolution via the alias as well. In the future we should probably find // some way to improve this diagnostic (likely by diagnosing when we decide // this case suppresses alias creation). __attribute__((ifunc("resolve_foo"))) void foo(); // expected-error{{ifunc must point to a defined function}} } The error that I get is as follows: Command Output (stderr): -- + : 'RUN: at line 1' + /mnt/entschuldigung/LLVM/llvm-main/build-release/bin/clang -cc1 -internal-isystem /mnt/entschuldigung/LLVM/llvm-main/build-release/lib/clang/17/include -nostdsysteminc -emit-llvm-only -triple x86_64-linux-gnu -verify /mnt/entschuldigung/LLVM/llvm-main/clang/test/SemaCXX/externc-ifunc-resolver.cpp error: 'note' diagnostics seen but not expected: File /mnt/entschuldigung/LLVM/llvm-main/clang/test/SemaCXX/externc-ifunc-resolver.cpp Line 14: 'resolve_foo' exists as a mangled name, did you mean to use '_ZL11resolve_foov'? File /mnt/entschuldigung/LLVM/llvm-main/clang/test/SemaCXX/externc-ifunc-resolver.cpp Line 14: 'resolve_foo' exists as a mangled name, did you mean to use '_ZN2NSL11resolve_fooEv'? 2 errors generated. -- which confuses me because an extern "C" block is not supposed to mangle any names, right? Appreciate any inputs on this. Comment Actions Looks like maybe a Clang feature, that since they're "static"/internal linkage, Clang decides it can still mangle them: https://godbolt.org/z/6oMfjced1 - GCC doesn't do this, and fails if you try to overload them, whereas clang doesn't. That does surprise me - if only for GCC/Clang compatibility, regardless of what the spec says, exactly... Comment Actions
That IS strange, that has internal linkage, but so the 'extern "C"' doesn't do anything to it, so we choose to just mangle it. I guess there is some sense in that. GCC doesn't mangle EITHER of those (so leaving them both causes a multiple definition error!), but there is apparently a runtime error even trying to use an ifunc to those functions. We COULD just prohibit ifuncs to functions without external linkage, but that is a bigger change than I'm sure I would want to commit to just yet. As far as this patch, I think there is value with improving this diagnostic, but I'm not sure this is the one. I don't have a great idea of an alternate, BUT: error: ifunc must point to a defined function note: the name specified in an ifunc must refer to the <linkage name> (needs better words here for what we mean by the name it needs to call) note: function by that name is mangled as %0 <and notes for each similar name> Comment Actions I will try to come up with a better diagnostic for this issue and will try and update the patch as soon as I can. Are all functional changes logged in the release notes? I am not really aware of how they work.
Comment Actions Not quite all, but somewhat close to it -- if the changes are "user facing", we usually try to write a release note for it: https://llvm.org/docs/DeveloperPolicy.html#release-notes
Comment Actions
Comment Actions Okay, I have now modified the diagnostic to look something like (as per the discussion at https://discord.com/channels/636084430946959380/636732781086638081/1079356357024694363): ../../bug/ifunc-#59164.cpp:17:16: error: ifunc must point to a defined function __attribute__((ifunc("resolver"))) ^ ../../bug/ifunc-#59164.cpp:17:16: note: the name specified in an ifunc must refer to the mangled name ../../bug/ifunc-#59164.cpp:17:16: note: function by that name is mangled as "_ZL8resolverv" __attribute__((ifunc("resolver"))) ^~~~~~~~~~~~~~~~~ ifunc("_ZL8resolverv") ../../bug/ifunc-#59164.cpp:20:16: error: alias must point to a defined variable or function __attribute__((alias("resolver"))) ^ ../../bug/ifunc-#59164.cpp:20:16: note: the name specified in an alias must refer to the mangled name ../../bug/ifunc-#59164.cpp:20:16: note: function by that name is mangled as "_ZL8resolverv" __attribute__((alias("resolver"))) ^~~~~~~~~~~~~~~~~ alias("_ZL8resolverv") ../../bug/ifunc-#59164.cpp:23:24: error: ifunc must point to a defined function __attribute__((unused, ifunc("resolver"), deprecated("hahahaha, isn't C great?"))) void func(); ^ ../../bug/ifunc-#59164.cpp:23:24: note: the name specified in an ifunc must refer to the mangled name ../../bug/ifunc-#59164.cpp:23:24: note: function by that name is mangled as "_ZL8resolverv" __attribute__((unused, ifunc("resolver"), deprecated("hahahaha, isn't C great?"))) void func(); ^~~~~~~~~~~~~~~~~ ifunc("_ZL8resolverv") 3 errors generated. However, clang/test/SemaCXX/externc-ifunc-resolver.cpp still fails, and I am not entirely sure what to do with it. Should I update it to check the diagnostic? Also, it seems that the code I wrote prints "must refer to the mangled name" everywhere, even when the resolver or aliasee is not a function. Should I try to fix this? Or is it OK as it is? Comment Actions I think updating that test with this additional note is the right thing to do. As far as that note, saying 'mangled name' is perhaps not correct there, since what we really care is that it is the name-as-emitted to the linker. I don't have an idea on exactly what to call it. If we could come up with a better phrase, it probably makes the diagnostic on the thing not being a function. ALSO, it would be worth updating the error here to mention that it must point to a defined function, <x, y, Z> (where x,y,z are the things that it is allowed to target). Comment Actions Will do, will also add checks for the fix-its.
First few that come to mind:
It may also be worth splitting the diagnostic for ifuncs and aliases to be something like:
I feel externally-visible name fits the best, though it doesn't really make sense with internal linkage.
Hmm, I do not really understand this point, could you please clarify it? Comment Actions I don't think any of those are accurate with internal names. ABI-mangled is incorrect as the ABI says nothing about these. "Linked Symbol" isnt really accurate, as these aren't really 'linked'. AND, they aren't externally-visible. I wish I was better at this part :D Perhaps @shafik might have a better ability to bikeshed here?
Exactly what you were saying above with the 'splitting the diagnostic', I was saying in less accurate words, that I'd prefer that. Comment Actions I think "mangled name" is probably the closest without being overly verbose for the average user. We do use "mangled name" in a few places already, some which look not too unrelated to this one: clang/include/clang/Basic/DiagnosticSemaKinds.td: "mangled name of %0 will change in C++17 due to non-throwing exception " clang/include/clang/Basic/DiagnosticSemaKinds.td- "specification in function signature">, InGroup<CXX17CompatMangling>; clang/include/clang/Basic/DiagnosticSemaKinds.td- -- clang/include/clang/Basic/DiagnosticSemaKinds.td:def err_hip_invalid_args_builtin_mangled_name : Error< clang/include/clang/Basic/DiagnosticSemaKinds.td- "invalid argument: symbol must be a device-side function or global variable">; -- clang/include/clang/Basic/DiagnosticFrontendKinds.td:def err_duplicate_mangled_name : Error< clang/include/clang/Basic/DiagnosticFrontendKinds.td: "definition with same mangled name '%0' as another definition">; Comment Actions Not thrilled about 'mangled name' still, but I can't think of anything better after all this time, so LGTM. Comment Actions Okay, I have now modified the diagnostic to look like this: ../bug/ifunc-#59164.cpp:17:16: error: ifunc must point to a defined function __attribute__((ifunc("resolver"))) ^ ../bug/ifunc-#59164.cpp:17:16: note: the function specified in an ifunc must refer to its mangled name ../bug/ifunc-#59164.cpp:17:16: note: function by that name is mangled as "_ZL8resolverv" __attribute__((ifunc("resolver"))) ^~~~~~~~~~~~~~~~~ ifunc("_ZL8resolverv") ../bug/ifunc-#59164.cpp:20:16: error: alias must point to a defined variable or function __attribute__((alias("resolver"))) ^ ../bug/ifunc-#59164.cpp:20:16: note: the function or variable specified in an alias must refer to its mangled name ../bug/ifunc-#59164.cpp:20:16: note: function by that name is mangled as "_ZL8resolverv" __attribute__((alias("resolver"))) ^~~~~~~~~~~~~~~~~ alias("_ZL8resolverv") ../bug/ifunc-#59164.cpp:23:24: error: ifunc must point to a defined function __attribute__((unused, ifunc("resolver"), deprecated("hahahaha, isn't C great?"))) void func(); ^ ../bug/ifunc-#59164.cpp:23:24: note: the function specified in an ifunc must refer to its mangled name ../bug/ifunc-#59164.cpp:23:24: note: function by that name is mangled as "_ZL8resolverv" __attribute__((unused, ifunc("resolver"), deprecated("hahahaha, isn't C great?"))) void func(); ^~~~~~~~~~~~~~~~~ ifunc("_ZL8resolverv") 3 errors generated. Honestly I think this is good enough, I don't really think its worth bikeshedding over <mangled name>. I would anyways expect a user of these features to know how mangling works, so :shrug: from me. I have also added checks for the fix-its. Comment Actions Oh wow your reply was much faster than I expected 😅. If you can, please land this patch on my behalf as I do not have commit access, using "Dhruv Chawla <dhruv263.dc@gmail.com>" |
Does clang-format do this? It looks far beyond the usual 80 col limit we use.