diff --git a/include/stdbool.h b/include/stdbool.h index d2ee446..8fcd97b 100644 --- a/include/stdbool.h +++ b/include/stdbool.h @@ -4,8 +4,13 @@ /* ISOC99 boolean */ #define bool _Bool -#define true 1 -#define false 0 +#if __STDC_VERSION__ >= 202000L +# define true ((_Bool)1) +# define false ((_Bool)0) +#else +# define true 1 +# define false 0 +#endif #define __bool_true_false_are_defined 1 #endif /* _STDBOOL_H */ diff --git a/libtcc.c b/libtcc.c index ec33591..c46fd49 100644 --- a/libtcc.c +++ b/libtcc.c @@ -782,7 +782,6 @@ LIBTCCAPI TCCState *tcc_new(void) #undef gnu_ext s->gnu_ext = 1; - s->tcc_ext = 1; s->nocommon = 1; s->dollars_in_identifiers = 1; /*on by default like in gcc/clang*/ s->cversion = 199901; /* default unless -std=c11 is supplied */ @@ -1808,10 +1807,32 @@ reparse: case TCC_OPTION_static: s->static_link = 1; break; - case TCC_OPTION_std: - if (strcmp(optarg, "=c11") == 0) - s->cversion = 201112; + case TCC_OPTION_std: { + const char *targ = optarg; + if (strncmp(targ, "=gnu", 4) == 0) { + s->gnu_ext = 1; + targ += 4; + } else if (strncmp(targ, "=c", 2) == 0) { + /*s->gnu_ext = 0;*/ /*TODO- tccdefs requires gnu extensions*/ + targ += 2; + } else { + tcc_warning("no such version '%s'", optarg); + break; + } + if (strcmp(targ, "89") == 0) + s->cversion = 199409L; + else if (strcmp(targ, "99") == 0) + s->cversion = 199901L; + else if (strcmp(targ, "11") == 0) + s->cversion = 201112L; + else if (strcmp(targ, "17") == 0 || strcmp(targ, "18") == 0) + s->cversion = 201710L; + else if (strcmp(targ, "2x") == 0) + s->cversion = 202000L; + else + tcc_warning("no such version '%s'", optarg); break; + } case TCC_OPTION_shared: x = TCC_OUTPUT_DLL; goto set_output_type; diff --git a/tccgen.c b/tccgen.c index c36032a..ed26711 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1283,6 +1283,8 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c) Sym *s, **ps; TokenSym *ts; + if (!v) + return NULL; if (local_stack) ps = &local_stack; else @@ -5364,17 +5366,19 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) if (tok == '(') { /* function type, or recursive declarator (return if so) */ next(); - if (td && !(td & TYPE_ABSTRACT)) - return 0; - if (tok == ')') - l = 0; - else if (parse_btype(&pt, &ad1)) - l = FUNC_NEW; - else if (td) { - merge_attr (ad, &ad1); - return 0; - } else - l = FUNC_OLD; + if (td && !(td & TYPE_ABSTRACT)) + return 0; + if (tok == ')') + l = 0; + else if (parse_btype(&pt, &ad1)) + l = FUNC_NEW; + else if (td) { + merge_attr (ad, &ad1); + return 0; + } else if (tcc_state->cversion >= 202000L) + tcc_error("K&R-style function definitions are not allowed in c2x"); + else + l = FUNC_OLD; first = NULL; plast = &first; arg_size = 0; @@ -5411,10 +5415,17 @@ static int post_type(CType *type, AttributeDef *ad, int storage, int td) if (l == FUNC_NEW && !parse_btype(&pt, &ad1)) tcc_error("invalid type"); } - } else - /* if no parameters, then old type prototype */ - l = FUNC_OLD; - skip(')'); + skip(')'); + } else { + skip(')'); + + /* in c2x, no parameters create a new type prototype, but only + in a definition */ + if (tok == '{' && tcc_state->cversion >= 202000L) + l = FUNC_NEW; + else + l = FUNC_OLD; + } /* NOTE: const is ignored in returned type as it has a special meaning in gcc / C++ */ type->t &= ~VT_CONSTANT; @@ -7650,8 +7661,10 @@ again: block_after_label: vla_restore(cur_scope->vla.loc); - /* we accept this, but it is a mistake */ - if (tok == '}') { + if (tcc_state->cversion >= 202000L) { + return; + } else if (tok == '}') { + /* we accept this, but it is a mistake */ tcc_warning("deprecated use of label at end of compound statement"); } else { goto again; @@ -8726,6 +8739,8 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) c = expr_const(); if (tok == ')') { + if (tcc_state->cversion < 202000L) + tcc_warning("_Static_assert with no message is not supported before c2x"); if (!c) tcc_error("_Static_assert fail"); next(); @@ -8862,10 +8877,14 @@ static int decl0(int l, int is_for_loop_init, Sym *func_sym) make old style params without decl have int type */ sym = type.ref; while ((sym = sym->next) != NULL) { - if (!(sym->v & ~SYM_FIELD)) + if (!(sym->v & ~SYM_FIELD) && tcc_state->cversion < 202000L) expect("identifier"); - if (sym->type.t == VT_VOID) - sym->type = int_type; + if (sym->type.t == VT_VOID) { + if (tcc_state->cversion >= 202000L) + tcc_error("K&R-style function definitions are not allowed in c2x"); + else + sym->type = int_type; + } } /* apply post-declaraton attributes */ diff --git a/tccpp.c b/tccpp.c index 815ffe4..e730ccb 100644 --- a/tccpp.c +++ b/tccpp.c @@ -2358,7 +2358,7 @@ static void parse_number(const char *p) q--; ch = *p++; b = 16; - } else if (tcc_state->tcc_ext && (ch == 'b' || ch == 'B')) { + } else if ((gnu_ext || tcc_state->cversion >= 202000L) && (ch == 'b' || ch == 'B')) { q--; ch = *p++; b = 2; diff --git a/tests/tests2/126_unnamed_parameters.c b/tests/tests2/126_unnamed_parameters.c new file mode 100644 index 0000000..6bac7ba --- /dev/null +++ b/tests/tests2/126_unnamed_parameters.c @@ -0,0 +1,2 @@ +void f(int) {} +int main() {} diff --git a/tests/tests2/126_unnamed_parameters.expect b/tests/tests2/126_unnamed_parameters.expect new file mode 100644 index 0000000..b817358 --- /dev/null +++ b/tests/tests2/126_unnamed_parameters.expect @@ -0,0 +1 @@ +126_unnamed_parameters.c:1: error: identifier expected diff --git a/tests/tests2/127_unnamed_parameters.c b/tests/tests2/127_unnamed_parameters.c new file mode 100644 index 0000000..74c0ee5 --- /dev/null +++ b/tests/tests2/127_unnamed_parameters.c @@ -0,0 +1,6 @@ +#include + +int f(int x, int, int y) { return x + y; } +int main() { + printf("%d\n", f(1, 2, 3)); +} diff --git a/tests/tests2/127_unnamed_parameters.expect b/tests/tests2/127_unnamed_parameters.expect new file mode 100644 index 0000000..b8626c4 --- /dev/null +++ b/tests/tests2/127_unnamed_parameters.expect @@ -0,0 +1 @@ +4 diff --git a/tests/tests2/Makefile b/tests/tests2/Makefile index 5f32cbc..808d9a1 100644 --- a/tests/tests2/Makefile +++ b/tests/tests2/Makefile @@ -69,6 +69,7 @@ NORUN = # Some tests might need different flags FLAGS = 76_dollars_in_identifiers.test : FLAGS += -fdollars-in-identifiers +127_unnamed_parameters.test : FLAGS += -std=c2x # These tests run several snippets from the same file one by one 60_errors_and_warnings.test : FLAGS += -dt