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

Reply via email to