🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.std.c
Article #3823

unreliable structures?

#3823
From: Ben Wing
Date: Wed, 23 Aug 1995 05:59
72 lines
3019 bytes
This question arises out of a discussion I had with Chris Torek
<torek@elf.bsdi.com>.  Basically, after discovering about the 12th
case in which GCC apparently generated incorrect code (in cases
where other compilers certainly did not do this), I posted a
message to gnu.gcc.bugs about how GCC sucked, etc. and here were
all the bugs, etc.  One of these bugs occurred in the statement

     keymap = make_number (string_char (XSYMBOL (keysym)->name, 0));

keymap is a structure (or more precisely, a union of structures)
like this:

typedef
union Lisp_Object
  {
    struct
      {
        unsigned int type_mark: 4;
        signed int val: 28;
      } s;
    struct
      {
        unsigned int type: 3;
        /* The markbit is not really part of the value of a Lisp_Object,
           and is always zero except during garbage collection.  */
        unsigned int markbit: 1;
        unsigned int val: 28;
      } gu;
    struct __nosuchstruct__ *v;
    CONST struct __nosuchstruct__ *cv;             /* C wanks */
  }
Lisp_Object;

make_number() is actually a macro that uses GCC's "construct a union"
language extension, like this:

/* Use GCC's struct initializers feature */
#define XMAKE_LISP(vartype,ptr) \
   ((union Lisp_Object) { gu: { markbit: 0, \
                                type: (vartype), \
                                val: ((unsigned int) ptr) } })

#define make_number(a) (XMAKE_LISP (Lisp_Int, (a)))

XSYMBOL() is a macro that retrieves the pointer out of the union
and casts it to a (struct Lisp_Symbol *), and also contains an
assert() that assures that the type tag is actually for a symbol.
string_char() is also a macro.

Anyway ...  the statement as written triggers the assertion failure
even though keysym is of the correct type before the statement.
What appears to be happening is that GCC is modifying the value
of keymap *before* completely evaluating the right-hand-side; in
other words, the expression is being converted to

keysym.gu.markbit = 0;
keysym.gu.type = Lisp_Int; /* Lisp_Int is an enum constant */
keysym.val = (unsigned int) string_char (XSYMBOL (keysym)->name, 0);

I claim that this behavior is completely bogus and is a bug in GCC.
Chris claims that the ANSI C standard does not actually forbid this
bogosity from happening, or at least is not explicit about this.

What does the net think?

If Chris is right, then it basically makes using structure types as
if they were fundamental types completely useless and unreliable.

ben
-- 
"... then the day came when the risk to remain tight in a bud was
more painful than the risk it took to blossom." -- Anais Nin
Technical Details
Message-ID: <wingDDr1ys.CG1@netcom.com>
Path: arc1-ca.pugleaf.net!netcom.com!wing

Show Full Headers
Complete Article Headers
Newsgroups: comp.std.c
Path: arc1-ca.pugleaf.net!netcom.com!wing
From: wing@netcom.com (Ben Wing)
Subject: unreliable structures?
Message-ID: <wingDDr1ys.CG1@netcom.com>
Cc: torek@elf.bsdi.com
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
Date: Wed, 23 Aug 1995 05:59:15 GMT
Sender: wing@netcom14.netcom.com