|
5 | 5 | // RUN: %clang_cc1 -pedantic -std=c++14 -verify=ref,both %s |
6 | 6 | // RUN: %clang_cc1 -pedantic -std=c++20 -verify=ref,both %s |
7 | 7 |
|
| 8 | +#define fold(x) (__builtin_constant_p(0) ? (x) : (x)) |
| 9 | + |
8 | 10 | constexpr void doNothing() {} |
9 | 11 | constexpr int gimme5() { |
10 | 12 | doNothing(); |
@@ -654,14 +656,26 @@ namespace { |
654 | 656 | } |
655 | 657 |
|
656 | 658 | namespace FunctionCast { |
657 | | - // When folding, we allow functions to be cast to different types. Such |
658 | | - // cast functions cannot be called, even if they're constexpr. |
| 659 | + // When folding, we allow functions to be cast to different types. We only |
| 660 | + // allow calls if the dynamic type of the pointer matches the type of the |
| 661 | + // call. |
659 | 662 | constexpr int f() { return 1; } |
| 663 | + constexpr void* f2() { return nullptr; } |
| 664 | + constexpr int f3(int a) { return a; } |
660 | 665 | typedef double (*DoubleFn)(); |
661 | 666 | typedef int (*IntFn)(); |
662 | | - int a[(int)DoubleFn(f)()]; // both-error {{variable length array}} \ |
663 | | - // both-warning {{are a Clang extension}} |
664 | | - int b[(int)IntFn(f)()]; // ok |
| 667 | + typedef int* (*IntPtrFn)(); |
| 668 | + constexpr int test1 = (int)DoubleFn(f)(); // both-error {{constant expression}} both-note {{reinterpret_cast}} |
| 669 | + // FIXME: We should print a note explaining the error. |
| 670 | + constexpr int test2 = (int)fold(DoubleFn(f))(); // both-error {{constant expression}} |
| 671 | + constexpr int test3 = (int)IntFn(f)(); // no-op cast |
| 672 | + constexpr int test4 = fold(IntFn(DoubleFn(f)))(); |
| 673 | + constexpr int test5 = IntFn(fold(DoubleFn(f)))(); // both-error {{constant expression}} \ |
| 674 | + // both-note {{cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression}} |
| 675 | + // FIXME: Interpreter is less strict here. |
| 676 | + constexpr int test6 = fold(IntPtrFn(f2))() == nullptr; // ref-error {{constant expression}} |
| 677 | + // FIXME: The following crashes interpreter |
| 678 | + // constexpr int test6 = fold(IntFn(f3)()); |
665 | 679 | } |
666 | 680 |
|
667 | 681 | #if __cplusplus >= 202002L |
|
0 commit comments