[Sema][NFC] Improve test coverage of builtin operators.

In preparation for D112453.

Fix numbering of tests for [over.built]: 15->16, 16->17.
This commit is contained in:
Clement Courbet 2021-11-04 14:58:31 +01:00
parent 8720149d9b
commit d3dc7d077f
13 changed files with 357 additions and 145 deletions

View File

@ -2,8 +2,8 @@
struct A{};
template <typename T>
auto Test(T* pt) {
template <typename T, typename U>
auto Test(T* pt, U* pu) {
// CHECK: UnaryOperator {{.*}} '<dependent type>' prefix '*'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
(void)*pt;
@ -24,7 +24,18 @@ auto Test(T* pt) {
// CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
(void)(pt -pt);
(void)(pt - pt);
// CHECK: BinaryOperator {{.*}} '<dependent type>' '-'
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
// CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
(void)(pt - pu);
// CHECK: BinaryOperator {{.*}} '<dependent type>' '=='
// CHECK-NEXT: DeclRefExpr {{.*}} 'T *' lvalue ParmVar {{.*}} 'pt' 'T *'
// CHECK-NEXT: DeclRefExpr {{.*}} 'U *' lvalue ParmVar {{.*}} 'pu' 'U *'
(void)(pt == pu);
}

View File

@ -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 <typename T, typename U>
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);
}

View File

@ -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}}
}

View File

@ -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}}
}

View File

@ -0,0 +1,82 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
template <typename T, typename U>
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);
}

View File

@ -0,0 +1,24 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
template <typename T>
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;
}

View File

@ -0,0 +1,12 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
template <typename T, typename U>
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;
}

View File

@ -0,0 +1,13 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
struct A {
};
template <typename T>
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;
}

View File

@ -0,0 +1,12 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
template <typename T>
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
}

View File

@ -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 <typename T> operator T();
};
template <typename T, typename U>
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();
}
struct ExplicitVariant {
template <typename T> explicit operator T();
};
ExplicitVariant getExplicitValue();
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;
i |= 3;
f |= 3; // expected-error {{invalid operands}}
b |= 3;
pi |= 3; // expected-error {{invalid operands}}
pt |= 3; // FIXME
t |= 3;
i <<= 3;
f <<= 3; // expected-error {{invalid operands}}
b <<= 3;
pi <<= 3; // expected-error {{invalid operands}}
pt <<= 3; // FIXME
t <<= 3;
i >>= 3;
f >>= 3; // expected-error {{invalid operands}}
b >>= 3;
pi >>= 3; // expected-error {{invalid operands}}
pt >>= 3; // FIXME
t >>= 3;
}

View File

@ -1,12 +1,26 @@
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
template <typename T>
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 <typename T> operator T();
};
Variant getValue();
void testVariant() {
bool ret1 = getValue() || getValue();
bool ret2 = getValue() && getValue();
bool ret3 = !getValue();
}
struct ExplicitVariant {
template <typename T> explicit operator T();
};
ExplicitVariant getExplicitValue();
void testExplicitVariant() {
bool ret1 = getExplicitValue() || getExplicitValue();
bool ret2 = getExplicitValue() && getExplicitValue();
bool ret3 = !getExplicitValue();
}

View File

@ -1,16 +1,12 @@
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// expected-no-diagnostics
// RUN: %clang_cc1 -std=c++11 -verify %s -Wno-tautological-compare
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;
template <typename T>
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

View File

@ -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;
}