On 1/20/24 09:30, grischka wrote:
On 19.01.2024 07:18, Herman ten Brugge via Tinycc-devel wrote:
I wanted to avoid an extra check for ';' because I found code like:

     case xxx: ; }

Instead of writing 'break;' they used ';'.
Without checking for ';' a warning was printed:

Always same problem: we want something and do something else.

Anyway, what you told tcc is to accept declarations instead of
an expression, alternatively:

-                } else {
+                } else if (!decl(VT_JMP)) {
                     gexpr();
                     vpop();


Which is what happens.  Current tcc accepts:

    if (x)
        int y;
    else
        int z;

So how about the next patch:
C23: Implement declaration after label (see attached patch)

    block_after_label:
            ...
            if (tok != ':')
                decl(VT_LOCAL);
            if (tok != '}')
                goto again;
            /* we accept this, but it is a mistake */
            tcc_warning_c(warn_all)("deprecated use of label...

Yes, I'd read this as "accept declarations after a label", too.
So it might be what you want, but is it C23?

Because then, to have a declaration where it was not possible
previously, we'd now just need to put a label in front:

Not accepted
      if (x)
          int n;
          for (n = 0; n < x; ++n)
               ;
      else ...

Accepted:
      if (x)
          decl_please: int n;
          for (n = 0; n < x; ++n)
               ;
       else ...

I'd think that feels a bit strange, because the label would not
serve any purpose other than to support the declaration.

And of course, if that is C23, then people then will start to
write this.

Thanks for this long mail.

The first patch I made was clearly not correct,
The second patch was more correct but allowed too much.
I hope the third patch is more acceptable. I now only allow
declaration after label if it is inside a '{...}'.
C23: Implement declaration after label (see attached patch)

I now see another problem between gcc and clang.
The code:

   if (x) int a;
   if (x) label: int a;

Is now accepted by clang 18.0.0(pre release)
gcc >= 13.2.1 (and now tcc) and clang 17.0.6 do not allow this.

    Herman






diff --git a/tccgen.c b/tccgen.c
index d5e9bf5..688557e 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -139,7 +139,7 @@ static CType *type_decl(CType *type, AttributeDef *ad, int 
*v, int td);
 static void parse_expr_type(CType *type);
 static void init_putv(init_params *p, CType *type, unsigned long c);
 static void decl_initializer(init_params *p, CType *type, unsigned long c, int 
flags);
-static void block(int is_expr);
+static void block(int is_expr, int allow_decl);
 static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, int 
has_init, int v, int scope);
 static int decl(int l);
 static void expr_eq(void);
@@ -5566,7 +5566,7 @@ ST_FUNC void unary(void)
               as statement expressions can't ever be entered from the
               outside, so any reactivation of code emission (from labels
               or loop heads) can be disabled again after the end of it. */
-            block(1);
+            block(1, 0);
             /* If the statement expr can be entered, then we retain the current
                nocode_wanted state (from e.g. a 'return 0;' in the stmt-expr).
                If it can't be entered then the state is that from before the
@@ -6908,7 +6908,7 @@ static void lblock(int *bsym, int *csym)
         loop_scope = co;
     }
     co->bsym = bsym;
-    block(0);
+    block(0, 0);
     co->bsym = b;
     if (csym) {
         co->csym = c;
@@ -6916,7 +6916,7 @@ static void lblock(int *bsym, int *csym)
     }
 }
 
-static void block(int is_expr)
+static void block(int is_expr, int allow_decl)
 {
     int a, b, c, d, e, t;
     struct scope o;
@@ -6945,12 +6945,12 @@ again:
         gexpr();
         skip(')');
         a = gvtst(1, 0);
-        block(0);
+        block(0, 0);
         if (tok == TOK_ELSE) {
             d = gjmp(0);
             gsym(a);
             next();
-            block(0);
+            block(0, 0);
             gsym(d); /* patch else jmp */
         } else {
             gsym(a);
@@ -6993,7 +6993,7 @@ again:
             if (tok != '}') {
                 if (is_expr)
                     vpop();
-                block(is_expr);
+                block(is_expr, 1);
             }
         }
 
@@ -7253,6 +7253,9 @@ again:
             if (debug_modes)
                 tcc_tcov_reset_ind(tcc_state);
             vla_restore(cur_scope->vla.loc);
+            /* c23 declaration after label */
+            if (allow_decl && tok != ';')
+                decl(VT_LOCAL);
             if (tok != '}')
                 goto again;
             /* we accept this, but it is a mistake */
@@ -7266,7 +7269,7 @@ again:
                 if (is_expr) {
                     vpop();
                     gexpr();
-                } else if (!decl(VT_JMP)) {
+                } else {
                     gexpr();
                     vpop();
                 }
@@ -8313,7 +8316,7 @@ static void gen_function(Sym *sym)
     rsym = 0;
     clear_temp_local_var_list();
     func_vla_arg(sym);
-    block(0);
+    block(0, 0);
     gsym(rsym);
 
     nocode_wanted = 0;
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to