[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Scoping fix

From: Michael Matz
Subject: Re: [Tinycc-devel] Scoping fix
Date: Fri, 22 Jan 2021 15:33:07 +0100 (CET)
User-agent: Alpine 2.21 (LSU 202 2017-01-01)


On Thu, 21 Jan 2021, Elijah Stone wrote:

 You can't declare a struct in the declaration part of the for stmt
 (6.8.5p3), only objects of auto and register class.

Hmmm.  I think the spec is somewhat ambiguous here.
The specific wording is:

 The declaration part of a for statement shall only declare identifiers for
 objects having storage class auto or register

Does that mean that:

1. all objects which have identifiers declared for them must have
   storage class auto or register

2. all identifiers which are declared must be for objects, and those
   objects must have storage class auto or register

Yep, I stumbled over the same ambiguity here, but as clang and gcc behaved consistently and interpretation 2 is reasonable (I didn't think to check msvc or icc^Wedg) I thought tcc should follow suit. Now, with your experiments on other compilers the picture is different, but I'd still like to have the testcases in tests2 to be compilable with GCC. In the extreme it would be okay to compile f2 and f4 only for TCC (with a comment about this discussion), but perhaps there's a different way to test the same scoping rules without having to deal with the interpretation of 6.8.5p3, e.g. for f2:

f2_1 (void)
    struct foo { int m; };
    int i;
    for (i = sizeof(struct foo {int m;});;)
        return sizeof(struct foo { int m; });

Another expression of the inconsistency, which I think makes it even clearer: under this interpretation, the first two of the following forms are allowed but the third is not:

// 1, ok
int i; for (i = sizeof(struct foo { int m; });;)

// 2, ok
int i = sizeof(struct foo { int m; });

// 3, not ok; why not?
for (int i = sizeof(struct foo { int m; });;)

Yeah, there's no conceivable reason why (3) should not be allowed. Often some of the stranger rules in the standard are to cater for very simple (one-pass) parsers, but as tcc plus your patch proves in this case that's not necessary.

I suspect that no one ever intended for it to be possible to declare an identifier inside of an expression, and now we're dealing with the fallout.

Yeah, the wonders and fun of fine-print language lawyering :-)

I don't know if there's a _good_ solution, but I think that the most consistent option is to allow struct declarations there.

FWIW, I agree with you. In fact I don't even see the necessity to have _any_ restriction at all for the decl-form of 'for', it's just not explainable why 'for (decl;;)' shouldn't be 100% equivalent to
 'decl; for(;;)' So the decl part could be a typedef, so what?.

I've written a short paper on the topic outlining the problem and a few potential solutions for future versions of the spec; would appreciate any feedback: https://elronnd.net/sl.pdf

Ah, nice.  So I'd argue for your proposal 3.

While I agree that in the abstract your proposal 4 (don't leak decls from expressions) is the best I think it sufficiently changes the language that it wouldn't be acceptable anymore for something as mature as C (and would need either of the first three proposals anyway).


reply via email to

[Prev in Thread] Current Thread [Next in Thread]