[comp.lang.c++] Does C++ 2.0 Emit Following C Construct?

deb@svax.cs.cornell.edu (David Baraff) (10/03/89)

C++ 1.2 emits the following peice of C code often: it is annoying
because some C compilers (i.e. mine, HP-UX 800) don't handle it.

The construct is

	&(f())

where f() returns (usually) a structure. The C compiler says

	error: Address operator requires an lvalue.

Now, I don't want to start a debate over whether or not this is legal
C -- the question is, does C++ 2.0 emit this sort of C code, and if
so, is there a way to stop it? I notice in the 2.0 release notes
the variable "FDOTRIGHT"; but this doesn't look like it would
help (although the HP-UX C compiler DOES allow the f().x expression).

Any C++ 2.0 authors out there who can answer this one?

	Thanks,
		David Baraff
		deb@cs.cornell.edu

jima@hplsla.HP.COM (Jim Adcock) (10/05/89)

My C++ 2.0 compiler [an s300 version] doesn't accept this construct --
squawking about not a lvalue.

NOTE:  I said the <C++ 2.0 compiler> NOT the backend C compiler won't accept 
this -- my s300 C compiler will accept the construct.

g++ 1.35.x will accept the construct.  

To my way of thinking, not accepting a structure returned from a function
as an lvalue makes perfect sense.  Or alternately, letting a returned 
structure be an lvalue makes no more or less sense than letting a 
returned "int" be an lvalue.  Compilers should be free to use a registered
return value protocol for small structures.  Requiring a returned value
to be an lvalue prevents this [or at least complicates it greatly.]

Return a reference instead.  References are lvalues. See "thingcopy" verses
"badcopy" below.

See example program below:


#include <stdio.h>

class thing
{
  const char* const name;
public:
  thing(char* nm):name(nm){}
  thing(const thing& that):name(that.name){}
  void print(){printf("thing is named: %s\n",name);}
  friend thing& thingcopy(const thing& that) {return *(new thing(that));}
  friend thing badcopy(const thing& that) {return that;}
};

main()
{
  thing* p;
  thing amagig("IamAgig");

  p = &(thingcopy(amagig));
  p->print();

  // p = &(badcopy(amagig));  C++ 2.0 complains: not an lvalue
  p->print();
}

shankar@hpclscu.HP.COM (Shankar Unni) (10/05/89)

> 	&(f())
> C -- the question is, does C++ 2.0 emit this sort of C code, and if
> so, is there a way to stop it? I notice in the 2.0 release notes

As far as I know, this particular abomination has been fixed in 2.0. We
have not encountered it yet.
-----
Shankar Unni                                   E-Mail: 
Hewlett-Packard California Language Lab.     Internet: shankar@hpda.hp.com
Phone : (408) 447-5797                           UUCP: ...!hplabs!hpda!shankar

deb@svax.cs.cornell.edu (David Baraff) (10/05/89)

In article <6590277@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes:
>My C++ 2.0 compiler [an s300 version] doesn't accept this construct --
>squawking about not a lvalue.
>
>NOTE:  I said the <C++ 2.0 compiler> NOT the backend C compiler won't accept 
>this -- my s300 C compiler will accept the construct.
>
>g++ 1.35.x will accept the construct.  
>
>To my way of thinking, not accepting a structure returned from a function
>as an lvalue makes perfect sense.  Or alternately, letting a returned 
>structure be an lvalue makes no more or less sense than letting a 
>returned "int" be an lvalue.  Compilers should be free to use a registered
>return value protocol for small structures.  Requiring a returned value
>to be an lvalue prevents this [or at least complicates it greatly.]
>
>Return a reference instead.  References are lvalues. See "thingcopy" verses
>"badcopy" below.

Perhaps I didn't make the problem clear enough. It was the 1.2
C++ compiler that emitted this code -- NOT me. All I was doing
was writing some standard matrix/vector stuff and I found
that the C code emitted contained these &f() constructs -- the original
C++ code had nothing resembling them!

So the 1.2 compiler emits bad C code. Original q: does the 2.0 compiler
ever do this?

jima@hplsla.HP.COM (Jim Adcock) (10/07/89)

