summaryrefslogtreecommitdiff
path: root/test/SemaCXX/builtins.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaCXX/builtins.cpp')
-rw-r--r--test/SemaCXX/builtins.cpp92
1 files changed, 92 insertions, 0 deletions
diff --git a/test/SemaCXX/builtins.cpp b/test/SemaCXX/builtins.cpp
index f26931b55bdb0..fbe2c457dad97 100644
--- a/test/SemaCXX/builtins.cpp
+++ b/test/SemaCXX/builtins.cpp
@@ -53,3 +53,95 @@ extern "C" int vfprintf(FILE *__restrict, const char *__restrict,
void synchronize_args() {
__sync_synchronize(0); // expected-error {{too many arguments}}
}
+
+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); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(cvp); // expected-error {{void pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(fnp); // expected-error {{function pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(mfp); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(cmfp); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ (void)__builtin_launder(&fnp);
+ __builtin_launder(42); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(nullptr); // expected-error {{non-pointer argument to '__builtin_launder' is not allowed}}
+ __builtin_launder(foo); // expected-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); // expected-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); // expected-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; // expected-note {{declared here}}
+ constexpr const int *ip = __builtin_launder(&i); // expected-error {{constexpr variable 'ip' must be initialized by a constant expression}}
+ // expected-note@-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; // expected-note {{forward declaration}}
+struct IncompleteMember {
+ Incomplete &i;
+};
+void test_incomplete(Incomplete *i, IncompleteMember *im) {
+ // expected-error@+1 {{incomplete type 'test_launder::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