From: rfg@netcom.com (Ronald F. Guilmette)
Subject: Standard conformance and GCC 2.3.3
Organization: Netcom - Online Communication Services  (408 241-9760 guest) 
Date: Wed, 30 Dec 1992 01:12:11 GMT


The following testing report for GCC 2.3.3 may be of interest to readers of
the comp.std.c newsgroup.

GCC is often held up as an example of a compiler which conforms well to the
ANSI C standard.  In this report, I note a number of instances in which the
most recent version of GCC fails to act in a fully conformant fashion.
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 and/or by other C compilers claiming to conform
to the ANSI C standard.

// rfg


=============================================================================
I have just finished running my own tests on the recently released GCC 2.3.3.
These tests reveal twenty bugs, all of which are described below.

The tests were run on a copy of GCC 2.3.3 which was the final product of a
full three stage bootstrap for/on an i486 system running SVR4.  (The target
configuration for the compiler was i486-svr4.)

All tests were run with the following GCC options in effect:

	-ansi -pedantic-errors -fno-common -w -O

Note that the -O (optimization) option seems to have no relevance to any of
the bugs I have found.

Also note that most of the bugs described below are "platform independent"
and I would expect them to afflict GCC when it is hosted and/or targeted
to platforms other than i486/svr4 as well.

Most (but not all) of these twenty bugs are problems with standard conformance.
GCC is either issuing errors for valid ANSI C code or else it is failing to
issue errors for constructs which violate some constraint given in the ANSI
C standard.

-----------------------------------------------------------------------------
#1)  GCC fails to detect the error in the following code, even when the
     -pedantic-errors option is used.

void foo ()
{
  extern void bar (int i, ...);

  bar (99, 88, 77);
}

void bar (int i, int j, int k) { }      /* ERROR */
-----------------------------------------------------------------------------
#2)  GCC fails to detect the error in the following code, even when the
     -pedantic-errors option is used.

unsigned long overflow = LONG_MAX + 3; /* ERROR */
-----------------------------------------------------------------------------
#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) { }
-----------------------------------------------------------------------------
#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 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;
}
-----------------------------------------------------------------------------
#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";
-----------------------------------------------------------------------------
#6)  The following erroneous code causes GCC to crash with a signal 6.

extern volatile struct s evs;
void evs_test () { evs; }
-----------------------------------------------------------------------------
#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.  (The line number indicated
     in the error message is equal to the number of lines actually in the
     file plus one.)  Issuing error messages which reference non-existant
     source lines may cause some related tools (e.g. emacs) to go bonkers.
-----------------------------------------------------------------------------
#8)  GCC fails to issue errors for the following erroneous code, even when
     the -pedantic-errors option is in effect.  (Note that the argument type
     for the function is *not* a type which would result from integral
     promotions.)

void test_0 (char);
void test_0 (c) char c; { }
-----------------------------------------------------------------------------
#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.

     Example:

static void s (); int main () { s (); return 1; }
-----------------------------------------------------------------------------
#10)  GCC fails to issue an error for the following invalid C code, even when
      the -pedantic-errors option is used.

void (*func_ptr) ();
int i;
void test () { func_ptr = i ? 0 : 0; }         /* ERROR */
-----------------------------------------------------------------------------
#11)  GCC fails to issue errors for the following invalid C code involving
      comparison operators, even when the -pedantic-errors option is used.

typedef int b_array[3];
typedef int u_array[];

typedef b_array *b_array_ptr;
typedef u_array *u_array_ptr;

b_array b_array_src;
extern u_array u_array_src;
int *ip;
int i;
b_array_ptr b_array_dest;
u_array_ptr u_array_dest;

void test_relational_operators ()
{
  i = & u_array_src > & b_array_src;            /* ERROR */
  i = & b_array_src > & u_array_src;            /* ERROR */

  i = & u_array_src <= & b_array_src;           /* ERROR */
  i = & b_array_src <= & u_array_src;           /* ERROR */

  i = u_array_dest > b_array_dest;              /* ERROR */
  i = b_array_dest > u_array_dest;              /* ERROR */

  i = u_array_dest <= b_array_dest;             /* ERROR */
  i = b_array_dest <= u_array_dest;             /* ERROR */
}

