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

[conv.lval] Determine the value of a constant without accessing an object #4495

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jensmaurer
Copy link
Member

Fixes #4493

@jensmaurer jensmaurer added the decision-required A decision of the editorial group (or the Project Editor) is required. label Feb 12, 2021
Comment on lines 664 to 666
\item Otherwise, if $E$ is a constant expression that designates an object
that is usable in constant expressions ([expr.const]),
the result is the value of that object.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems much broader than the rule in /2.2. This would also remove the access in:

struct X { int a; };
constexpr X x = {1};
int n = (&x)->a;

... which currently does result in an odr-use of x and an access. Changing that doesn't seem editorial.

Can we make the words here more directly refer back to the /2.2 case somehow? Maybe something like:

\item Otherwise, if $E$ is potentially evaluated and the object designated by $E$ is not accessed, as specified above, the designated object is necessarily usable in constant expressions ([expr.const]) and the result is the value of that object.

(I don't like "is necessarily" here. Do we have another way to say "must be" without making ISO angry?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Or maybe we could inline /2 into these bullets?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also has interactions with the very definition of "lvalue":

struct S
{
     static const int a = 1;
};

int main()
{
     return S::a;  // no odr-use; no definition of S::a needed
}

[intro.object] p1 "An object is created by a definition (6.2) ..."

[basic.lval] p1 "A glvalue is an expression whose evaluation determines the identity of an object or function.

How can you identify an object that wasn't ever created (because there is no definition)?

http://lists.isocpp.org/core/2021/02/10513.php

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it works best to integrate p2 into the "result" bullets.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe say the result is the value of \tcode{x}'s initializer. in non-odr-used variable case? Variable is not an object, it doesn't have value.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BTW

struct S
{
	int m;
};

int main()
{
	&S::m;
}

[expr.prim.id.qual] says that a qualified-id denoting data member is an lvalue, but I don't think S::m in &S::m can denote an object. Even though we have pointer-to-member, IIUC S::m is still an lvalue there, which makes me feel uncomfortable. Should this be a Core issue? 🤔

Copy link
Contributor

@xmh0511 xmh0511 Mar 31, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe say the result is the value of \tcode{x}'s initializer. A variable that is usable in constant expressions does not always have an initializer

A variable or temporary object o is constant-initialized if.

  • either it has an initializer or its default-initialization results in some initialization being performed
struct A{
    int v = 1;
};

@cplusplus cplusplus deleted a comment from languagelawyer Feb 13, 2021
@jensmaurer
Copy link
Member Author

jensmaurer commented Apr 16, 2021

Editorial meeting 2021-04-16: "const int x = 10000; sizeof(char{x})" needs the value of x, but is not potentially evaluated. Fix by moving the "set of potential results" wording to the front. Then, create a diff so that CWG can sign off. Also add the example.
What's the intended behavior for lvalue-to-rvalue conversion of class types under the "set of potential results" bullet? (Happens with passing class arguments to ellipsis parameters; maybe also with conditional operator.)
The proposed resolution also fixes non-access for nullptr_t values.
Make it a core issue.

@jensmaurer jensmaurer added cwg Issue must be reviewed by CWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking. and removed decision-required A decision of the editorial group (or the Project Editor) is required. labels Apr 16, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cwg Issue must be reviewed by CWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[conv.lval] doesn't specify the result for objects that are not accessed?
4 participants