12d2a3ad8SAndrii Nakryiko // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
22d2a3ad8SAndrii Nakryiko 
32d2a3ad8SAndrii Nakryiko /*
42d2a3ad8SAndrii Nakryiko  * BTF-to-C dumper test for majority of C syntax quirks.
52d2a3ad8SAndrii Nakryiko  *
62d2a3ad8SAndrii Nakryiko  * Copyright (c) 2019 Facebook
72d2a3ad8SAndrii Nakryiko  */
82d2a3ad8SAndrii Nakryiko /* ----- START-EXPECTED-OUTPUT ----- */
92d2a3ad8SAndrii Nakryiko enum e1 {
102d2a3ad8SAndrii Nakryiko 	A = 0,
112d2a3ad8SAndrii Nakryiko 	B = 1,
122d2a3ad8SAndrii Nakryiko };
132d2a3ad8SAndrii Nakryiko 
142d2a3ad8SAndrii Nakryiko enum e2 {
152d2a3ad8SAndrii Nakryiko 	C = 100,
167cb30aaaSAndrii Nakryiko 	D = 4294967295,
172d2a3ad8SAndrii Nakryiko 	E = 0,
182d2a3ad8SAndrii Nakryiko };
192d2a3ad8SAndrii Nakryiko 
202d2a3ad8SAndrii Nakryiko typedef enum e2 e2_t;
212d2a3ad8SAndrii Nakryiko 
222d2a3ad8SAndrii Nakryiko typedef enum {
232d2a3ad8SAndrii Nakryiko 	F = 0,
242d2a3ad8SAndrii Nakryiko 	G = 1,
252d2a3ad8SAndrii Nakryiko 	H = 2,
262d2a3ad8SAndrii Nakryiko } e3_t;
272d2a3ad8SAndrii Nakryiko 
289d234974SAndrii Nakryiko /* ----- START-EXPECTED-OUTPUT ----- */
299d234974SAndrii Nakryiko /*
309d234974SAndrii Nakryiko  *enum e_byte {
319d234974SAndrii Nakryiko  *	EBYTE_1 = 0,
329d234974SAndrii Nakryiko  *	EBYTE_2 = 1,
339d234974SAndrii Nakryiko  *} __attribute__((mode(byte)));
349d234974SAndrii Nakryiko  *
359d234974SAndrii Nakryiko  */
369d234974SAndrii Nakryiko /* ----- END-EXPECTED-OUTPUT ----- */
379d234974SAndrii Nakryiko enum e_byte {
389d234974SAndrii Nakryiko 	EBYTE_1,
399d234974SAndrii Nakryiko 	EBYTE_2,
409d234974SAndrii Nakryiko } __attribute__((mode(byte)));
419d234974SAndrii Nakryiko 
429d234974SAndrii Nakryiko /* ----- START-EXPECTED-OUTPUT ----- */
439d234974SAndrii Nakryiko /*
449d234974SAndrii Nakryiko  *enum e_word {
459d234974SAndrii Nakryiko  *	EWORD_1 = 0LL,
469d234974SAndrii Nakryiko  *	EWORD_2 = 1LL,
479d234974SAndrii Nakryiko  *} __attribute__((mode(word)));
489d234974SAndrii Nakryiko  *
499d234974SAndrii Nakryiko  */
509d234974SAndrii Nakryiko /* ----- END-EXPECTED-OUTPUT ----- */
519d234974SAndrii Nakryiko enum e_word {
529d234974SAndrii Nakryiko 	EWORD_1,
539d234974SAndrii Nakryiko 	EWORD_2,
549d234974SAndrii Nakryiko } __attribute__((mode(word))); /* force to use 8-byte backing for this enum */
559d234974SAndrii Nakryiko 
569d234974SAndrii Nakryiko /* ----- START-EXPECTED-OUTPUT ----- */
579d234974SAndrii Nakryiko enum e_big {
589d234974SAndrii Nakryiko 	EBIG_1 = 1000000000000ULL,
599d234974SAndrii Nakryiko };
609d234974SAndrii Nakryiko 
612d2a3ad8SAndrii Nakryiko typedef int int_t;
622d2a3ad8SAndrii Nakryiko 
632d2a3ad8SAndrii Nakryiko typedef volatile const int * volatile const crazy_ptr_t;
642d2a3ad8SAndrii Nakryiko 
652d2a3ad8SAndrii Nakryiko typedef int *****we_need_to_go_deeper_ptr_t;
662d2a3ad8SAndrii Nakryiko 
672d2a3ad8SAndrii Nakryiko typedef volatile const we_need_to_go_deeper_ptr_t * restrict * volatile * const * restrict volatile * restrict const * volatile const * restrict volatile const how_about_this_ptr_t;
682d2a3ad8SAndrii Nakryiko 
692d2a3ad8SAndrii Nakryiko typedef int *ptr_arr_t[10];
702d2a3ad8SAndrii Nakryiko 
712d2a3ad8SAndrii Nakryiko typedef void (*fn_ptr1_t)(int);
722d2a3ad8SAndrii Nakryiko 
732d2a3ad8SAndrii Nakryiko typedef void (*printf_fn_t)(const char *, ...);
742d2a3ad8SAndrii Nakryiko 
752d2a3ad8SAndrii Nakryiko /* ------ END-EXPECTED-OUTPUT ------ */
762d2a3ad8SAndrii Nakryiko /*
772d2a3ad8SAndrii Nakryiko  * While previous function pointers are pretty trivial (C-syntax-level
782d2a3ad8SAndrii Nakryiko  * trivial), the following are deciphered here for future generations:
792d2a3ad8SAndrii Nakryiko  *
802d2a3ad8SAndrii Nakryiko  * - `fn_ptr2_t`: function, taking anonymous struct as a first arg and pointer
812d2a3ad8SAndrii Nakryiko  *   to a function, that takes int and returns int, as a second arg; returning
822d2a3ad8SAndrii Nakryiko  *   a pointer to a const pointer to a char. Equivalent to:
832d2a3ad8SAndrii Nakryiko  *	typedef struct { int a; } s_t;
842d2a3ad8SAndrii Nakryiko  *	typedef int (*fn_t)(int);
852d2a3ad8SAndrii Nakryiko  *	typedef char * const * (*fn_ptr2_t)(s_t, fn_t);
862d2a3ad8SAndrii Nakryiko  *
87*df71a42cSTaichi Nishimura  * - `fn_complex_t`: pointer to a function returning struct and accepting
882d2a3ad8SAndrii Nakryiko  *   union and struct. All structs and enum are anonymous and defined inline.
892d2a3ad8SAndrii Nakryiko  *
902d2a3ad8SAndrii Nakryiko  * - `signal_t: pointer to a function accepting a pointer to a function as an
912d2a3ad8SAndrii Nakryiko  *   argument and returning pointer to a function as a result. Sane equivalent:
922d2a3ad8SAndrii Nakryiko  *	typedef void (*signal_handler_t)(int);
932d2a3ad8SAndrii Nakryiko  *	typedef signal_handler_t (*signal_ptr_t)(int, signal_handler_t);
942d2a3ad8SAndrii Nakryiko  *
952d2a3ad8SAndrii Nakryiko  * - fn_ptr_arr1_t: array of pointers to a function accepting pointer to
962d2a3ad8SAndrii Nakryiko  *   a pointer to an int and returning pointer to a char. Easy.
972d2a3ad8SAndrii Nakryiko  *
982d2a3ad8SAndrii Nakryiko  * - fn_ptr_arr2_t: array of const pointers to a function taking no arguments
992d2a3ad8SAndrii Nakryiko  *   and returning a const pointer to a function, that takes pointer to a
1002d2a3ad8SAndrii Nakryiko  *   `int -> char *` function and returns pointer to a char. Equivalent:
1012d2a3ad8SAndrii Nakryiko  *   typedef char * (*fn_input_t)(int);
1022d2a3ad8SAndrii Nakryiko  *   typedef char * (*fn_output_outer_t)(fn_input_t);
1032d2a3ad8SAndrii Nakryiko  *   typedef const fn_output_outer_t (* fn_output_inner_t)();
1042d2a3ad8SAndrii Nakryiko  *   typedef const fn_output_inner_t fn_ptr_arr2_t[5];
1052d2a3ad8SAndrii Nakryiko  */
1062d2a3ad8SAndrii Nakryiko /* ----- START-EXPECTED-OUTPUT ----- */
1072d2a3ad8SAndrii Nakryiko typedef char * const * (*fn_ptr2_t)(struct {
1082d2a3ad8SAndrii Nakryiko 	int a;
1092d2a3ad8SAndrii Nakryiko }, int (*)(int));
1102d2a3ad8SAndrii Nakryiko 
1112d2a3ad8SAndrii Nakryiko typedef struct {
1122d2a3ad8SAndrii Nakryiko 	int a;
1132d2a3ad8SAndrii Nakryiko 	void (*b)(int, struct {
1142d2a3ad8SAndrii Nakryiko 		int c;
1152d2a3ad8SAndrii Nakryiko 	}, union {
1162d2a3ad8SAndrii Nakryiko 		char d;
1172d2a3ad8SAndrii Nakryiko 		int e[5];
1182d2a3ad8SAndrii Nakryiko 	});
1192d2a3ad8SAndrii Nakryiko } (*fn_complex_t)(union {
1202d2a3ad8SAndrii Nakryiko 	void *f;
1212d2a3ad8SAndrii Nakryiko 	char g[16];
1222d2a3ad8SAndrii Nakryiko }, struct {
1232d2a3ad8SAndrii Nakryiko 	int h;
1242d2a3ad8SAndrii Nakryiko });
1252d2a3ad8SAndrii Nakryiko 
1262d2a3ad8SAndrii Nakryiko typedef void (* (*signal_t)(int, void (*)(int)))(int);
1272d2a3ad8SAndrii Nakryiko 
1282d2a3ad8SAndrii Nakryiko typedef char * (*fn_ptr_arr1_t[10])(int **);
1292d2a3ad8SAndrii Nakryiko 
1304050764cSYonghong Song typedef char * (* (* const fn_ptr_arr2_t[5])())(char * (*)(int));
1312d2a3ad8SAndrii Nakryiko 
1322d2a3ad8SAndrii Nakryiko struct struct_w_typedefs {
1332d2a3ad8SAndrii Nakryiko 	int_t a;
1342d2a3ad8SAndrii Nakryiko 	crazy_ptr_t b;
1352d2a3ad8SAndrii Nakryiko 	we_need_to_go_deeper_ptr_t c;
1362d2a3ad8SAndrii Nakryiko 	how_about_this_ptr_t d;
1372d2a3ad8SAndrii Nakryiko 	ptr_arr_t e;
1382d2a3ad8SAndrii Nakryiko 	fn_ptr1_t f;
1392d2a3ad8SAndrii Nakryiko 	printf_fn_t g;
1402d2a3ad8SAndrii Nakryiko 	fn_ptr2_t h;
1412d2a3ad8SAndrii Nakryiko 	fn_complex_t i;
1422d2a3ad8SAndrii Nakryiko 	signal_t j;
1432d2a3ad8SAndrii Nakryiko 	fn_ptr_arr1_t k;
1442d2a3ad8SAndrii Nakryiko 	fn_ptr_arr2_t l;
1452d2a3ad8SAndrii Nakryiko };
1462d2a3ad8SAndrii Nakryiko 
1472d2a3ad8SAndrii Nakryiko typedef struct {
1482d2a3ad8SAndrii Nakryiko 	int x;
1492d2a3ad8SAndrii Nakryiko 	int y;
1502d2a3ad8SAndrii Nakryiko 	int z;
1512d2a3ad8SAndrii Nakryiko } anon_struct_t;
1522d2a3ad8SAndrii Nakryiko 
1532d2a3ad8SAndrii Nakryiko struct struct_fwd;
1542d2a3ad8SAndrii Nakryiko 
1552d2a3ad8SAndrii Nakryiko typedef struct struct_fwd struct_fwd_t;
1562d2a3ad8SAndrii Nakryiko 
1572d2a3ad8SAndrii Nakryiko typedef struct struct_fwd *struct_fwd_ptr_t;
1582d2a3ad8SAndrii Nakryiko 
1592d2a3ad8SAndrii Nakryiko union union_fwd;
1602d2a3ad8SAndrii Nakryiko 
1612d2a3ad8SAndrii Nakryiko typedef union union_fwd union_fwd_t;
1622d2a3ad8SAndrii Nakryiko 
1632d2a3ad8SAndrii Nakryiko typedef union union_fwd *union_fwd_ptr_t;
1642d2a3ad8SAndrii Nakryiko 
1652d2a3ad8SAndrii Nakryiko struct struct_empty {};
1662d2a3ad8SAndrii Nakryiko 
1672d2a3ad8SAndrii Nakryiko struct struct_simple {
1682d2a3ad8SAndrii Nakryiko 	int a;
1692d2a3ad8SAndrii Nakryiko 	char b;
1702d2a3ad8SAndrii Nakryiko 	const int_t *p;
1712d2a3ad8SAndrii Nakryiko 	struct struct_empty s;
1722d2a3ad8SAndrii Nakryiko 	enum e2 e;
1732d2a3ad8SAndrii Nakryiko 	enum {
1742d2a3ad8SAndrii Nakryiko 		ANON_VAL1 = 1,
1752d2a3ad8SAndrii Nakryiko 		ANON_VAL2 = 2,
1762d2a3ad8SAndrii Nakryiko 	} f;
1772d2a3ad8SAndrii Nakryiko 	int arr1[13];
1782d2a3ad8SAndrii Nakryiko 	enum e2 arr2[5];
1792d2a3ad8SAndrii Nakryiko };
1802d2a3ad8SAndrii Nakryiko 
1812d2a3ad8SAndrii Nakryiko union union_empty {};
1822d2a3ad8SAndrii Nakryiko 
1832d2a3ad8SAndrii Nakryiko union union_simple {
1842d2a3ad8SAndrii Nakryiko 	void *ptr;
1852d2a3ad8SAndrii Nakryiko 	int num;
1862d2a3ad8SAndrii Nakryiko 	int_t num2;
1872d2a3ad8SAndrii Nakryiko 	union union_empty u;
1882d2a3ad8SAndrii Nakryiko };
1892d2a3ad8SAndrii Nakryiko 
1902d2a3ad8SAndrii Nakryiko struct struct_in_struct {
1912d2a3ad8SAndrii Nakryiko 	struct struct_simple simple;
1922d2a3ad8SAndrii Nakryiko 	union union_simple also_simple;
1932d2a3ad8SAndrii Nakryiko 	struct {
1942d2a3ad8SAndrii Nakryiko 		int a;
1952d2a3ad8SAndrii Nakryiko 	} not_so_hard_as_well;
1962d2a3ad8SAndrii Nakryiko 	union {
1972d2a3ad8SAndrii Nakryiko 		int b;
1982d2a3ad8SAndrii Nakryiko 		int c;
1992d2a3ad8SAndrii Nakryiko 	} anon_union_is_good;
2002d2a3ad8SAndrii Nakryiko 	struct {
2012d2a3ad8SAndrii Nakryiko 		int d;
2022d2a3ad8SAndrii Nakryiko 		int e;
2032d2a3ad8SAndrii Nakryiko 	};
2042d2a3ad8SAndrii Nakryiko 	union {
2052d2a3ad8SAndrii Nakryiko 		int f;
2062d2a3ad8SAndrii Nakryiko 		int g;
2072d2a3ad8SAndrii Nakryiko 	};
2082d2a3ad8SAndrii Nakryiko };
2092d2a3ad8SAndrii Nakryiko 
210f118aac6SJean-Philippe Brucker struct struct_in_array {};
211f118aac6SJean-Philippe Brucker 
212f118aac6SJean-Philippe Brucker struct struct_in_array_typed {};
213f118aac6SJean-Philippe Brucker 
214f118aac6SJean-Philippe Brucker typedef struct struct_in_array_typed struct_in_array_t[2];
215f118aac6SJean-Philippe Brucker 
2162d2a3ad8SAndrii Nakryiko struct struct_with_embedded_stuff {
2172d2a3ad8SAndrii Nakryiko 	int a;
2182d2a3ad8SAndrii Nakryiko 	struct {
2192d2a3ad8SAndrii Nakryiko 		int b;
2202d2a3ad8SAndrii Nakryiko 		struct {
2212d2a3ad8SAndrii Nakryiko 			struct struct_with_embedded_stuff *c;
2222d2a3ad8SAndrii Nakryiko 			const char *d;
2232d2a3ad8SAndrii Nakryiko 		} e;
2242d2a3ad8SAndrii Nakryiko 		union {
2257e3cbd34SYucong Sun 			volatile long f;
2262d2a3ad8SAndrii Nakryiko 			void * restrict g;
2272d2a3ad8SAndrii Nakryiko 		};
2282d2a3ad8SAndrii Nakryiko 	};
2292d2a3ad8SAndrii Nakryiko 	union {
2302d2a3ad8SAndrii Nakryiko 		const int_t *h;
2312d2a3ad8SAndrii Nakryiko 		void (*i)(char, int, void *);
2322d2a3ad8SAndrii Nakryiko 	} j;
2332d2a3ad8SAndrii Nakryiko 	enum {
2342d2a3ad8SAndrii Nakryiko 		K = 100,
2352d2a3ad8SAndrii Nakryiko 		L = 200,
2362d2a3ad8SAndrii Nakryiko 	} m;
2372d2a3ad8SAndrii Nakryiko 	char n[16];
2382d2a3ad8SAndrii Nakryiko 	struct {
2392d2a3ad8SAndrii Nakryiko 		char o;
2402d2a3ad8SAndrii Nakryiko 		int p;
2412d2a3ad8SAndrii Nakryiko 		void (*q)(int);
2422d2a3ad8SAndrii Nakryiko 	} r[5];
2432d2a3ad8SAndrii Nakryiko 	struct struct_in_struct s[10];
2442d2a3ad8SAndrii Nakryiko 	int t[11];
245f118aac6SJean-Philippe Brucker 	struct struct_in_array (*u)[2];
246f118aac6SJean-Philippe Brucker 	struct_in_array_t *v;
2472d2a3ad8SAndrii Nakryiko };
2482d2a3ad8SAndrii Nakryiko 
249ccb0e23cSIlya Leoshkevich struct float_struct {
250ccb0e23cSIlya Leoshkevich 	float f;
251ccb0e23cSIlya Leoshkevich 	const double *d;
252ccb0e23cSIlya Leoshkevich 	volatile long double *ld;
253ccb0e23cSIlya Leoshkevich };
254ccb0e23cSIlya Leoshkevich 
2552d2a3ad8SAndrii Nakryiko struct root_struct {
2562d2a3ad8SAndrii Nakryiko 	enum e1 _1;
2572d2a3ad8SAndrii Nakryiko 	enum e2 _2;
2582d2a3ad8SAndrii Nakryiko 	e2_t _2_1;
2592d2a3ad8SAndrii Nakryiko 	e3_t _2_2;
2609d234974SAndrii Nakryiko 	enum e_byte _100;
2619d234974SAndrii Nakryiko 	enum e_word _101;
2629d234974SAndrii Nakryiko 	enum e_big _102;
2632d2a3ad8SAndrii Nakryiko 	struct struct_w_typedefs _3;
2642d2a3ad8SAndrii Nakryiko 	anon_struct_t _7;
2652d2a3ad8SAndrii Nakryiko 	struct struct_fwd *_8;
2662d2a3ad8SAndrii Nakryiko 	struct_fwd_t *_9;
2672d2a3ad8SAndrii Nakryiko 	struct_fwd_ptr_t _10;
2682d2a3ad8SAndrii Nakryiko 	union union_fwd *_11;
2692d2a3ad8SAndrii Nakryiko 	union_fwd_t *_12;
2702d2a3ad8SAndrii Nakryiko 	union_fwd_ptr_t _13;
2712d2a3ad8SAndrii Nakryiko 	struct struct_with_embedded_stuff _14;
272ccb0e23cSIlya Leoshkevich 	struct float_struct _15;
2732d2a3ad8SAndrii Nakryiko };
2742d2a3ad8SAndrii Nakryiko 
2752d2a3ad8SAndrii Nakryiko /* ------ END-EXPECTED-OUTPUT ------ */
2762d2a3ad8SAndrii Nakryiko 
f(struct root_struct * s)2772d2a3ad8SAndrii Nakryiko int f(struct root_struct *s)
2782d2a3ad8SAndrii Nakryiko {
2792d2a3ad8SAndrii Nakryiko 	return 0;
2802d2a3ad8SAndrii Nakryiko }
281