1 | // RUN: %clang_cc1 -fsyntax-only -verify %s |
2 | |
3 | extern int funcInt(int); |
4 | extern float funcFloat(float); |
5 | extern double funcDouble(double); |
6 | // figure out why "char *" doesn't work (with gcc, nothing to do with clang) |
7 | //extern void funcCharPtr(char *); |
8 | |
9 | #define func(expr) \ |
10 | do { \ |
11 | typeof(expr) tmp; \ |
12 | if (__builtin_types_compatible_p(typeof(expr), int)) funcInt(tmp); \ |
13 | else if (__builtin_types_compatible_p(typeof(expr), float)) funcFloat(tmp); \ |
14 | else if (__builtin_types_compatible_p(typeof(expr), double)) funcDouble(tmp); \ |
15 | } while (0) |
16 | #define func_choose(expr) \ |
17 | __builtin_choose_expr(__builtin_types_compatible_p(typeof(expr), int), funcInt(expr), \ |
18 | __builtin_choose_expr(__builtin_types_compatible_p(typeof(expr), float), funcFloat(expr), \ |
19 | __builtin_choose_expr(__builtin_types_compatible_p(typeof(expr), double), funcDouble(expr), (void)0))) |
20 | |
21 | static void test() |
22 | { |
23 | int a; |
24 | float b; |
25 | double d; |
26 | |
27 | func(a); |
28 | func(b); |
29 | func(d); |
30 | a = func_choose(a); |
31 | b = func_choose(b); |
32 | d = func_choose(d); |
33 | |
34 | int c; |
35 | struct xx { int a; } x, y; |
36 | |
37 | c = __builtin_choose_expr(a+3-7, b, x); // expected-error{{'__builtin_choose_expr' requires a constant expression}} |
38 | c = __builtin_choose_expr(0, b, x); // expected-error{{assigning to 'int' from incompatible type 'struct xx'}} |
39 | c = __builtin_choose_expr(5+3-7, b, x); |
40 | y = __builtin_choose_expr(4+3-7, b, x); |
41 | |
42 | } |
43 | |
44 | enum E1 { E1Foo }; |
45 | enum E2 { E2Foo }; |
46 | |
47 | static void testGccCompatibility() { |
48 | _Static_assert(__builtin_types_compatible_p(const volatile int, int), ""); |
49 | _Static_assert(__builtin_types_compatible_p(int[5], int[]), ""); |
50 | _Static_assert(!__builtin_types_compatible_p(int[5], int[4]), ""); |
51 | _Static_assert(!__builtin_types_compatible_p(int *, int **), ""); |
52 | _Static_assert(!__builtin_types_compatible_p(const int *, int *), ""); |
53 | _Static_assert(!__builtin_types_compatible_p(enum E1, enum E2), ""); |
54 | |
55 | // GCC's __builtin_types_compatible_p ignores qualifiers on arrays. |
56 | _Static_assert(__builtin_types_compatible_p(const int[4], int[4]), ""); |
57 | _Static_assert(__builtin_types_compatible_p(int[4], const int[4]), ""); |
58 | _Static_assert(__builtin_types_compatible_p(const int[5][4], int[][4]), ""); |
59 | _Static_assert(!__builtin_types_compatible_p(const int(*)[], int(*)[]), ""); |
60 | } |
61 | |