struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / support / regression / tests / p99-conformance.c
blob870eff9aac4bee186432051cd1b510401bf0283f
1 /*
2 test-p99-conformance.c modified from the C conformance test of P99
3 */
5 /* This may look like nonsense, but it really is -*- mode: C; coding: utf-8 -*- */
6 /* */
7 /* Except of parts copied from previous work and as explicitly stated below, */
8 /* the author and copyright holder for this work is */
9 /* (C) copyright 2011 Jens Gustedt, INRIA, France */
10 /* */
11 /* This file is free software; it is part of the P99 project. */
12 /* You can redistribute it and/or modify it under the terms of the QPL as */
13 /* given in the file LICENSE. It is distributed without any warranty; */
14 /* without even the implied warranty of merchantability or fitness for a */
15 /* particular purpose. */
16 /* */
18 /**
19 ** @file
20 ** @brief conformance test for C99
22 ** This file only tests the "compiler" part of C, that is without any
23 ** include files. Any C implementation, whether hosted or
24 ** freestanding should comply to this.
26 ** To convince your compiler to compile this you have perhaps to
27 ** provide some additional parameters on the command line. E.g for
28 ** the gcc family of compilers (including third party pretenders) you
29 ** usually have to give "-std=c99" to switch to C99 mode. But other
30 ** parameters may be in order, consult your compiler documentation.
32 ** This file is split into several parts that hopefully are
33 ** self explaining. Each of the parts has a macro @c SKIP_... that
34 ** lets you skip a test.
35 **/
37 #include <testfwk.h>
39 #pragma disable_warning 85
41 #define SKIP_EVALUATED_COMMA_ASSIGN /* Looks like testing for some particular implementation-defined behaviour to me */
43 #ifdef PORT_HOST /* Common GCC issues */
44 # define SKIP_UNIVERSAL_UTF8 /* Only works for GCC when -finput-charset= option is specified */
45 # if (defined (__GNUC__) && __GNUC__ < 5)
46 # define SKIP_UNIVERSAL /* Fails for older GCC (works for me in 6.1.1 but fails on some SDCC build machines*/
47 # define SKIP_INLINE /* fails for some older GCC that is still used on the FreeBSD build machines */
48 # endif
49 #else /* SDCC issues */
50 # define SKIP_HEXDOUBLE /* bug #2536 */
51 # define SKIP_LONG_DOUBLE /* long double not yet supported */
52 # define SKIP_COMPOUND /* compound literals not yet supported */
53 # define SKIP_VLA /* variable-length arrays not supported */
54 # define SKIP_INLINE /* bug #1900 */
55 # define SKIP_PRAGMA /* Standard pragmas not supported */
56 # pragma disable_warning 93 /* Using float for double. */
57 # if defined(__SDCC_pic14) || defined(__SDCC_pic16)
58 # define SKIP_LONG_LONG
59 # endif
60 #endif
62 #ifdef __SDCC_pdk14 // Lack of memory
63 #define SKIP_INITIALIZERS
64 #define SKIP_COMPOUND
65 #define SKIP_EXPANDS
66 #define SKIP_FLEXIBLE
67 #define SKIP_LONG_LONG
68 #define SKIP_DIGRAPH
69 #define SKIP_TRIGRAPH
70 #define SKIP_UNIVERSAL
71 #endif
73 #if defined(__SDCC_mcs51) && defined(__SDCC_MODEL_SMALL) // Lack of memory
74 #define SKIP_UNIVERSAL
75 #endif
77 #ifndef SKIP_VA_ARGS_MACRO
78 # define FIRST(X, ...) X
79 # if FIRST(0, something)
80 # error "The preprocessor lacks variable argument list support. Run test with -DSKIP_VA_ARGS_MACRO to be able to see the other tests."
81 # endif
82 #endif
85 #ifndef SKIP_BOOL
86 enum { hasTrue = (_Bool)127, hasFalse = (_Bool)0 };
87 _Bool has_Bool[1];
88 _Bool has_Bool[hasTrue] = { hasFalse };
89 #endif
91 #ifndef SKIP_VLA
92 double has_VLA_function(unsigned n, double A[n][n]) {
93 double ret = 0.0;
94 unsigned i, j;
95 for (i = 0; i < n; ++i)
96 for (j = 0; j < n; ++j)
97 ret += A[i][j];
98 return ret;
100 double has_VLA(unsigned n) {
101 double VLA[n][n];
102 return has_VLA_function(n, VLA);
106 #endif
108 #ifndef SKIP_INLINE
109 typedef void (*func)(void);
111 /* This alone should not result in a generation of a symbol
112 "has_undefined_symbol1". It should even not have an entry as
113 "undefined" in the symbol table, but such an entry would be
114 tolerable. */
115 inline
116 void
117 has_undefined_symbol1(void) {
118 /* empty */
121 /* This alone should not result in a generation of a symbol
122 "undefined_symbol2" but insert an "undefined" symbol to such a
123 function in the symbol table. */
124 inline
125 void
126 has_undefined_symbol2(void) {
127 /* empty */
129 func undefined_symbol2_tester[] = { has_undefined_symbol2 };
131 /* This should result in a generation of a symbol has_mandatory_symbol1 */
132 inline
133 void
134 has_mandatory_symbol1(void) {
135 /* empty */
137 extern inline
138 void
139 has_mandatory_symbol1(void);
141 /* This should result in a generation of a symbol has_mandatory_symbol2 */
142 inline
143 void
144 has_mandatory_symbol2(void) {
145 /* empty */
147 func mandatory_symbol2_tester[] = { has_mandatory_symbol2 };
148 extern inline
149 void
150 has_mandatory_symbol2(void);
152 /* This should result in a generation of a symbol has_mandatory_symbol3 */
153 inline
154 void
155 has_mandatory_symbol3(void) {
156 /* empty */
158 void
159 has_mandatory_symbol3(void);
161 /* This should result in a generation of a symbol has_mandatory_symbol4 */
162 inline
163 void
164 has_mandatory_symbol4(void) {
165 /* empty */
167 func mandatory_symbol4_tester[] = { has_mandatory_symbol4 };
168 extern inline
169 void
170 has_mandatory_symbol4(void);
172 #endif
174 #ifndef SKIP_HEXDOUBLE
175 enum { hasHexdouble = (0x1P2 > 10) };
176 double has_hexdouble[hasHexdouble];
177 #endif
179 #ifndef SKIP_COMPOUND
180 unsigned has_compound_literal(void) {
181 return (unsigned){ 0 };
183 #endif
185 #ifndef SKIP_INITIALIZERS
186 unsigned has_designated_array_initializer[4] = { [3] = 1u };
187 unsigned A1[] = { [3] = 1u };
188 unsigned has_length_from_initializer[sizeof(has_designated_array_initializer) == sizeof(A1)];
189 struct {
190 unsigned first;
191 double second;
192 } has_designated_struct_initializer = { .second = 1, .first = 2 };
193 #endif
195 #define GLUE2(A, B) A ## B
196 #define CONCAT2(A, B) GLUE2(A, B)
197 #define STRINGIFY(A) STRINGIFY_(A)
198 #define STRINGIFY_(A) #A
200 #ifndef SKIP_TOKEN_CONCAT
201 double has_concat_of_floats_1E = CONCAT2(1E, 3);
202 double has_concat_of_floats_1Ep = CONCAT2(1E+, 3);
203 /* This one should iteratively compose a double value from left to
204 right. */
205 # ifndef SKIP_TOKEN_CONCAT_ITERATIVE
206 double has_concat_of_floats_iterative = CONCAT2(CONCAT2(CONCAT2(1, E), +), 3);
207 # endif
208 /* These ones are tricky. The terms inside the STRINGIFY should lead to
209 valid preprocessing tokens but which are invalid tokens for the
210 following phases. */
211 char const has_concat_of_floats_1Ep3Em[] = STRINGIFY(CONCAT2(CONCAT2(1E+, 3E-), 3));
212 # ifndef SKIP_TOKEN_HASH_HASH_AS_ARGUMENT
213 #define DONT_CONCAT_(X) A X B
214 #define DONT_CONCAT(X) DONT_CONCAT_(X)
215 char const has_hash_hash_as_argument[] = STRINGIFY(DONT_CONCAT(##));
216 # endif
217 # ifndef SKIP_TOKEN_CONCAT_HASH_HASH
218 char const has_concat_of_hash_hash[] = STRINGIFY(CONCAT2(#, #));
219 # endif
220 # ifndef SKIP_STRINGIFY_EMPTY
221 char const has_stringify_empty[] = STRINGIFY();
222 # endif
223 #endif
225 #ifndef SKIP_EXPANDS
227 /* expand arguments after assigment, but before call */
228 # define COMMA ,
229 # define GLUE1(X) GLUE2(X)
230 # define CONCAT3(A, B, C) GLUE2(A, B C)
231 # define GLUE3(A, B, C) A ## B ## C
232 unsigned has_determines_macro_arguments_first[GLUE1(0 COMMA 1)];
234 /* Expand args before ## concatenation? The rules for this are
235 subtle. */
236 # define EATEAT 0
237 # define EAT 1
238 enum { CONCAT2(eat, GLUE2(EAT, EAT)) = GLUE2(EAT, EAT),
239 CONCAT2(eat, CONCAT2(EAT, EAT)) = CONCAT2(EAT, EAT),
240 /* Only replace the empty argument by a placeholder if it is
241 preceded or followed by a ## in the replacement text. */
242 eat2 = CONCAT3(EAT,,EAT),
243 eat3 = GLUE3(EAT,,EAT),
245 unsigned has_preprocessor_expands_before_concatenation1[(eat0 == 0)*2 - 1] = { eat0 };
246 unsigned has_preprocessor_expands_before_concatenation2[(eat11 == 11)*2 - 1] = { eat0 };
247 unsigned has_preprocessor_no_placeholder_on_recursion[(eat2 == 11)*2 - 1] = { eat0 };
248 unsigned has_preprocessor_placeholder[(eat3 == 0)*2 - 1] = { eat0 };
249 #endif
251 #ifndef SKIP_TRAILING_COMMA
252 enum { enumConstant, } has_enum_trailing_commas;
253 unsigned has_initializer_trailing_commas[] = { 0, };
254 #endif
256 #ifndef SKIP_FLEXIBLE
257 typedef struct {
258 unsigned len;
259 double arr[];
260 } flexible;
261 typedef union {
262 flexible flex;
263 char buffer[sizeof(flexible) + 2*sizeof(double)];
264 } flex2;
265 flex2 has_flexible_array = { .flex.len = 2 };
266 #endif
268 #ifndef SKIP_RESTRICT
269 char restrict_buffer[4];
270 char *restrict has_restrict_keyword = restrict_buffer;
271 #endif
273 #ifndef SKIP_STATIC_PARAMETER
274 void has_static_parameter(double A[static 10]){
275 /* empty */
277 #endif
278 #ifndef SKIP_CONST_PARAMETER
279 void has_const_parameter(double A[const 10]){
280 /* empty */
282 #endif
283 #ifndef SKIP_VOLATILE_PARAMETER
284 void has_volatile_parameter(double A[volatile 10]){
285 /* empty */
287 #endif
288 #ifndef SKIP_RESTRICT_PARAMETER
289 # ifndef SKIP_RESTRICT
290 void has_restrict_parameter(double A[restrict 10]){
291 /* empty */
293 # endif
294 #endif
296 #ifndef SKIP_COMMENTS
297 enum { hasCppComment = -2
299 //* for C99 all of this is a comment to the end of the line */ 3
300 /* for C89 this resolves in division by 3 */
302 unsigned has_cpp_comment[hasCppComment];
303 #endif
305 #ifndef SKIP_MIXED
306 unsigned has_mixed_declaration(void) {
307 /* infinite recursion, but who cares */
308 has_mixed_declaration();
309 unsigned a = 10;
310 return a;
312 #endif
314 #ifndef SKIP_FOR_DECLARATION
315 unsigned has_for_declaration(void) {
316 unsigned a = 10;
317 for (unsigned i = 0; i < a; ++i) {
318 a -= i;
320 switch (0)
321 for (unsigned var; 0;)
322 default:
323 switch((var = 0), 0)
324 default: {
325 return var;
327 return a;
329 #endif
331 #ifndef SKIP_IDEM
332 unsigned const const has_idempotent_const = 1;
333 unsigned volatile volatile has_idempotent_volatile = 1;
334 # ifndef SKIP_RESTRICT
335 unsigned *restrict restrict has_idempotent_restrict = 0;
336 # endif
337 #endif
339 #ifndef SKIP_PRAGMA
340 # pragma STDC FP_CONTRACT ON
341 # define PRAGMA(MESS) _Pragma(# MESS)
342 PRAGMA(STDC FP_CONTRACT OFF)
343 #endif
345 #ifndef SKIP_FUNC
346 void has_func_macro(char const* where[]) {
347 *where = __func__;
349 #endif
351 #ifndef SKIP_LONG_LONG
352 long long has_long_long = 0;
353 unsigned long long has_ullong_max[-1 + 2*((0ULL - 1) >= 18446744073709551615ULL)];
354 #endif
356 #ifndef SKIP_LONG_DOUBLE
357 long double has_long_double = 1.0L;
358 #endif
360 #ifndef SKIP_PREPRO_ARITH
361 # if (0 - 1) >= 0
362 # error "this should be a negative value"
363 # else
364 unsigned const has_preprocessor_minus = 1;
365 # endif
366 /* Unsigned arithmetic should be done in the type that corresponds to
367 uintmax_t and it should use modulo arithmetic. */
368 # if ~0U < 0
369 # error "this should be a large positive value"
370 # endif
371 # if ~0U != (0U - 1)
372 # error "the preprocessor should do modulo arithmetic on unsigned values"
373 # endif
374 unsigned const has_preprocessor_bitneg = 1;
375 # if (~0U < 65535)
376 # error "this should be a large positive value, at least UINT_MAX >= 2^{16} - 1"
377 # endif
378 # if (~0U < 4294967295)
379 # error "this should be a large positive value, at least ULONG_MAX >= 2^{32} - 1"
380 # endif
381 # if (~0U < 18446744073709551615ULL)
382 # error "this should be a large positive value, at least ULLONG_MAX >= 2^{64} - 1"
383 # endif
384 unsigned has_preprocessor_uintmax;
385 # if (1 ? -1 : 0U) < 0
386 # warning "ternary operator should promote to unsigned value"
387 # else
388 unsigned const has_preprocessor_ternary_unsigned = 1;
389 # endif
390 # if (1 ? -1 : 0) > 0
391 # warning "ternary operator should result in signed value"
392 # else
393 unsigned const has_preprocessor_ternary_signed = 1;
394 # endif
395 /* Bool operation should return a signed integer */
396 # if (1 ? -1 : (0 && 0)) > 0
397 # error "logical operations should return signed values"
398 #endif
399 # if (1 ? -1 : (0U && 0)) > 0
400 # error "logical operations should return signed values"
401 #endif
402 # if (1 ? -1 : (0 && 0U)) > 0
403 # error "logical operations should return signed values"
404 #endif
405 # if (1 ? -1 : (0U && 0U)) > 0
406 # error "logical operations should return signed values"
407 #endif
408 unsigned const has_preprocessor_logical_signed = 1;
409 #endif
411 /* A comma operator shall not appear in a constant expression, unless
412 it is not evaluated. First test for the good case: it isn't
413 evaluated. First this should be accepted by the compiler but also
414 it should do the correct type promotions. This test can have
415 different results when we try this for constant expressions in the
416 compiler phase or in the preprocessor phase. */
417 #define GOOD ((1 ? -1 : (0, 0u)) < 0 )
418 #ifndef SKIP_NON_EVALUATED_COMMA_ASSIGN
419 unsigned const has_non_evaluated_comma_expression_assign[2*!GOOD - 1] = { 0 };
420 #endif
421 #ifndef SKIP_NON_EVALUATED_COMMA_PREPRO
422 # if GOOD
423 # warning "non evaluated comma expression yields wrong result"
424 # else
425 unsigned const has_non_evaluated_comma_expression_prepro = GOOD;
426 # endif
427 #endif
429 /* Now if it is in the evaluated part, this is undefined
430 behavior. This could lead to anything, but also to the nice
431 behavior that the compiler tells us. Some compilers do tell us in
432 fact, but only as a warning. Some just refuse to compile. */
433 #define BAD ((0 ? -1 : (0, 0u)) > -1 )
434 #ifndef SKIP_EVALUATED_COMMA_ASSIGN
435 enum { bad = BAD };
436 #else
437 unsigned const has_evaluated_comma_expression_assign = 1;
438 #endif
439 #ifndef SKIP_EVALUATED_COMMA_PREPRO
440 # if BAD
441 # warning "evaluated comma expression yields wrong result"
442 # endif
443 #else
444 unsigned const has_evaluated_comma_expression_prepro = 1;
445 #endif
447 #ifndef SKIP_UNIVERSAL
448 int has_hex_character = L'\x0401';
449 int has_universal_character_4 = L'\u2118';
450 int has_universal_character_8 = L'\U00000401';
451 int const* has_universal_string_4 = L"\u2018\u03A7\u2060X\u2019";
452 int const* has_universal_string_8 = L"\U00002018\U000003A7\U00002060X\U00002019";
453 int has_\u03BA\u03B1\u03B8\u03BF\u03BB\u03B9\u03BA\u03CC\u03C2_\u03c7\u03B1\u03C1\u03B1\u03BA\u03C4\u03AE\u03C1 = 1;
454 const int \u03BA = 0;
455 int const*const has_keeps_token_boundary_for_universal = &\u03BA;
456 # ifndef SKIP_UNIVERSAL_MANGLE
457 /* When compiled, the two static variables that are defined here must
458 result in two different symbols. There is no way to check this at
459 compile time, unfortunately. So we have to check the object file
460 by hand to determine this. */
461 int has_universal_good_mangle(int a) {
462 static int volatile \u03ba;
463 static int volatile _u03ba;
464 \u03ba = !!a;
465 _u03ba = !a;
466 return \u03ba == _u03ba;
468 # else
469 int has_universal_bad_mangle;
470 # endif
471 # ifndef SKIP_UNIVERSAL_UTF8
472 double const π = 3.14159265;
473 double const* has_utf8 = &π;
474 # endif
475 #endif
479 /* Have checks for digraphs and trigraphs at the end, since they may
480 mix up the pretty printing. */
482 #ifndef SKIP_DIGRAPH
484 /* check for the four "language" digraphs */
485 double has_punctuation_digraph <::> = <% 0 %>;
487 %: define HAS_HASH_DIGRAPH 1
488 enum { hasHashDigraph = !!HAS_HASH_DIGRAPH };
489 %: define DIGRAPH_STRINGIFY(X) %:X
490 char const has_digraph_stringify[] = DIGRAPH_STRINGIFY(digraph);
491 # if !defined(HAS_HASH_DIGRAPH)
492 # error "The preprocessor lacks digraph %: support. Run test with -DSKIP_DIGRAPH to be able to see the other tests."
493 # endif
495 %: define HAS_HASH_HASH_DIGRAPH_(a, b) a %:%: b
496 %: define HAS_HASH_HASH_DIGRAPH HAS_HASH_HASH_DIGRAPH_(0, 1)
497 enum { hasHashHashDigraph = !!HAS_HASH_HASH_DIGRAPH};
498 /* This one here and the one in the trigraph section should be merged
499 into one symbol. */
500 double has_hash_hash_interpretedCorrectly[hasHashHashDigraph];
501 # if !defined(HAS_HASH_HASH_DIGRAPH) || (HAS_HASH_HASH_DIGRAPH != 1)
502 # error "The preprocessor lacks quadgraph %:%: support. Run test with -DSKIP_DIGRAPH to be able to see the other tests."
503 # endif
505 #endif
508 #ifndef SKIP_TRIGRAPH
510 /* Check for the eight "language" trigraphs. If this works and you
511 run this through your preprocessor phase (usually with -E) this
512 should, all of a sudden look like valid C code. */
513 int has_punctuation_trigraph ??(??) = ??< (0 ??' 1), (0 ??! 1), ??-0, '??/0' ??>;
514 /* don't get confused by the syntax highlighting the ??' aint't too bad for that */
516 ??= define HAS_HASH_TRIGRAPH 1
517 enum { hasHashTrigraph = !!HAS_HASH_TRIGRAPH };
518 ??= define TRIGRAPH_STRINGIFY(X) ??=X
519 char const has_trigraph_stringfy[] = TRIGRAPH_STRINGIFY(trigraph);
520 # if !defined(HAS_HASH_TRIGRAPH)
521 # error "The preprocessor lacks trigraph ??= support. Run test with -DSKIP_TRIGRAPH to be able to see the other tests."
522 # endif
524 ??= define HAS_HASH_HASH_TRIGRAPH_(a, b) a ??=??= b
525 ??= define HAS_HASH_HASH_TRIGRAPH HAS_HASH_HASH_TRIGRAPH_(0, 1)
526 enum { hasHashHashTrigraph = !!HAS_HASH_HASH_TRIGRAPH};
527 /* This one here and the one in the digraph section should be merged
528 into one symbol. */
529 double has_hash_hash_interpretedCorrectly[hasHashHashTrigraph];
530 # if !defined(HAS_HASH_HASH_TRIGRAPH) || (HAS_HASH_HASH_TRIGRAPH != 1)
531 # error "The preprocessor lacks hexgraph ??=??= support. Run test with -DSKIP_TRIGRAPH to be able to see the other tests."
532 # endif
534 #endif
536 void testP99(void)