On 6/3/22 14:13, Patrick Palka wrote:
On Thu, 2 Jun 2022, Patrick Palka wrote:
On Thu, 2 Jun 2022, Jason Merrill wrote:
On 6/1/22 14:20, Patrick Palka wrote:
r12-7564-gec0f53a3a542e7 made us instantiate non-constant non-dependent
decltype operands by relaxing instantiate_non_dependent_expr to check
instantiation_dependent_uneval_expression_p. But as the testcase below
demonstrates, this predicate is too permissive here because it allows
value-dependent-only expressions to go through and get instantiated
ahead of time, which causes us to crash during constexpr evaluation of
(5 % N).
Why are we doing constexpr evaluation in unevaluated context?
Looks like because cp_build_binary_op attempts to fold the resulting
operator expression via cp_fully_fold (which performs speculate
constexpr evaluation):
6261 if (!processing_template_decl)
6262 {
6263 if (resultcode == SPACESHIP_EXPR)
6264 result = get_target_expr (result, complain);
6265 op0 = cp_fully_fold (op0);
6266 /* Only consider the second argument if the first isn't overflowed.
*/
6267 if (!CONSTANT_CLASS_P (op0) || TREE_OVERFLOW_P (op0))
6268 return result;
6269 op1 = cp_fully_fold (op1);
6270 if (!CONSTANT_CLASS_P (op1) || TREE_OVERFLOW_P (op1))
6271 return result;
6272 }
But in an unevaluated context I suppose we don't need or want to do this
folding. I'll work on a patch to that effect.
Here it is:
-- >8 --
Subject: [PATCH] c++: value-dep but not type-dep decltype operand [PR105756]
Here we're crashing when instantiating ahead of time the value-dependent
but not type-dependent decltype operand (5 % N) == 0, ultimately
because cp_build_binary_op folds its operands for sake of its overflow
diagnostics, and as part of this folding it performs speculative
constexpr evaluation for the operand (5 % N) during which we crash since
it's value-dependent.
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 fixes this
crash by suppressing cp_build_binary_op's operand folding accordingly.
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12? The diff was generated with -w to suppress noisy whitespace
changes.
OK.
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 | 8 ++++++--
gcc/testsuite/g++.dg/cpp0x/decltype82.C | 10 ++++++++++
2 files changed, 16 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype82.C
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index 190d710cd27..7c910d57b7e 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -6263,10 +6263,13 @@ cp_build_binary_op (const op_location_t &location,
result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
instrument_expr, result);
+ if (resultcode == SPACESHIP_EXPR && !processing_template_decl)
+ result = get_target_expr_sfinae (result, complain);
+
+ if (!c_inhibit_evaluation_warnings)
+ {
if (!processing_template_decl)
{
- 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))
@@ -6282,6 +6285,7 @@ cp_build_binary_op (const op_location_t &location,
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 00000000000..915e5e37675
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype82.C
@@ -0,0 +1,10 @@
+// PR c++/105756
+// { dg-do compile { target c++11 } }
+
+template<int N>
+void f() {
+ using ty1 = decltype((5 % N) == 0);
+ using ty2 = decltype((5 / N) == 0);
+}
+
+template void f<0>();