* [PATCH] c++: value-dep but not type-dep decltype operand [PR105756]
@ 2022-06-01 18:20 Patrick Palka
2022-06-02 20:03 ` Jason Merrill
0 siblings, 1 reply; 5+ messages in thread
From: Patrick Palka @ 2022-06-01 18:20 UTC (permalink / raw)
To: gcc-patches
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).
This patch strengthens instantiate_non_dependent_expr to use the
non-uneval version of the predicate instead, which does consider value
dependence. In turn, we need to make finish_decltype_type avoid calling
i_n_d_e on a value-dependent-only expression; I assume we still want to
resolve the decltype ahead of time in this case. (Doing so seems
unintuitive to me since the expression could be ill-formed at
instantiation time as in the testcase, but it matches the behavior of
Clang and MSVC.)
Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12?
PR c++/105756
gcc/cp/ChangeLog:
* pt.cc (instantiate_non_dependent_expr_internal): Adjust
comment.
(instantiate_non_dependent_expr_sfinae): Assert i_d_e_p instead
of i_d_u_e_p.
* semantics.cc (finish_decltype_type): Don't instantiate the
expression when i_d_e_p is true.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/decltype82.C: New test.
---
gcc/cp/pt.cc | 4 ++--
gcc/cp/semantics.cc | 13 ++++++++++++-
gcc/testsuite/g++.dg/cpp0x/decltype82.C | 10 ++++++++++
3 files changed, 24 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype82.C
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index e4a473002a0..1ea2545e115 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -6372,7 +6372,7 @@ redeclare_class_template (tree type, tree parms, tree cons)
/* The actual substitution part of instantiate_non_dependent_expr_sfinae,
to be used when the caller has already checked
- !instantiation_dependent_uneval_expression_p (expr)
+ !instantiation_dependent_expression_p (expr)
and cleared processing_template_decl. */
tree
@@ -6397,7 +6397,7 @@ instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
if (processing_template_decl)
{
/* The caller should have checked this already. */
- gcc_checking_assert (!instantiation_dependent_uneval_expression_p (expr));
+ gcc_checking_assert (!instantiation_dependent_expression_p (expr));
processing_template_decl_sentinel s;
expr = instantiate_non_dependent_expr_internal (expr, complain);
}
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 3600d270ff8..b23848ab94c 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11302,9 +11302,20 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
return type;
}
+ else if (processing_template_decl
+ && potential_constant_expression (expr)
+ && value_dependent_expression_p (expr))
+ /* The above test is equivalent to instantiation_dependent_expression_p
+ after instantiation_dependent_uneval_expression_p has been ruled out.
+ In this case the expression is dependent but not type-dependent, so
+ we can resolve the decltype ahead of time but we can't instantiate
+ the expression. */;
else if (processing_template_decl)
{
- expr = instantiate_non_dependent_expr_sfinae (expr, complain|tf_decltype);
+ /* The expression isn't instantiation dependent, so we can fully
+ instantiate it ahead of time. */
+ expr = instantiate_non_dependent_expr_sfinae (expr,
+ complain|tf_decltype);
if (expr == error_mark_node)
return error_mark_node;
/* Keep processing_template_decl cleared for the rest of the function
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>();
--
2.36.1.203.g1bcf4f6271
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] c++: value-dep but not type-dep decltype operand [PR105756]
2022-06-01 18:20 [PATCH] c++: value-dep but not type-dep decltype operand [PR105756] Patrick Palka
@ 2022-06-02 20:03 ` Jason Merrill
2022-06-02 20:29 ` Patrick Palka
0 siblings, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2022-06-02 20:03 UTC (permalink / raw)
To: Patrick Palka, gcc-patches
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?
> This patch strengthens instantiate_non_dependent_expr to use the
> non-uneval version of the predicate instead, which does consider value
> dependence. In turn, we need to make finish_decltype_type avoid calling
> i_n_d_e on a value-dependent-only expression; I assume we still want to
> resolve the decltype ahead of time in this case. (Doing so seems
> unintuitive to me since the expression could be ill-formed at
> instantiation time as in the testcase, but it matches the behavior of
> Clang and MSVC.)
I don't think there's any problem with the testcase; decltype(1/0) is
well-formed because the expression is not evaluated.
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk/12?
>
> PR c++/105756
>
> gcc/cp/ChangeLog:
>
> * pt.cc (instantiate_non_dependent_expr_internal): Adjust
> comment.
> (instantiate_non_dependent_expr_sfinae): Assert i_d_e_p instead
> of i_d_u_e_p.
> * semantics.cc (finish_decltype_type): Don't instantiate the
> expression when i_d_e_p is true.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp0x/decltype82.C: New test.
> ---
> gcc/cp/pt.cc | 4 ++--
> gcc/cp/semantics.cc | 13 ++++++++++++-
> gcc/testsuite/g++.dg/cpp0x/decltype82.C | 10 ++++++++++
> 3 files changed, 24 insertions(+), 3 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype82.C
>
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index e4a473002a0..1ea2545e115 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -6372,7 +6372,7 @@ redeclare_class_template (tree type, tree parms, tree cons)
>
> /* The actual substitution part of instantiate_non_dependent_expr_sfinae,
> to be used when the caller has already checked
> - !instantiation_dependent_uneval_expression_p (expr)
> + !instantiation_dependent_expression_p (expr)
> and cleared processing_template_decl. */
>
> tree
> @@ -6397,7 +6397,7 @@ instantiate_non_dependent_expr_sfinae (tree expr, tsubst_flags_t complain)
> if (processing_template_decl)
> {
> /* The caller should have checked this already. */
> - gcc_checking_assert (!instantiation_dependent_uneval_expression_p (expr));
> + gcc_checking_assert (!instantiation_dependent_expression_p (expr));
> processing_template_decl_sentinel s;
> expr = instantiate_non_dependent_expr_internal (expr, complain);
> }
> diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> index 3600d270ff8..b23848ab94c 100644
> --- a/gcc/cp/semantics.cc
> +++ b/gcc/cp/semantics.cc
> @@ -11302,9 +11302,20 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p,
>
> return type;
> }
> + else if (processing_template_decl
> + && potential_constant_expression (expr)
> + && value_dependent_expression_p (expr))
> + /* The above test is equivalent to instantiation_dependent_expression_p
> + after instantiation_dependent_uneval_expression_p has been ruled out.
> + In this case the expression is dependent but not type-dependent, so
> + we can resolve the decltype ahead of time but we can't instantiate
> + the expression. */;
> else if (processing_template_decl)
> {
> - expr = instantiate_non_dependent_expr_sfinae (expr, complain|tf_decltype);
> + /* The expression isn't instantiation dependent, so we can fully
> + instantiate it ahead of time. */
> + expr = instantiate_non_dependent_expr_sfinae (expr,
> + complain|tf_decltype);
> if (expr == error_mark_node)
> return error_mark_node;
> /* Keep processing_template_decl cleared for the rest of the function
> 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>();
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] c++: value-dep but not type-dep decltype operand [PR105756]
2022-06-02 20:03 ` Jason Merrill
@ 2022-06-02 20:29 ` Patrick Palka
2022-06-03 18:13 ` Patrick Palka
0 siblings, 1 reply; 5+ messages in thread
From: Patrick Palka @ 2022-06-02 20:29 UTC (permalink / raw)
To: Jason Merrill; +Cc: Patrick Palka, gcc-patches
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.
>
> > This patch strengthens instantiate_non_dependent_expr to use the
> > non-uneval version of the predicate instead, which does consider value
> > dependence. In turn, we need to make finish_decltype_type avoid calling
> > i_n_d_e on a value-dependent-only expression; I assume we still want to
> > resolve the decltype ahead of time in this case. (Doing so seems
> > unintuitive to me since the expression could be ill-formed at
> > instantiation time as in the testcase, but it matches the behavior of
> > Clang and MSVC.)
>
> I don't think there's any problem with the testcase; decltype(1/0) is
> well-formed because the expression is not evaluated.
D'oh, that makes sense, not sure what I was on about :)
>
> > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> > trunk/12?
> >
> > PR c++/105756
> >
> > gcc/cp/ChangeLog:
> >
> > * pt.cc (instantiate_non_dependent_expr_internal): Adjust
> > comment.
> > (instantiate_non_dependent_expr_sfinae): Assert i_d_e_p instead
> > of i_d_u_e_p.
> > * semantics.cc (finish_decltype_type): Don't instantiate the
> > expression when i_d_e_p is true.
> >
> > gcc/testsuite/ChangeLog:
> >
> > * g++.dg/cpp0x/decltype82.C: New test.
> > ---
> > gcc/cp/pt.cc | 4 ++--
> > gcc/cp/semantics.cc | 13 ++++++++++++-
> > gcc/testsuite/g++.dg/cpp0x/decltype82.C | 10 ++++++++++
> > 3 files changed, 24 insertions(+), 3 deletions(-)
> > create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype82.C
> >
> > diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> > index e4a473002a0..1ea2545e115 100644
> > --- a/gcc/cp/pt.cc
> > +++ b/gcc/cp/pt.cc
> > @@ -6372,7 +6372,7 @@ redeclare_class_template (tree type, tree parms, tree
> > cons)
> > /* The actual substitution part of
> > instantiate_non_dependent_expr_sfinae,
> > to be used when the caller has already checked
> > - !instantiation_dependent_uneval_expression_p (expr)
> > + !instantiation_dependent_expression_p (expr)
> > and cleared processing_template_decl. */
> > tree
> > @@ -6397,7 +6397,7 @@ instantiate_non_dependent_expr_sfinae (tree expr,
> > tsubst_flags_t complain)
> > if (processing_template_decl)
> > {
> > /* The caller should have checked this already. */
> > - gcc_checking_assert (!instantiation_dependent_uneval_expression_p
> > (expr));
> > + gcc_checking_assert (!instantiation_dependent_expression_p (expr));
> > processing_template_decl_sentinel s;
> > expr = instantiate_non_dependent_expr_internal (expr, complain);
> > }
> > diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
> > index 3600d270ff8..b23848ab94c 100644
> > --- a/gcc/cp/semantics.cc
> > +++ b/gcc/cp/semantics.cc
> > @@ -11302,9 +11302,20 @@ finish_decltype_type (tree expr, bool
> > id_expression_or_member_access_p,
> > return type;
> > }
> > + else if (processing_template_decl
> > + && potential_constant_expression (expr)
> > + && value_dependent_expression_p (expr))
> > + /* The above test is equivalent to instantiation_dependent_expression_p
> > + after instantiation_dependent_uneval_expression_p has been ruled
> > out.
> > + In this case the expression is dependent but not type-dependent, so
> > + we can resolve the decltype ahead of time but we can't instantiate
> > + the expression. */;
> > else if (processing_template_decl)
> > {
> > - expr = instantiate_non_dependent_expr_sfinae (expr,
> > complain|tf_decltype);
> > + /* The expression isn't instantiation dependent, so we can fully
> > + instantiate it ahead of time. */
> > + expr = instantiate_non_dependent_expr_sfinae (expr,
> > + complain|tf_decltype);
> > if (expr == error_mark_node)
> > return error_mark_node;
> > /* Keep processing_template_decl cleared for the rest of the
> > function
> > 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>();
>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] c++: value-dep but not type-dep decltype operand [PR105756]
2022-06-02 20:29 ` Patrick Palka
@ 2022-06-03 18:13 ` Patrick Palka
2022-06-03 18:18 ` Jason Merrill
0 siblings, 1 reply; 5+ messages in thread
From: Patrick Palka @ 2022-06-03 18:13 UTC (permalink / raw)
To: Patrick Palka; +Cc: Jason Merrill, gcc-patches
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.
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>();
--
2.36.1.210.g2668e3608e
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] c++: value-dep but not type-dep decltype operand [PR105756]
2022-06-03 18:13 ` Patrick Palka
@ 2022-06-03 18:18 ` Jason Merrill
0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2022-06-03 18:18 UTC (permalink / raw)
To: Patrick Palka; +Cc: gcc-patches
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>();
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2022-06-03 18:18 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-01 18:20 [PATCH] c++: value-dep but not type-dep decltype operand [PR105756] Patrick Palka
2022-06-02 20:03 ` Jason Merrill
2022-06-02 20:29 ` Patrick Palka
2022-06-03 18:13 ` Patrick Palka
2022-06-03 18:18 ` Jason Merrill
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).