[clang] [Clang] Do not try emitting function body when substituting a constraint (PR #186380)

via cfe-commits cfe-commits at lists.llvm.org
Fri Mar 13 05:24:01 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang

Author: Younan Zhang (zyn0217)

<details>
<summary>Changes</summary>

The MS ABI does not appear to have implemented C++20 concept mangling yet. This has led to a bug after CWG2369, where lambdas within a requires body become un-mangleable because the surrounding function templates might not be instantiated.

Previously, we bypassed code emission for such lambdas. However, a lambda can also appear within a template argument, which breaks that workaround.

I really wish for a correct concept implementation in the MS ABI.

Fixes https://github.com/llvm/llvm-project/issues/173160

---
Full diff: https://github.com/llvm/llvm-project/pull/186380.diff


2 Files Affected:

- (modified) clang/lib/Sema/SemaTemplateInstantiateDecl.cpp (+6-14) 
- (modified) clang/test/CodeGenCXX/ms-mangle-requires.cpp (+34) 


``````````diff
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e74c41517ecbf..18a6f199adde6 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -5965,20 +5965,12 @@ void Sema::InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
     savedContext.pop();
   }
 
-  // We never need to emit the code for a lambda in unevaluated context.
-  // We also can't mangle a lambda in the require clause of a function template
-  // during constraint checking as the MSI ABI would need to mangle the (not yet
-  // specialized) enclosing declaration
-  // FIXME: Should we try to skip this for non-lambda functions too?
-  bool ShouldSkipCG = [&] {
-    auto *RD = dyn_cast<CXXRecordDecl>(Function->getParent());
-    if (!RD || !RD->isLambda())
-      return false;
-
-    return llvm::any_of(ExprEvalContexts, [](auto &Context) {
-      return Context.isUnevaluated() || Context.isImmediateFunctionContext();
-    });
-  }();
+  // We never need to emit the code in constriant substitution.
+  // For example, we can't mangle a lambda in the require clause of a function
+  // template during constraint checking as the MS ABI would need to mangle the
+  // (not yet specialized) enclosing declaration.
+  // FIXME: This can be removed when MS ABI supports concepts.
+  bool ShouldSkipCG = inConstraintSubstitution();
   if (!ShouldSkipCG) {
     DeclGroupRef DG(Function);
     Consumer.HandleTopLevelDecl(DG);
diff --git a/clang/test/CodeGenCXX/ms-mangle-requires.cpp b/clang/test/CodeGenCXX/ms-mangle-requires.cpp
index 88c432c54b117..755b151018fcf 100644
--- a/clang/test/CodeGenCXX/ms-mangle-requires.cpp
+++ b/clang/test/CodeGenCXX/ms-mangle-requires.cpp
@@ -69,3 +69,37 @@ void test() {
 }
 // CHECK-LABEL:define {{.*}} void @"??$f@$0CK@@GH147650@@YAXXZ"()
 }
+
+namespace GH173160 {
+
+template< typename TypeList, typename Func >
+auto for_each_type(Func func) {
+  return func;
+}
+
+template< class T >
+struct X {};
+
+template< class T >
+concept Component = requires(T component) {
+  for_each_type<typename T::required_type>( []{} );
+};
+
+struct EntityRegistry {
+  template< Component C >
+  auto get_component(const int id) -> X<C> {
+    return {};
+  }
+};
+
+struct A {
+  struct required_type {};
+};
+
+void foo() {
+  EntityRegistry entities;
+  entities.get_component<A>(0);
+  // CHECK: define {{.*}} @"??$get_component at UA@GH173160@@@EntityRegistry at GH173160@@QEAA?AU?$X at UA@GH173160@@@1 at H@Z"
+}
+
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/186380


More information about the cfe-commits mailing list