summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-10-21 02:36:37 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-10-21 02:36:37 +0000
commitc1d70e9b5c41fdb4c565638715a03a83503b7fae (patch)
tree52b37e45f32574e456b1eb30797a4939c33ec6fa /test
parent647ac262003d853d8b431ed6ca7dbeff61678cd7 (diff)
DR583, DR1512: Implement a rewrite to C++'s 'composite pointer type' rules.
This has two significant effects: 1) Direct relational comparisons between null pointer constants (0 and nullopt) and pointers are now ill-formed. This was always the case for C, and it appears that C++ only ever permitted by accident. For instance, cases like nullptr < &a are now rejected. 2) Comparisons and conditional operators between differently-cv-qualified pointer types now work, and produce a composite type that both source pointer types can convert to (when possible). For instance, comparison between 'int **' and 'const int **' is now valid, and uses an intermediate type of 'const int *const *'. Clang previously supported #2 as an extension. We do not accept the cases in #1 as an extension. I've tested a fair amount of code to check that this doesn't break it, but if it turns out that someone is relying on this, we can easily add it back as an extension. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@284800 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test')
-rw-r--r--test/CXX/drs/dr15xx.cpp132
-rw-r--r--test/CXX/drs/dr5xx.cpp11
-rw-r--r--test/CXX/expr/expr.const/p2-0x.cpp18
-rw-r--r--test/CXX/over/over.built/p15.cpp83
-rw-r--r--test/CXX/over/over.built/p16.cpp75
-rw-r--r--test/Misc/warning-flags.c3
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/distribute_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/parallel_for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/target_parallel_for_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/target_simd_aligned_messages.cpp3
-rw-r--r--test/OpenMP/taskloop_simd_aligned_messages.cpp3
-rw-r--r--test/SemaCXX/compare.cpp3
-rw-r--r--test/SemaCXX/composite-pointer-type.cpp4
-rw-r--r--test/SemaCXX/constant-expression-cxx11.cpp16
-rw-r--r--test/SemaCXX/libstdcxx_libcxx_less_hack.cpp67
-rw-r--r--test/SemaCXX/null_in_arithmetic_ops.cpp4
-rw-r--r--test/SemaCXX/nullptr.cpp46
-rw-r--r--test/SemaCXX/nullptr_in_arithmetic_ops.cpp8
-rw-r--r--test/SemaCXX/warn-memsize-comparison.cpp8
-rw-r--r--test/SemaObjCXX/null_objc_pointer.mm5
23 files changed, 434 insertions, 73 deletions
diff --git a/test/CXX/drs/dr15xx.cpp b/test/CXX/drs/dr15xx.cpp
index 5f85a196fd..2b4c900c76 100644
--- a/test/CXX/drs/dr15xx.cpp
+++ b/test/CXX/drs/dr15xx.cpp
@@ -3,9 +3,137 @@
// RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
// RUN: %clang_cc1 -std=c++1z -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
-#if __cplusplus < 201103L
-// expected-no-diagnostics
+namespace dr1512 { // dr1512: 4.0
+ void f(char *p) {
+ if (p > 0) {} // expected-error {{ordered comparison between pointer and zero}}
+#if __cplusplus >= 201103L
+ if (p > nullptr) {} // expected-error {{invalid operands}}
#endif
+ }
+ bool g(int **x, const int **y) {
+ return x < y;
+ }
+
+ template<typename T> T val();
+
+ template<typename A, typename B, typename C> void composite_pointer_type_is_base() {
+ typedef __typeof(true ? val<A>() : val<B>()) type;
+ typedef C type;
+
+ typedef __typeof(val<A>() == val<B>()) cmp;
+ typedef __typeof(val<A>() != val<B>()) cmp;
+ typedef bool cmp;
+ }
+
+ template<typename A, typename B, typename C> void composite_pointer_type_is_ord() {
+ composite_pointer_type_is_base<A, B, C>();
+
+ typedef __typeof(val<A>() < val<B>()) cmp;
+ typedef __typeof(val<A>() <= val<B>()) cmp;
+ typedef __typeof(val<A>() > val<B>()) cmp;
+ typedef __typeof(val<A>() >= val<B>()) cmp;
+ typedef bool cmp;
+ }
+
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(int = 0) {
+ composite_pointer_type_is_base<A, B, C>();
+ }
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() < val<B>()) * = 0);
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() <= val<B>()) * = 0);
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() > val<B>()) * = 0);
+ template <typename A, typename B, typename C>
+ void composite_pointer_type_is_unord(__typeof(val<A>() >= val<B>()) * = 0);
+
+ // A call to this is ambiguous if a composite pointer type exists.
+ template<typename A, typename B>
+ void no_composite_pointer_type(__typeof((true ? val<A>() : val<B>()), void()) * = 0);
+ template<typename A, typename B> void no_composite_pointer_type(int = 0);
+
+ struct A {};
+ struct B : A {};
+ struct C {};
+
+ void test() {
+#if __cplusplus >= 201103L
+ using nullptr_t = decltype(nullptr);
+ composite_pointer_type_is_unord<nullptr_t, nullptr_t, nullptr_t>();
+ no_composite_pointer_type<nullptr_t, int>();
+
+ composite_pointer_type_is_unord<nullptr_t, const char**, const char**>();
+ composite_pointer_type_is_unord<const char**, nullptr_t, const char**>();
+#endif
+
+ composite_pointer_type_is_ord<const int *, volatile void *, const volatile void*>();
+ composite_pointer_type_is_ord<const void *, volatile int *, const volatile void*>();
+
+ composite_pointer_type_is_ord<const A*, volatile B*, const volatile A*>();
+ composite_pointer_type_is_ord<const B*, volatile A*, const volatile A*>();
+
+ composite_pointer_type_is_unord<const int *A::*, volatile int *B::*, const volatile int *const B::*>();
+ composite_pointer_type_is_unord<const int *B::*, volatile int *A::*, const volatile int *const B::*>();
+ no_composite_pointer_type<int (A::*)(), int (C::*)()>();
+ no_composite_pointer_type<const int (A::*)(), volatile int (C::*)()>();
+
+#if __cplusplus > 201402
+ composite_pointer_type_is_ord<int (*)() noexcept, int (*)(), int (*)()>();
+ composite_pointer_type_is_ord<int (*)(), int (*)() noexcept, int (*)()>();
+ composite_pointer_type_is_unord<int (A::*)() noexcept, int (A::*)(), int (A::*)()>();
+ composite_pointer_type_is_unord<int (A::*)(), int (A::*)() noexcept, int (A::*)()>();
+ // FIXME: This looks like a standard defect; these should probably all have type 'int (B::*)()'.
+ composite_pointer_type_is_unord<int (B::*)(), int (A::*)() noexcept, int (B::*)()>();
+ composite_pointer_type_is_unord<int (A::*)() noexcept, int (B::*)(), int (B::*)()>();
+ composite_pointer_type_is_unord<int (B::*)() noexcept, int (A::*)(), int (B::*)()>();
+ composite_pointer_type_is_unord<int (A::*)(), int (B::*)() noexcept, int (B::*)()>();
+
+ // FIXME: It would be reasonable to permit these, with a common type of 'int (*const *)()'.
+ no_composite_pointer_type<int (**)() noexcept, int (**)()>();
+ no_composite_pointer_type<int (**)(), int (**)() noexcept>();
+
+ // FIXME: It would be reasonable to permit these, with a common type of 'int (A::*)()'.
+ no_composite_pointer_type<int (A::*)() const, int (A::*)()>();
+ no_composite_pointer_type<int (A::*)(), int (A::*)() const>();
+
+ // FIXME: It would be reasonable to permit these, with a common type of
+ // 'int (A::*)() &' and 'int (A::*)() &&', respectively.
+ no_composite_pointer_type<int (A::*)() &, int (A::*)()>();
+ no_composite_pointer_type<int (A::*)(), int (A::*)() &>();
+ no_composite_pointer_type<int (A::*)() &&, int (A::*)()>();
+ no_composite_pointer_type<int (A::*)(), int (A::*)() &&>();
+
+ no_composite_pointer_type<int (A::*)() &&, int (A::*)() &>();
+ no_composite_pointer_type<int (A::*)() &, int (A::*)() &&>();
+
+ no_composite_pointer_type<int (C::*)(), int (A::*)() noexcept>();
+ no_composite_pointer_type<int (A::*)() noexcept, int (C::*)()>();
+#endif
+ }
+
+ template<typename T> struct Wrap { operator T(); };
+ void test_overload() {
+#if __cplusplus >= 201103L
+ using nullptr_t = decltype(nullptr);
+ void(Wrap<nullptr_t>() == Wrap<nullptr_t>());
+ void(Wrap<nullptr_t>() != Wrap<nullptr_t>());
+ void(Wrap<nullptr_t>() < Wrap<nullptr_t>()); // expected-error {{invalid operands}}
+ void(Wrap<nullptr_t>() > Wrap<nullptr_t>()); // expected-error {{invalid operands}}
+ void(Wrap<nullptr_t>() <= Wrap<nullptr_t>()); // expected-error {{invalid operands}}
+ void(Wrap<nullptr_t>() >= Wrap<nullptr_t>()); // expected-error {{invalid operands}}
+
+ // The wording change fails to actually disallow this. This is valid
+ // via the builtin operator<(int*, int*) etc.
+ void(Wrap<nullptr_t>() == Wrap<int*>());
+ void(Wrap<nullptr_t>() != Wrap<int*>());
+ void(Wrap<nullptr_t>() < Wrap<int*>());
+ void(Wrap<nullptr_t>() > Wrap<int*>());
+ void(Wrap<nullptr_t>() <= Wrap<int*>());
+ void(Wrap<nullptr_t>() >= Wrap<int*>());
+#endif
+ }
+}
namespace dr1550 { // dr1550: yes
int f(bool b, int n) {
diff --git a/test/CXX/drs/dr5xx.cpp b/test/CXX/drs/dr5xx.cpp
index 6461712cf0..9bac700579 100644
--- a/test/CXX/drs/dr5xx.cpp
+++ b/test/CXX/drs/dr5xx.cpp
@@ -863,14 +863,13 @@ namespace dr580 { // dr580: partial
// dr582: na
-namespace dr583 { // dr583: no
+namespace dr583 { // dr583: 4.0
// see n3624
int *p;
- // FIXME: These are all ill-formed.
- bool b1 = p < 0;
- bool b2 = p > 0;
- bool b3 = p <= 0;
- bool b4 = p >= 0;
+ bool b1 = p < 0; // expected-error {{ordered comparison between pointer and zero}}
+ bool b2 = p > 0; // expected-error {{ordered comparison between pointer and zero}}
+ bool b3 = p <= 0; // expected-error {{ordered comparison between pointer and zero}}
+ bool b4 = p >= 0; // expected-error {{ordered comparison between pointer and zero}}
}
// dr584: na
diff --git a/test/CXX/expr/expr.const/p2-0x.cpp b/test/CXX/expr/expr.const/p2-0x.cpp
index fd15960647..b9927e49c7 100644
--- a/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/test/CXX/expr/expr.const/p2-0x.cpp
@@ -461,14 +461,14 @@ namespace UnspecifiedRelations {
constexpr bool u2 = p > q; // expected-error {{constant expression}}
constexpr bool u3 = p <= q; // expected-error {{constant expression}}
constexpr bool u4 = p >= q; // expected-error {{constant expression}}
- constexpr bool u5 = p < 0; // expected-error {{constant expression}}
- constexpr bool u6 = p <= 0; // expected-error {{constant expression}}
- constexpr bool u7 = p > 0; // expected-error {{constant expression}}
- constexpr bool u8 = p >= 0; // expected-error {{constant expression}}
- constexpr bool u9 = 0 < q; // expected-error {{constant expression}}
- constexpr bool u10 = 0 <= q; // expected-error {{constant expression}}
- constexpr bool u11 = 0 > q; // expected-error {{constant expression}}
- constexpr bool u12 = 0 >= q; // expected-error {{constant expression}}
+ constexpr bool u5 = p < (int*)0; // expected-error {{constant expression}}
+ constexpr bool u6 = p <= (int*)0; // expected-error {{constant expression}}
+ constexpr bool u7 = p > (int*)0; // expected-error {{constant expression}}
+ constexpr bool u8 = p >= (int*)0; // expected-error {{constant expression}}
+ constexpr bool u9 = (int*)0 < q; // expected-error {{constant expression}}
+ constexpr bool u10 = (int*)0 <= q; // expected-error {{constant expression}}
+ constexpr bool u11 = (int*)0 > q; // expected-error {{constant expression}}
+ constexpr bool u12 = (int*)0 >= q; // expected-error {{constant expression}}
void f(), g();
constexpr void (*pf)() = &f, (*pg)() = &g;
@@ -522,7 +522,7 @@ namespace UnspecifiedRelations {
constexpr void *null = 0;
constexpr void *pv = (void*)&s.a;
constexpr void *qv = (void*)&s.b;
- constexpr bool v1 = null < 0;
+ constexpr bool v1 = null < (int*)0;
constexpr bool v2 = null < pv; // expected-error {{constant expression}}
constexpr bool v3 = null == pv; // ok
constexpr bool v4 = qv == pv; // ok
diff --git a/test/CXX/over/over.built/p15.cpp b/test/CXX/over/over.built/p15.cpp
new file mode 100644
index 0000000000..64ed3e7b83
--- /dev/null
+++ b/test/CXX/over/over.built/p15.cpp
@@ -0,0 +1,83 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
+
+struct A { operator decltype(nullptr)(); };
+struct B { operator const int *(); };
+void f(A a, B b, volatile int *pi) {
+ (void)(a == a);
+ (void)(a != a);
+ (void)(a < a); // expected-error {{invalid operands}}
+ (void)(a > a); // expected-error {{invalid operands}}
+ (void)(a <= a); // expected-error {{invalid operands}}
+ (void)(a >= a); // expected-error {{invalid operands}}
+
+ (void)(a == b);
+ (void)(a != b);
+ // FIXME: These cases were intended to be made ill-formed by N3624, but it
+ // fails to actually achieve this goal.
+ (void)(a < b);
+ (void)(a > b);
+ (void)(a <= b);
+ (void)(a >= b);
+
+ (void)(b == a);
+ (void)(b != a);
+ // FIXME: These cases were intended to be made ill-formed by N3624, but it
+ // fails to actually achieve this goal.
+ (void)(b < a);
+ (void)(b > a);
+ (void)(b <= a);
+ (void)(b >= a);
+
+ (void)(a == pi);
+ (void)(a != pi);
+ // FIXME: These cases were intended to be made ill-formed by N3624, but it
+ // fails to actually achieve this goal.
+ (void)(a < pi);
+ (void)(a > pi);
+ (void)(a <= pi);
+ (void)(a >= pi);
+
+ (void)(pi == a);
+ (void)(pi != a);
+ // FIXME: These cases were intended to be made ill-formed by N3624, but it
+ // fails to actually achieve this goal.
+ (void)(pi < a);
+ (void)(pi > a);
+ (void)(pi <= a);
+ (void)(pi >= a);
+
+ (void)(b == pi);
+ (void)(b != pi);
+ (void)(b < pi);
+ (void)(b > pi);
+ (void)(b <= pi);
+ (void)(b >= pi);
+
+ (void)(pi == b);
+ (void)(pi != b);
+ (void)(pi < b);
+ (void)(pi > b);
+ (void)(pi <= b);
+ (void)(pi >= b);
+
+ (void)(b == b);
+ (void)(b != b);
+ (void)(b < b);
+ (void)(b > b);
+ (void)(b <= b);
+ (void)(b >= b);
+
+ (void)(pi == pi);
+ (void)(pi != pi);
+ (void)(pi < pi);
+ (void)(pi > pi);
+ (void)(pi <= pi);
+ (void)(pi >= pi);
+}
+
+// FIXME: This is wrong: the type T = 'const volatile int * const * const *'
+// would work here, and there exists a builtin candidate for that type.
+struct C { operator const int ***(); };
+void g(C c, volatile int ***p) {
+ (void)(c < p); // expected-error {{invalid operands}}
+}
diff --git a/test/CXX/over/over.built/p16.cpp b/test/CXX/over/over.built/p16.cpp
new file mode 100644
index 0000000000..139e864475
--- /dev/null
+++ b/test/CXX/over/over.built/p16.cpp
@@ -0,0 +1,75 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
+
+struct A { operator decltype(nullptr)(); };
+struct B { operator int A::*(); };
+void f(A a, B b, int A::*pi) {
+ (void)(a == a);
+ (void)(a != a);
+ (void)(a < a); // expected-error {{invalid operands}}
+ (void)(a > a); // expected-error {{invalid operands}}
+ (void)(a <= a); // expected-error {{invalid operands}}
+ (void)(a >= a); // expected-error {{invalid operands}}
+
+ (void)(a == b);
+ (void)(a != b);
+ (void)(a < b); // expected-error {{invalid operands}}
+ (void)(a > b); // expected-error {{invalid operands}}
+ (void)(a <= b); // expected-error {{invalid operands}}
+ (void)(a >= b); // expected-error {{invalid operands}}
+
+ (void)(b == a);
+ (void)(b != a);
+ (void)(b < a); // expected-error {{invalid operands}}
+ (void)(b > a); // expected-error {{invalid operands}}
+ (void)(b <= a); // expected-error {{invalid operands}}
+ (void)(b >= a); // expected-error {{invalid operands}}
+
+ (void)(a == pi);
+ (void)(a != pi);
+ (void)(a < pi); // expected-error {{invalid operands}}
+ (void)(a > pi); // expected-error {{invalid operands}}
+ (void)(a <= pi); // expected-error {{invalid operands}}
+ (void)(a >= pi); // expected-error {{invalid operands}}
+
+ (void)(pi == a);
+ (void)(pi != a);
+ (void)(pi < a); // expected-error {{invalid operands}}
+ (void)(pi > a); // expected-error {{invalid operands}}
+ (void)(pi <= a); // expected-error {{invalid operands}}
+ (void)(pi >= a); // expected-error {{invalid operands}}
+
+ (void)(b == pi);
+ (void)(b != pi);
+ (void)(b < pi); // expected-error {{invalid operands}}
+ (void)(b > pi); // expected-error {{invalid operands}}
+ (void)(b <= pi); // expected-error {{invalid operands}}
+ (void)(b >= pi); // expected-error {{invalid operands}}
+
+ (void)(pi == b);
+ (void)(pi != b);
+ (void)(pi < b); // expected-error {{invalid operands}}
+ (void)(pi > b); // expected-error {{invalid operands}}
+ (void)(pi <= b); // expected-error {{invalid operands}}
+ (void)(pi >= b); // expected-error {{invalid operands}}
+
+ (void)(b == b);
+ (void)(b != b);
+ (void)(b < b); // expected-error {{invalid operands}}
+ (void)(b > b); // expected-error {{invalid operands}}
+ (void)(b <= b); // expected-error {{invalid operands}}
+ (void)(b >= b); // expected-error {{invalid operands}}
+
+ (void)(pi == pi);
+ (void)(pi != pi);
+ (void)(pi < pi); // expected-error {{invalid operands}}
+ (void)(pi > pi); // expected-error {{invalid operands}}
+ (void)(pi <= pi); // expected-error {{invalid operands}}
+ (void)(pi >= pi); // expected-error {{invalid operands}}
+}
+
+// FIXME: This is wrong: type T = 'const volatile int * const A::* const B::*'
+// would work here, and there exists a builtin candidate for that type.
+struct C { operator const int *A::*B::*(); };
+void g(C c, volatile int *A::*B::*p) {
+ (void)(c == p); // expected-error {{invalid operands}}
+}
diff --git a/test/Misc/warning-flags.c b/test/Misc/warning-flags.c
index 69e820542a..18222986e6 100644
--- a/test/Misc/warning-flags.c
+++ b/test/Misc/warning-flags.c
@@ -18,7 +18,7 @@ This test serves two purposes:
The list of warnings below should NEVER grow. It should gradually shrink to 0.
-CHECK: Warnings without flags (84):
+CHECK: Warnings without flags (83):
CHECK-NEXT: ext_excess_initializers
CHECK-NEXT: ext_excess_initializers_in_char_array_initializer
CHECK-NEXT: ext_expected_semi_decl_list
@@ -31,7 +31,6 @@ CHECK-NEXT: ext_plain_complex
CHECK-NEXT: ext_template_arg_extra_parens
CHECK-NEXT: ext_typecheck_comparison_of_pointer_integer
CHECK-NEXT: ext_typecheck_cond_incompatible_operands
-CHECK-NEXT: ext_typecheck_cond_incompatible_operands_nonstandard
CHECK-NEXT: ext_typecheck_ordered_comparison_of_function_pointers
CHECK-NEXT: ext_typecheck_ordered_comparison_of_pointer_integer
CHECK-NEXT: ext_using_undefined_std
diff --git a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
index 9c9f3dda28..f865e0be42 100644
--- a/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_aligned_messages.cpp
@@ -166,7 +166,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute parallel for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+#pragma omp distribute parallel for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/distribute_simd_aligned_messages.cpp b/test/OpenMP/distribute_simd_aligned_messages.cpp
index 59e5be271d..10beb7198a 100644
--- a/test/OpenMP/distribute_simd_aligned_messages.cpp
+++ b/test/OpenMP/distribute_simd_aligned_messages.cpp
@@ -166,7 +166,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
#pragma omp target
#pragma omp teams
-#pragma omp distribute simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+#pragma omp distribute simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target
diff --git a/test/OpenMP/for_simd_aligned_messages.cpp b/test/OpenMP/for_simd_aligned_messages.cpp
index cef83c30e2..1d0918e449 100644
--- a/test/OpenMP/for_simd_aligned_messages.cpp
+++ b/test/OpenMP/for_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/parallel_for_simd_aligned_messages.cpp b/test/OpenMP/parallel_for_simd_aligned_messages.cpp
index 2ccdf06976..fc0f88cc38 100644
--- a/test/OpenMP/parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp parallel for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp parallel for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp parallel for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp parallel for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/simd_aligned_messages.cpp b/test/OpenMP/simd_aligned_messages.cpp
index 9515a0bca6..81aec960f2 100644
--- a/test/OpenMP/simd_aligned_messages.cpp
+++ b/test/OpenMP/simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp b/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
index 669cafeae1..538d65b82b 100644
--- a/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target parallel for simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp target parallel for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp target parallel for simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target parallel for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/target_simd_aligned_messages.cpp b/test/OpenMP/target_simd_aligned_messages.cpp
index 547f3b41fb..ae2859d5b6 100644
--- a/test/OpenMP/target_simd_aligned_messages.cpp
+++ b/test/OpenMP/target_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp target simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp target simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp target simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/OpenMP/taskloop_simd_aligned_messages.cpp b/test/OpenMP/taskloop_simd_aligned_messages.cpp
index b45f44fe1c..6085660b70 100644
--- a/test/OpenMP/taskloop_simd_aligned_messages.cpp
+++ b/test/OpenMP/taskloop_simd_aligned_messages.cpp
@@ -121,7 +121,8 @@ template<class I, class C> int foomain(I argc, C **argv) {
for (I k = 0; k < argc; ++k) ++k;
#pragma omp taskloop simd aligned (argc, // expected-error {{expected expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
for (I k = 0; k < argc; ++k) ++k;
- #pragma omp taskloop simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
+// FIXME: Should argc really be a pointer?
+ #pragma omp taskloop simd aligned (*argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
for (I k = 0; k < argc; ++k) ++k;
#pragma omp taskloop simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
for (I k = 0; k < argc; ++k) ++k;
diff --git a/test/SemaCXX/compare.cpp b/test/SemaCXX/compare.cpp
index ef0a524f92..0528b044fb 100644
--- a/test/SemaCXX/compare.cpp
+++ b/test/SemaCXX/compare.cpp
@@ -201,9 +201,10 @@ int test1(int i) {
enum E { e };
void test2(int i, void *vp) {
+ if (&i == vp) { } // ok
if (test1 == vp) { } // expected-warning{{equality comparison between function pointer and void pointer}}
if (test1 == e) { } // expected-error{{comparison between pointer and integer}}
- if (vp < 0) { }
+ if (vp < 0) { } // expected-error {{comparison between pointer and zero}}
if (test1 < e) { } // expected-error{{comparison between pointer and integer}}
}
diff --git a/test/SemaCXX/composite-pointer-type.cpp b/test/SemaCXX/composite-pointer-type.cpp
index 06fc8f4385..dddf424caa 100644
--- a/test/SemaCXX/composite-pointer-type.cpp
+++ b/test/SemaCXX/composite-pointer-type.cpp
@@ -53,8 +53,8 @@ bool f(Matrix4 m1, const Matrix4 m2) {
// PR6346
bool f1(bool b, void **p, const void **q) {
- if (p == q) // expected-warning{{comparison of distinct pointer types ('void **' and 'const void **') uses non-standard composite pointer type 'const void *const *'}}
+ if (p == q)
return false;
- return b? p : q; // expected-warning{{incompatible operand types ('void **' and 'const void **') use non-standard composite pointer type 'const void *const *'}}
+ return b? p : q;
}
diff --git a/test/SemaCXX/constant-expression-cxx11.cpp b/test/SemaCXX/constant-expression-cxx11.cpp
index e2b3f091f7..0b36f3b6cb 100644
--- a/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/test/SemaCXX/constant-expression-cxx11.cpp
@@ -279,17 +279,17 @@ static_assert(&s.x > &s.y, "false"); // expected-error {{false}}
static_assert(0 == &y, "false"); // expected-error {{false}}
static_assert(0 != &y, "");
-constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n3 = (int*)0 <= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n4 = (int*)0 >= &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n5 = (int*)0 < &y; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n6 = (int*)0 > &y; // expected-error {{must be initialized by a constant expression}}
static_assert(&x == 0, "false"); // expected-error {{false}}
static_assert(&x != 0, "");
-constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}}
-constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n9 = &x <= (int*)0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n10 = &x >= (int*)0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n11 = &x < (int*)0; // expected-error {{must be initialized by a constant expression}}
+constexpr bool n12 = &x > (int*)0; // expected-error {{must be initialized by a constant expression}}
static_assert(&x == &x, "");
static_assert(&x != &x, "false"); // expected-error {{false}}
diff --git a/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp b/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp
new file mode 100644
index 0000000000..53b6a3b2c4
--- /dev/null
+++ b/test/SemaCXX/libstdcxx_libcxx_less_hack.cpp
@@ -0,0 +1,67 @@
+// This is a test for a hack in Clang that works around a problem introduced by
+// DR583: it's no longer possible to compare a pointer against nullptr_t, but
+// we still want to permit those comparisons within less<> and friends.
+
+// RUN: %clang_cc1 -verify %s -std=c++14
+
+namespace std {
+ template<typename T = void> struct less {};
+ template<typename T = void> struct less_equal {};
+ template<typename T = void> struct greater {};
+ template<typename T = void> struct greater_equal {};
+
+ template<> struct less<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u))
+ -> decltype(t < u) {
+ return t < u;
+ }
+ };
+
+ template<> struct less_equal<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t <= u))
+ -> decltype(t <= u) {
+ return t <= u;
+ }
+ };
+
+ template<> struct greater<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t > u))
+ -> decltype(t > u) {
+ return t > u;
+ }
+ };
+
+ template<> struct greater_equal<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t >= u))
+ -> decltype(t >= u) {
+ return t >= u;
+ }
+ };
+
+ template<typename = void> struct unrelated;
+ template<> struct unrelated<> {
+ template <class T1, class T2>
+ auto operator()(T1 &&t, T2 &&u) const noexcept(noexcept(t < u)) // expected-note {{substitution failure}}
+ -> decltype(t < u) {
+ return t < u;
+ }
+ };
+};
+
+void test(int *p) {
+ using namespace std;
+ less<>()(p, nullptr);
+ less<>()(nullptr, p);
+ less_equal<>()(p, nullptr);
+ less_equal<>()(nullptr, p);
+ greater<>()(p, nullptr);
+ greater<>()(nullptr, p);
+ greater_equal<>()(p, nullptr);
+ greater_equal<>()(nullptr, p);
+
+ unrelated<>()(p, nullptr); // expected-error {{no matching function}}
+}
diff --git a/test/SemaCXX/null_in_arithmetic_ops.cpp b/test/SemaCXX/null_in_arithmetic_ops.cpp
index 3b42ab44fe..ee695ff242 100644
--- a/test/SemaCXX/null_in_arithmetic_ops.cpp
+++ b/test/SemaCXX/null_in_arithmetic_ops.cpp
@@ -71,8 +71,8 @@ void f() {
b = a == NULL || a != NULL; // expected-warning 2{{comparison between NULL and non-pointer ('int' and NULL)}}
b = NULL == a || NULL != a; // expected-warning 2{{comparison between NULL and non-pointer (NULL and 'int')}}
- b = &a < NULL || NULL < &a || &a > NULL || NULL > &a;
- b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a;
+ b = &a < NULL || NULL < &a || &a > NULL || NULL > &a; // expected-error 4{{ordered comparison between pointer and zero}}
+ b = &a <= NULL || NULL <= &a || &a >= NULL || NULL >= &a; // expected-error 4{{ordered comparison between pointer and zero}}
b = &a == NULL || NULL == &a || &a != NULL || NULL != &a;
b = 0 == a;
diff --git a/test/SemaCXX/nullptr.cpp b/test/SemaCXX/nullptr.cpp
index 7d765b482c..9a092910b6 100644
--- a/test/SemaCXX/nullptr.cpp
+++ b/test/SemaCXX/nullptr.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 -ffreestanding -Wno-null-conversion -Wno-tautological-compare %s
#include <stdint.h>
typedef decltype(nullptr) nullptr_t;
@@ -32,17 +32,17 @@ nullptr_t f(nullptr_t null)
// Operators
(void)(null == nullptr);
- (void)(null <= nullptr);
+ (void)(null <= nullptr); // expected-error {{invalid operands to binary expression}}
(void)(null == 0);
(void)(null == (void*)0);
(void)((void*)0 == nullptr);
- (void)(null <= 0);
- (void)(null <= (void*)0);
- (void)((void*)0 <= nullptr);
+ (void)(null <= 0); // expected-error {{invalid operands to binary expression}}
+ (void)(null <= (void*)0); // expected-error {{invalid operands to binary expression}}
+ (void)((void*)0 <= nullptr); // expected-error {{invalid operands to binary expression}}
(void)(0 == nullptr);
(void)(nullptr == 0);
- (void)(nullptr <= 0);
- (void)(0 <= nullptr);
+ (void)(nullptr <= 0); // expected-error {{invalid operands to binary expression}}
+ (void)(0 <= nullptr); // expected-error {{invalid operands to binary expression}}
(void)(1 > nullptr); // expected-error {{invalid operands to binary expression}}
(void)(1 != nullptr); // expected-error {{invalid operands to binary expression}}
(void)(1 + nullptr); // expected-error {{invalid operands to binary expression}}
@@ -118,24 +118,24 @@ static_assert(__is_scalar(nullptr_t), "");
static_assert(__is_pod(nullptr_t), "");
static_assert(sizeof(nullptr_t) == sizeof(void*), "");
-static_assert(!(nullptr < nullptr), "");
-static_assert(!(nullptr > nullptr), "");
-static_assert( nullptr <= nullptr, "");
-static_assert( nullptr >= nullptr, "");
+static_assert(!(nullptr < nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert(!(nullptr > nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr <= nullptr, ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr >= nullptr, ""); // expected-error {{invalid operands to binary expression}}
static_assert( nullptr == nullptr, "");
static_assert(!(nullptr != nullptr), "");
-static_assert(!(0 < nullptr), "");
-static_assert(!(0 > nullptr), "");
-static_assert( 0 <= nullptr, "");
-static_assert( 0 >= nullptr, "");
+static_assert(!(0 < nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert(!(0 > nullptr), ""); // expected-error {{invalid operands to binary expression}}
+static_assert( 0 <= nullptr, ""); // expected-error {{invalid operands to binary expression}}
+static_assert( 0 >= nullptr, ""); // expected-error {{invalid operands to binary expression}}
static_assert( 0 == nullptr, "");
static_assert(!(0 != nullptr), "");
-static_assert(!(nullptr < 0), "");
-static_assert(!(nullptr > 0), "");
-static_assert( nullptr <= 0, "");
-static_assert( nullptr >= 0, "");
+static_assert(!(nullptr < 0), ""); // expected-error {{invalid operands to binary expression}}
+static_assert(!(nullptr > 0), ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr <= 0, ""); // expected-error {{invalid operands to binary expression}}
+static_assert( nullptr >= 0, ""); // expected-error {{invalid operands to binary expression}}
static_assert( nullptr == 0, "");
static_assert(!(nullptr != 0), "");
@@ -154,10 +154,10 @@ namespace overloading {
void test_conversion(ConvertsToNullPtr ctn) {
(void)(ctn == ctn);
(void)(ctn != ctn);
- (void)(ctn <= ctn);
- (void)(ctn >= ctn);
- (void)(ctn < ctn);
- (void)(ctn > ctn);
+ (void)(ctn <= ctn); // expected-error {{invalid operands to binary expression}}
+ (void)(ctn >= ctn); // expected-error {{invalid operands to binary expression}}
+ (void)(ctn < ctn); // expected-error {{invalid operands to binary expression}}
+ (void)(ctn > ctn); // expected-error {{invalid operands to binary expression}}
}
}
diff --git a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp
index 60b4670b3a..6273d9c42e 100644
--- a/test/SemaCXX/nullptr_in_arithmetic_ops.cpp
+++ b/test/SemaCXX/nullptr_in_arithmetic_ops.cpp
@@ -45,12 +45,12 @@ void foo() {
b = a == nullptr || nullptr == a; // expected-error 2{{invalid operands to binary expression}}
b = a != nullptr || nullptr != a; // expected-error 2{{invalid operands to binary expression}}
- b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a;
- b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a;
+ b = &a < nullptr || nullptr < &a || &a > nullptr || nullptr > &a; // expected-error 4{{invalid operands}}
+ b = &a <= nullptr || nullptr <= &a || &a >= nullptr || nullptr >= &a; // expected-error 4{{invalid operands}}
b = &a == nullptr || nullptr == &a || &a != nullptr || nullptr != &a;
- b = nullptr < nullptr || nullptr > nullptr;
- b = nullptr <= nullptr || nullptr >= nullptr;
+ b = nullptr < nullptr || nullptr > nullptr; // expected-error 2{{invalid operands to binary expression}}
+ b = nullptr <= nullptr || nullptr >= nullptr; // expected-error 2{{invalid operands to binary expression}}
b = nullptr == nullptr || nullptr != nullptr;
b = ((nullptr)) != a; // expected-error{{invalid operands to binary expression}}
diff --git a/test/SemaCXX/warn-memsize-comparison.cpp b/test/SemaCXX/warn-memsize-comparison.cpp
index 54c410e3dc..b5c7a9d696 100644
--- a/test/SemaCXX/warn-memsize-comparison.cpp
+++ b/test/SemaCXX/warn-memsize-comparison.cpp
@@ -5,7 +5,7 @@ typedef __SIZE_TYPE__ size_t;
extern "C" void *memset(void *, int, size_t);
extern "C" void *memmove(void *s1, const void *s2, size_t n);
extern "C" void *memcpy(void *s1, const void *s2, size_t n);
-extern "C" void *memcmp(void *s1, const void *s2, size_t n);
+extern "C" int memcmp(void *s1, const void *s2, size_t n);
extern "C" int strncmp(const char *s1, const char *s2, size_t n);
extern "C" int strncasecmp(const char *s1, const char *s2, size_t n);
extern "C" char *strncpy(char *dst, const char *src, size_t n);
@@ -28,11 +28,12 @@ void f() {
expected-note {{explicitly cast the argument}}
if (memmove(b1, b2, sizeof(b1)) == 0) {}
+ // FIXME: This fixit is bogus.
if (memcpy(b1, b2, sizeof(b1) < 0)) {} // \
expected-warning{{size argument in 'memcpy' call is a comparison}} \
expected-note {{did you mean to compare}} \
expected-note {{explicitly cast the argument}}
- if (memcpy(b1, b2, sizeof(b1)) < 0) {}
+ if (memcpy(b1, b2, sizeof(b1)) < 0) {} // expected-error {{ordered comparison between pointer and zero}}
if (memcmp(b1, b2, sizeof(b1) <= 0)) {} // \
expected-warning{{size argument in 'memcmp' call is a comparison}} \
@@ -58,11 +59,12 @@ void f() {
expected-note {{explicitly cast the argument}}
if (strncpy(b1, b2, sizeof(b1)) == 0 || true) {}
+ // FIXME: This fixit is bogus.
if (strncat(b1, b2, sizeof(b1) - 1 >= 0 && true)) {} // \
expected-warning{{size argument in 'strncat' call is a comparison}} \
expected-note {{did you mean to compare}} \
expected-note {{explicitly cast the argument}}
- if (strncat(b1, b2, sizeof(b1) - 1) >= 0 && true) {}
+ if (strncat(b1, b2, sizeof(b1) - 1) >= 0 && true) {} // expected-error {{ordered comparison between pointer and zero}}
if (strndup(b1, sizeof(b1) != 0)) {} // \
expected-warning{{size argument in 'strndup' call is a comparison}} \
diff --git a/test/SemaObjCXX/null_objc_pointer.mm b/test/SemaObjCXX/null_objc_pointer.mm
index e0232bf3c8..2be397e31e 100644
--- a/test/SemaObjCXX/null_objc_pointer.mm
+++ b/test/SemaObjCXX/null_objc_pointer.mm
@@ -1,5 +1,4 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wnull-arithmetic %s
-// expected-no-diagnostics
#define NULL __null
@interface X
@@ -8,7 +7,7 @@
void f() {
bool b;
X *d;
- b = d < NULL || NULL < d || d > NULL || NULL > d;
- b = d <= NULL || NULL <= d || d >= NULL || NULL >= d;
+ b = d < NULL || NULL < d || d > NULL || NULL > d; // expected-error 4{{ordered comparison between pointer and zero}}
+ b = d <= NULL || NULL <= d || d >= NULL || NULL >= d; // expected-error 4{{ordered comparison between pointer and zero}}
b = d == NULL || NULL == d || d != NULL || NULL != d;
}