aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2022-10-24 17:17:24 -0400
committerJason Merrill <jason@redhat.com>2022-10-25 12:38:25 -0400
commitac8f92c18886057261d61d45b8d339629464c77e (patch)
tree0e7beb4f9c726f91550e35f0bf96d2015bf8be79 /gcc
parent4ba3902e8f1ee3ca35e3194053ebdc1e174808ea (diff)
downloadgcc-ac8f92c18886057261d61d45b8d339629464c77e.zip
gcc-ac8f92c18886057261d61d45b8d339629464c77e.tar.gz
gcc-ac8f92c18886057261d61d45b8d339629464c77e.tar.bz2
c++: improve failed constexpr assume diagnostic
I noticed that we were printing "the comparison reduces to (x == 42)" when we should be able to give the value of x. Fixed by doing the same evaluation in diagnose_failing_condition that we already do in find_failing_clause. gcc/cp/ChangeLog: * constexpr.cc (fold_operand): New function. (find_failing_clause_r): Add const. (find_failing_clause): Add const. (diagnose_failing_condition): Add ctx parameter. (cxx_eval_internal_function): Pass it. * semantics.cc (diagnose_failing_condition): Move to constexpr.cc. * cp-tree.h: Adjust. gcc/testsuite/ChangeLog: * g++.dg/cpp23/attr-assume2.C: Expect constant values.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constexpr.cc63
-rw-r--r--gcc/cp/cp-tree.h5
-rw-r--r--gcc/cp/semantics.cc27
-rw-r--r--gcc/testsuite/g++.dg/cpp23/attr-assume2.C4
4 files changed, 55 insertions, 44 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 94b54fc..fc1bc53 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1799,6 +1799,24 @@ cx_error_context (void)
return r;
}
+/* E is an operand of a failed assertion, fold it either with or without
+ constexpr context. */
+
+static tree
+fold_operand (tree e, const constexpr_ctx *ctx)
+{
+ if (ctx)
+ {
+ bool new_non_constant_p = false, new_overflow_p = false;
+ e = cxx_eval_constant_expression (ctx, e, vc_prvalue,
+ &new_non_constant_p,
+ &new_overflow_p);
+ }
+ else
+ e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true);
+ return e;
+}
+
/* If we have a condition in conjunctive normal form (CNF), find the first
failing clause. In other words, given an expression like
@@ -1807,7 +1825,7 @@ cx_error_context (void)
return the first 'false'. EXPR is the expression. */
static tree
-find_failing_clause_r (constexpr_ctx *ctx, tree expr)
+find_failing_clause_r (const constexpr_ctx *ctx, tree expr)
{
if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR)
{
@@ -1818,16 +1836,7 @@ find_failing_clause_r (constexpr_ctx *ctx, tree expr)
e = find_failing_clause_r (ctx, TREE_OPERAND (expr, 1));
return e;
}
- tree e = contextual_conv_bool (expr, tf_none);
- if (ctx)
- {
- bool new_non_constant_p = false, new_overflow_p = false;
- e = cxx_eval_constant_expression (ctx, e, vc_prvalue,
- &new_non_constant_p,
- &new_overflow_p);
- }
- else
- e = fold_non_dependent_expr (e, tf_none, /*manifestly_const_eval=*/true);
+ tree e = fold_operand (expr, ctx);
if (integer_zerop (e))
/* This is the failing clause. */
return expr;
@@ -1837,7 +1846,7 @@ find_failing_clause_r (constexpr_ctx *ctx, tree expr)
/* Wrapper for find_failing_clause_r. */
tree
-find_failing_clause (constexpr_ctx *ctx, tree expr)
+find_failing_clause (const constexpr_ctx *ctx, tree expr)
{
if (TREE_CODE (expr) == TRUTH_ANDIF_EXPR)
if (tree e = find_failing_clause_r (ctx, expr))
@@ -1845,6 +1854,34 @@ find_failing_clause (constexpr_ctx *ctx, tree expr)
return expr;
}
+/* Emit additional diagnostics for failing condition BAD.
+ Used by finish_static_assert and IFN_ASSUME constexpr diagnostics.
+ If SHOW_EXPR_P is true, print the condition (because it was
+ instantiation-dependent). */
+
+void
+diagnose_failing_condition (tree bad, location_t cloc, bool show_expr_p,
+ const constexpr_ctx *ctx /* = nullptr */)
+{
+ /* Nobody wants to see the artificial (bool) cast. */
+ bad = tree_strip_nop_conversions (bad);
+
+ /* Actually explain the failure if this is a concept check or a
+ requires-expression. */
+ if (concept_check_p (bad) || TREE_CODE (bad) == REQUIRES_EXPR)
+ diagnose_constraints (cloc, bad, NULL_TREE);
+ else if (COMPARISON_CLASS_P (bad)
+ && ARITHMETIC_TYPE_P (TREE_TYPE (TREE_OPERAND (bad, 0))))
+ {
+ tree op0 = fold_operand (TREE_OPERAND (bad, 0), ctx);
+ tree op1 = fold_operand (TREE_OPERAND (bad, 1), ctx);
+ tree cond = build2 (TREE_CODE (bad), boolean_type_node, op0, op1);
+ inform (cloc, "the comparison reduces to %qE", cond);
+ }
+ else if (show_expr_p)
+ inform (cloc, "%qE evaluates to false", bad);
+}
+
/* Evaluate a call T to a GCC internal function when possible and return
the evaluated result or, under the control of CTX, give an error, set
NON_CONSTANT_P, and return the unevaluated call T otherwise. */
@@ -1897,7 +1934,7 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
/* Report the error. */
error_at (cloc,
"failed %<assume%> attribute assumption");
- diagnose_failing_condition (bad, cloc, false);
+ diagnose_failing_condition (bad, cloc, false, &new_ctx);
}
*non_constant_p = true;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2cca20b..cec376d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7758,7 +7758,6 @@ extern tree build_transaction_expr (location_t, tree, int, tree);
extern bool cxx_omp_create_clause_info (tree, tree, bool, bool,
bool, bool);
extern tree baselink_for_fns (tree);
-extern void diagnose_failing_condition (tree, location_t, bool);
extern void finish_static_assert (tree, tree, location_t,
bool, bool);
extern tree finish_decltype_type (tree, bool, tsubst_flags_t);
@@ -8497,7 +8496,9 @@ extern void clear_cv_and_fold_caches (void);
extern tree unshare_constructor (tree CXX_MEM_STAT_INFO);
extern bool decl_implicit_constexpr_p (tree);
struct constexpr_ctx;
-extern tree find_failing_clause (constexpr_ctx *ctx, tree);
+extern tree find_failing_clause (const constexpr_ctx *ctx, tree);
+extern void diagnose_failing_condition (tree, location_t, bool,
+ const constexpr_ctx * = nullptr);
extern bool replace_decl (tree *, tree, tree);
/* An RAII sentinel used to restrict constexpr evaluation so that it
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 82f9dd8..36aa9c4 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11183,33 +11183,6 @@ init_cp_semantics (void)
}
-/* Emit additional diagnostics for failing condition BAD.
- Used by finish_static_assert and IFN_ASSUME constexpr diagnostics.
- If SHOW_EXPR_P is true, print the condition (because it was
- instantiation-dependent). */
-
-void
-diagnose_failing_condition (tree bad, location_t cloc, bool show_expr_p)
-{
- /* Nobody wants to see the artificial (bool) cast. */
- bad = tree_strip_nop_conversions (bad);
-
- /* Actually explain the failure if this is a concept check or a
- requires-expression. */
- if (concept_check_p (bad) || TREE_CODE (bad) == REQUIRES_EXPR)
- diagnose_constraints (cloc, bad, NULL_TREE);
- else if (COMPARISON_CLASS_P (bad)
- && ARITHMETIC_TYPE_P (TREE_TYPE (TREE_OPERAND (bad, 0))))
- {
- tree op0 = fold_non_dependent_expr (TREE_OPERAND (bad, 0));
- tree op1 = fold_non_dependent_expr (TREE_OPERAND (bad, 1));
- tree cond = build2 (TREE_CODE (bad), boolean_type_node, op0, op1);
- inform (cloc, "the comparison reduces to %qE", cond);
- }
- else if (show_expr_p)
- inform (cloc, "%qE evaluates to false", bad);
-}
-
/* Build a STATIC_ASSERT for a static assertion with the condition
CONDITION and the message text MESSAGE. LOCATION is the location
of the static assertion in the source code. When MEMBER_P, this
diff --git a/gcc/testsuite/g++.dg/cpp23/attr-assume2.C b/gcc/testsuite/g++.dg/cpp23/attr-assume2.C
index 9e54c14..4dd1221 100644
--- a/gcc/testsuite/g++.dg/cpp23/attr-assume2.C
+++ b/gcc/testsuite/g++.dg/cpp23/attr-assume2.C
@@ -26,7 +26,7 @@ f2 (int x)
{
#if __cpp_constexpr >= 201304L
[[assume (x == 42)]]; // { dg-error "failed 'assume' attribute assumption" "" { target c++14 } }
-#endif // { dg-message "the comparison reduces to '\\\(x == 42\\\)'" "" { target c++14 } .-1 }
+#endif // { dg-message "the comparison reduces to '\\\(44 == 42\\\)'" "" { target c++14 } .-1 }
return x;
}
@@ -76,7 +76,7 @@ f7 (int x, int y, int z, int w)
{
#if __cpp_constexpr >= 201304L
[[assume (x == 42 && y == 43 && z == 44 && w == 45)]]; // { dg-error "failed 'assume' attribute assumption" "" { target c++14 } }
-#endif // { dg-message "the comparison reduces to '\\\(z == 44\\\)'" "" { target c++14 } .-1 }
+#endif // { dg-message "the comparison reduces to '\\\(45 == 44\\\)'" "" { target c++14 } .-1 }
return x;
}