Bug 118661 - [12 regression] Reading volatile qualified std::nullptr_t should be valid in a constant expression
Summary: [12 regression] Reading volatile qualified std::nullptr_t should be valid in ...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 15.0
: P2 normal
Target Milestone: 12.5
Assignee: Jakub Jelinek
URL:
Keywords: rejects-valid
Depends on:
Blocks: constexpr
  Show dependency treegraph
 
Reported: 2025-01-26 09:03 UTC by Halalaluyafail3
Modified: 2026-02-27 06:00 UTC (History)
4 users (show)

See Also:
Host:
Target:
Build:
Known to work: 7.5.0
Known to fail: 8.1.0, 9.1.0
Last reconfirmed: 2025-01-26 00:00:00


Attachments
gcc15-pr118661.patch (987 bytes, patch)
2025-02-06 09:14 UTC, Jakub Jelinek
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Halalaluyafail3 2025-01-26 09:03:25 UTC
The following code is not accepted by GCC:

#include<cstddef>
constexpr volatile std::nullptr_t n{};
constexpr std::nullptr_t m=n;
int main(){}

Clang and MSVC accept this code. It should be valid since there is a specific exemption for volatile std::nullptr_t in [expr.const], quoting section 7.7 paragraph 10 from N5001:
> An expression E is a core constant expression unless the evaluation of E,
> following the rules of the abstract machine (6.9.1), would evaluate one of the
> following:
> 
> ...
> 
> - an lvalue-to-rvalue conversion (7.3.2) unless it is applied to
>   - a glvalue of type cv std::nullptr_t,
>   - a non-volatile glvalue that refers to an object that is usable in constant
>     expressions, or
>   - a non-volatile glvalue of literal type that refers to a non-volatile
>     object whose lifetime began within the evaluation of E;
Comment 1 Sam James 2025-01-26 09:06:25 UTC
Regression, even.
Comment 2 Drea Pinski 2025-01-26 09:29:29 UTC
Related
https://cplusplus.github.io/CWG/issues/2140.html
Comment 3 Drea Pinski 2025-01-26 18:33:14 UTC
Confirmed. Note I think there is 2 different changes which caused this.

That is a change in 8 caused use to reject:
```
typedef decltype(nullptr) tt;
constexpr volatile tt n{};
constexpr tt m=n;
```

