From d3dc7d077f1d9c9478813a34ed38abbcb4fc1ef5 Mon Sep 17 00:00:00 2001 From: Clement Courbet Date: Thu, 4 Nov 2021 14:58:31 +0100 Subject: [PATCH] [Sema][NFC] Improve test coverage of builtin operators. In preparation for D112453. Fix numbering of tests for [over.built]: 15->16, 16->17. --- .../CXX/over/over.built/{p7-ast.cpp => ast.cpp} | 17 ++++- clang/test/CXX/over/over.built/p15.cpp | 81 +++------------------ clang/test/CXX/over/over.built/p16.cpp | 46 ++++++------ clang/test/CXX/over/over.built/p17.cpp | 75 ++++++++++++++++++++ clang/test/CXX/over/over.built/p18.cpp | 82 ++++++++++++++++++++++ clang/test/CXX/over/over.built/p19.cpp | 24 +++++++ clang/test/CXX/over/over.built/p20.cpp | 12 ++++ clang/test/CXX/over/over.built/p21.cpp | 13 ++++ clang/test/CXX/over/over.built/p22.cpp | 12 ++++ clang/test/CXX/over/over.built/p23.cpp | 58 ++++++++++----- clang/test/CXX/over/over.built/p24.cpp | 36 +++++++--- clang/test/CXX/over/over.built/p25.cpp | 26 +++---- clang/test/CXX/over/over.built/p26.cpp | 16 +++++ 13 files changed, 355 insertions(+), 143 deletions(-) rename clang/test/CXX/over/over.built/{p7-ast.cpp => ast.cpp} (64%) create mode 100644 clang/test/CXX/over/over.built/p17.cpp create mode 100644 clang/test/CXX/over/over.built/p18.cpp create mode 100644 clang/test/CXX/over/over.built/p19.cpp create mode 100644 clang/test/CXX/over/over.built/p20.cpp create mode 100644 clang/test/CXX/over/over.built/p21.cpp create mode 100644 clang/test/CXX/over/over.built/p22.cpp create mode 100644 clang/test/CXX/over/over.built/p26.cpp diff --git a/clang/test/CXX/over/over.built/p7-ast.cpp b/clang/test/CXX/over/over.built/ast.cpp similarity index 64% rename from clang/test/CXX/over/over.built/p7-ast.cpp rename to clang/test/CXX/over/over.built/ast.cpp index f3c44cf..f76606b 100644 --- a/clang/test/CXX/over/over.built/p7-ast.cpp +++ b/clang/test/CXX/over/over.built/ast.cpp @@ -2,8 +2,8 @@ struct A{}; -template -auto Test(T* pt) { +template +auto Test(T* pt, U* pu) { // CHECK: UnaryOperator {{.*}} '' prefix '*' // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' (void)*pt; @@ -24,7 +24,18 @@ auto Test(T* pt) { // CHECK: BinaryOperator {{.*}} '' '-' // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' - (void)(pt -pt); + (void)(pt - pt); + + // CHECK: BinaryOperator {{.*}} '' '-' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + (void)(pt - pu); + + // CHECK: BinaryOperator {{.*}} '' '==' + // CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *' + // CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *' + (void)(pt == pu); + } diff --git a/clang/test/CXX/over/over.built/p15.cpp b/clang/test/CXX/over/over.built/p15.cpp index 9b223bc..680ffa9 100644 --- a/clang/test/CXX/over/over.built/p15.cpp +++ b/clang/test/CXX/over/over.built/p15.cpp @@ -1,75 +1,12 @@ // RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare -struct A { operator decltype(nullptr)(); }; // expected-note 16{{implicitly converted}} -struct B { operator const int *(); }; // expected-note 8{{implicitly converted}} -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); - (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); - (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}} +template +void f(int* pi, float* pf, T* pt, U* pu, T t) { + (void)(pi - pi); + (void)(pi - pf); // expected-error {{not pointers to compatible types}} + (void)(pi - pt); + (void)(pu - pi); + (void)(pu - pt); + (void)(pu - t); + (void)(pi - t); } diff --git a/clang/test/CXX/over/over.built/p16.cpp b/clang/test/CXX/over/over.built/p16.cpp index 139e864..9b223bc 100644 --- a/clang/test/CXX/over/over.built/p16.cpp +++ b/clang/test/CXX/over/over.built/p16.cpp @@ -1,8 +1,8 @@ // 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) { +struct A { operator decltype(nullptr)(); }; // expected-note 16{{implicitly converted}} +struct B { operator const int *(); }; // expected-note 8{{implicitly converted}} +void f(A a, B b, volatile int *pi) { (void)(a == a); (void)(a != a); (void)(a < a); // expected-error {{invalid operands}} @@ -40,36 +40,36 @@ void f(A a, B b, int A::*pi) { (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)(b < pi); + (void)(b > pi); + (void)(b <= pi); + (void)(b >= pi); (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)(pi < b); + (void)(pi > b); + (void)(pi <= b); + (void)(pi >= b); (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)(b < b); + (void)(b > b); + (void)(b <= b); + (void)(b >= b); (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}} + (void)(pi < pi); + (void)(pi > pi); + (void)(pi <= pi); + (void)(pi >= pi); } -// FIXME: This is wrong: type T = 'const volatile int * const A::* const B::*' +// 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 *A::*B::*(); }; -void g(C c, volatile int *A::*B::*p) { - (void)(c == p); // expected-error {{invalid operands}} +struct C { operator const int ***(); }; +void g(C c, volatile int ***p) { + (void)(c < p); // expected-error {{invalid operands}} } diff --git a/clang/test/CXX/over/over.built/p17.cpp b/clang/test/CXX/over/over.built/p17.cpp new file mode 100644 index 0000000..139e864 --- /dev/null +++ b/clang/test/CXX/over/over.built/p17.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/clang/test/CXX/over/over.built/p18.cpp b/clang/test/CXX/over/over.built/p18.cpp new file mode 100644 index 0000000..698a943 --- /dev/null +++ b/clang/test/CXX/over/over.built/p18.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +template +void f(int i, float f, bool b, int* pi, T* pt, T t) { + (void)(i % 3); + (void)(f % 3); // expected-error {{invalid operands}} + (void)(b % 3); + (void)(pi % 3); // expected-error {{invalid operands}} + (void)(pt % 3); // FIXME + (void)(t % 3); + (void)(3 % i); + (void)(3 % f); // expected-error {{invalid operands}} + (void)(3 % b); + (void)(3 % pi); // expected-error {{invalid operands}} + (void)(3 % pt); // FIXME + (void)(3 % t); + + (void)(i & 3); + (void)(f & 3); // expected-error {{invalid operands}} + (void)(b & 3); + (void)(pi & 3); // expected-error {{invalid operands}} + (void)(pt & 3); // FIXME + (void)(t & 3); + (void)(3 & i); + (void)(3 & f); // expected-error {{invalid operands}} + (void)(3 & b); + (void)(3 & pi); // expected-error {{invalid operands}} + (void)(3 & pt); // FIXME + (void)(3 & t); + + (void)(i ^ 3); + (void)(f ^ 3); // expected-error {{invalid operands}} + (void)(b ^ 3); + (void)(pi ^ 3); // expected-error {{invalid operands}} + (void)(pt ^ 3); // FIXME + (void)(t ^ 3); + (void)(3 ^ i); + (void)(3 ^ f); // expected-error {{invalid operands}} + (void)(3 ^ b); + (void)(3 ^ pi); // expected-error {{invalid operands}} + (void)(3 ^ pt); // FIXME + (void)(3 ^ t); + + (void)(i | 3); + (void)(f | 3); // expected-error {{invalid operands}} + (void)(b | 3); + (void)(pi | 3); // expected-error {{invalid operands}} + (void)(pt | 3); // FIXME + (void)(t | 3); + (void)(3 | i); + (void)(3 | f); // expected-error {{invalid operands}} + (void)(3 | b); + (void)(3 | pi); // expected-error {{invalid operands}} + (void)(3 | pt); // FIXME + (void)(3 | t); + + (void)(i << 3); + (void)(f << 3); // expected-error {{invalid operands}} + (void)(b << 3); + (void)(pi << 3); // expected-error {{invalid operands}} + (void)(pt << 3); // FIXME + (void)(t << 3); + (void)(3 << i); + (void)(3 << f); // expected-error {{invalid operands}} + (void)(3 << b); + (void)(3 << pi); // expected-error {{invalid operands}} + (void)(3 << pt); // FIXME + (void)(3 << t); + + (void)(i >> 3); + (void)(f >> 3); // expected-error {{invalid operands}} + (void)(b >> 3); + (void)(pi >> 3); // expected-error {{invalid operands}} + (void)(pt >> 3); // FIXME + (void)(t >> 3); + (void)(3 >> i); + (void)(3 >> f); // expected-error {{invalid operands}} + (void)(3 >> b); + (void)(3 >> pi); // expected-error {{invalid operands}} + (void)(3 >> pt); // FIXME + (void)(3 >> t); +} diff --git a/clang/test/CXX/over/over.built/p19.cpp b/clang/test/CXX/over/over.built/p19.cpp new file mode 100644 index 0000000..0317f6b --- /dev/null +++ b/clang/test/CXX/over/over.built/p19.cpp @@ -0,0 +1,24 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +template +void f(int i, float f, int* pi, T* pt, T t) { + i = i; + i *= i; + i /= i; + i += i; + i -= i; + i -= f; + i -= pi; // expected-error {{invalid operands}} + i -= pt; // FIXME + i -= t; + + f = f; + f *= f; + f /= f; + f += f; + f -= f; + f -= i; + f -= pi; // expected-error {{invalid operands}} + f -= pt; // FIXME + f -= t; +} diff --git a/clang/test/CXX/over/over.built/p20.cpp b/clang/test/CXX/over/over.built/p20.cpp new file mode 100644 index 0000000..92ba118 --- /dev/null +++ b/clang/test/CXX/over/over.built/p20.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +template +void f(int* pi, float* pf, T* pt, U* pu, T t) { + pi = pi; + pi = pf; // expected-error {{incompatible pointer types}} + pi = pt; + pu = pi; + pu = pt; + pi = t; + pu = t; +} diff --git a/clang/test/CXX/over/over.built/p21.cpp b/clang/test/CXX/over/over.built/p21.cpp new file mode 100644 index 0000000..33db664 --- /dev/null +++ b/clang/test/CXX/over/over.built/p21.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +struct A { +}; + +template +void f(int A::* pi, float A::* pf, int T::* pt, T A::* pu, T t) { + pi = pi; + pi = pf; // expected-error {{assigning to 'int A::*' from incompatible type 'float A::*'}} + pi = pt; + pi = pu; + pi = t; +} diff --git a/clang/test/CXX/over/over.built/p22.cpp b/clang/test/CXX/over/over.built/p22.cpp new file mode 100644 index 0000000..330f1c9 --- /dev/null +++ b/clang/test/CXX/over/over.built/p22.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +template +void f(int* pi, T* pt, T t) { + pi += 3; + pi += pi; // expected-error {{invalid operands}} + pt += 3; + pi += t; + pi += pt; // FIXME + pt += pi; //FIXME + pt += pt; //FIXME +} diff --git a/clang/test/CXX/over/over.built/p23.cpp b/clang/test/CXX/over/over.built/p23.cpp index a1c0d4f3..dfea859 100644 --- a/clang/test/CXX/over/over.built/p23.cpp +++ b/clang/test/CXX/over/over.built/p23.cpp @@ -1,26 +1,46 @@ -// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s -// expected-no-diagnostics +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare -struct Variant { - template operator T(); -}; +template +void f(int i, float f, bool b, int* pi, T* pt, T t) { + i %= 3; + f %= 3; // expected-error {{invalid operands}} + b %= 3; + pi %= 3; // expected-error {{invalid operands}} + pt %= 3; // FIXME + t %= 3; -Variant getValue(); + i &= 3; + f &= 3; // expected-error {{invalid operands}} + b &= 3; + pi &= 3; // expected-error {{invalid operands}} + pt &= 3; // FIXME + t &= 3; -void testVariant() { - bool ret1 = getValue() || getValue(); - bool ret2 = getValue() && getValue(); - bool ret3 = !getValue(); -} + i ^= 3; + f ^= 3; // expected-error {{invalid operands}} + b ^= 3; + pi ^= 3; // expected-error {{invalid operands}} + pt ^= 3; // FIXME + t ^= 3; -struct ExplicitVariant { - template explicit operator T(); -}; + i |= 3; + f |= 3; // expected-error {{invalid operands}} + b |= 3; + pi |= 3; // expected-error {{invalid operands}} + pt |= 3; // FIXME + t |= 3; -ExplicitVariant getExplicitValue(); + i <<= 3; + f <<= 3; // expected-error {{invalid operands}} + b <<= 3; + pi <<= 3; // expected-error {{invalid operands}} + pt <<= 3; // FIXME + t <<= 3; -void testExplicitVariant() { - bool ret1 = getExplicitValue() || getExplicitValue(); - bool ret2 = getExplicitValue() && getExplicitValue(); - bool ret3 = !getExplicitValue(); + i >>= 3; + f >>= 3; // expected-error {{invalid operands}} + b >>= 3; + pi >>= 3; // expected-error {{invalid operands}} + pt >>= 3; // FIXME + t >>= 3; } diff --git a/clang/test/CXX/over/over.built/p24.cpp b/clang/test/CXX/over/over.built/p24.cpp index 3c48dcd..a1c0d4f3 100644 --- a/clang/test/CXX/over/over.built/p24.cpp +++ b/clang/test/CXX/over/over.built/p24.cpp @@ -1,12 +1,26 @@ -// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare - -template -void f(int i, float f, bool b, char c, int* pi, T* pt) { - (void)!i; - (void)!f; - (void)!b; - (void)!c; - (void)!pi; - (void)!pt; -} +// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s // expected-no-diagnostics + +struct Variant { + template operator T(); +}; + +Variant getValue(); + +void testVariant() { + bool ret1 = getValue() || getValue(); + bool ret2 = getValue() && getValue(); + bool ret3 = !getValue(); +} + +struct ExplicitVariant { + template explicit operator T(); +}; + +ExplicitVariant getExplicitValue(); + +void testExplicitVariant() { + bool ret1 = getExplicitValue() || getExplicitValue(); + bool ret2 = getExplicitValue() && getExplicitValue(); + bool ret3 = !getExplicitValue(); +} diff --git a/clang/test/CXX/over/over.built/p25.cpp b/clang/test/CXX/over/over.built/p25.cpp index 09e550d..3c48dcd 100644 --- a/clang/test/CXX/over/over.built/p25.cpp +++ b/clang/test/CXX/over/over.built/p25.cpp @@ -1,16 +1,12 @@ -// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s -// expected-no-diagnostics - -enum class Color { Red, Green, Blue }; - -struct ConvertsToColorA { - operator Color(); -}; - -struct ConvertsToColorB { - operator Color(); -}; - -Color foo(bool cond, ConvertsToColorA ca, ConvertsToColorB cb) { - return cond? ca : cb; +// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare + +template +void f(int i, float f, bool b, char c, int* pi, T* pt) { + (void)!i; + (void)!f; + (void)!b; + (void)!c; + (void)!pi; + (void)!pt; } +// expected-no-diagnostics diff --git a/clang/test/CXX/over/over.built/p26.cpp b/clang/test/CXX/over/over.built/p26.cpp new file mode 100644 index 0000000..09e550d --- /dev/null +++ b/clang/test/CXX/over/over.built/p26.cpp @@ -0,0 +1,16 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s +// expected-no-diagnostics + +enum class Color { Red, Green, Blue }; + +struct ConvertsToColorA { + operator Color(); +}; + +struct ConvertsToColorB { + operator Color(); +}; + +Color foo(bool cond, ConvertsToColorA ca, ConvertsToColorB cb) { + return cond? ca : cb; +} -- 2.7.4