public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Jason Merrill <jason@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc r13-3488] c++: improve failed constexpr assume diagnostic
Date: Tue, 25 Oct 2022 16:38:38 +0000 (GMT)	[thread overview]
Message-ID: <20221025163838.BC81C3856DCA@sourceware.org> (raw)

https://gcc.gnu.org/g:ac8f92c18886057261d61d45b8d339629464c77e

commit r13-3488-gac8f92c18886057261d61d45b8d339629464c77e
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Oct 24 17:17:24 2022 -0400

    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.

Diff:
---
 gcc/cp/cp-tree.h                          |  5 ++-
 gcc/cp/constexpr.cc                       | 63 ++++++++++++++++++++++++-------
 gcc/cp/semantics.cc                       | 27 -------------
 gcc/testsuite/g++.dg/cpp23/attr-assume2.C |  4 +-
 4 files changed, 55 insertions(+), 44 deletions(-)

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 2cca20be6c1..cec376d90af 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/constexpr.cc b/gcc/cp/constexpr.cc
index 94b54fc71dc..fc1bc53f68a 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/semantics.cc b/gcc/cp/semantics.cc
index 82f9dd8dd4e..36aa9c4499f 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -11183,33 +11183,6 @@ init_cp_semantics (void)
 }
 \f
 
-/* 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 9e54c14974f..4dd12216d06 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;
 }

                 reply	other threads:[~2022-10-25 16:38 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221025163838.BC81C3856DCA@sourceware.org \
    --to=jason@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).