IOCCC 1987/westley.c - lvalue issues with GCC

120 views Asked by At

This line-palindromic entry from the 1987 IOCCC:

https://www.ioccc.org/years.html#1987_westley

...is causing TCC 0.9.27 no issues during default compilation and works as intended.

However, GCC 9.3.0, even in -std=c89 mode, complains that the following instances of (int) (tni) are not lvalues:

    for (; (int) (tni);)
        (int) (tni) = reviled;
                    ^
(lvalue required as left operand of assignment)
...
    for ((int) (tni)++, ++reviled; reviled * *deliver; deliver++, ++(int) (tni))
                                                                  ^~
(lvalue required as increment operand)

(code beautified for better context)

My current thoughts:

In the = case, I suspect that the use of (int) (tni) as a condition in the for loop is disqualifying it as a lvalue, but I am not sure.

In the ++ case, I can see later in that code how its palindromic nature forces the author to use a -- operator between (int) and (tni) which is not considered as an issue. So GCC requires the ++ operator just before the variable, not before its casting, but hints at this requirement with a lvalue complaint.

Is there a definitive answer to these GCC complaints? Is TCC too lax in letting these off the hook?

Thanks in advance!

EDIT: I was kindly pointed towards a similar question which answers the casting issue here - please see my comment below for the solution!

1

There are 1 answers

4
Antti Haapala -- Слава Україні On

TCC is not a conforming C implementation as is well known - TCC tries to be small and fast compiler that attempts to compile correct C code, and it often does not produce diagnostics that would be required by the standard. And as is known even more widely is that the first C standard came into being in 1989, and most widely known is that year 1987 preceded 1989.

C11 6.5.4p5:

  1. Preceding an expression by a parenthesized type name converts the value of the expression to the named type. This construction is called a cast. 104) A cast that specifies no conversion has no effect on the type or value of an expression.

The footnote 104 notes that:

  1. A cast does not yield an lvalue. Thus, a cast to a qualified type has the same effect as a cast to the unqualified version of the type.

For assignment operator, 6.5.16p2 says:

  1. An assignment operator shall have a modifiable lvalue as its left operand.

6.5.16p2 is in constraint section, so violations must be diagnosed.