[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 --- Comment #13 from Jonathan Wakely --- Although this is accepted even though it's in a template, so it's more complicated than just template vs non-template: template consteval void f( char const* p ) { char buf[N]{}; if (p == buf) // unspecified return; for (int i = 0; i < 5; ++i) buf[i] = p[i]; } int main() { f("test"); }
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 --- Comment #12 from Jonathan Wakely --- If the comparison happens in a template, GCC rejects it (see PR 113200).
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 Jonathan Wakely changed: What|Removed |Added Last reconfirmed|2020-10-15 00:00:00 |2024-1-3 --- Comment #11 from Jonathan Wakely --- And another: struct S { char data_[ 5 ]; constexpr S( char const* p ) : data_() { if (p == data_) return; for (int i = 0; i < 5; ++i) data_[i] = p[i]; } }; constexpr S s( "test" );
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 Paul Keir changed: What|Removed |Added CC||pkeir at outlook dot com --- Comment #10 from Paul Keir --- Here is another example which GCC accepts, but Clang correctly rejects: constexpr bool test() { int arr[2]{}; void *p1 = [0]; void *p2 = [1]; return p1 < p2; } constexpr bool b = test();
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 --- Comment #9 from Marek Polacek --- *** Bug 85474 has been marked as a duplicate of this bug. ***
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 --- Comment #8 from Jonathan Wakely --- In gcc/cp/typeck.c:cp_build_binary_op this warning should be an error during constant evaluation for EQ_EXPR and NE_EXPR: if (complain & tf_warning) { tree stripped_orig_op0 = tree_strip_any_location_wrapper (orig_op0); tree stripped_orig_op1 = tree_strip_any_location_wrapper (orig_op1); if ((TREE_CODE (stripped_orig_op0) == STRING_CST && !integer_zerop (cp_fully_fold (op1))) || (TREE_CODE (stripped_orig_op1) == STRING_CST && !integer_zerop (cp_fully_fold (op0 warning_at (location, OPT_Waddress, "comparison with string literal results in " "unspecified behavior"); } And this one for rel ops and spaceships: if (TREE_CODE (orig_op0) == STRING_CST || TREE_CODE (orig_op1) == STRING_CST) { if (complain & tf_warning) warning_at (location, OPT_Waddress, "comparison with string literal results " "in unspecified behavior"); } That only handles the string literals cases though, we also need to reject pointers to distinct objects at the same places.
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 Jonathan Wakely changed: What|Removed |Added Last reconfirmed||2020-10-15 Severity|minor |normal Ever confirmed|0 |1 Status|UNCONFIRMED |NEW --- Comment #7 from Jonathan Wakely --- Another example with a relational operator: constexpr const char* s = ""; constexpr const char* n = nullptr; constexpr bool b = s > n; The result of the comparison is unspecified because the pointers are not equal and don't point to subobjects of the same object. Clang, EDG and MSVC all reject it as expected.
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 Martin Sebor changed: What|Removed |Added See Also||https://gcc.gnu.org/bugzill ||a/show_bug.cgi?id=85437 --- Comment #6 from Martin Sebor --- I raised bug 85437 for the regression.
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org, ||jason at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- That started with r249088.
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 --- Comment #4 from Martin Sebor --- Rejecting the test case because of the initialization is a regression. The cast is not a reinterpret cast. GCC gives the same error with a static cast too: $ gcc -S -Wall pr70248.C pr70248.C:4:24: error: a reinterpret_cast is not a constant expression constexpr int A::*bx = static_cast(::x); ^ pr70248.C:5:24: error: a reinterpret_cast is not a constant expression constexpr int A::*cx = static_cast (::x); ^
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 --- Comment #3 from Jonathan Wakely --- GCC trunk (8.0.1 20180410) now rejects comment 0 with: c0.cc:4:24: error: a reinterpret_cast is not a constant expression constexpr int A::*bx = (int(A::*))::x; ^ c0.cc:5:24: error: a reinterpret_cast is not a constant expression constexpr int A::*cx = (int(A::*))::x; ^
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 Martin Sebor changed: What|Removed |Added Known to fail|6.0 |6.1.0 --- Comment #2 from Martin Sebor --- Below is another example, one that even elicits a warning where GCC points out the unspecified behavior: $ cat xx.cpp && gcc -S -Wall -Wextra -Wpedantic -o/dev/null xx.cpp constexpr int b = "" == ""; xx.cpp:1:25: warning: comparison with string literal results in unspecified behavior [-Waddress] constexpr int b = "" == ""; ^~
[Bug c++/70248] constexpr initialization with unspecified equality expression accepted
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70248 --- Comment #1 from Martin Sebor --- Below is a test case (derived from a test discussed in the context of another bug: https://gcc.gnu.org/ml/gcc-patches/2016-03/msg01644.html) for another example of a constexpr function whose use in a constexpr context is invalid due to its return value relying on unspecified effects, this time the result of the relational expression involving null pointers. The test case shows two problems: first, that the invalid initialization of the constexpr variables a0 and b1 is accepted, and second, an error on the use of SFINAE to select one of the two overloads of the function template f (see also bug 70380 for a similar SFINAE example that's not handled correctly, though for a different reason). The main point of the example is to demonstrate the first problem, but fixing it should take into consideration the SFINAE case. $ cat v.c && /build/gcc-trunk-bootstrap/gcc/xgcc -B /build/gcc-trunk-bootstrap/gcc -S -Wall -Wextra -Wpedantic -xc++ v.c constexpr int *p = 0; constexpr int *q = 0; struct A { constexpr A (bool b) : m (b ? 1 : p < q) { } constexpr int foo () const { return m; } int m; }; struct B { constexpr B (bool b) : m (b ? p < q : 1) { } constexpr int bar () const { return m; } int m; }; constexpr int a0 = A (false).foo (); // invalid, accepted constexpr int a1 = A (true).foo ();// valid, accepted constexpr int b0 = B (false).bar (); // valid, accepted constexpr int b1 = B (true).bar ();// invalid, accepted template int f (int (*)[A (X).foo ()] = 0) { return !X; } template int f (int (*)[B (X).bar ()] = 0) { return X; } constexpr int f0 = f<0>();// valid, rejected constexpr int f1 = f<1>();// valid, rejected v.c:27:24: error: call to non-constexpr function ‘int f(int (*)[(B)(X).B::bar()]) [with bool X = false]’ constexpr int f0 = f<0>();// valid, rejected ^~ v.c:28:24: error: call to non-constexpr function ‘int f(int (*)[(A)(X).A::foo()]) [with bool X = true]’ constexpr int f1 = f<1>();// valid, rejected ^~