From 0ecb6b906f215ec56df1a555139abe9ad95414fb Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Fri, 3 Jun 2022 14:58:22 -0400 Subject: [PATCH] c++: value-dep but not type-dep decltype expr [PR105756] Here during ahead of time instantiation of the value-dependent but not type-dependent decltype expression (5 % N) == 0, cp_build_binary_op folds the operands of the == via cp_fully_fold, which performs speculative constexpr evaluation, and from which we crash for (5 % N) due to the value-dependence. Since the operand folding performed by cp_build_binary_op appears to be solely for sake of diagnosing overflow, and since these diagnostics are suppressed when in an unevaluated context, this patch avoids this crash by suppressing cp_build_binary_op's operand folding accordingly. PR c++/105756 gcc/cp/ChangeLog: * typeck.cc (cp_build_binary_op): Don't fold operands when c_inhibit_evaluation_warnings. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/decltype82.C: New test. --- gcc/cp/typeck.cc | 38 ++++++++++++++++++--------------- gcc/testsuite/g++.dg/cpp0x/decltype82.C | 10 +++++++++ 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype82.C diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 190d710..f9ce14f 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -4939,7 +4939,7 @@ cp_build_binary_op (const op_location_t &location, convert it to this type. */ tree final_type = 0; - tree result, result_ovl; + tree result; /* Nonzero if this is an operation like MIN or MAX which can safely be computed in short if both args are promoted shorts. @@ -6263,25 +6263,29 @@ cp_build_binary_op (const op_location_t &location, result = build2 (COMPOUND_EXPR, TREE_TYPE (result), instrument_expr, result); - if (!processing_template_decl) + if (resultcode == SPACESHIP_EXPR && !processing_template_decl) + result = get_target_expr_sfinae (result, complain); + + if (!c_inhibit_evaluation_warnings) { - if (resultcode == SPACESHIP_EXPR) - result = get_target_expr_sfinae (result, complain); - op0 = cp_fully_fold (op0); - /* Only consider the second argument if the first isn't overflowed. */ - if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0)) - return result; - op1 = cp_fully_fold (op1); - if (!CONSTANT_CLASS_P (op1) || TREE_OVERFLOW_P (op1)) + if (!processing_template_decl) + { + op0 = cp_fully_fold (op0); + /* Only consider the second argument if the first isn't overflowed. */ + if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0)) + return result; + op1 = cp_fully_fold (op1); + if (!CONSTANT_CLASS_P (op1) || TREE_OVERFLOW_P (op1)) + return result; + } + else if (!CONSTANT_CLASS_P (op0) || !CONSTANT_CLASS_P (op1) + || TREE_OVERFLOW_P (op0) || TREE_OVERFLOW_P (op1)) return result; - } - else if (!CONSTANT_CLASS_P (op0) || !CONSTANT_CLASS_P (op1) - || TREE_OVERFLOW_P (op0) || TREE_OVERFLOW_P (op1)) - return result; - result_ovl = fold_build2 (resultcode, build_type, op0, op1); - if (TREE_OVERFLOW_P (result_ovl)) - overflow_warning (location, result_ovl); + tree result_ovl = fold_build2 (resultcode, build_type, op0, op1); + if (TREE_OVERFLOW_P (result_ovl)) + overflow_warning (location, result_ovl); + } return result; } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype82.C b/gcc/testsuite/g++.dg/cpp0x/decltype82.C new file mode 100644 index 0000000..915e5e3 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype82.C @@ -0,0 +1,10 @@ +// PR c++/105756 +// { dg-do compile { target c++11 } } + +template +void f() { + using ty1 = decltype((5 % N) == 0); + using ty2 = decltype((5 / N) == 0); +} + +template void f<0>(); -- 2.7.4