[comp.std.c] ANSI vs K&R 3.7.1 structures Help!

jkelly@world.std.com (john c kelly) (03/23/91)

         Sorry to bother everyone but  I  am  about to port a fair size
    application from one machine to another.  I had not done much  work
    on  the  target  machine  so  I  decided to checkout the compiler's
    capabilities.  I took a copy  of  the  C torture tests and tried to
    compile the code on the new machine.  I could not  do  the  testing
    myself, the  system administrator  had to,  so I  placed all of the
    code  into  one single file and he ran the compiler, which promptly
    died.  The sysadmin put in  a  service  call and sent a copy of the
    code to the engineers  and they replied:

              This note is to explain why we do not think that the
         test case code is a valid ANSI C program.  Please note we
         only  support the K&R standard where it agrees with ANSI.

              In ANSI  3.7.1,  5th  paragraph  of the 'Contraints'
         section, it  states:   'If  the  declarator  includes  an
         identifier list, each declaration in the declaration list
         shall have at least one declarator, and those declarators
         shall declare only identifiers from the identifier list.'

              The  key  point  is  that  each function must have a
         declarator.


         In function s22(pd0) you declared a structure :

              struct defs {
                            ... some stuff
                            ... some more stuff
              };     /* <--- should be a declarator here. */

              struct defs *pd0;


              The problem with your code is that the 'struct defs'
         statement does  not  have  a  declarator.   The  compiler
         dosen't  like  the  semi-colon because it is expecting an
         identifier for the  declarator.

              The following is what  the ANSI version of the above
         code looks like:


              struct defs {
                            ... some stuff
                            ... some more stuff
              } *pd0;  /* <--- now the declaration has a declarator. */


              We converted the test case to ANSI format,  and  got
         further  compile  errors  becasue  the compiler gives the
         definition of  'struct  defs'  tag  in  function s22 file
         scope, and so  each  subsequent  declaration  of  'struct
         defs' receives an error message that stuct tags cannot be
         redefined.   The  way  to  resolve that is to only do one
         defintion of the 'struct  defs' tag.


         HELP!   I am highly suspicious of their response.  I have used
    this stye of code before.  In  fact  the code compiles fine using 5
    other compilers!   I don't  have the  ANSI spec  to quote from so I
    appeal to the C-NET-GODS to tell me if they are blowing smoke or  I
    am  just  stupid.  One thing that really wories me is that they say
    the 'stuct defs' tag  has  been  given file scope.  It was declared
    INSIDE the function!  I thought that this made it local not global.

         ANY  help  or  suggstions  would  be  greatly appreciated.  If
    possible e-mail directly to  me  I'll summarize if enough interest.

    John C. Kelly                           MaBell: 717-986-5038
    Prime System Integration  (prefered)--> Prime:  j.kelly@md-b.prime.com
    Prime Computer Inc.                     Client: ampt0659@s2901b.amp.com
    DISCLAIMER: I speak for me.  Only.      Home:   jkelly@world.std.com
    "You can demonstrate a program for an executive - but  you  can't  make
     him computer literate."
-- 

  John C. Kelly                           MaBell: 717-986-5038
  Prime System Integration                Prime:  j.kelly@md-b.prime.com
  Prime Computer Inc.                     Client: ampt0659@s2901b.amp.com

henry@zoo.toronto.edu (Henry Spencer) (03/24/91)

You do not specify where the troublesome declarations were, and that is
crucial.  Context indicates they were within a function, but it matters
a lot whether they were in the parameter list or inside the {}.  The rule
quoted from 3.7.1 really does constrain parameter-list declarations to
contain at least one declarator.  No such constraint applies to declarations
within the function body.

Many older compilers were looser about what they allowed in parameter lists.
Argument by example is always unreliable, and is especially so for C, because
many superfically-different C compilers have common ancestry.

>    ... One thing that really wories me is that they say
>    the 'stuct defs' tag  has  been  given file scope.  It was declared
>    INSIDE the function!  I thought that this made it local not global.

Now *this* sounds seriously bogus.  Struct tags obey the same scope rules
as other declared identifiers.
-- 
"[Some people] positively *wish* to     | Henry Spencer @ U of Toronto Zoology
believe ill of the modern world."-R.Peto|  henry@zoo.toronto.edu  utzoo!henry

bhoughto@nevin.intel.com (Blair P. Houghton) (03/24/91)

Henry's right, it's not clear where you made this declaration.

Your supplier's citation of X3.159-1989, however,
applies to only two situation, which are:

    type1 s22( struct defs { ... }; struct defs *pdo ) /* <--parameter list */
    {                         /*  ^missing identifier */
            ...
    }

and:

    type1 s22( pdo )            /* <-- identifier list */
    struct defs { ... }; struct defs *pdo;
    {
	    ...
    }

Both of these are declaring two parameters, but listing only one.

Similarly

    struct defs {
       ...
    };

    type1 func( bar )            /* <-- identifier list */
    struct defs;
    {
	    ...
    }

This is broken not because the listed parameter is not declared,
but because the declaration specifier `struct defs' does not
declare one of the listed parameters.  In the absence of a declaration,
the listed parameters' types default to `int'.  Here, though,
the extraneous declaration ought to cause compilation to end.

