130 lines · cpp
1// RUN: %clang_cc1 -fsyntax-only %s2// RUN: %clang_cc1 -fsyntax-only -std=c++20 -DWITH_AUTO_FUNCTION_PARAMETER=1 %s3 4// When __array_rank is used with a template type parameter, this test5// ensures clang considers the final expression could be used with6// static_assert/constexpr.7//8// Although array_extent was handled well, we add it as a precaution.9 10template <typename T>11using remove_reference_t = __remove_reference_t(T);12 13template <typename T, int N>14constexpr int array_rank(T (&lhs)[N]) {15 return __array_rank(T[N]);16}17 18template <int I, typename T, int N>19 constexpr int array_extent(T (&lhs)[N]) {20 return __array_extent(T[N], I);21}22 23template <typename T>24struct Rank {25 using ArrayT = remove_reference_t<T>;26 27 template <int N>28 static constexpr int call(ArrayT (&lhs)[N]) {29 return __array_rank(ArrayT[N]);30 }31};32 33template <typename T>34struct Extent {35 using ArrayT = remove_reference_t<T>;36 37 template <int I, int N>38 static constexpr int call(ArrayT (&lhs)[N]) {39 return __array_extent(ArrayT[N], I);40 }41};42 43#ifdef WITH_AUTO_FUNCTION_PARAMETER44template <int N>45constexpr int array_rank_auto(auto (&lhs)[N]) {46 return __array_rank(remove_reference_t<decltype(lhs[0])>[N]);47}48 49template <int I, int N>50constexpr int array_extent_auto(auto (&lhs)[N]) {51 return __array_extent(remove_reference_t<decltype(lhs[0])>[N], I);52}53#endif54 55template <int N>56constexpr int array_rank_int(const int (&lhs)[N]) {57 return __array_rank(const int[N]);58}59 60template <int I, int N>61constexpr int array_extent_int(const int (&lhs)[N]) {62 return __array_extent(const int[N], I);63}64 65template <int M, int N>66constexpr int array_rank_int(const int (&lhs)[M][N]) {67 return __array_rank(const int[M][N]);68}69 70template <int I, int M, int N>71constexpr int array_extent_int(const int (&lhs)[M][N]) {72 return __array_extent(const int[M][N], I);73}74 75int main() {76 constexpr int vec[] = {0, 1, 2, 1};77 constexpr int mat[4][4] = {78 {1, 0, 0, 0},79 {0, 1, 0, 0},80 {0, 0, 1, 0},81 {0, 0, 0, 1}82 };83 84#define ATT_TESTS_WITH_ASSERT(ATT_ASSERT) \85 { ATT_ASSERT(RANK(vec) == 1); } \86 { ATT_ASSERT(RANK(mat) == 2); } \87 { ATT_ASSERT(EXTENT(vec, 0) == 4); } \88 { ATT_ASSERT(EXTENT(vec, 1) == 0); } \89 { ATT_ASSERT(EXTENT(mat, 1) == 4); }90 91#define ATT_TESTS() \92 ATT_TESTS_WITH_ASSERT( constexpr bool cst = ) \93 ATT_TESTS_WITH_ASSERT( (void) ) \94 ATT_TESTS_WITH_ASSERT( static_assert )95 96 {97#define RANK(lhs) array_rank(lhs)98#define EXTENT(lhs, i) array_extent<i>(lhs)99 ATT_TESTS();100#undef RANK101#undef EXTENT102 }103 104 {105#define RANK(lhs) Rank<decltype(lhs[0])>::call(lhs)106#define EXTENT(lhs, i) Extent<decltype(lhs[0])>::call<i>(lhs)107 ATT_TESTS();108#undef RANK109#undef EXTENT110 }111 112#ifdef WITH_AUTO_FUNCTION_PARAMETER113 {114#define RANK(lhs) array_rank_auto(lhs)115#define EXTENT(lhs, i) array_extent_auto<i>(lhs)116 ATT_TESTS();117#undef RANK118#undef EXTENT119 }120#endif121 122 {123#define RANK(lhs) array_rank_int(lhs)124#define EXTENT(lhs, i) array_extent_int<i>(lhs)125 ATT_TESTS();126#undef RANK127#undef EXTENT128 }129}130