From: diamond@jit533.jit.dec.com (Norman Diamond)
Subject: Re: Standard conformance and GCC 2.3.3
Reply-To: diamond@jit.dec.com (Norman Diamond)
Organization: Digital Equipment Corporation Japan , Tokyo
Date: Wed, 30 Dec 1992 10:24:18 GMT

In article <1992Dec30.011211.11409@netcom.com> rfg@netcom.com (Ronald F. Guilmette) writes:
>This report, and the examples given within it, may prove useful for some
>readers of comp.std.c who are attempting to assess the level of standard
>conformace provided by GCC

or who use GCC to try to verify whether a program is strictly conforming :-)

>Most (but not all) of these twenty bugs are problems with standard conformance.

I think you should have stated which ones you believe to be conformance issues.
>-----------------------------------------------------------------------------
>#1)  GCC [-pedantic-errors] fails to detect the error in the following code
>void foo () {
>  extern void bar (int i, ...);
>  bar (99, 88, 77);
>}
>void bar (int i, int j, int k) { }      /* ERROR */

The call is irrelevant.  The two definitions are incompatible and the result
is undefined (ANSI Classic 3.1.2.6).  However, I do not see a violation of any
constraint here, so GCC's silence does not indicate a failure to conform.  A
diagnostic would be nice for quality, perhaps -hyper-pedantic-errors :-)
>-----------------------------------------------------------------------------
>#2)  GCC [-pedantic-errors] fails to detect the error in the following code
>unsigned long overflow = LONG_MAX + 3; /* ERROR */

Again I see no violation of a constrant.
>-----------------------------------------------------------------------------
>#3)  GCC incorrectly flags an error on the following standard-conformant code
>     when the -pedantic-errors option is in effect.
>typedef int T;
>void test_1 (int T) { }

Spurious diagnostics are allowed.  Does GCC proceed to produce a valid result,
i.e. can the program be executed with correct output?

Incidentally, it seems rather easy to misread ANSI Classic 3.7.1, page 83
line 9, without realizing that the "If" antecedent in line 7 should apply
to this sentence as well.
>-----------------------------------------------------------------------------
>#4)  On x86 machines, GCC fails to properly implement explicit floating-point
>     casts of those floating-point expressions which get evaluated using the
>     (internal) 80-bit floating-point format.

This might well be true, but your example didn't test for it.  You only cast
a double operand to type double.

>     This causes the following program to yield a non-zero exit status.
>double point_four = 0.4;
>double point_one_six;
>int main() {
>  point_one_six = (point_four * point_four);
>  if ((double)(point_four * point_four) != point_one_six) { return 1; }
>  return 0;
>}

This example tests (maybe) whether the expression (point_four * point_four)
yields the same result, of type double, twice in a row.  The standard does
not require this kind of consistency.  You might start by checking the value
of FLT_ROUNDS.  Most possible values indicate implementation-defined rounding
behavior, while -1 indicates indeterminable, and only a few values indicate
moderately well defined behavior.
>-----------------------------------------------------------------------------
>#5)  GCC incorrectly issues an error for the following standard-conformant
>     code.  (Note that `wchar_t' is the same as type `long int' on i486-svr4.)
>typedef long int wchar_t;
>wchar_t array5[4] = L"abcd";

This is a tough call.  ANSI Classic section 4.1.5 says that <stddef.h> defines
the type wchar_t, and section 4.10 says that <stdlib.h> declares type wchar_t
as described in 4.1.5.  But the standard does not guarantee that programmers
can read the standard headers.  Both wordings "defined" and "declared" omit
saying "implementation defined", so I'm not sure if you're guaranteed to know
the implementation's choice for wchar_t.  It might be allowed to play dirty
pool with you, as with enums.

However, even if they have to tell you what wchar_t is, spurious diagnostics
are allowed.  What happens when you try executing the program?
>-----------------------------------------------------------------------------
>#6)  The following erroneous code causes GCC to crash with a signal 6.
>extern volatile struct s evs;
>void evs_test () { evs; }

The standard doesn't require diagnostics to be in a natural human language :-)

Uh, wait a minute.  Your expression "evs" neither evaluates nor modifies the
object, so it is not necessary to know the size of the object.  Although an
implementation-defined access occurs, the access includes neither evaluation
nor modification.  I think your code is not erroneous, and must be accepted.
(Now we finally agree that GCC failed to conform, but for different reasons.)
>-----------------------------------------------------------------------------
>#7)  When compiling an empty source file while the -pedantic-errors option
>     is in effect, GCC will generate an error message for a line number which
>     does not actually exist in the source file.

I believe that diagnostics are allowed to contain spurious line numbers unless
they follow a #line directive.  (And of course a #line directive is allowed to
command similar garbage.)
>-----------------------------------------------------------------------------
>#8)  GCC [-pedantic-errors] fails to issue errors for the following
>void test_0 (char);
>void test_0 (c) char c; { }

