On Fri, 18 Jun 2021, Christian Jullien wrote:
C evolves and supports new features over the time.
Do we want to support upcoming features like prototypes without
parameters (as in C++)?
I think it would be a good idea. As far as I can tell, the current c2x
draft (http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2596.pdf) entails
the following compiler changes:
+ void f(int) {} (N2480)
+ single-argument _Static_assert (N2265) (already implemented)
+ get rid of k&r definitions (N2432)
+ also: void foo(){} is equivalent to void foo(void){}. The meaning of
void foo() (just a prototype) is unchanged + allow labels to precede
declarations (e.g. lb: int x;) (N2508) + 'true' and 'false' have type
bool (N2393)
- use of booleans in arithmetic expressions is 'deprecated'; consider
emiting warnings?
+ support binary literals (N2549, already supported as a gnu ext.
Actually as a 'tcc ext', but it's a gnu ext)
- u8'x' -> (unsigned char)'x' (N2418)
- u8"", U"" et al (from c11) are already not supported, need to add them
- mixed-type literal concatenation is now illegal (u"" U"" is an error;
"" u"" is fine though. See above) (N2594)
- Change rules about conversions of pointers to qualified arrays (N2607)
- [[attributes]] (N2335)
I've attached a patch implementing the changes marked '+'. Currently
they're all guarded behind -std=c2x, but perhaps that should be limited to
the backwards-incompatible ones?
-E
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 <stdio.h>
+
+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
_______________________________________________
Tinycc-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/tinycc-devel