>Perhaps I didn't make the problem clear enough. It was the 1.2
>C++ compiler that emitted this code -- NOT me. All I was doing
>was writing some standard matrix/vector stuff and I found
>that the C code emitted contained these &f() constructs -- the original
>C++ code had nothing resembling them!

>So the 1.2 compiler emits bad C code. Original q: does the 2.0 compiler
>ever do this?

According to Shankar, no.  I was assuming that if 2.0 wouldn't accept a 
construct, it ought to be smart enough not to emit it either.  So
both by practical experience, and my indirect test, the answer seems to
be that 2.0 has fixed this.

shankar@hpclscu.HP.COM (Shankar Unni) (10/07/89)

> So the 1.2 compiler emits bad C code. Original q: does the 2.0 compiler
> ever do this?

As I said previously: No. We have not yet encountered a case where 2.0
generates this type of code.
-----
Shankar Unni                                   E-Mail: 
Hewlett-Packard California Language Lab.     Internet: shankar@hpda.hp.com
Phone : (408) 447-5797                           UUCP: ...!hplabs!hpda!shankar

rfg@ics.uci.edu (Ronald Guilmette) (10/08/89)

In article <6590285@hplsla.HP.COM> jima@hplsla.HP.COM (Jim Adcock) writes:
>
>...  I was assuming that if 2.0 wouldn't accept a 
>construct, it ought to be smart enough not to emit it either. 

One would hope so.  One would also hope that Cfront would be smart enough
to avoid emitting code that your native C compiler will subsequently choke
on.  Unfortunately, this is not always true.

Try this little gem (but first make sure that your CC script does *not*
invoke the GNU C compiler):

	int i;

	int main ()
	{

		i = sizeof (main);
		return 0;
	}

// rfg

shankar@hpclscu.HP.COM (Shankar Unni) (10/10/89)

> Try this little gem (but first make sure that your CC script does *not*
> invoke the GNU C compiler):
> 
> 	int i;
> 	int main ()
> 	{
> 		i = sizeof (main);
> 		return 0;
> 	}

I got perfectly reasonable code from 2.0 (formatting cleaned up):

    int main ()
    {
	_main();
	{
	    i = (sizeof main );
	    return (int )0 ;
	}
    }

Looks kosher. You mean your compiler choked on "(sizeof main)"?
-----
Shankar Unni                                   E-Mail: 
Hewlett-Packard California Language Lab.     Internet: shankar@hpda.hp.com
Phone : (408) 447-5797                           UUCP: ...!hplabs!hpda!shankar

shankar@hpclscu.HP.COM (Shankar Unni) (10/12/89)

> 		i = sizeof (main);

Corrections from our ANSI C expert:

This expression is not legal, according to the ANSI C standard (function
names are not converted to pointers to functions when they are arguments to
the "sizeof" operator (section 3.2.2.1), and there is a constraint under
the sizeof operator (section 3.3.3.4) that specifically forbids expressions
of function type).

So cfront should catch this expression and flag it as an error. If it intends
for "main" to be converted to a function pointer, it should emit explicit
C code to do that ("&main") (which, in my opinion, would be a bad thing to
do). If not, it should flag the error.

I stand corrected.
-----
Shankar Unni                                   E-Mail: 
Hewlett-Packard California Language Lab.     Internet: shankar@hpda.hp.com
Phone : (408) 447-5797                           UUCP: ...!hplabs!hpda!shankar

rfg@ics.uci.edu (Ron Guilmette) (10/12/89)

In article <1000032@hpclscu.HP.COM> shankar@hpclscu.HP.COM (Shankar Unni) writes:
>> Try this little gem (but first make sure that your CC script does *not*
>> invoke the GNU C compiler):
>> 
>> 	int i;
>> 	int main ()
>> 	{
>> 		i = sizeof (main);
>> 		return 0;
>> 	}
>
>I got perfectly reasonable code from 2.0 (formatting cleaned up):
>
>    int main ()
>    {
>	_main();
>	{
>	    i = (sizeof main );
>	    return (int )0 ;
>	}
>    }
>
>Looks kosher. You mean your compiler choked on "(sizeof main)"?

You mean that yours didn't????  Maybe you had better have a look at the
ANSI C (draft) standard.

// rfg