[clang] 6728207 - [clang][Interp] Implement __builtin_launder

Timm Bäder via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 15 23:08:55 PST 2024


Author: Timm Bäder
Date: 2024-02-16T08:08:42+01:00
New Revision: 67282077ea460cbeec3f837b1a448a1bc958ec10

URL: https://github.com/llvm/llvm-project/commit/67282077ea460cbeec3f837b1a448a1bc958ec10
DIFF: https://github.com/llvm/llvm-project/commit/67282077ea460cbeec3f837b1a448a1bc958ec10.diff

LOG: [clang][Interp] Implement __builtin_launder

Just forward the pointer.
Copy tests from SemaCXX

Added: 
    

Modified: 
    clang/lib/AST/Interp/InterpBuiltin.cpp
    clang/test/AST/Interp/builtin-functions.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/InterpBuiltin.cpp b/clang/lib/AST/Interp/InterpBuiltin.cpp
index 8f76b51ac03348..9b3f70fef35998 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -658,6 +658,15 @@ static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,
   return true;
 }
 
+static bool interp__builtin_launder(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 true;
+}
+
 bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
                       const CallExpr *Call) {
   InterpFrame *Frame = S.Current;
@@ -887,6 +896,11 @@ bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
       return false;
     break;
 
+  case Builtin::BI__builtin_launder:
+    if (!interp__builtin_launder(S, OpPC, Frame, F, Call))
+      return false;
+    break;
+
   default:
     return false;
   }

diff  --git a/clang/test/AST/Interp/builtin-functions.cpp b/clang/test/AST/Interp/builtin-functions.cpp
index 3aa01d501a3e2a..cbcfe7d5374d1a 100644
--- a/clang/test/AST/Interp/builtin-functions.cpp
+++ b/clang/test/AST/Interp/builtin-functions.cpp
@@ -351,3 +351,96 @@ namespace EhReturnDataRegno {
     __builtin_eh_return_data_regno(X);  // both-error {{argument to '__builtin_eh_return_data_regno' must be a constant integer}}
   }
 }
+
+/// From test/SemaCXX/builtins.cpp
+namespace test_launder {
+#define TEST_TYPE(Ptr, Type) \
+  static_assert(__is_same(decltype(__builtin_launder(Ptr)), Type), "expected same type")
+
+struct Dummy {};
+
+using FnType = int(char);
+using MemFnType = int (Dummy::*)(char);
+using ConstMemFnType = int (Dummy::*)() const;
+
+void foo() {}
+
+void test_builtin_launder_diags(void *vp, const void *cvp, FnType *fnp,
+                                MemFnType mfp, ConstMemFnType cmfp, int (&Arr)[5]) {
+  __builtin_launder(vp);   // both-error {{void pointer argument to '__builtin_launder' is not allowed}}
+  __builtin_launder(cvp);  // both-error {{void pointer argument to '__builtin_launder' is not allowed}}
+  __builtin_launder(fnp);  // both-error {{function pointer argument to '__builtin_launder' is not allowed}}
+  __builtin_launder(mfp);  // both-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+  __builtin_launder(cmfp); // both-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+  (void)__builtin_launder(&fnp);
+  __builtin_launder(42);      // both-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+  __builtin_launder(nullptr); // both-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+  __builtin_launder(foo);     // both-error {{function pointer argument to '__builtin_launder' is not allowed}}
+  (void)__builtin_launder(Arr);
+}
+
+void test_builtin_launder(char *p, const volatile int *ip, const float *&fp,
+                          double *__restrict dp) {
+  int x;
+  __builtin_launder(x); // both-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+
+  TEST_TYPE(p, char*);
+  TEST_TYPE(ip, const volatile int*);
+  TEST_TYPE(fp, const float*);
+  TEST_TYPE(dp, double *__restrict);
+
+  char *d = __builtin_launder(p);
+  const volatile int *id = __builtin_launder(ip);
+  int *id2 = __builtin_launder(ip); // both-error {{cannot initialize a variable of type 'int *' with an rvalue of type 'const volatile int *'}}
+  const float* fd = __builtin_launder(fp);
+}
+
+void test_launder_return_type(const int (&ArrayRef)[101], int (&MArrRef)[42][13],
+                              void (**&FuncPtrRef)()) {
+  TEST_TYPE(ArrayRef, const int *);
+  TEST_TYPE(MArrRef, int(*)[13]);
+  TEST_TYPE(FuncPtrRef, void (**)());
+}
+
+template <class Tp>
+constexpr Tp *test_constexpr_launder(Tp *tp) {
+  return __builtin_launder(tp);
+}
+constexpr int const_int = 42;
+constexpr int const_int2 = 101;
+constexpr const int *const_ptr = test_constexpr_launder(&const_int);
+static_assert(&const_int == const_ptr, "");
+static_assert(const_ptr != test_constexpr_launder(&const_int2), "");
+
+void test_non_constexpr() {
+  constexpr int i = 42;                            // both-note {{address of non-static constexpr variable 'i' may 
diff er on each invocation}}
+  constexpr const int *ip = __builtin_launder(&i); // both-error {{constexpr variable 'ip' must be initialized by a constant expression}}
+  // both-note at -1 {{pointer to 'i' is not a constant expression}}
+}
+
+constexpr bool test_in_constexpr(const int &i) {
+  return (__builtin_launder(&i) == &i);
+}
+
+static_assert(test_in_constexpr(const_int), "");
+void f() {
+  constexpr int i = 42;
+  static_assert(test_in_constexpr(i), "");
+}
+
+struct Incomplete; // both-note {{forward declaration}}
+struct IncompleteMember {
+  Incomplete &i;
+};
+void test_incomplete(Incomplete *i, IncompleteMember *im) {
+  // both-error at +1 {{incomplete type 'Incomplete' where a complete type is required}}
+  __builtin_launder(i);
+  __builtin_launder(&i); // OK
+  __builtin_launder(im); // OK
+}
+
+void test_noexcept(int *i) {
+  static_assert(noexcept(__builtin_launder(i)), "");
+}
+#undef TEST_TYPE
+} // end namespace test_launder


        


More information about the cfe-commits mailing list