AIL: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 80) FAIL: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 84) spawn -ignore SIGHUP /home/dave/gnu/gcc/objdir/gcc/testsuite/g++/../../xg++ -B/h ome/dave/gnu/gcc/objdir/gcc/testsuite/g++/../../ /home/dave/gnu/gcc/gcc/gcc/test suite/g++.dg/cpp23/consteval-if2.C -fdiagnostics-plain-output -nostdinc++ -I/hom e/dave/gnu/gcc/objdir/hppa-linux-gnu/libstdc++-v3/include/hppa-linux-gnu -I/home /dave/gnu/gcc/objdir/hppa-linux-gnu/libstdc++-v3/include -I/home/dave/gnu/gcc/gc c/libstdc++-v3/libsupc++ -I/home/dave/gnu/gcc/gcc/libstdc++-v3/include/backward -I/home/dave/gnu/gcc/gcc/libstdc++-v3/testsuite/util -fmessage-length=0 -std=gnu ++20 -S -o consteval-if2.s /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C: In function ' constexpr bool f()': /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:7:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exten sions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:7:22: error: e xpected ';' before '{' token /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:7:6: error: 'i f consteval' requires compound statement /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:10:10: warning : 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-ext ensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:10:27: error: expected ';' before '{' token /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:10:10: error: 'if consteval' requires compound statement /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:13:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exte nsions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:13:6: error: ' if consteval' requires compound statement /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:15:8: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exte nsions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:15:21: error: 'if consteval' requires compound statement /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:17:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exte nsions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:17:19: error: 'if consteval' requires compound statement /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:20:8: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exte nsions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:23:5: error: ' if consteval' requires compound statement /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C: In function ' constexpr int baz(int)': /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:34:10: warning : 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-ext ensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:36:16: error: 'x' is not a constant expression /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:42:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exte nsions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:48:16: error: 'x' is not a constant expression /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:50:8: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exte nsions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:52:16: error: 'x' is not a constant expression /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:54:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-exte nsions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C: In function 'constexpr int qux(int)': /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:66:10: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:68:16: error: 'x' is not a constant expression /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:74:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:82:8: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:86:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C: In function 'constexpr T corge(T)': /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:98:10: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:106:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:114:8: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:118:6: warning: 'if consteval' only available with '-std=c++2b' or '-std=gnu++2b' [-Wc++23-extensions] /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C: In instantiation of 'constexpr T corge(T) [with T = int]': /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:128:16: required from here /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:100:16: error: 'x' is not a constant expression /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:112:16: error: 'x' is not a constant expression /home/dave/gnu/gcc/gcc/gcc/testsuite/g++.dg/cpp23/consteval-if2.C:116:16: error: 'x' is not a constant expression compiler exited with status 1 PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 7) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 at line 8 (test for errors, line 7) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 at line 9 (test for warnings, line 7) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 10) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 at line 11 (test for errors, line 10) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 at line 12 (test for warnings, line 10) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 13) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 at line 14 (test for warnings, line 13) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 15) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 at line 16 (test for warnings, line 15) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 17) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 at line 18 (test for warnings, line 17) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 20) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 23) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 34) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 36) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 42) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 48) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 50) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 52) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 54) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 66) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 68) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 74) FAIL: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 80) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 82) FAIL: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 84) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 86) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 98) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 100) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 106) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 112) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 114) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 116) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for warnings, line 118) PASS: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for excess errors)
I see it on x86_64 too. Confirmed.
FAIL: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 80) FAIL: g++.dg/cpp23/consteval-if2.C -std=gnu++20 (test for errors, line 84) After r12-7264-gc19f317a78c0e4 these two errors only show up with -fchecking=2.
Reduced testcase for -std=c++23 consteval int foo (int x) { return x; } consteval int bar () { return 2; } template <typename T> constexpr int qux (int x) { int r = 0; if consteval { r += 2 * bar (); } else { r += foo (8 * x); // { dg-error "is not a constant expression" } } if ! consteval { r += foo (32 * x);// { dg-error "is not a constant expression" } } if consteval { r += 32 * bar (); } return r; } The intent of the testcase was to test whether we catch at least some of the non-dependent consteval calls already during template parsing and so regardless of whether we actually instantiate them or not. Worst case it will be diagnosed during instantiation, sure. But x is not type nor value dependent and neither is 8 * x nor 32 * x. And make_args_non_dependent calls build_non_dependent_arg which will not wrap say x or 8, but does wrap x * 8 even when both arguments have integral types. So, either build_non_dependent_arg should be made smarter and not wrap even simple arithmetics etc. where no C++ template-ish trees appear inside of it and everything is like in normal non-template-ish code, or we should reconsider the r12-7264 case because clearly often we can handle NON_DEPENDENT_EXPR just fine.
Another testcase to consider is: consteval int foo (int x) { return x; } consteval int bar () { return 2; } constexpr int baz (int x) { return x; } template <typename T> constexpr int qux (int x) { int r = 0; if consteval // { dg-warning "'if consteval' only available with" "" { target c++20_only } } { r += 2 * bar (); } else { r += foo (8 * baz (0)); } if ! consteval // { dg-warning "'if consteval' only available with" "" { target c++20_only } } { r += foo (32 * baz (0)); } if consteval // { dg-warning "'if consteval' only available with" "" { target c++20_only } } { r += 32 * bar (); } return r; } This one is valid, but before your r12-7264 was incorrectly rejected because 8 * baz (0) etc. is wrapped in NON_DEPENDENT_EXPR, potential_constant_expression_1 recursed on the NON_DEPENDENT_EXPR operand, found it is ok but cxx_eval_constant_expression rejected the NON_DEPENDENT_EXPR. Bet for the build_over_call processing_template_decl immediate_invocation_p code we need to punt silently if there is something we can't handle but fail loudly if we can handle everything but it is clearly always not a constant expression. potential_constant_expression_1 isn't 100% accurate, there are cases where it gets stuff through.
Some context: consider the simplified/extended C++20 testcase (the consteval-if seems to be a red herring): consteval int foo(int x) { return x; } template<class> void bar(int x) { constexpr int y = 0; foo(8 * x); // #1 foo(8 * y); // #2 } Before r12-7264, we would indeed correctly reject #1 ahead of time (which has a non-constant arg), but we would also incorrectly reject #2 (which has a constant arg), because both arguments are wrapped in NON_DEPENDENT_EXPR which cxx_eval_constant_expr considers to be always non-constant. So essentially we used to reject the two now-failing tests in consteval-if2.C only by accident. After r12-7264, is_constant_expr returns false for NON_DEPENDENT_EXPR (mirroring cxx_eval_constant_expr) which in particular means that fold_non_dependent_expr no longer tries to check a non-dependent consteval call ahead of time if it has a "complex" argument (i.e. one that is wrapped in NON_DEPENDENT_EXPR). Thus we no longer reject #1 ahead of time, and we also no longer incorrectly reject #2. IMHO this is overall an improvement, since not rejecting #1 ahead of time is a QoI issue, whereas rejecting #2 is a correctness issue. This also fixed PR103443 for a similar reason. (In reply to Jakub Jelinek from comment #3) > So, either build_non_dependent_arg should be made smarter and not wrap even > simple arithmetics etc. where no C++ template-ish trees appear inside of it > and everything is like in normal non-template-ish code, or we should > reconsider > the r12-7264 case because clearly often we can handle NON_DEPENDENT_EXPR > just fine. I wonder if we can get rid of NON_DEPENDENT_EXPR entirely? I'm not sure if it's at all necessary anymore. Or perhaps we could change tsubst / is_constant_expr / eval_constant_expr to actually look through NON_DEPENDENT_EXPR. These ideas seem out of scope for GCC 12 though :/
The reason that the two tests in constexpr-if2.C don't fail with -fchecking=2 after r12-7264 seems to be a latent bug. The error comes from the call to fold_non_dependent_expr in build_non_dependent_expr (which is guarded by flag_checking > 1), despite passing complain=tf_none. I think build_over_call needs to use cxx_constant_value_sfinae instead of cxx_constant_value when evaluating a consteval call... I have a patch for this.
(In reply to Jakub Jelinek from comment #4) > This one is valid, but before your r12-7264 was incorrectly rejected because > 8 * baz (0) etc. is wrapped in NON_DEPENDENT_EXPR, > potential_constant_expression_1 recursed on the NON_DEPENDENT_EXPR operand, > found it is ok but cxx_eval_constant_expression > rejected the NON_DEPENDENT_EXPR. Makes sense, similar to the #2 case in comment #5. > Bet for the build_over_call > processing_template_decl immediate_invocation_p code we need to punt > silently if there is something we can't handle but fail loudly if we can > handle everything but it is clearly always not a constant expression. > potential_constant_expression_1 isn't 100% accurate, there are cases where > it gets stuff through. IIUC as long as NON_DEPENDENT_EXPR doesn't appear inside a non-dependent consteval call then we'll currently correctly accept/reject it ahead of time, e.g.: consteval int foo(int x) { return x; } template<class> void bar(int x) { constexpr int y = 0; foo(x); // error: 'x' is not a constant expression foo(y); // OK foo(x * 1); // no (ahead of time) error due to NON_DEPENDENT_EXPR }
(In reply to Patrick Palka from comment #7) > IIUC as long as NON_DEPENDENT_EXPR doesn't appear inside a non-dependent > consteval call then we'll currently correctly accept/reject it ahead of > time, e.g.: Right. The problem we're hitting is that within a template we're trying to evaluate the immediate invocation inside build_over_call rather than when we return to e.g. finish_call_expr and build up the call to actually go into the template trees: if we fold_non_dependent_expr at that point instead, it should be fine. The only problem with that is that there are a bunch of places that need to be changed.
The master branch has been updated by Patrick Palka <ppalka@gcc.gnu.org>: https://gcc.gnu.org/g:647537adefb34041cc2d44585252fd765cc0daae commit r12-7802-g647537adefb34041cc2d44585252fd765cc0daae Author: Patrick Palka <ppalka@redhat.com> Date: Thu Mar 24 11:42:31 2022 -0400 c++: missing SFINAE for non-constant consteval calls [PR104620] Here we weren't respecting SFINAE when evaluating a call to a consteval function, which caused us to reject the new testcase below. This patch fixes this by making build_over_call use the SFINAE-friendly version of cxx_constant_value. This change causes us to no longer diagnose ahead of time a couple of non-constant non-dependent consteval calls in consteval-if2.C with -fchecking=2. These errors were apparently coming from the call to fold_non_dependent_expr in build_non_dependent_expr (for the RHS of the +=) despite complain=tf_none being passed. Now that build_over_call respects the value of complain during constant evaluation of a consteval call, the errors are gone. That the errors are also gone without -fchecking=2 is a regression caused by r12-7264-gc19f317a78c0e4 and is the subject of PR104620. As described in comment #5, I think it's basically an accident that we were diagnosing these two calls correctly before r12-7264, so perhaps we can live without these errors for GCC 12. Thus this patch just XFAILs the two tests. PR c++/104620 gcc/cp/ChangeLog: * call.cc (build_over_call): Use cxx_constant_value_sfinae instead of cxx_constant_value to evaluate a consteval call. * constexpr.cc (cxx_constant_value_sfinae): Add decl parameter and pass it to cxx_eval_outermost_constant_expr. * cp-tree.h (cxx_constant_value_sfinae): Add decl parameter. * pt.cc (fold_targs_r): Pass NULL_TREE as decl parameter to cxx_constant_value_sfinae. gcc/testsuite/ChangeLog: * g++.dg/cpp23/consteval-if2.C: XFAIL two dg-error tests where the argument to the non-constant non-dependent consteval call is wrapped by NON_DEPENDENT_EXPR. * g++.dg/cpp2a/consteval30.C: New test.
(In reply to Jason Merrill from comment #8) > (In reply to Patrick Palka from comment #7) > > IIUC as long as NON_DEPENDENT_EXPR doesn't appear inside a non-dependent > > consteval call then we'll currently correctly accept/reject it ahead of > > time, e.g.: > > Right. The problem we're hitting is that within a template we're trying to > evaluate the immediate invocation inside build_over_call rather than when we > return to e.g. finish_call_expr and build up the call to actually go into > the template trees: if we fold_non_dependent_expr at that point instead, it > should be fine. The only problem with that is that there are a bunch of > places that need to be changed. That'd work for finish_call_expr and build_new_method call since they're given the original arguments, but other callers e.g. build_new_op never see the original arguments, so we wouldn't be able to do fold_non_dependent_expr from there IIUC. For build_new_op in particular, we'd have to instead fold_non_dependent_expr from _its_ callers, the build_x_* class of functions, I think..
(In reply to Patrick Palka from comment #10) > That'd work for finish_call_expr and build_new_method call since they're > given the original arguments, but other callers e.g. build_new_op never see > the original arguments, so we wouldn't be able to do fold_non_dependent_expr > from there IIUC. For build_new_op in particular, we'd have to instead > fold_non_dependent_expr from _its_ callers, the build_x_* class of > functions, I think.. Agreed. Or possibly reorganize them to share the non-dep handling between them better.
GCC 12.1 is being released, retargeting bugs to GCC 12.2.
GCC 12.2 is being released, retargeting bugs to GCC 12.3.
GCC 12.3 is being released, retargeting bugs to GCC 12.4.
GCC 12.4 is being released, retargeting bugs to GCC 12.5.