Timm Baeder f86050de73
[clang][bytecode] Don't call checkLiteralType() in visitInitializer() (#109530)
We were calling checkLiteralType() too many time and rejecting some
things we shouldn't. Add The calls manually when handling
MaterializeTemporaryExprs. Maybe we should call it in other places as
well, but adding more calls is easier than removing them from a generic
code path.
2024-09-21 20:01:21 +02:00

108 lines
2.6 KiB
C++

// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -std=c++17 -verify=expected,both %s
// RUN: %clang_cc1 -std=c++17 -verify=ref,both %s
struct F { int a; int b;};
constexpr F getF() {
return {12, 3};
}
constexpr int f() {
auto [a1, b1] = getF();
auto [a2, b2] = getF();
return a1 + a2 + b1 + b2;
}
static_assert(f() == 30);
constexpr int structRefs() {
const auto &[a, b] = getF();
return a + b;
}
static_assert(structRefs() == 15);
constexpr int structRefs2() {
F f = getF();
const auto &[a, b] = f;
return a + b;
}
static_assert(structRefs2() == 15);
template<typename T>
struct Tuple {
T first;
T second;
constexpr Tuple(T a, T b) : first(a), second(b) {}
};
template<typename T>
constexpr T addTuple(const Tuple<T> &Tu) {
auto [a, b] = Tu;
return a + b;
}
template<typename T>
constexpr T addTuple2(const Tuple<T> &Tu) {
auto [a, b] = Tu;
return Tu.first + Tu.second;
}
constexpr Tuple<int> T1 = Tuple(1,2);
static_assert(addTuple(T1) == 3);
static_assert(addTuple2(T1) == 3);
constexpr Tuple<short> T2 = Tuple<short>(11,2);
static_assert(addTuple(T2) == 13);
static_assert(addTuple2(T2) == 13);
constexpr int Modify() {
auto T = Tuple<int>(10, 20);
auto &[x, y] = T;
x += 1;
y += 1;
return T.first + T.second;
}
static_assert(Modify() == 32, "");
constexpr int a() {
int a[2] = {5, 3};
auto [x, y] = a;
return x + y;
}
static_assert(a() == 8);
constexpr int b() {
int a[2] = {5, 3};
auto &[x, y] = a;
x += 1;
y += 2;
return a[0] + a[1];
}
static_assert(b() == 11);
namespace cwg1872 {
template<typename T> struct A : T {
constexpr int f() const { return 0; }
};
struct X {};
struct Y { virtual int f() const; };
struct Z : virtual X {};
constexpr int z = A<Z>().f(); // both-error {{must be initialized by a constant expression}} \
// both-note {{non-literal type 'A<Z>' cannot be used in a constant expression}}
}
/// The diagnostics between the two interpreters used to be different here.
struct S { int a; };
constexpr S getS() { // both-error {{constexpr function never produces a constant expression}}
(void)(1/0); // both-note 2{{division by zero}} \
// both-warning {{division by zero}}
return S{12};
}
constexpr S s = getS(); // both-error {{must be initialized by a constant expression}} \
// both-note {{in call to 'getS()'}} \
// both-note {{declared here}}
static_assert(s.a == 12, ""); // both-error {{not an integral constant expression}} \
// both-note {{initializer of 's' is not a constant expression}}