https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80078

            Bug ID: 80078
           Summary: Incorrect classification of address of volatile as not
                    constant
           Product: gcc
           Version: 6.3.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: headch at gmail dot com
  Target Milestone: ---

Consider the following code:

volatile int ary[1];
static_assert(&ary[0], "");
static_assert(ary + 0, "");

The first static_assert fails, claiming that the condition is non-constant
because the expression ary[0] has side effects. The second static assert
passes. Removing the volatile qualifier also results in the code passing.

>From reading the spec, I *believe* (but could be wrong) that the &ary[0] should
meet the criteria for being a constant expression. As far as I can tell, the
evaluation of &arr[0] proceeds as follows (references are to N4296, as that is
AFAICT very close to C++14 and I don’t have the actual standard):

1. 5.2.1 says the subscripting operator takes a pointer or array, that ary[0]
is identical by definition to *(ary+0), and that because ary is an lvalue, then
so should be ary[0].

2. 5.7 says that the addition operator can take two arithmetic or unscoped enum
types, or one pointer and one arithmetic or unscoped enum type. It doesn’t say
that the addition operator can take an array. Array-to-pointer conversion
therefore happens on ary, which 4.2 says yields a prvalue of type
pointer-to-volatile-int. Then the addition operator proceeds, taking the
prvalue pointer and the prvalue integer literal and returning a (I believe)
prvalue pointer-to-volatile-int.

3. 5.3.1 paragraph 1 says that operator* returns an lvalue, in this case of
type volatile int.

4. 5.3.1 paragraph 3 says that the operand to & can be an lvalue and the result
is a prvalue, in this case of type pointer-to-volatile-int.

As far as I can tell, none of the above violates 5.20’s rules on what
constitutes a core constant expression.

https://gcc.godbolt.org/ says that GCC5 accepts the code, GCC6 and GCC7 both
reject the first static_assert but accept the second, the Microsoft compiler
rejects both, Clang 3.0 rejects both but 3.1 and above accept both, and icc
13.0.1 rejects both but 16 and 17 accept both.

Reply via email to