In article <1991Mar22.183721.11779@world.std.com> jkelly@world.std.com (john c kelly) writes:
>
>         Sorry to bother everyone but  I  am  about to port a fair size
>    application from one machine to another.  I had not done much  work
>    on  the  target  machine  so  I  decided to checkout the compiler's
>    capabilities.  I took a copy  of  the  C torture tests and tried to

Torture tests?  This one seems to have broken
down when shown to a suite at the Marriott... :-)

>    compile the code on the new machine.  I could not  do  the  testing
>    myself, the  system administrator  had to,  so I  placed all of the
>    code  into  one single file and he ran the compiler, which promptly
>    died.  The sysadmin put in  a  service  call and sent a copy of the
>    code to the engineers  and they replied:
>
>              This note is to explain why we do not think that the
>         test case code is a valid ANSI C program.  Please note we
>         only  support the K&R standard where it agrees with ANSI.
>
>              In ANSI  3.7.1,  5th  paragraph  of the 'Contraints'
>         section, it  states:   'If  the  declarator  includes  an
>         identifier list, each declaration in the declaration list
>         shall have at least one declarator, and those declarators
>         shall declare only identifiers from the identifier list.'
>
>              The  key  point  is  that  each function must have a
>         declarator.
>
>
>         In function s22(pd0) you declared a structure :

"In function" does not invoke para 5 of 3.7.1.

"In the parameter declarations for function", would.

>
>              struct defs {
>                            ... some stuff
>                            ... some more stuff
>              };     /* <--- should be a declarator here. */

There most explicitly may be no declarator there.  The
standard is full of examples of this sort of declaration.

>              struct defs *pd0;
>
>
>              The problem with your code is that the 'struct defs'
>         statement does  not  have  a  declarator.   The  compiler
>         dosen't  like  the  semi-colon because it is expecting an
>         identifier for the  declarator.
>
>              The following is what  the ANSI version of the above
>         code looks like:
>
>
>              struct defs {
>                            ... some stuff
>                            ... some more stuff
>              } *pd0;  /* <--- now the declaration has a declarator. */
>
>
>              We converted the test case to ANSI format,  and  got

Bogus "ANSI format".  Not even KnR would allow you to put an
declaratorless structure definition in the parameter declarators;
but I don't think you did, anyway.

>         further  compile  errors  becasue  the compiler gives the
>         definition of  'struct  defs'  tag  in  function s22 file
>         scope,

This is illegal.  Even if the tag's declaration appears in the
parameter list or identifier list declarators, it has
scope within the function only, just as does the parameter
identifier.

>         and so  each  subsequent  declaration  of  'struct
>         defs' receives an error message that stuct tags cannot be
>         redefined.   The  way  to  resolve that is to only do one
>         defintion of the 'struct  defs' tag.

The way to resolve it is to fix the compiler.

>         HELP!   I am highly suspicious of their response.  I have used
>    this stye of code before.  In  fact  the code compiles fine using 5
>    other compilers!   I don't  have the  ANSI spec  to quote from so I
>    appeal to the C-NET-GODS to tell me if they are blowing smoke or  I
>    am  just  stupid.  One thing that really wories me is that they say
>    the 'stuct defs' tag  has  been  given file scope.  It was declared
>    INSIDE the function!  I thought that this made it local not global.

You're exactly correct.  It would have block scope.  Giving
it file scope when it does not appear outside of a function
definition or a block is broken, broken, broken.

Is this what you did?

        type1 s22 ( ... )
        ...
        {
            struct defs {
                ...
            };
            ...
            struct defs *pdo;
            ...
        }

If it is, then you did right.  3.7.1 has absolutely nothing
to do with this, since 3.7.1 applies only to function
definitions, and has no bearing on structure definitions.

Tell these "engineers" to read ANSI X3.159-1989, sec.
3.1.2.1, p. 21, ll. 27-42, taking note that scope is
defined by where the identifier "appears", and in the case
of tags (a tag is an identifier; see sec. 3.5.2.3) the
scope "begins just after the appearance of the tag in a
type specifier that declares the tag," which means only
that it doesn't have scope before the tag appears.  Most
importantly, that latter phrase does not change the point
at which the scope ends, which in your case is the closing
`}' of that function's body's block.

Nothing you show indicates that any part of your structure
should get file scope.

Show them also sec. 3.5, p. 58, l. 4.  It clearly
shows that the init-declarator-list in a declaration
is OPTIONAL.  l. 16 states that the minimum a declaration
must do is declare one of "a declarator, a tag, or the
members of an enumeration."  You satisfied that with `defs'.

You can leave out the variable declarators.

>         ANY  help  or  suggstions  would  be  greatly appreciated.  If
>    possible e-mail directly to  me  I'll summarize if enough interest.

What? and miss a chance to flame a truly broken compiler implementation?

The only way you could have gone wrong is if you did:

    /* no prior declaration of `defs' in scope */

    type1 s22 ( ... )
    ...
    {                           /* begin block */
        struct defs {           /* block-scope `defs' */
            ...
        };                      /* legally absent init-declarator-list */
        ...
    }                           /* end block */
    ...
    struct defs *pdo;           /* `defs' ended scope at `}' */

or:

    /* no prior declaration of `defs' in scope */

    type1 s22(pdo)
    struct defs pdo;            /* `defs' not yet in scope */
    {
        struct defs {           /* scope of `defs' begins here */
            ...
        };
        ...
    }

which mean that the tag `defs' is undefined when you declare pdo.

                                --Blair
                                  "Warning: illegal use of ellipsis."