mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 13:36:08 +00:00

Reapply https://github.com/llvm/llvm-project/pull/102848. The description in this PR will detail the changes from the reverted original PR above. For `auto&&` return types that can partake in reference collapsing we weren't properly handling that mangling that can arise. When collapsing occurs an inner reference is created with the collapsed reference type. If we return `int&` from such a function then an inner reference of `int&` is created within the `auto&&` return type. `getPointeeType` on a reference type goes through all inner references before returning the pointee type which ends up being a builtin type, `int`, which is unexpected. We can use `getPointeeTypeAsWritten` to get the `AutoType` as expected however for the instantiated template declaration reference collapsing already occurred on the return type. This means `auto&&` is turned into `auto&` in our example above. We end up mangling an lvalue reference type. This is unintended as MSVC mangles on the declaration of the return type, `auto&&` in this case, which is treated as an rvalue reference. ``` template<class T> auto&& AutoReferenceCollapseT(int& x) { return static_cast<int&>(x); } void test() { int x = 1; auto&& rref = AutoReferenceCollapseT<void>(x); // "??$AutoReferenceCollapseT@X@@YA$$QEA_PAEAH@Z" // Mangled as an rvalue reference to auto } ``` If we are mangling a template with a placeholder return type we want to get the first template declaration and use its return type to do the mangling of any instantiations. This fixes the bug reported in the original PR that caused the revert with libcxx `std::variant`. I also tested locally with libcxx and the following test code which fails in the original PR but now works in this PR. ``` #include <variant> void test() { std::variant<int> v{ 1 }; int& r = std::get<0>(v); (void)r; } ```
25 lines
867 B
C++
25 lines
867 B
C++
// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19.20 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-windows-msvc | FileCheck --check-prefix=AFTER %s
|
|
// RUN: %clang_cc1 -std=c++17 -fms-compatibility-version=19.14 -emit-llvm %s -o - -fms-extensions -fdelayed-template-parsing -triple=x86_64-pc-windows-msvc | FileCheck --check-prefix=BEFORE %s
|
|
|
|
template <auto a>
|
|
class AutoParmTemplate {
|
|
public:
|
|
AutoParmTemplate() {}
|
|
};
|
|
|
|
template <auto a>
|
|
auto AutoFunc() {
|
|
return a;
|
|
}
|
|
|
|
void template_mangling() {
|
|
|
|
AutoParmTemplate<nullptr> auto_nullptr;
|
|
// AFTER: call {{.*}} @"??0?$AutoParmTemplate@$M$$T0A@@@QEAA@XZ"
|
|
// BEFORE: call {{.*}} @"??0?$AutoParmTemplate@$0A@@@QEAA@XZ"
|
|
|
|
AutoFunc<nullptr>();
|
|
// AFTER: call {{.*}} @"??$AutoFunc@$M$$T0A@@@YA?A_PXZ"
|
|
// BEFORE: call {{.*}} @"??$AutoFunc@$0A@@@YA?A?<auto>@@XZ"
|
|
}
|