[clang] 95566af - [Clang][AST] Fix MS Mangle concept uneval context template instantiation crash (#117845)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 3 20:18:20 PST 2024
Author: Max Winkler
Date: 2024-12-03T20:18:16-08:00
New Revision: 95566af789d208b8fc422644ab282a43911041f2
URL: https://github.com/llvm/llvm-project/commit/95566af789d208b8fc422644ab282a43911041f2
DIFF: https://github.com/llvm/llvm-project/commit/95566af789d208b8fc422644ab282a43911041f2.diff
LOG: [Clang][AST] Fix MS Mangle concept uneval context template instantiation crash (#117845)
Fixes https://github.com/llvm/llvm-project/issues/115990.
MSVC mangling got inadvertently broken here,
https://github.com/llvm/llvm-project/pull/83997, when it was fixed what
decl context a lambda is apart of for uneval contexts.
https://godbolt.org/z/K6jb5v145 for reference.
Given the following code snippet
```
template <typename T>
concept C = requires(const T& t)
{
{ T::test([](){}) };
};
template<typename T, typename = void>
struct Widget;
template <C T>
struct Widget<T> {};
struct Baz
{
template<typename F>
static constexpr decltype(auto) test(F&& f) {}
};
void test()
{
Widget<Baz> w;
}
```
`Baz::test` has a deduced return type which means we must instantiate
that template even in an unevaluated context.
The lambda inside the concept is within the decl context of `struct
Widget<T> {};`. So we end up needing to mangle a name of
`Baz::test<Widget<template-type-0-0>::lambda()>>()` since the lambda
isn't apart of an instantiated substituted class `Widget` yet at the
point the lambda is instantiated.
Upon template instantation of `test` we end up asking for the mangled
name so we can add this instantiation to `CodeGenModule::DefferredDecls`
since `test` is now referenced but not yet used.
I think the longer term more correct solution is to key `DefferedDecls`
off of something else than the mangled name to avoid having to mangle
names for instantations that are referenced but will never be used since
they are only instantiated from an unevaluated context.
As a fix for the regression I just created a custom mangling scheme for
this case since MSVC has no comparable naming scheme as such a template
will never be emitted into the resulting obj as it will never be used.
Added:
clang/test/CodeGenCXX/ms-uneval-context-crash.cpp
Modified:
clang/lib/AST/MicrosoftMangle.cpp
Removed:
################################################################################
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index 94a7ce6c1321d3..7642ff7ca606cd 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -3372,7 +3372,15 @@ void MicrosoftCXXNameMangler::mangleType(const MemberPointerType *T,
void MicrosoftCXXNameMangler::mangleType(const TemplateTypeParmType *T,
Qualifiers, SourceRange Range) {
- Error(Range.getBegin(), "template type parameter type") << Range;
+ Out << '?';
+
+ llvm::SmallString<64> Name;
+ Name += "<TTPT_";
+ Name += llvm::utostr(T->getDepth());
+ Name += "_";
+ Name += llvm::utostr(T->getIndex());
+ Name += ">";
+ mangleSourceName(Name);
}
void MicrosoftCXXNameMangler::mangleType(const SubstTemplateTypeParmPackType *T,
diff --git a/clang/test/CodeGenCXX/ms-uneval-context-crash.cpp b/clang/test/CodeGenCXX/ms-uneval-context-crash.cpp
new file mode 100644
index 00000000000000..b2f7e58381da81
--- /dev/null
+++ b/clang/test/CodeGenCXX/ms-uneval-context-crash.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++20 -fms-compatibility -fms-compatibility-version=19.33 -emit-llvm %s -o - -triple=x86_64-windows-msvc | FileCheck %s
+
+template <typename T>
+concept C = requires
+{
+ { T::test([](){}) };
+};
+
+template<typename T>
+struct Widget {};
+
+template <C T>
+struct Widget<T> {};
+
+struct Baz
+{
+ template<typename F>
+ static constexpr decltype(auto) test(F&&) {}
+};
+
+void test()
+{
+ Widget<Baz> w;
+}
+// CHECK: @"?test@@YAXXZ"
More information about the cfe-commits
mailing list