int u_array_src[20] = { 0 };    /* complete its type */
-----------------------------------------------------------------------------
#12)  GCC fails to issue errors for the following invalid C code involving
      the binary `-' operator, even when the -pedantic-errors option is used.

typedef int b_array[3];
typedef int u_array[];

typedef b_array *b_array_ptr;
typedef u_array *u_array_ptr;

b_array b_array_src;
extern u_array u_array_src;
int *ip;
int i;
b_array_ptr b_array_dest;
u_array_ptr u_array_dest;

void test_pointer_subtraction ()
{
  i = & u_array_src - & b_array_src;            /* ERROR */
  i = & b_array_src - & u_array_src;            /* ERROR */

  i = u_array_dest - b_array_dest;              /* ERROR */
  i = b_array_dest - u_array_dest;              /* ERROR */
}

int u_array_src[20] = { 0 };    /* complete its type */
-----------------------------------------------------------------------------
#13)  GCC fails to issue errors for the following invalid C code involving
      invalid null pointer constants, even when the -pedantic-errors option
      is used.  (GCC also fails to properly flag these kinds of invalid
      null pointer constants in other contexts as well.)

int (*fp) ();
void test () { fp = (void *) (void *) 0; }    /* ERROR */
-----------------------------------------------------------------------------
#14)  GCC fails to issue errors for the following invalid C code involving
      invalid pointer type conversions, even when the -pedantic-errors option
      is used.

struct incomp1; /* never completed */
struct incomp2; /* completed towards the end - may make a difference */

typedef int             *p_to_object_type;
typedef struct incomp1  *p_to_incomp1_type;
typedef struct incomp2  *p_to_incomp2_type;
typedef int             (*p_to_func_type) ();

p_to_object_type        p_to_object_value;
p_to_incomp1_type       p_to_incomp1_value;
p_to_incomp2_type       p_to_incomp2_value;
p_to_func_type          p_to_func_value;

void
test ()
{
  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 */
}

struct incomp2 { int i; };
-----------------------------------------------------------------------------
#15)  GCC fails to issue errors for the following invalid C code involving
      invalid pointer type conversions, even when the -pedantic-errors option
      is used.

struct incomp1; /* never completed */
struct incomp2; /* completed towards the end - may make a difference */

typedef int             *p_to_object_type;
typedef struct incomp1  *p_to_incomp1_type;
typedef struct incomp2  *p_to_incomp2_type;
typedef int             (*p_to_func_type) ();

p_to_object_type        p_to_object_value;
p_to_incomp1_type       p_to_incomp1_value;
p_to_incomp2_type       p_to_incomp2_value;
p_to_func_type          p_to_func_value;

void
test ()
{
  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 */
}

struct incomp2 { int i; };
-----------------------------------------------------------------------------
#16)  GCC fails to issue errors for the following invalid C code involving
      local redeclarations of objects, even when the -pedantic-errors option
      is used.

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 */
}
-----------------------------------------------------------------------------
#17)  GCC fails to issue errors for the following invalid C code involving
      incompatible redeclarations, even when the -pedantic-errors option
      is used.

void callee (char c);
void foobar () { void callee(); }     /* ERROR */
void callee (char c) { }
-----------------------------------------------------------------------------
#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 ();
-----------------------------------------------------------------------------
#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 */
-----------------------------------------------------------------------------
#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; };
}
-----------------------------------------------------------------------------
-- 

// Ron ("Loose Cannon") Guilmette    uucp: ...uunet!lupine!segfault!rfg
//
//      "On the one hand I knew that programs could have a compelling
//       and deep logical beauty, on the other hand I was forced to
//       admit that most programs are presented in a way fit for
//       mechanical execution, but even if of any beauty at all,
//       totally unfit for human appreciation."
//                                              -- Edsger W. Dijkstra