[comp.std.c++] type definitions and scopes

daniel@terra.ucsc.edu (Daniel Edelson) (04/02/91)

I have tried unsuccessfully to find an unambiguous statement
in the standard that allows or prohibits the following cases:
	1) a function declaration that defines a new 
	   type in the return type, and,
	2) a function declaration that defines a new
	   type in a parameter

For example:

	/*
	 * The return type of foo() defines a new type, struct S
	 */
	struct S { int a; } foo(void) { }

	/*
	 * The parameter of bar() defines a new type, struct T
	 */
	void bar(struct T { int b; } p) { }

The function ``bar'' is not particularly
useful because the only type-safe calls to it can be
recursive calls, since ``struct T'' has block scope.

Are these strictly conformant ANSI C code?
If so, in the above example, must ``struct S'' be given
file scope? 

Thanks,
Daniel Edelson

daniel@terra.ucsc.edu (Daniel Edelson) (04/02/91)

In article <13998@darkstar.ucsc.edu> daniel@terra.ucsc.edu (Daniel Edelson) writes:
>I have tried unsuccessfully to find an unambiguous statement....

Sorry, I meant to send this to comp.std.c...

apologies,

daniel

david@lpi.liant.com (David Michaels) (04/05/91)

In <13998@darkstar.ucsc.edu> daniel@terra.ucsc.edu (Daniel Edelson) writes:

-> I have tried unsuccessfully to find an unambiguous statement....
-> in the standard that allows or prohibits the following cases:
-> 	1) a function declaration that defines a new 
-> 	   type in the return type, and,
-> 	2) a function declaration that defines a new type in a parameter

In <13999@darkstar.ucsc.edu> daniel@terra.ucsc.edu (Daniel Edelson) writes:

-> Sorry, I meant to send this to comp.std.c...

Well, comp.std.c++ is also appropriate; I've been meaning to bring up this nit.

According to ANSI-C, defining a new type in a (1) return type,
(2) parameter, (3) cast expression, and (4) sizeof expression,
is legal (well, at least it doesn't say that any of these are illegal,
and the Plum-Hall validation suite explicitly tests for (2) and (4)).

But, in the C++ARM, defining a new type in a (1) return type,
(2) parameter, and (3) cast expression is explicitly prohibited
(sec.8.2.5, p.139 and sec.5.4, p.67).

The stated reason for (1) and (2) is that C++ relies on name equivalence,
and since the defined tag name would be in the scope of the function, the
*only* legal calls of the function would be from within the function itself.

This reasoning does not seem to apply at all to case (1); I don't see any
reason for this restriction whatsoever; it seems to be a fairly reasonable
thing to want to do, e.g.:

        struct S { int a, b; } f () { }
        main () { struct S x = f (); }

As for case (2), this just isn't true; consider:

        void f (struct S { int a, b; } *arg) { }
        main () { f (0); /* legal call to f with null pointer constant */ }

And as for case (3), the reasoning that the result would not be usable
is also not true; consider:

        main () { void *p = (struct T { int c, d; } *)0; }

Restrictions (2) and (3) are perfectly fine with me, but I think the real
reason for these restrictions is simply that it's bad programming practice,
not for any other technical reasons.  No?

Anyways, my question is, does the same kind of restriction apply to
defining a new type in a sizeof expression, and new expression.  E.g.

        int x = sizeof (struct S { int a, b; });  // legal ?
        void *p = new (struct T { int c, d; });   // legal ?

I can't find anything in the C++ARM which prohibits these.
Did I miss it?  Should I assume it's simply an oversight?  Thanks.

                                + -------------------------------------+
                                | David Michaels (david@lpi.liant.com) |
                                | Language Processors, Inc. (LPI)      |
                                | Framingham, MA (508) 626-0006        |
                                + -------------------------------------+