But it was not until GCC 9 we (correctly) rejected:
```
constexpr volatile int n1{};
constexpr short m1=n1;
```
Comment 4 Marek Polacek 2025-01-27 16:46:58 UTC
(In reply to Andrew Pinski from comment #3)
> Confirmed. Note I think there is 2 different changes which caused this.
> 
> That is a change in 8 caused use to reject:
> ```
> typedef decltype(nullptr) tt;
> constexpr volatile tt n{};
> constexpr tt m=n;
> ```

Since my r9-4793:

commit 3c393a2c012f7f5f1c3df7d6d7b17a9cf992af17
Author: Marek Polacek <polacek@redhat.com>
Date:   Tue Dec 11 18:53:03 2018 +0000

    PR c++/86608 - reading constexpr volatile variable.


> But it was not until GCC 9 we (correctly) rejected:
> ```
> constexpr volatile int n1{};
> constexpr short m1=n1;
> ```

Same change.
Comment 5 Jakub Jelinek 2025-02-06 09:14:37 UTC
Created attachment 60392 [details]
gcc15-pr118661.patch

Untested fix.
Comment 6 GCC Commits 2025-02-07 13:30:58 UTC
The master branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:6c8e6d6febaed3c167ca9534935c2cb18045528e

commit r15-7413-g6c8e6d6febaed3c167ca9534935c2cb18045528e
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Feb 7 14:27:18 2025 +0100

    c++: Allow constexpr reads from volatile std::nullptr_t objects [PR118661]
    
    As mentioned in the PR, https://eel.is/c++draft/conv.lval#note-1
    says that even volatile reads from std::nullptr_t typed objects actually
    don't read anything and https://eel.is/c++draft/expr.const#10.9
    says that even those are ok in constant expressions.
    
    So, the following patch adjusts the r9-4793 changes to have an exception
    for NULLPTR_TYPE.
    As [conv.lval]/3 also talks about accessing to inactive member, I've added
    testcase to cover that as well.
    
    2025-02-07  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/118661
            * constexpr.cc (potential_constant_expression_1): Don't diagnose
            lvalue-to-rvalue conversion of volatile lvalue if it has NULLPTR_TYPE.
            * decl2.cc (decl_maybe_constant_var_p): Return true for constexpr
            decls with NULLPTR_TYPE even if they are volatile.
    
            * g++.dg/cpp0x/constexpr-volatile4.C: New test.
            * g++.dg/cpp0x/constexpr-union9.C: New test.
Comment 7 Jakub Jelinek 2025-02-07 13:33:45 UTC
Fixed on the trunk so far.
Comment 8 GCC Commits 2025-02-10 18:19:58 UTC
The releases/gcc-14 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:6f5ada57162c10d5ff4b04de275aadf9c81a3da5

commit r14-11295-g6f5ada57162c10d5ff4b04de275aadf9c81a3da5
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Feb 7 14:27:18 2025 +0100

    c++: Allow constexpr reads from volatile std::nullptr_t objects [PR118661]
    
    As mentioned in the PR, https://eel.is/c++draft/conv.lval#note-1
    says that even volatile reads from std::nullptr_t typed objects actually
    don't read anything and https://eel.is/c++draft/expr.const#10.9
    says that even those are ok in constant expressions.
    
    So, the following patch adjusts the r9-4793 changes to have an exception
    for NULLPTR_TYPE.
    As [conv.lval]/3 also talks about accessing to inactive member, I've added
    testcase to cover that as well.
    
    2025-02-07  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/118661
            * constexpr.cc (potential_constant_expression_1): Don't diagnose
            lvalue-to-rvalue conversion of volatile lvalue if it has NULLPTR_TYPE.
            * decl2.cc (decl_maybe_constant_var_p): Return true for constexpr
            decls with NULLPTR_TYPE even if they are volatile.
    
            * g++.dg/cpp0x/constexpr-volatile4.C: New test.
            * g++.dg/cpp0x/constexpr-union9.C: New test.
    
    (cherry picked from commit 6c8e6d6febaed3c167ca9534935c2cb18045528e)
Comment 9 Jakub Jelinek 2025-02-13 09:55:52 UTC
Fixed for 14.3 too.
Comment 10 GCC Commits 2025-04-23 13:09:58 UTC
The releases/gcc-13 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:eb3e7de323a67e5a92f1c2224f3251cb47b49c0b

commit r13-9588-geb3e7de323a67e5a92f1c2224f3251cb47b49c0b
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Feb 7 14:27:18 2025 +0100

    c++: Allow constexpr reads from volatile std::nullptr_t objects [PR118661]
    
    As mentioned in the PR, https://eel.is/c++draft/conv.lval#note-1
    says that even volatile reads from std::nullptr_t typed objects actually
    don't read anything and https://eel.is/c++draft/expr.const#10.9
    says that even those are ok in constant expressions.
    
    So, the following patch adjusts the r9-4793 changes to have an exception
    for NULLPTR_TYPE.
    As [conv.lval]/3 also talks about accessing to inactive member, I've added
    testcase to cover that as well.
    
    2025-02-07  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/118661
            * constexpr.cc (potential_constant_expression_1): Don't diagnose
            lvalue-to-rvalue conversion of volatile lvalue if it has NULLPTR_TYPE.
            * decl2.cc (decl_maybe_constant_var_p): Return true for constexpr
            decls with NULLPTR_TYPE even if they are volatile.
    
            * g++.dg/cpp0x/constexpr-volatile4.C: New test.
            * g++.dg/cpp0x/constexpr-union9.C: New test.
    
    (cherry picked from commit 6c8e6d6febaed3c167ca9534935c2cb18045528e)
Comment 11 Jakub Jelinek 2025-04-24 08:43:10 UTC
Fixed also for 13.4.
Comment 12 GCC Commits 2025-06-13 15:41:54 UTC
The releases/gcc-12 branch has been updated by Jakub Jelinek <jakub@gcc.gnu.org>:

https://gcc.gnu.org/g:c95cd1c5effaec023360c902b38376dc461d41e4

commit r12-11166-gc95cd1c5effaec023360c902b38376dc461d41e4
Author: Jakub Jelinek <jakub@redhat.com>
Date:   Fri Feb 7 14:27:18 2025 +0100

    c++: Allow constexpr reads from volatile std::nullptr_t objects [PR118661]
    
    As mentioned in the PR, https://eel.is/c++draft/conv.lval#note-1
    says that even volatile reads from std::nullptr_t typed objects actually
    don't read anything and https://eel.is/c++draft/expr.const#10.9
    says that even those are ok in constant expressions.
    
    So, the following patch adjusts the r9-4793 changes to have an exception
    for NULLPTR_TYPE.
    As [conv.lval]/3 also talks about accessing to inactive member, I've added
    testcase to cover that as well.
    
    2025-02-07  Jakub Jelinek  <jakub@redhat.com>
    
            PR c++/118661
            * constexpr.cc (potential_constant_expression_1): Don't diagnose
            lvalue-to-rvalue conversion of volatile lvalue if it has NULLPTR_TYPE.
            * decl2.cc (decl_maybe_constant_var_p): Return true for constexpr
            decls with NULLPTR_TYPE even if they are volatile.
    
            * g++.dg/cpp0x/constexpr-volatile4.C: New test.
            * g++.dg/cpp0x/constexpr-union9.C: New test.
    
    (cherry picked from commit 6c8e6d6febaed3c167ca9534935c2cb18045528e)
Comment 13 Jakub Jelinek 2025-06-13 18:47:15 UTC
Fixed also for 12.5.
Comment 14 Drea Pinski 2026-02-27 06:00:54 UTC
(In reply to Halalaluyafail3 from comment #0)
> > - an lvalue-to-rvalue conversion (7.3.2) unless it is applied to
> >   - a glvalue of type cv std::nullptr_t,

https://cplusplus.github.io/CWG/issues/2907.html added the above part.