================
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -triple 
x86_64-unknown-unknown %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -triple 
x86_64-unknown-unknown %s -fexperimental-new-constant-interpreter
+
+constexpr int arr[10] = {};
+
+constexpr bool test_constexpr_valid() {
+  __builtin_assume_dereferenceable(arr, 40);
+  return true;
+}
+static_assert(test_constexpr_valid(), "");
+
+constexpr bool test_constexpr_partial() {
+  __builtin_assume_dereferenceable(&arr[5], 20);
+  return true;
+}
+static_assert(test_constexpr_partial(), "");
+
+constexpr bool test_constexpr_nullptr() {
+  __builtin_assume_dereferenceable(nullptr, 4);
+  return true;
+}
+static_assert(test_constexpr_nullptr(), ""); // expected-error {{not an 
integral constant expression}}
+
+constexpr bool test_constexpr_too_large() {
+  __builtin_assume_dereferenceable(arr, 100);
+  return true;
+}
+static_assert(test_constexpr_too_large(), ""); // expected-error {{not an 
integral constant expression}}
+
+constexpr int single_var = 42;
+constexpr bool test_single_var() {
+  __builtin_assume_dereferenceable(&single_var, 4);
+  return true;
+}
+static_assert(test_single_var(), "");
+
+constexpr bool test_exact_boundary() {
+  __builtin_assume_dereferenceable(&arr[9], 4);
+  return true;
+}
+static_assert(test_exact_boundary(), "");
+
+constexpr bool test_one_over() {
+  __builtin_assume_dereferenceable(&arr[9], 5);
+  return true;
+}
+static_assert(test_one_over(), ""); // expected-error {{not an integral 
constant expression}}
+
+constexpr bool test_zero_size() {
+  __builtin_assume_dereferenceable(arr, 0);
+  return true;
+}
+static_assert(test_zero_size(), ""); // expected-error {{not an integral 
constant expression}}
+
+struct S {
+  int x;
+  int y;
+};
+constexpr S s = {1, 2};
+constexpr bool test_struct_member() {
+  __builtin_assume_dereferenceable(&s.x, 4);
+  return true;
+}
+static_assert(test_struct_member(), "");
----------------
philnik777 wrote:

It would be a valid implementation to just ignore the builtin I guess, but I'd 
be much happier if it actually checked that bytes are dereferenceable. That's 
quite useful to catch problems in loops that can return early. e.g. `find_if` 
requires the whole range to be dereferenceable, but may never actually reach 
the end of the data. The compiler is still allowed to read past the element 
that is returned, resulting potentially in crashes.

In general my goal is to catch all the UB possible during constant evaluation 
that the compiler can optimize on. With `__builtin_assume_dereferenceable` we 
currently can produce a program which, with identical inputs, is accepted 
during constant evaluation by the compiler but crashes during runtime. I'm 
aware of some other places this is the case, but I'd rather reduce that number, 
not increase it.

I'm not quite sure what you're asking in your example. It's not a constant 
expression at this point, is it?

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

Reply via email to