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" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits