Bug 97195 - construct_at on a union member is not a constant expression
Summary: construct_at on a union member is not a constant expression
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.0
: P3 normal
Target Milestone: ---
Assignee: Jakub Jelinek
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-09-24 14:37 UTC by Barry Revzin
Modified: 2020-10-13 08:18 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2020-09-28 00:00:00


Attachments
gcc11-pr97195.patch (1009 bytes, patch)
2020-09-29 16:43 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Barry Revzin 2020-09-24 14:37:47 UTC
In trying to test adding more constexpr support to std::optional:

#include <bits/stl_construct.h>

union S {
    int i;
};

constexpr int f() {
    S s;
    std::construct_at(&s.i, 0);
    return 0;
}

constexpr int z = f();

gcc rejects with:

<source>:13:20:   in 'constexpr' expansion of 'f()'
<source>:9:22:   in 'constexpr' expansion of 'std::construct_at<int, int>((& s.S::i), 0)'
<source>:13:21: error: '(void*)(& s.S::i)' is not a constant expression
   13 | constexpr int z = f();
      |                     ^

But this should be fine.
Comment 1 David Stone 2020-09-28 01:12:54 UTC
This is actually a broader bug in construct_at, unrelated to unions:


```
#include <memory>

constexpr bool test() {
	int a = 5;
	std::construct_at(
		&a,
		-1
	);
	return true;
}
constexpr bool b = test();
```

is also rejected. See it live: https://godbolt.org/z/KWK8n1

The real problem here appears to be that std::construct_at is not a constant expression for values with non-constant addresses. The following code, for example, is accepted:

```
#include <memory>

struct S {
	constexpr S() {
		std::construct_at(
			&m,
			-1
		);
	}

	int m;
};

constexpr S s;
```

See it live: https://godbolt.org/z/Wdx9Kx
Comment 2 Jakub Jelinek 2020-09-29 16:43:54 UTC
Created attachment 49290 [details]
gcc11-pr97195.patch

Untested fix.
Comment 3 GCC Commits 2020-10-01 09:17:41 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:2805fcb32660bc0cdcd5ba54310f1f02651e039f

commit r11-3581-g2805fcb32660bc0cdcd5ba54310f1f02651e039f
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Oct 1 11:16:44 2020 +0200

    c++: Handle std::construct_at on automatic vars during constant evaluation [PR97195]
    
    As mentioned in the PR, we only support due to a bug in constant expressions
    std::construct_at on non-automatic variables, because we VERIFY_CONSTANT the
    second argument of placement new, which fails verification if it is an
    address of an automatic variable.
    The following patch fixes it by not performing that verification, the
    placement new evaluation later on will verify it after it is dereferenced.
    
    2020-10-01  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/97195
            * constexpr.c (cxx_eval_call_expression): Don't VERIFY_CONSTANT the
            second argument.
    
            * g++.dg/cpp2a/constexpr-new14.C: New test.
Comment 4 GCC Commits 2020-10-05 08:24:55 UTC
The releases/gcc-10 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:355b42c5d9d58d266829d2e44528f7a5ca0eae37

commit r10-8852-g355b42c5d9d58d266829d2e44528f7a5ca0eae37
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Thu Oct 1 11:16:44 2020 +0200

    c++: Handle std::construct_at on automatic vars during constant evaluation [PR97195]
    
    As mentioned in the PR, we only support due to a bug in constant expressions
    std::construct_at on non-automatic variables, because we VERIFY_CONSTANT the
    second argument of placement new, which fails verification if it is an
    address of an automatic variable.
    The following patch fixes it by not performing that verification, the
    placement new evaluation later on will verify it after it is dereferenced.
    
    2020-10-01  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/97195
            * constexpr.c (cxx_eval_call_expression): Don't VERIFY_CONSTANT the
            second argument.
    
            * g++.dg/cpp2a/constexpr-new14.C: New test.
    
    (cherry picked from commit 2805fcb32660bc0cdcd5ba54310f1f02651e039f)
Comment 5 Jakub Jelinek 2020-10-13 08:18:40 UTC
Fixed.