[Bug c++/104803] if consteval error from branch that isn't evaluated anyway
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104803 Jakub Jelinek changed: What|Removed |Added Status|UNCONFIRMED |RESOLVED Resolution|--- |INVALID --- Comment #7 from Jakub Jelinek --- .
[Bug c++/104803] if consteval error from branch that isn't evaluated anyway
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104803 --- Comment #6 from Barry Revzin --- Ugh, sorry. You guys are right. gcc is correct to reject the example. Bad bug report.
[Bug c++/104803] if consteval error from branch that isn't evaluated anyway
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104803 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org, ||jason at gcc dot gnu.org, ||redi at gcc dot gnu.org --- Comment #5 from Jakub Jelinek --- Sure, the first branch of if consteval is immediate function context and therefore p(i) at line 5 is not an immediate invocation. But the p(i) at line 9 is not in an immediate function context and because it calls an immediate function (operator () of the lambda), it is an immediate invocation and because i at that point is not constant, it should be rejected. This is diagnosed during the instantiation of the function template, not during constant evaluation of the function template. And IMHO it should be diagnosed even if you don't cal none_of at all, just instantiate it (if it wouldn't be a template, even when just parsed). So yes, I agree clang is buggy because it diagnoses it even on line 5. Note, I'm not a C++ lawyer, but the consteval and if consteval implementation was done on the assumption it is like that.
[Bug c++/104803] if consteval error from branch that isn't evaluated anyway
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104803 --- Comment #4 from Barry Revzin --- For instance, clang accepts this version: consteval int p(int i) { return i > 2; } constexpr auto none_of(int const* f, int const* l) -> bool { for (; f != l; ++f) { int i = *f; if consteval { if (p(i)) { return false; } } else { return false; } } return true; } constexpr int vals[] = {1, 0, -1}; static_assert(none_of(vals, vals+3)); But not if you change none_of to be a template (in any way, e.g. taking f and l as auto).
[Bug c++/104803] if consteval error from branch that isn't evaluated anyway
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104803 --- Comment #3 from Barry Revzin --- clang is also wrong. p(i) doesn't have to be a constant expression there. The rule (http://eel.is/c++draft/expr.const#13) is "An immediate invocation shall be a constant expression." but an expression is only an immediate invocation if it's not in an immediate function context, and the first branch of if consteval is an immediate function context.
[Bug c++/104803] if consteval error from branch that isn't evaluated anyway
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104803 --- Comment #2 from Andrew Pinski --- clang does a better job of explaining though: :6:17: error: call to consteval function '(anonymous class)::operator()' is not a constant expression if (p(i)) { // <== line 5 ^ :19:15: note: in instantiation of function template specialization 'none_of:20:5)>' requested here static_assert(none_of(vals, ^ :6:19: note: read of non-const variable 'i' is not allowed in a constant expression if (p(i)) { // <== line 5 ^ :4:14: note: declared here for (int i : r) { ^ :10:17: error: call to consteval function '(anonymous class)::operator()' is not a constant expression if (p(i)) { // <== line 9 ^ :10:19: note: read of non-const variable 'i' is not allowed in a constant expression if (p(i)) { // <== line 9 ^ :4:14: note: declared here for (int i : r) { ^
[Bug c++/104803] if consteval error from branch that isn't evaluated anyway
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104803 --- Comment #1 from Andrew Pinski --- clang fails for the same reason.