https://github.com/brunodf-snps created 
https://github.com/llvm/llvm-project/pull/172289

In cases where multiple template instations occur (e.g. with a generic lambda), 
the loop hint argument expression may still be value dependent. (It is also not 
needed to do the constant evaluation when the loop hint is not an unroll count 
anyway.)

>From 0e2ed4b9b2ffe0763c0de82cb688636490e10cbe Mon Sep 17 00:00:00 2001
From: Bruno De Fraine <[email protected]>
Date: Mon, 15 Dec 2025 11:43:13 +0100
Subject: [PATCH] [clang] Fix TemplateInstantiator crash transforming loop hint
 argument

In cases where multiple template instations occur (e.g. with a generic
lambda), the loop hint argument expression may still be value dependent.
(It is also not needed to do the constant evaluation when the loop hint
is not an unroll count anyway.)
---
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 18 +++++++------
 .../test/Sema/unroll-template-value-crash.cpp | 25 +++++++++++++++++++
 2 files changed, 36 insertions(+), 7 deletions(-)

diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 35205f40cbcef..dcbedb2c2ee22 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2197,19 +2197,23 @@ TemplateInstantiator::TransformLoopHintAttr(const 
LoopHintAttr *LH) {
 
   // Generate error if there is a problem with the value.
   if (getSema().CheckLoopHintExpr(TransformedExpr, LH->getLocation(),
-                                  LH->getSemanticSpelling() ==
+                                  /*AllowZero=*/LH->getSemanticSpelling() ==
                                       LoopHintAttr::Pragma_unroll))
     return LH;
 
   LoopHintAttr::OptionType Option = LH->getOption();
   LoopHintAttr::LoopHintState State = LH->getState();
 
-  llvm::APSInt ValueAPS =
-      TransformedExpr->EvaluateKnownConstInt(getSema().getASTContext());
-  // The values of 0 and 1 block any unrolling of the loop.
-  if (ValueAPS.isZero() || ValueAPS.isOne()) {
-    Option = LoopHintAttr::Unroll;
-    State = LoopHintAttr::Disable;
+  if (Option == LoopHintAttr::UnrollCount &&
+      !TransformedExpr->isValueDependent()) {
+    llvm::APSInt ValueAPS =
+        TransformedExpr->EvaluateKnownConstInt(getSema().getASTContext());
+    // The values of 0 and 1 block any unrolling of the loop (also see
+    // handleLoopHintAttr in SemaStmtAttr).
+    if (ValueAPS.isZero() || ValueAPS.isOne()) {
+      Option = LoopHintAttr::Unroll;
+      State = LoopHintAttr::Disable;
+    }
   }
 
   // Create new LoopHintValueAttr with integral expression in place of the
diff --git a/clang/test/Sema/unroll-template-value-crash.cpp 
b/clang/test/Sema/unroll-template-value-crash.cpp
index d8953c4845c26..cda4b897509b9 100644
--- a/clang/test/Sema/unroll-template-value-crash.cpp
+++ b/clang/test/Sema/unroll-template-value-crash.cpp
@@ -8,3 +8,28 @@ template <int Unroll> void foo() {
   #pragma GCC unroll Unroll
   for (int i = 0; i < Unroll; ++i);
 }
+
+struct val {
+  constexpr operator int() const { return 1; }
+};
+
+// generic lambda (using double template instantiation)
+
+template<typename T>
+void use(T t) {
+  auto lam = [](auto N) {
+    #pragma clang loop unroll_count(N+1)
+    for (int i = 0; i < 10; ++i);
+
+    #pragma unroll N+1
+    for (int i = 0; i < 10; ++i);
+
+    #pragma GCC unroll N+1
+    for (int i = 0; i < 10; ++i);
+  };
+  lam(t);
+}
+
+void test() {
+  use(val());
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to