[comp.bugs.4bsd] strange effects with enumerated types

phrrngtn@cs.tcd.ie (Paul Harrington) (10/14/88)

(I tried posting this before but it did not arrive)
The following code was tested on a SUN 3/50 under SunOS 3.3.
Depending on wheter you give an initialiser to the enum elements in the
declaration of the type of p or not you get very different outputs from
test_fn() ranging from 1,3,5 to 1,2,4 to 2,4,6 with my old favourite 2,3,4 when
you say a=1,b=2,c=3 in the declaration of the type of p in test_fn()

An RPC package called Courier generates this unusual type of code with
parameter types being redeclared  even for functions that have the same
effective types for their parameters.

why does the compiler (I don't know which compiler it is. I assume it is
the standard one supplied with a SUN 3/50) produce this result and is it a bug of this compiler or a "feature" of C ?





typedef struct {
	enum{a=1,b,c}choice;
	union{
	int a;
	long b;
	short c;
	}u;
	}new_struct;

typedef enum {e,f,g,h} e1;


void test_fn1(p)
struct {
	enum{a=1,b=2,c=3}choice;
	union{
	int a;
	long b;
	short c;
	}u;
	}*p;
{
printf("the size of p is %d\n",sizeof(p));
printf("(test_fn1) a=%d,b=%d,c=%d\n",a,b,c);
}

main()
{
new_struct *v;
printf("(main) a=%d,b=%d,c=%d\n",a,b,c);
printf("the size of e1 is %d\n",sizeof(e1));
printf("the size of a is %d\n",sizeof(a));
test_fn1(v);
}

guy@auspex.UUCP (Guy Harris) (10/19/88)

>why does the compiler (I don't know which compiler it is. I assume it is
>the standard one supplied with a SUN 3/50)

...which is based on PCC or its descendants, like many (most?) UNIX C
compilers, so I suspect this bug may exist in other UNIX C compilers as
well...

>produce this result and is it a bug of this compiler or a "feature" of C ?

According to K&R, second edition (which includes stuff from a recent
ANSI C draft):

	   Enumerator names in the same scope must all be distinct from
	each other and from ordinary variable names, but the values need
	not be distinct.

I infer from K&R 2 that the scope of the "enum" in "new_struct" is the
entire source file and the scope of the "enum" in "*p" to be the
function "test_fn1".  Now, K&R 2 also says

	   If an identifier is explicitly declared at the head of a block,
	including the block constituting a function, any declaration of
	the identifier ouside the block is suspended until the end of
	the block.

From that, I infer that the declaration "a", "b",and "c" in the
definition of "new_struct" should be suspended inside the block
constituting "test_fn1", so that this is a compiler bug.

chris@mimsy.UUCP (Chris Torek) (10/19/88)

In article <20@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
>... From that, I infer that the declaration "a", "b",and "c" in the
>definition of "new_struct" should be suspended inside the block
>constituting "test_fn1", so that this is a compiler bug.

It is quite definitely a compiler bug.  Anything that causes a, b, and
c to have the values 2, 3, and 4 when the most recent `enum'
declaration read `enum { a=1, b, c }' is clearly a bug!  I even know
just where, but not precisely what to do to fix it.  In mip/pftn.c we
find the routine `defid', which, for a `MOE' (Member Of Enum) type, has
the following code:

	if( scl == class ){
		if( p->offset!= strucoff++ ) break;
		psave( idp );
		}
	break;

What happens is that `strucoff' (which keeps track of the offset of
members of structures---enum type declarations are fudged as structures
inside pcc) is incremented *twice*, once here (where it checks for
a mismatch and may or may not allow the redeclaration, depending on
whether this hides a previous declaration) and once below.  I *think*
that it should return after calling psave(), except that I am not sure
that, if p->offset != strucoff++, strucoff should have been incremented.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris

chris@mimsy.UUCP (Chris Torek) (10/20/88)

In article <14065@mimsy.UUCP> I noted that the bug was in the following
few lines from src/lib/mip/pftn.c:
>	if( scl == class ){
>		if( p->offset!= strucoff++ ) break;
>		psave( idp );
>		}
>	break;

but then added
>...  I *think* that it should return after calling psave(), except that
>I am not sure that, if p->offset != strucoff++, strucoff should have
>been incremented.

Of course not!  The code should read

	if( scl == class && p->offset == strucoff ){
		strucoff++;
		psave( idp );
		return;
		}
	break;
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris