[clang] [clang][Interp] Handle std::move etc. builtins (PR #70772)

Timm Baeder via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 2 01:17:58 PDT 2023


Timm =?utf-8?q?Bäder?= <tbaeder at redhat.com>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/70772 at github.com>


https://github.com/tbaederr updated https://github.com/llvm/llvm-project/pull/70772

>From b670986c19e412b3c140b610f2c26d957544b23a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Tue, 31 Oct 2023 07:17:16 +0100
Subject: [PATCH 1/2] [clang][Interp] Handle std::move etc. builtins

---
 clang/lib/AST/Interp/InterpBuiltin.cpp | 17 +++++++++++++++++
 clang/test/AST/Interp/functions.cpp    | 16 ++++++++++++++++
 2 files changed, 33 insertions(+)

diff --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index e329794cb79243d..10e703d868f168a 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -412,6 +412,15 @@ static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
   return true;
 }
 
+static bool interp__builtin_move(InterpState &S, CodePtr OpPC,
+                                 const InterpFrame *Frame, const Function *Func,
+                                 const CallExpr *Call) {
+
+  const Pointer &Arg = S.Stk.peek<Pointer>();
+  S.Stk.push<Pointer>(Arg);
+  return Func->getDecl()->isConstexpr();
+}
+
 bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
                       const CallExpr *Call) {
   InterpFrame *Frame = S.Current;
@@ -537,6 +546,14 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
       return retInt(S, OpPC, Dummy);
     break;
 
+  case Builtin::BIas_const:
+  case Builtin::BIforward:
+  case Builtin::BIforward_like:
+  case Builtin::BImove:
+    if (interp__builtin_move(S, OpPC, Frame, F, Call))
+      return Ret<PT_Ptr>(S, OpPC, Dummy);
+    break;
+
   default:
     return false;
   }
diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp
index 4bef9c2f7c0d1fa..364744203424380 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -371,3 +371,19 @@ namespace Variadic {
   constexpr int (*VFP)(...) = variadic_function2;
   static_assert(VFP() == 12, "");
 }
+
+
+namespace std {
+template <typename T> struct remove_reference { using type = T; };
+template <typename T> struct remove_reference<T &> { using type = T; };
+template <typename T> struct remove_reference<T &&> { using type = T; };
+template <typename T>
+constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept {
+  return static_cast<typename std::remove_reference<T>::type &&>(t);
+}
+}
+/// The std::move declaration above gets translated to a builtin function.
+namespace Move {
+  constexpr int A = std::move(5);
+  static_assert(A == 5, "");
+}

>From 84b0f98a1ab95f49d3f4fe10bb8c2add63e4d55c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbaeder at redhat.com>
Date: Thu, 2 Nov 2023 09:17:41 +0100
Subject: [PATCH 2/2] Add more tests

---
 clang/test/AST/Interp/functions.cpp | 74 +++++++++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp
index 364744203424380..c9a6b348adc0174 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -384,6 +384,80 @@ constexpr typename std::remove_reference<T>::type&& move(T &&t) noexcept {
 }
 /// The std::move declaration above gets translated to a builtin function.
 namespace Move {
+#if __cplusplus >= 202002L
+  consteval int f_eval() { // expected-note 12{{declared here}} \
+                           // ref-note 12{{declared here}}
+    return 0;
+  }
+
+  /// From test/SemaCXX/cxx2a-consteval.
+  struct Copy {
+    int(*ptr)();
+    constexpr Copy(int(*p)() = nullptr) : ptr(p) {}
+    consteval Copy(const Copy&) = default;
+  };
+
+  constexpr const Copy &to_lvalue_ref(const Copy &&a) {
+    return a;
+  }
+
+  void test() {
+    constexpr const Copy C;
+    // there is no the copy constructor call when its argument is a prvalue because of garanteed copy elision.
+    // so we need to test with both prvalue and xvalues.
+    { Copy c(C); }
+    { Copy c((Copy(&f_eval))); } // expected-error {{cannot take address of consteval}} \
+                                 // ref-error {{cannot take address of consteval}}
+    { Copy c(std::move(C)); }
+    { Copy c(std::move(Copy(&f_eval))); } // expected-error {{is not a constant expression}} \
+                                          // expected-note {{to a consteval}} \
+                                          // ref-error {{is not a constant expression}} \
+                                          // ref-note {{to a consteval}}
+    { Copy c(to_lvalue_ref((Copy(&f_eval)))); } // expected-error {{is not a constant expression}} \
+                                                // expected-note {{to a consteval}} \
+                                                // ref-error {{is not a constant expression}} \
+                                                // ref-note {{to a consteval}}
+    { Copy c(to_lvalue_ref(std::move(C))); }
+    { Copy c(to_lvalue_ref(std::move(Copy(&f_eval)))); } // expected-error {{is not a constant expression}} \
+                                                         // expected-note {{to a consteval}} \
+                                                         // ref-error {{is not a constant expression}} \
+                                                         // ref-note {{to a consteval}}
+    { Copy c = Copy(C); }
+    { Copy c = Copy(Copy(&f_eval)); } // expected-error {{cannot take address of consteval}} \
+                                      // ref-error {{cannot take address of consteval}}
+    { Copy c = Copy(std::move(C)); }
+    { Copy c = Copy(std::move(Copy(&f_eval))); } // expected-error {{is not a constant expression}} \
+                                                 // expected-note {{to a consteval}} \
+                                                 // ref-error {{is not a constant expression}} \
+                                                 // ref-note {{to a consteval}}
+    { Copy c = Copy(to_lvalue_ref(Copy(&f_eval))); } // expected-error {{is not a constant expression}} \
+                                                     // expected-note {{to a consteval}} \
+                                                     // ref-error {{is not a constant expression}} \
+                                                     // ref-note {{to a consteval}}
+    { Copy c = Copy(to_lvalue_ref(std::move(C))); }
+    { Copy c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); } // expected-error {{is not a constant expression}} \
+                                                                // expected-note {{to a consteval}} \
+                                                                // ref-error {{is not a constant expression}} \
+                                                                // ref-note {{to a consteval}}
+    { Copy c; c = Copy(C); }
+    { Copy c; c = Copy(Copy(&f_eval)); } // expected-error {{cannot take address of consteval}} \
+                                         // ref-error {{cannot take address of consteval}}
+    { Copy c; c = Copy(std::move(C)); }
+    { Copy c; c = Copy(std::move(Copy(&f_eval))); } // expected-error {{is not a constant expression}} \
+                                                    // expected-note {{to a consteval}} \
+                                                    // ref-error {{is not a constant expression}} \
+                                                    // ref-note {{to a consteval}}
+    { Copy c; c = Copy(to_lvalue_ref(Copy(&f_eval))); } // expected-error {{is not a constant expression}} \
+                                                        // expected-note {{to a consteval}} \
+                                                        // ref-error {{is not a constant expression}} \
+                                                        // ref-note {{to a consteval}}
+    { Copy c; c = Copy(to_lvalue_ref(std::move(C))); }
+    { Copy c; c = Copy(to_lvalue_ref(std::move(Copy(&f_eval)))); } // expected-error {{is not a constant expression}} \
+                                                                   // expected-note {{to a consteval}} \
+                                                                   // ref-error {{is not a constant expression}} \
+                                                                   // ref-note {{to a consteval}}
+  }
+#endif
   constexpr int A = std::move(5);
   static_assert(A == 5, "");
 }



More information about the cfe-commits mailing list