Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[basic.lval] Remove an incorrect statement that assignment expects PR-value right operands #4875

Closed
wants to merge 1 commit into from

Conversation

geryogam
Copy link
Contributor

@geryogam geryogam commented Sep 7, 2021

This is a perfectly valid assignment with an L-value right operand:

int x{3}, y;
y = x;

@geryogam geryogam changed the title Remove an incorrect statement that assignment expects an R-value right operand [basic.lval] Remove an incorrect statement that assignment expects an R-value right operand Sep 7, 2021
@geryogam geryogam changed the title [basic.lval] Remove an incorrect statement that assignment expects an R-value right operand [basic.lval] Remove an incorrect statement that assignment expects an PR-value right operand Sep 7, 2021
@geryogam geryogam changed the title [basic.lval] Remove an incorrect statement that assignment expects an PR-value right operand [basic.lval] Remove an incorrect statement that assignment expects PR-value right operands Sep 7, 2021
@jensmaurer
Copy link
Member

This proposed change is incorrect. Assignment does expect a prvalue as the right operand, and the lvalue-to-rvalue conversion [conv.lval] is applied if it isn't. (That conversion actually reads the value designated by the lvalue, which is obviously necessary to actually perform the assignment.)

@jensmaurer jensmaurer closed this Sep 7, 2021
@geryogam
Copy link
Contributor Author

geryogam commented Sep 7, 2021

@jensmaurer Based on Christoper Strachey’s papers, I thought that what makes an expression an L-value expression is that it has two values (so there are two possible evaluation modes): a value representing its content (called an R-value) and a value representing its storage location (called an L-value). And that what makes an expression an R-value expression is that it has a single value: a value representing its content (R-value). And that the assignment command E1 = E2; where E1 and E2 are expressions retrieves the R-value of E2 (R-value evaluation mode) and stores it into the L-value of E1 (L-value evaluation mode). So that the assignment command only requires E1 to be an L-value expression (there is no requirement on E2 since it is evaluated in R-value evaluation mode, which is possible for both L-value expressions and R-value expressions).

Thus what the C++ standard calls ‘lvalue-to-rvalue conversion’ seems to be R-value evaluation mode. We are not really converting the value category of an expression, we are evaluating an expression in a particular mode. So I find the C++ terminology ‘lvalue-to-rvalue conversion’ a little confusing here.

@jwakely
Copy link
Member

jwakely commented Sep 8, 2021

Strachey's model may be isomorphic with the one in the C++ standard, but obviously the C++ standard uses its own model.

You can think in terms of Strachey's model if it helps you, but the standard doesn't use it. And you definitely can't change bits of the C++ standard to inconsistently use that model in just one place.

@geryogam geryogam deleted the patch-2 branch September 8, 2021 06:41
@geryogam
Copy link
Contributor Author

geryogam commented Sep 8, 2021

Yes, when I proposed this change I was not aware of this lvalue-to-rvalue conversion terminology and thought it was a mistake. Sorry for the noise.

@tkoeppe
Copy link
Contributor

tkoeppe commented Sep 8, 2021

I'm not even sure that alternative model is quite right. You can have glvalues of incomplete type, but you cannot convert those to prvalues. So I don't find it helpful to think of "two values at once", but I think the standard's approach of allowing conversion of one to the other is more appropriate.

@jwakely
Copy link
Member

jwakely commented Sep 8, 2021

Strachey wasn't even talking about C (maybe Pascal?) so it's unsurprising if it doesn't work for C++, invented years after his death.

@geryogam
Copy link
Contributor Author

geryogam commented Sep 8, 2021

You can have glvalues of incomplete type, but you cannot convert those to prvalues.

That is true, we get a compiler warning when trying to use a glvalue denoting an automatic object of incomplete type:

#include <iostream>

int main() {
    int i;            // creates an automatic object of incomplete type
    std::cout << &i;  // okay: prints the lvalue of i
    std::cout << i;   // warning: prints the indeterminate rvalue of i
    return 0;
}

I am not sure if Strachey wrote about this, but I think he did when developing his denotational semantics.

Strachey wasn't even talking about C (maybe Pascal?) so it's unsurprising if it doesn't work for C++, invented years after his death.

In his influential paper ‘Fundamental Concepts in Programming Languages’, Strachey was actually talking about CPL, an early ancestor of the C language via the BCPL and B languages.

@jwakely
Copy link
Member

jwakely commented Sep 8, 2021

int i; // creates an automatic object of incomplete type

No it doesn't, int is a complete type.

This is what tkoeppe was talking about:

struct IncompleteType;
IncompleteType& getLvalueOfIncompleteType();

But this also belongs on Stack Overflow, not here.

@geryogam
Copy link
Contributor Author

geryogam commented Sep 9, 2021

My bad, I mixed up incomplete type with indeterminate value, though in both cases glvalue expressions cannot be converted to prvalue expressions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants