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.