char arr[10];
char *ptr;
arr = ptr;
... does the compilation fail because
1) arr is not a modifiable lvalue,
or
2) because of conversion rule, that says that "arr" is converted to
pointer to
char and is not an lvalue ?
The code fragment above (when converted to a complete translation
unit) produces a diagnostic from any conformant compiler. The
diagnostic is required by the C standard. The clauses in the
C standard that requires this essentially boil down to the first
reason, that "arr" is not a "modifiable lvalue". In that sense,
we could say that the "compilation fails" because of reason 1.
However, the C Standard never requires compilation to fail at all.
It only requires "at least one diagnostic" if the translation unit
violates a constraint (as in this case). So this is *not* the
reason the compilation fails after all. The compilation fails
because the compiler-writer chose to have that particular diagnostic
*also* suppress compilation.
Moreover, the C standard merely requires *a* diagnostic. If the
compiler manages to come up with a diagnostic, even through some
arguably "wrong" method, this satisfies the requirements in the C
standard.
Imagine for a moment, that the compiler works via divine miracles
and inspiration. That is, there is no code, and not even a computer,
involved in compiling. You simply copy the program onto a floppy,
put the floppy on an altar, pray, and when you remove the floppy
and put it back into a computer later, you now have any executable
that may have been miraculously conceived.
This particular translation unit, when prayed, produces an ominous
thunderclap. This is the method by which a diagnostic is delivered
from this compiler.
Did the God or gods in question cause the thunderclap for the "right
reason" as per the C standard, or did they not really understand
(or perhaps care) *why* a diagnostic was required, yet produce a
thunderclap anwyay? How will you tell?
Returning to reality (as it were), suppose a compiler applied the
idea given in reason 2, converting the (non-modifiable) lvalue
"arr" to an rvalue, and then emit the diagnostic because the left
hand side of the assignment had an rvalue (rather than a non-modifiable
lvalue). The diagnostic came out, as required by the C standard.
How will you tell whether the diagnostic came out because of the
"wrong" reason (reason 2) instead of the "right" one (reason 1)?
If the diagnostic consists only of a beep -- the computer's equivalent
of the thunderclap -- you cannot even guess whether the compiler-writer
wrote:
diagnostic("non-modifiable lvalue as LHS of = operator");
or:
diagnostic("rvalue as LHS of = operator");
since the string itself never comes out, only the beep. (If the
string given as the argument here comes out, you *can* guess. But
then you do not know whether the programmer was malicious, either
-- suppose the compiler contains code like this:
if (!assignment_compatible(lhs, rhs))
/* C standard only requires a diagnostic, not a sensible one */
diagnostic("invalid operand to sizeof");
or, for subtraction:
if (is_ptr(arg1)) {
if (is_integer(arg2)) {
/* ptr - integer: result has same type as arg1 */
result_type = arg1_type;
...
} else {
/* only other value you can subtract from a pointer is another
pointer of compatible type */
if (!is_ptr(arg2) || !types_compatible(arg1_type, arg2_type))
diagnostic("did anyone ever tell you your nose is green?");
/* ptr - ptr: result is ptrdiff_t */
result_type = ptrdiff_type;
...
}
} else ...
just to cause weird error messages?)