diff --git a/test/val/constexpr.c b/test/val/constexpr.c new file mode 100644 index 000000000..c92302a58 --- /dev/null +++ b/test/val/constexpr.c @@ -0,0 +1,112 @@ + +/* + +This tests a couple of expressions which yield constant results. While we cant +really check if the compiler figures out they are constant, we can still check +if they are being compiled/evaluated correctly. + +related: + +pr #1424 - More compile-time constant expressions regarding object addresses +issue #1196 - Constant expressions in general + +*/ + +#include + +int fails = 0; + +#define TESTEXPR(expr) \ + if (!(expr)) { \ + printf("fail line %d\n", __LINE__); \ + fails++; \ + } + +#define TESTEXPRFALSE(expr) \ + if (expr) { \ + printf("fail line %d\n", __LINE__); \ + fails++; \ + } + +int a; +volatile int b; +const int c = 1; +#define d 1 +enum { e = 1 }; +int f() { return 1; } + +/* we cant really test these at runtime (because the result is constant, but not + * compile-time known), so compile only */ +void test0(void) +{ + TESTEXPR(a); /* Pure: Yes; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPR(b); /* Pure: No?; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPR(&a > &b); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: No */ +} + +void test1(void) +{ + TESTEXPR(1); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(c); /* Pure: Yes; Static: ???; Immutable: ???; Compile-Time-Known: ??? */ + TESTEXPR(d); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(e); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(c == c); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPRFALSE(c != c); + TESTEXPR(f() == f()); /* Pure: Yes; Static: Yes?; Immutable: Yes; Compile-Time-Known: Yes? */ + TESTEXPRFALSE(f() != f()); + TESTEXPR(&a == &a); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPRFALSE(&a != &a); + TESTEXPR(&a != 0); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes* */ + TESTEXPRFALSE(&a == 0); +/* in a real program we cant rely on these, but in this test we can */ + TESTEXPR(&a); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: No */ + TESTEXPR((int)&a != 0); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: No */ + TESTEXPRFALSE((int)&a == 0); + TESTEXPR(&a != &b); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: ??** */ + TESTEXPRFALSE(&a == &b); +/* this may fail in a real world program, but here we can rely on it anyway */ + TESTEXPR(b == b); /* Pure: No?; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPRFALSE(b != b); +/* NOT detected by the compiler as constant */ + TESTEXPR(a == a); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPRFALSE(a != a); + TESTEXPR(f()); /* Pure: Yes; Static: Yes?; Immutable: Yes; Compile-Time-Known: Yes? */ +} + +/* Taken from #1196 reply */ +struct S { + int a; + int b; +} s[2]; + +void test2(void) +{ + TESTEXPR((void*)&s == (void*)&s[0]); + TESTEXPRFALSE((void*)&s != (void*)&s[0]); + TESTEXPR(&s[0] < &s[1]); + TESTEXPR(&s[0].b > &s[0].a); + TESTEXPR(&s[0].b < &s[1].a); +} + +/* FIXME: how to deal with the extern stuff in the testbench? */ +extern int g(); + +void test3(void) +{ +#if 0 + TESTEXPR(g()); /* Pure: No; Static: No; Immutable: No; Compile-Time-Known: No */ + TESTEXPR(g(), 1); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR((void)g()); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ + TESTEXPR(sizeof(g())); /* Pure: Yes; Static: Yes; Immutable: Yes; Compile-Time-Known: Yes */ + /* NOT detected by the compiler as constant */ + TESTEXPR(g() * 0); /* Pure: No; Static: No; Immutable: Yes; Compile-Time-Known: Yes */ +#endif +} + +int main(void) +{ + test1(); + test2(); + test3(); + return fails; +}