137 lines · c
1// RUN: %clang_cc1 -std=c2x -fsyntax-only -verify -Wno-unused %s2// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused -x c++ -std=c++17 %s3 4// Test that the semantic behavior of the extension allowing the user to pass a5// type as the first argument to _Generic.6 7// Test that we match on basic types.8static_assert(_Generic(int, int : 1, default : 0) == 1);9static_assert(_Generic(_BitInt(12), int : 1, _BitInt(10) : 2, _BitInt(12) : 3) == 3);10 11// Test that we correctly fall back to the default association appropriately.12static_assert(_Generic(int, long : 1, default : 0) == 0);13 14// Ensure we correctly match constant arrays by their extent.15static_assert(_Generic(int[12], int[0] : 0, int * : 0, int[12] : 1, default : 0) == 1);16 17// Ensure we correctly match function types by their signature.18static_assert(_Generic(int(int), void(void) : 0, int(void) : 0, void(int) : 0, int(int) : 1, default : 0) == 1);19 20// Test that we still diagnose when no associations match and that the21// diagnostic includes qualifiers.22static_assert(_Generic(const int, long : 1)); // expected-error {{controlling expression type 'const int' not compatible with any generic association type}}23 24// Test that qualifiers work as expected and do not issue a diagnostic when25// using the type form.26static_assert(_Generic(const int, int : 0, const int : 1) == 1);27static_assert(_Generic(int volatile _Atomic const, int : 0, const int : 0, volatile int : 0, _Atomic int : 0, _Atomic const volatile int : 1) == 1);28 29// Test that inferred qualifiers also work as expected.30const int ci = 0;31static_assert(_Generic(__typeof__(ci), int : 0, const int : 1) == 1);32// And that the expression form still complains about qualified associations33// and matches the correct association.34static_assert(_Generic(ci, int : 1, const int : 0) == 1); // expected-warning {{due to lvalue conversion of the controlling expression, association of type 'const int' will never be selected because it is qualified}}35 36// The type operand form of _Generic allows incomplete and non-object types,37// but the expression operand form still rejects them.38static_assert(_Generic(struct incomplete, struct incomplete : 1, default : 0) == 1);39static_assert(_Generic(struct another_incomplete, struct incomplete : 1, default : 0) == 0);40static_assert(_Generic(1, struct also_incomplete : 1, default : 0) == 0);41 42void foo(int);43static_assert(_Generic(__typeof__(foo), void(int) : 1, default : 0) == 1);44static_assert(_Generic(foo, void(int) : 1, default : 0) == 0); // expected-error {{type 'void (int)' in generic association not an object type}}45 46// Ensure we still get a diagnostic for duplicated associations for the type47// form, even when using qualified type, and that the diagnostic includes48// qualifiers.49static_assert(_Generic(const int,50 const int : 1, // expected-note {{compatible type 'const int' specified here}}51 int : 2,52 const int : 3 // expected-error {{type 'const int' in generic association compatible with previously specified type 'const int'}}53 ) == 1);54 55// Verify that we are matching using the canonical type of the type operand...56typedef int Int;57typedef const Int CInt;58typedef CInt OtherCInt;59static_assert(_Generic(volatile CInt, const volatile int : 1, default : 0) == 1);60static_assert(_Generic(const int, CInt : 1, default : 0) == 1);61 62// ...and that duplicate associations are doing so as well.63static_assert(_Generic(const int,64 CInt : 1, // expected-note {{compatible type 'CInt' (aka 'const int') specified here}}65 const volatile int : 2,66 OtherCInt : 3 // expected-error {{type 'OtherCInt' (aka 'const int') in generic association compatible with previously specified type 'CInt' (aka 'const int')}}67 ) == 1);68 69// Also test that duplicate array or function types are caught.70static_assert(_Generic(const int,71 int[12] : 0, // expected-note {{compatible type 'int[12]' specified here}}72 int[12] : 0, // expected-error {{type 'int[12]' in generic association compatible with previously specified type 'int[12]'}}73 int(int) : 0, // expected-note {{compatible type 'int (int)' specified here}}74 int(int) : 0, // expected-error {{type 'int (int)' in generic association compatible with previously specified type 'int (int)'}}75 default : 176 ) == 1);77 78 79// Tests that only make sense for C++:80#ifdef __cplusplus81// Ensure that _Generic works within a template argument list.82template <typename Ty, int N = _Generic(Ty, int : 0, default : 1)>83constexpr Ty bar() { return N; }84 85static_assert(bar<int>() == 0);86static_assert(bar<float>() == 1);87 88// Or that it can be used as a non-type template argument.89static_assert(bar<int, _Generic(int, int : 1, default : 0)>() == 1);90 91// Ensure that a dependent type works as expected.92template <typename Ty>93struct Dependent {94 // If we checked the type early, this would fail to compile without any95 // instantiation. Instead, it only fails with the bad instantiation.96 static_assert(_Generic(Ty, int : 1)); // expected-error {{controlling expression type 'double' not compatible with any generic association type}} \97 expected-note@#BadInstantiation {{in instantiation of template class 'Dependent<double>' requested here}}98};99 100template struct Dependent<int>; // Good instantiation101template struct Dependent<double>; // #BadInstantiation102 103// Another template instantiation test, this time for a variable template with104// a type-dependent initializer.105template <typename Ty>106constexpr auto Val = _Generic(Ty, Ty : Ty{});107 108static_assert(Val<int> == 0);109static_assert(__is_same(decltype(Val<Dependent<int>>), const Dependent<int>));110 111// Ensure that pack types also work as expected.112template <unsigned Arg, unsigned... Args> struct Or {113 enum { result = Arg | Or<Args...>::result };114};115 116template <unsigned Arg> struct Or<Arg> {117 enum { result = Arg };118};119 120template <class... Args> struct TypeMask {121 enum {122 result = Or<_Generic(Args, int: 1, long: 2, short: 4, float: 8)...>::result123 };124};125 126static_assert(TypeMask<int, long, short>::result == 7, "fail");127static_assert(TypeMask<float, short>::result == 12, "fail");128static_assert(TypeMask<int, float, float>::result == 9, "fail");129 130template <typename... T>131void f() {132 // Because _Generic only accepts a single type argument, it does not make133 // sense for it to accept a pack, so a pack is rejected while parsing.134 _Generic(T..., int : 1); // expected-error {{expected ','}}135}136#endif // __cplusplus137