|  | // RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-unused %s | 
|  | // RUN: %clang_cc1 -fsyntax-only -verify=expected,cpp -Wno-unused -x c++ -std=c++17 %s | 
|  |  | 
|  | // Test various parsing situations for the Clang extension to _Generic which | 
|  | // accepts a type name instead of an expression as the first operand. | 
|  |  | 
|  | int foo(); | 
|  |  | 
|  | void test() { | 
|  | // We can parse a simple type name. | 
|  | _Generic(int, int : 0); | 
|  |  | 
|  | // We can also parse tag types. | 
|  | struct S { int i; }; | 
|  | enum E { A }; | 
|  | union U { int i; }; | 
|  | _Generic(struct S, default : 0); | 
|  | _Generic(enum E, default : 0); | 
|  | _Generic(union U, default : 0); | 
|  |  | 
|  | // We can also parse array types. | 
|  | _Generic(int[12], default : 0); | 
|  |  | 
|  | // And pointer to array types, too. | 
|  | _Generic(int(*)[12], default : 0); | 
|  |  | 
|  | // We do not accept a parenthesized type name. | 
|  | _Generic((int), int : 0); // expected-error {{expected expression}} | 
|  |  | 
|  | // We can parse more complex types as well. Note, this is a valid spelling of | 
|  | // a function  pointer type in C but is not a valid spelling of a function | 
|  | // pointer type in C++. Surprise! | 
|  | _Generic(__typeof__(foo())(*)(__typeof__(&foo)), int (*)(int (*)()) : 0); // cpp-error {{expected expression}} \ | 
|  | cpp-error {{expected '(' for function-style cast or type construction}} | 
|  |  | 
|  | // C being the magical language that it is, lets you define a type anywhere | 
|  | // you can spell a type. | 
|  | _Generic(struct T { int a; }, default : 0); // cpp-error {{'T' cannot be defined in a type specifier}} | 
|  | } | 
|  |  | 
|  | #ifdef __cplusplus | 
|  | template <typename Ty> | 
|  | struct S { | 
|  | template <template <typename> typename Uy> | 
|  | struct T { | 
|  | typedef typename Uy<Ty>::type foo; | 
|  | }; | 
|  | }; | 
|  |  | 
|  | template <typename Ty> | 
|  | struct inst { | 
|  | typedef Ty type; | 
|  | }; | 
|  |  | 
|  | void cpp_test() { | 
|  | // Ensure we can parse more complex C++ typenames as well. | 
|  | _Generic(S<int>::T<inst>::foo, int : 1); | 
|  |  | 
|  | // And that the type name doesn't confuse us when given an initialization | 
|  | // expression. | 
|  | _Generic(S<int>::T<inst>::foo{}, int : 1); | 
|  | } | 
|  |  | 
|  | template <typename Ty, int N = _Generic(Ty, int : 0, default : 1)> | 
|  | constexpr Ty bar() { return N; } | 
|  |  | 
|  | static_assert(bar<int>() == 0); | 
|  | static_assert(bar<float>() == 1); | 
|  | #endif // __cplusplus |