[clang] [Clang] Fix dependent expression handling for assumptions (PR #115646)

Younan Zhang via cfe-commits cfe-commits at lists.llvm.org
Sun Nov 10 01:45:18 PST 2024


https://github.com/zyn0217 created https://github.com/llvm/llvm-project/pull/115646

The function definition instantiation assumes any declarations used inside are already transformed before transforming the body, so we need to preserve the transformed expression of CXXAssumeAttr even if it is not a constant expression. Moreover, the full expression of the assumption should also entail a potential lambda capture transformation, hence the call to `ActOnFinishFullExpr()` after `TransformExpr()`

There's still a question as to whether to return an untransformed form of CXXAssumeAttr when any error occurs. It might be worthwhile for better error recovery, but it is also error-prone, especially when multiple passes of instantiation are necessary.

Fixes #114787


>From 2660114ec49f6b9b28153ee8f4b152db42185780 Mon Sep 17 00:00:00 2001
From: Younan Zhang <zyn7109 at gmail.com>
Date: Sun, 10 Nov 2024 17:23:50 +0800
Subject: [PATCH] [Clang] Fix dependent expression handling for assumptions

---
 clang/docs/ReleaseNotes.rst                |  2 ++
 clang/lib/Sema/SemaTemplateInstantiate.cpp | 11 +++++++--
 clang/test/SemaCXX/cxx23-assume.cpp        | 28 ++++++++++++++++++++++
 3 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c3424e0e6f34c9..367576b3a435df 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -652,6 +652,8 @@ Bug Fixes to C++ Support
   an implicitly instantiated class template specialization. (#GH51051)
 - Fixed an assertion failure caused by invalid enum forward declarations. (#GH112208)
 - Name independent data members were not correctly initialized from default member initializers. (#GH114069)
+- Fixed expression transformation for ``[[assume(...)]]``, allowing using pack indexing expressions within the
+  assumption if they also occur inside of a dependent lambda. (#GH114787)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 9e76b60fd509c7..3a3b5984fe740d 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2196,11 +2196,18 @@ TemplateInstantiator::TransformCXXAssumeAttr(const CXXAssumeAttr *AA) {
   if (!Res.isUsable())
     return AA;
 
-  Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(),
-                                     AA->getRange());
+  Res = getSema().ActOnFinishFullExpr(Res.get(),
+                                      /*DiscardedValue=*/false);
   if (!Res.isUsable())
     return AA;
 
+  if (!(Res.get()->getDependence() & ExprDependence::TypeValueInstantiation)) {
+    Res = getSema().BuildCXXAssumeExpr(Res.get(), AA->getAttrName(),
+                                       AA->getRange());
+    if (!Res.isUsable())
+      return AA;
+  }
+
   return CXXAssumeAttr::CreateImplicit(getSema().Context, Res.get(),
                                        AA->getRange());
 }
diff --git a/clang/test/SemaCXX/cxx23-assume.cpp b/clang/test/SemaCXX/cxx23-assume.cpp
index eeae59daea3f70..7f80cdfe7d4523 100644
--- a/clang/test/SemaCXX/cxx23-assume.cpp
+++ b/clang/test/SemaCXX/cxx23-assume.cpp
@@ -2,6 +2,8 @@
 // RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected
 // RUN: %clang_cc1 -std=c++23  -x c++ %s -verify -fexperimental-new-constant-interpreter
 // RUN: %clang_cc1 -std=c++20 -pedantic -x c++ %s -verify=ext,expected -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -std=c++26  -x c++ %s -verify
+// RUN: %clang_cc1 -std=c++26  -x c++ %s -verify -fexperimental-new-constant-interpreter
 
 struct A{};
 struct B{ explicit operator bool() { return true; } };
@@ -167,3 +169,29 @@ int foo () {
     __attribute__((assume (a < b)));
 }
 }
+
+namespace GH114787 {
+
+// FIXME: Correct the C++26 value
+#if __cplusplus >= 202400L
+
+constexpr int test(auto... xs) {
+  // FIXME: Investigate why addresses of PackIndexingExprs are printed for the next
+  // 'in call to' note.
+  return [&]<int I>() { // expected-note {{in call to}}
+    [[assume(
+      xs...[I] == 2
+    )]];
+    [[assume(
+      xs...[I + 1] == 0 // expected-note {{assumption evaluated to false}}
+    )]];
+    return xs...[I];
+  }.template operator()<1>();
+}
+
+static_assert(test(1, 2, 3, 5, 6) == 2); // expected-error {{not an integral constant expression}} \
+                                         // expected-note {{in call to}}
+
+#endif
+
+} // namespace GH114787



More information about the cfe-commits mailing list