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

[dcl.constexpr] Uninitialized non-static data members of fundamental type CWG2558 #5422

Open
xmh0511 opened this issue Apr 28, 2022 · 9 comments · May be fixed by #6267
Open

[dcl.constexpr] Uninitialized non-static data members of fundamental type CWG2558 #5422

xmh0511 opened this issue Apr 28, 2022 · 9 comments · May be fixed by #6267

Comments

@xmh0511
Copy link
Contributor

xmh0511 commented Apr 28, 2022

Consider this example

struct A{
   constexpr A(){}
   int value;
};
constexpr A obj;  // #1

In C++17 standard, we have the restriction on the constructor that is declared with constexpr. [dcl.constexpr] p4

The definition of a constexpr constructor shall satisfy the following requirements:

  • [...]
  • every non-variant non-static data member and base class subobject shall be initialized

Since the member value does not have a default initializer or specified its initialization with the mem-initializer, thus its default initialization performs no initialization. From this perspective, we can justify that #1 is ill-formed. However, in the current draft, we do not have this restriction anymore, and I do not find any replaceable rules. The full-expression of the initialization does not violate [expr.const] p5 nor [expr.const] p11, however, the example is rejected by all implementations. The reason for the rejection is basically:

subobject of type 'int' is not initialized
'A()' is not a constant expression because it refers to an incompletely initialized variable

We do not have the restrictions in either [dcl.constexpr] or [expr.const]. Is the revision of the draft omit the restriction?

@xmh0511 xmh0511 changed the title [dcl.contexpr] The restriction that non-static data member of fundamention type shall be initialized lacks in the current draft [dcl.contexpr] The restriction that non-static data member of fundamental type shall be initialized lacks in the current draft Apr 28, 2022
@xmh0511 xmh0511 changed the title [dcl.contexpr] The restriction that non-static data member of fundamental type shall be initialized lacks in the current draft [dcl.constexpr] The restriction that non-static data members of fundamental type shall be initialized lacks in the current draft Apr 28, 2022
@JohelEGP
Copy link
Contributor

@jensmaurer
Copy link
Member

This is CWG2558.

@jensmaurer jensmaurer changed the title [dcl.constexpr] The restriction that non-static data members of fundamental type shall be initialized lacks in the current draft [dcl.constexpr] Uninitialized non-static data members of fundamental type CWG2558 Apr 28, 2022
@xmh0511
Copy link
Contributor Author

xmh0511 commented Apr 28, 2022

If the omission will be identified to be an accident, the proposed wording might be that add an item in [expr.const] p5, which is:

a default-initialization that performs no initialization.

@jensmaurer
Copy link
Member

It was intentional that we can have core constant expressions with undefined data. We might not want to have undefined results when initializing a constexpr variable, though. See the issue cross-linked in CWG2558 for details.

@frederick-vs-ja
Copy link
Contributor

If the omission will be identified to be an accident, the proposed wording might be that add an item in [expr.const] p5, which is:

a default-initialization that performs no initialization.

No. What you suggested is partially reverting P1331R2, i.e. still disallowing trivial default initialization in constant evaluation while just allowing them in constexpr functions (like throw-expressions). I don't think this is wanted.


I think the resolution would be like this (added to [expr.cons]/11):

(11.?) - if the value is of scalar type, it does not contain an indeterminate value.
(11.?) - if the value is of union type, it has one active member.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Apr 29, 2022

still disallowing trivial default initialization in constant evaluation

That is what the implementations do here. I'm not seeing the wording in P1331R2 that supports this behavior.

If we want to augment [expr.cons]/11 to fix this issue. I think [expr.cons]/11 should first be clarified since the wording is not clear

a prvalue core constant expression whose value satisfies the following constraints:

  • if the value is an object of class type.

How could the value be an object? At least, an object can have a lifetime, how could the value of a prvalue have?

@frederick-vs-ja
Copy link
Contributor

frederick-vs-ja commented Apr 30, 2022

still disallowing trivial default initialization in constant evaluation

That is what the implementations do here. I'm not seeing the wording in P1331R2 that supports this behavior.

Implementations do allow it. See here. In this example, x is trivially default-initialized.

constexpr int foo = []{
    int x;
    x = 42;
    return x;
}();

How could the value be an object? At least, an object can have a lifetime, how could the value of a prvalue have?

I suspect that using "object" may be OK here, as the prvalue will eventually be materialized. Perhaps the key problem is lack of a term corresponding to "subobject", in order to specify a sub-portion of a prvalue.

@xmh0511
Copy link
Contributor Author

xmh0511 commented Apr 30, 2022

I suspect that using "object" may be OK here, as the prvalue will eventually be materialized.
A prvalue should keep its meaning that to be a pure value until given a result object, see [class.temporary] p2.
The materialization of a temporary object is generally delayed as long as possible in order to avoid creating unnecessary temporary objects.

If we discussed any object in a prvalue, the design of prvalue is meaningless. Again, an object occupy storage, prvalue does not.

To clarify this point, we might say

the object... in the result object of the prvalue.

@frederick-vs-ja
Copy link
Contributor

The part for CWG2558 is resolved (a union value without an active member can be a constant expression, while an indeterminate scalar value can't). But it's still a bit weird to say a subobject of a prvalue.

To clarify this point, we might say

the object... in the result object of the prvalue.

I think it's safe to check the result object, since in contexts needing to determine whether a expression of a class or array type is a constant expression, the result object must exist.

It might be better to replace the occurence of "the value" with "the result object", not sure whether this is editorial.

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 a pull request may close this issue.

4 participants