[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 --- Comment #11 from Aaron Ballman --- (In reply to Jakub Jelinek from comment #10) > (In reply to Aaron Ballman from comment #9) > > Doesn't [expr.eq] make it unspecified though? > > Will defer that answer to Jason. > But please have a look at the comment 6 testcase. I strongly hope that > constexpr const char *p = "abc"; > constexpr const char *q = p; > static_assert (p == q, ""); > doesn't actually mean the string literal is evaluated multiple times, because > if it would be, then one pretty much can't use string literals for anything > reliably. Oh yeah, I agree with you in that case. I was talking about the summary example with function calls returning a string literal. Sorry for not being more clear! > I bet the wording in there is for the > constexpr const char *r = "abc"; > constexpr const char *s = "abc"; > case, where the standard doesn't force implementations to unify same string > literals within the same TU but allows it (and also allows say tail merging > of them). From what I can see in the LLVM constant expression evaluation > behavior, it doesn't track what comes from which evaluation of a string > literal (GCC doesn't track that either) and just assumes that it could be > different evaluation, while GCC assumes it is not. Yeah, that sounds plausible.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 --- Comment #10 from Jakub Jelinek --- (In reply to Aaron Ballman from comment #9) > Doesn't [expr.eq] make it unspecified though? Will defer that answer to Jason. But please have a look at the comment 6 testcase. I strongly hope that constexpr const char *p = "abc"; constexpr const char *q = p; static_assert (p == q, ""); doesn't actually mean the string literal is evaluated multiple times, because if it would be, then one pretty much can't use string literals for anything reliably. I bet the wording in there is for the constexpr const char *r = "abc"; constexpr const char *s = "abc"; case, where the standard doesn't force implementations to unify same string literals within the same TU but allows it (and also allows say tail merging of them). From what I can see in the LLVM constant expression evaluation behavior, it doesn't track what comes from which evaluation of a string literal (GCC doesn't track that either) and just assumes that it could be different evaluation, while GCC assumes it is not.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 Aaron Ballman changed: What|Removed |Added CC||aaron at aaronballman dot com --- Comment #9 from Aaron Ballman --- (In reply to Jason Merrill from comment #8) > (In reply to Nicolas Lesser from comment #1) > > For clarity, b1 shouldn't compile. > > > > [lex.string]p16 says: "whether successive evaluations of a string-literal > > yield the same or a different object is unspecified." > > > > [expr.const]p2 says: "An expression e is a core constant expression unless > > the evaluation of e, [...], would evaluate one of the following expressions: > > [...]; a relational or equality operator where the result is unspecified;" > > I think the second quote refers to places in [expr.eq] that say "the result > is unspecified", not to all instances of unspecified behavior in the > standard. Doesn't [expr.eq] make it unspecified though? [expr.eq]p6 says: "If two operands compare equal, the result is true for the == operator and false for the != operator. If two operands compare unequal, the result is false for the == operator and true for the != operator. Otherwise, the result of each of the operators is unspecified." If it is unspecified whether a subsequent string literal evaluation produces the same object or a different object then it's unspecified whether the two operands will or won't compare equal, so the result of the operators is also unspecified.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 Jason Merrill changed: What|Removed |Added CC||jason at gcc dot gnu.org --- Comment #8 from Jason Merrill --- (In reply to Nicolas Lesser from comment #1) > For clarity, b1 shouldn't compile. > > [lex.string]p16 says: "whether successive evaluations of a string-literal > yield the same or a different object is unspecified." > > [expr.const]p2 says: "An expression e is a core constant expression unless > the evaluation of e, [...], would evaluate one of the following expressions: > [...]; a relational or equality operator where the result is unspecified;" I think the second quote refers to places in [expr.eq] that say "the result is unspecified", not to all instances of unspecified behavior in the standard.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 --- Comment #7 from Richard Biener --- constexpr evaluation shouldn't blindly call fold* if it doesn't expect things to end up constant that are not or non-constant that are. fold* is _not_ a constexpr evaluator in the C++ semantic sense. So no, match.pd isn't at fault and we shouldn't change it. Fix the constexpr code instead.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 --- Comment #6 from Jakub Jelinek --- Another possibility would be to detect it in cxx_eval_binary_expression before calling fold_binary_loc and punt. But, the constant evaluation actually doesn't track whether it is the same or different evaluation of the same string literal, so not optimizing it would on the other side mean we'd reject valid code. Consider constexpr auto name3(const char *p) { return p; } int main() { constexpr auto p1 = "test3"; constexpr auto p2 = "test4"; constexpr auto b1 = (name3(p1) == name3(p1)); // should be true constexpr auto b2 = (name3(p1) == name3(p2)); // should be false } Note, latest clang++ seems to accept b1 in both #c0 and #c6 testcases and reject b2 in both.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org, ||rguenth at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- So, either those match.pd rules should be marked #ifdef GIMPLE only, or perhaps we should have some flag whether C++ constexpr evaluation is in progress and allow some foldings if GENERIC only if C++ constexpr evaluation is not in progress?
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 Jonathan Wakely changed: What|Removed |Added Ever confirmed|0 |1 Keywords||accepts-invalid Last reconfirmed||2021-08-05 Status|UNCONFIRMED |NEW Known to work|10.1.0 | --- Comment #4 from Jonathan Wakely --- Confirming as accepts-invalid based on comment 1. GCC started to accept both comparisons with r270845: re PR tree-optimization/87314 (pointless comparison of malloc result to a string not eliminated) 2019-05-03 Richard Biener PR middle-end/87314 * match.pd (cmp (convert1?@2 addr@0) (convert2? addr@1)): Handle STRING_CST vs DECL or STRING_CST. * gcc.dg/pr87314-1.c: New testcase.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 --- Comment #3 from Andrew Pinski --- GCC accepts both with GCC 10+.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 --- Comment #2 from Jonathan Wakely --- Clang trunk also rejects it for the same reason, icc accepts it.
[Bug c++/86369] constexpr const char* comparison fails
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86369 Nicolas Lesser changed: What|Removed |Added CC||blitzrakete at gmail dot com --- Comment #1 from Nicolas Lesser --- For clarity, b1 shouldn't compile. [lex.string]p16 says: "whether successive evaluations of a string-literal yield the same or a different object is unspecified." [expr.const]p2 says: "An expression e is a core constant expression unless the evaluation of e, [...], would evaluate one of the following expressions: [...]; a relational or equality operator where the result is unspecified;"