Again (as in #1) I see no violation of a constraint.
>-----------------------------------------------------------------------------
>#9)  GCC fails to issue errors in cases where a static function is referenced
>     but never defined, even when the -pedantic-errors option is used.
>static void s (); int main () { s (); return 1; }

Again I see no violation of a constraint.  Furthermore, if you returned
EXIT_SUCCESS instead of 1, I believe it would be strictly conforming.
Hard to believe, isn't it?  My best guess is that the invocation of s()
acts as a no-op.  The standard doesn't seem to permit any other behavior.
>-----------------------------------------------------------------------------
>#10)  GCC [-pedantic-errors] fails to issue an error for the following invalid
>void (*func_ptr) ();
>int i;
>void test () { func_ptr = i ? 0 : 0; }         /* ERROR */

The code looks valid to me.  The conditional expression  i ? 0 : 0  is an
integral constant expression with value 0.  Null pointer constants can be
assigned to function pointers.  (I expect no debate on this one.)
>-----------------------------------------------------------------------------
>#11)  GCC fails to issue errors for the following invalid C code involving
>      comparison operators, even when the -pedantic-errors option is used.
[Much editing by N.D.]
 int b_array_src[3];
 extern int u_array_src[];
>int i;
>void test_relational_operators () {
>  i = & u_array_src > & b_array_src;            /* ERROR */
>}
>int u_array_src[20] = { 0 };    /* complete its type */

Hmm, we agree that GCC failed to conform this time, but I find the constraints
for this very odd.  I wonder why there wasn't one allowance for "both operands
are pointers to qualified or unqualified versions of compatible object or
incomplete types."  The semantics could handle it without further adjustment.
>-----------------------------------------------------------------------------
>#12)  GCC fails to issue errors for the following invalid C code involving
>      the binary `-' operator, even when the -pedantic-errors option is used.
[Declarations similar to #11.]
>  i = & u_array_src - & b_array_src;            /* ERROR */

A more serious problem.  Again, we agree that GCC failed to conform.
>-----------------------------------------------------------------------------
>#13)  GCC fails to issue errors for the following invalid C code involving
>      invalid null pointer constants, even when the -pedantic-errors option
>int (*fp) ();
>void test () { fp = (void *) (void *) 0; }    /* ERROR */

To be a bit more precise, (void *) (void *) 0 is not a null pointer constant.
(To be pedantic, if that means invalid null pointer constant, it also means
invalid typedef, since it actually is neither.)  The code violates the
constraints on the assignment operator, and we agree that GCC failed.
>-----------------------------------------------------------------------------
>#14)  GCC [-pedantic-errors] fails to issue errors for the following invalid
[Declarations deleted but all had pointer types, i.e. all scalars -- N.D.]
>  p_to_func_value = (p_to_func_type) p_to_object_value;         /* ERROR */
>  p_to_func_value = (p_to_func_type) p_to_incomp1_value;        /* ERROR */
>  p_to_func_value = (p_to_func_type) p_to_incomp2_value;        /* ERROR */

I see no violation of a constraint.
[The behavior would be undefined, though on some machines you would even be
able to do a function call using the result of any of those casts.]
>-----------------------------------------------------------------------------
>#15)  GCC [-pedantic-errors] fails to issue errors for the following invalid
[Declarations deleted but all had pointer types, i.e. all scalars -- N.D.]
>  p_to_object_value = (p_to_object_type) p_to_func_value;       /* ERROR */
>  p_to_incomp1_value = (p_to_incomp1_type) p_to_func_value;     /* ERROR */
>  p_to_incomp2_value = (p_to_incomp2_type) p_to_func_value;     /* ERROR */

Ditto.  [s/function call/arithmetic/.]
>-----------------------------------------------------------------------------
>#16)  GCC [-pedantic-errors] fails to issue errors for the following invalid
>static int object_decl_6;
>static int object_defn_6 = 0;
>void test () {
>    extern double object_decl_6;                /* ERROR */
>    extern double object_defn_6;                /* ERROR */
>}

As in #1, I see no violation of a constraint.  The behavior is undefined but
silence is allowed.
>-----------------------------------------------------------------------------
>#17)  GCC [-pedantic-errors] fails to issue errors for the following invalid
>void callee (char c);
>void foobar () { void callee(); }     /* ERROR */
>void callee (char c) { }

Ditto.
>-----------------------------------------------------------------------------
>#18)  GCC incorrectly issues an error for the following standard-conformant
>      ANSI C code when the -pedantic-errors option is used.
>extern const int func_1 ();

Spurious diagnostics are allowed.  In fact, a spurious warning on this one
would be rather friendly, as long as the program still executes properly.
What happened when you tried executing it?
>-----------------------------------------------------------------------------
>#19)  GCC fails to issue an error for the following pair of incompatible
>      function declarations, even when the -pedantic-errors option is used.
>extern const int func_4 ();
>extern int func_4 ();                   /* ERROR */

For the fourth time, this does not violate a constraint.
>-----------------------------------------------------------------------------
>#20)  GCC incorrectly issues errors for the following standard-conformant
>      ANSI C code when the -pedantic-errors option is used.
>static enum E1 { red, green, blue};
>static struct S1 { int member; };
>static union U2 { int member; };
>void foobar () {
>	auto enum E2 { red, green, blue };
>	auto struct S2 { int member; };
>	auto union U2 { int member; };
>}

Spurious diagnostics are allowed, though now they return to the status of
unfriendly and misleading.  What happened when you tried executing it?
--
Norman Diamond                diamond@jit.dec.com
If this were the company's opinion, I wouldn't be allowed to post it.
Pardon me?  Or do I have to commit a crime first?