Subject: RE: [hackers-il] Re: GCC's statement expressions

From: Omer Musaev <[email-masked]>
Date: Wed, 9 Jan 2002 18:55:44 +0200

> -----Original Message-----
> From: Adi Stav [mailto:[email-masked]]
> Sent: Wednesday, January 09, 2002 9:15 PM
> To: [email-masked]
> Subject: Re: [hackers-il] Re: GCC's statement expressions
> 
> 
> On Wed, Jan 09, 2002 at 05:37:12PM +0200, Arik Baratz wrote:
> > 
> > An rvalue MUST resolve to a value.
> > 
> > e.g. a=3
> > 
> > An lvalue MUST resolve to an address, but MAY resolve to a 
> value as well.
> 
> Is that necessarily so? A register variable cannot have its address
> taken but is an lvalue. Which lvalue does not resolve to a value?

My 2 cents:
1. resolve to an address != can have its address taken. 
The fact you can not have both:
void foo()
{
   register a = 1 ;
   register int *b ;

   b = &a ;
}
and a strictly in register does not invalidate b for being 
registreable. In other words, the fact that register var does 
not support "take_address_of" operation does not mean that 
a compiler can not operate an "address" of register available, 
which is the register itself:)

2. In C every l-value is r-value as well. I guess that there are
languages that support l-values that are not r-values. There are 
many languages out there....

> 
> ------------------------ Yahoo! Groups Sponsor 
> ---------------------~-->
> Tiny Wireless Camera under $80!
> Order Now! FREE VCR Commander!
> Click Here - Only 1 Day Left!
> http://us.click.yahoo.com/WoOlbB/7.PDAA/ySSFAA/saFolB/TM
> --------------------------------------------------------------
> -------~->
> 
> To unsubscribe from this group, send an email to:
> [email-masked]
> 
>  
> 
> Your use of Yahoo! Groups is subject to 
> http://docs.yahoo.com/info/terms/ 
> 
>

---

From: Oleg Goldshmidt <[email-masked]>
Date: 09 Jan 2002 20:37:35 +0200

> > > An lvalue MUST resolve to an address, but MAY resolve to a 

Note that this is a less strict definition than "an object that can
appear on the LHS of an assignment". The above will include constants.
I don't know what the current mainstream CS says. I suspect that the
term lvalue was coined before const modifier was introduced to C.

A more thorough definition should involve const explicitly, as in:

[ "addressable": &x is legal; "assignable": x = y is legal ]

* A mutable lvalue is addressable and assignable 
* An immutable lvalue is addressable, but not assignable. 
* An rvalue is neither addressable nor assignable.

> many languages out there....

You probably mean "in C every lvalue can be converted to an rvalue".

I think that even in C++ you might get into trouble with volatile
incompletely typed objects:

struct s;
volatile s *p = (s*)something; // ok (sort of - C cast)
*p;                            // incomplete type warning or error

My point is that a compiler will not quite barf only if it does
not treat derefencing as a read (which would mandate that *p is
an rvalue). 

I am not sure this makes much sense, and it's academic at best.

-- 
Oleg Goldshmidt | [email-masked] 
"If it ain't broken, it has not got enough features yet."

---

From: Nimster <[email-masked]>
Date: Wed, 09 Jan 2002 20:45:24 +0200

[snipped]

> many languages out there....

This doesn't qualify as an l-value not being an r-value, but in C++, if 
a function returns a class object by value as a const, the return value 
of that function cannot be an lvalue (that is, it cannot be assigned to 
or otherwise modified), while being an rvalue is completely fine.

class X {
   int i;
public:
   X(int ii);
   int modify(int ii);
};

X::X(int ii) { i = ii; }
int X::modify(int ii) { i = ii; }

const X foo() {
   return X(1);
}

int main() {
   foo().modify(2); //is illegal, foo cannot be an lvalue
   foo() = X(2); //is illegal even if there *was* an operator defined
   const X b = foo(); //is completely legal as an rvalue
   return 0;
}

Thus, there's a case in C++ where an rvalue does not act like an lvalue.

This is a modified excerpt from Thinking in C++ Vol. 1 (Chapter 8), 
available from http://www.bruceeckel.com/

-Nimster

---

From: Adi Stav <[email-masked]>
Date: Thu, 10 Jan 2002 12:37:53 +0200

> not treat derefencing as a read (which would mandate that *p is

I don't think objects of incomplete types /can be/ lvalues in C, or 
any values at all. I didn't know they could be in C++. My g++ 2.95.2 
doesn't like your code snippet even if *p is not volatile, which is 
consistent with C. But it lets me assign the result of *p to a (s&), 
if volatility matches, but it won't let me "just" dereference p like 
your code does! So if I understand that correctly, C++ objects of 
incomplete types are lvalues that have no values... And assignment to 
a reference does /not/ have an rvalue on its right side. 

Speaking of incomplete types in C, I've always longed for the ability 
to do something like:

extern struct foo {
   int bar;
};

which would put the /size/ of struct foo in a symbol "foo" in the 
object file, and so let a program declare variables of the 
incomplete struct foo type, without actually exposing it and risking
binary incompatilibty. But that would not mean a valueless lvalue, 
just a struct with unknown members.