1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259
|
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
// RUN: %clang_cc1 -verify=ref %s
constexpr void doNothing() {}
constexpr int gimme5() {
doNothing();
return 5;
}
static_assert(gimme5() == 5, "");
template<typename T> constexpr T identity(T t) {
static_assert(true, "");
return t;
}
static_assert(identity(true), "");
static_assert(identity(true), ""); /// Compiled bytecode should be cached
static_assert(!identity(false), "");
template<typename A, typename B>
constexpr bool sameSize() {
static_assert(sizeof(A) == sizeof(B), ""); // expected-error {{static assertion failed}} \
// ref-error {{static assertion failed}} \
// expected-note {{evaluates to}} \
// ref-note {{evaluates to}}
return true;
}
static_assert(sameSize<int, int>(), "");
static_assert(sameSize<unsigned int, int>(), "");
static_assert(sameSize<char, long>(), ""); // expected-note {{in instantiation of function template specialization}} \
// ref-note {{in instantiation of function template specialization}}
constexpr auto add(int a, int b) -> int {
return identity(a) + identity(b);
}
constexpr int sub(int a, int b) {
return a - b;
}
static_assert(sub(5, 2) == 3, "");
static_assert(sub(0, 5) == -5, "");
constexpr int norm(int n) {
if (n >= 0) {
return identity(n);
}
return -identity(n);
}
static_assert(norm(5) == norm(-5), "");
constexpr int square(int n) {
return norm(n) * norm(n);
}
static_assert(square(2) == 4, "");
constexpr int add_second(int a, int b, bool doAdd = true) {
if (doAdd)
return a + b;
return a;
}
static_assert(add_second(10, 3, true) == 13, "");
static_assert(add_second(10, 3) == 13, "");
static_assert(add_second(300, -20, false) == 300, "");
constexpr int sub(int a, int b, int c) {
return a - b - c;
}
static_assert(sub(10, 8, 2) == 0, "");
constexpr int recursion(int i) {
doNothing();
i = i - 1;
if (i == 0)
return identity(0);
return recursion(i);
}
static_assert(recursion(10) == 0, "");
template<int N = 5>
constexpr decltype(N) getNum() {
return N;
}
static_assert(getNum<-2>() == -2, "");
static_assert(getNum<10>() == 10, "");
static_assert(getNum() == 5, "");
constexpr int f(); // expected-note {{declared here}} \
// ref-note {{declared here}}
static_assert(f() == 5, ""); // expected-error {{not an integral constant expression}} \
// expected-note {{undefined function 'f'}} \
// ref-error {{not an integral constant expression}} \
// ref-note {{undefined function 'f'}}
constexpr int a() {
return f();
}
constexpr int f() {
return 5;
}
static_assert(a() == 5, "");
constexpr int invalid() {
// Invalid expression in visit().
while(huh) {} // expected-error {{use of undeclared identifier}} \
// ref-error {{use of undeclared identifier}}
return 0;
}
constexpr void invalid2() {
int i = 0;
// Invalid expression in discard().
huh(); // expected-error {{use of undeclared identifier}} \
// ref-error {{use of undeclared identifier}}
}
namespace FunctionPointers {
constexpr int add(int a, int b) {
return a + b;
}
struct S { int a; };
constexpr S getS() {
return S{12};
}
constexpr int applyBinOp(int a, int b, int (*op)(int, int)) {
return op(a, b);
}
static_assert(applyBinOp(1, 2, add) == 3, "");
constexpr int ignoreReturnValue() {
int (*foo)(int, int) = add;
foo(1, 2);
return 1;
}
static_assert(ignoreReturnValue() == 1, "");
constexpr int createS(S (*gimme)()) {
gimme(); // Ignored return value
return gimme().a;
}
static_assert(createS(getS) == 12, "");
namespace FunctionReturnType {
typedef int (*ptr)(int*);
typedef ptr (*pm)();
constexpr int fun1(int* y) {
return *y + 10;
}
constexpr ptr fun() {
return &fun1;
}
static_assert(fun() == nullptr, ""); // expected-error {{static assertion failed}} \
// ref-error {{static assertion failed}}
constexpr int foo() {
int (*f)(int *) = fun();
int m = 0;
m = f(&m);
return m;
}
static_assert(foo() == 10, "");
struct S {
int i;
void (*fp)();
};
constexpr S s{ 12 };
static_assert(s.fp == nullptr, ""); // zero-initialized function pointer.
}
namespace Comparison {
void f(), g();
constexpr void (*pf)() = &f, (*pg)() = &g;
constexpr bool u13 = pf < pg; // ref-warning {{ordered comparison of function pointers}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{comparison between '&f' and '&g' has unspecified value}} \
// expected-warning {{ordered comparison of function pointers}} \
// expected-error {{must be initialized by a constant expression}} \
// expected-note {{comparison between '&f' and '&g' has unspecified value}}
constexpr bool u14 = pf < (void(*)())nullptr; // ref-warning {{ordered comparison of function pointers}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{comparison between '&f' and 'nullptr' has unspecified value}} \
// expected-warning {{ordered comparison of function pointers}} \
// expected-error {{must be initialized by a constant expression}} \
// expected-note {{comparison between '&f' and 'nullptr' has unspecified value}}
static_assert(pf != pg, "");
static_assert(pf == &f, "");
static_assert(pg == &g, "");
}
}
struct F {
constexpr bool ok() const {
return okRecurse();
}
constexpr bool okRecurse() const {
return true;
}
};
struct BodylessMemberFunction {
constexpr int first() const {
return second();
}
constexpr int second() const {
return 1;
}
};
constexpr int nyd(int m);
constexpr int doit() { return nyd(10); }
constexpr int nyd(int m) { return m; }
static_assert(doit() == 10, "");
namespace InvalidCall {
struct S {
constexpr int a() const { // expected-error {{never produces a constant expression}} \
// ref-error {{never produces a constant expression}}
return 1 / 0; // expected-note 2{{division by zero}} \
// expected-warning {{is undefined}} \
// ref-note 2{{division by zero}} \
// ref-warning {{is undefined}}
}
};
constexpr S s;
static_assert(s.a() == 1, ""); // expected-error {{not an integral constant expression}} \
// expected-note {{in call to}} \
// ref-error {{not an integral constant expression}} \
// ref-note {{in call to}}
/// This used to cause an assertion failure in the new constant interpreter.
constexpr void func(); // expected-note {{declared here}} \
// ref-note {{declared here}}
struct SS {
constexpr SS() { func(); } // expected-note {{undefined function }} \
// ref-note {{undefined function}}
};
constexpr SS ss; // expected-error {{must be initialized by a constant expression}} \
// expected-note {{in call to 'SS()'}} \
// ref-error {{must be initialized by a constant expression}} \
// ref-note {{in call to 'SS()'}}
}
|