]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++, contracts: Fix ICE in create_tmp_var [PR113968]
authorNina Ranns <dinka.ranns@gmail.com>
Thu, 4 Jul 2024 16:08:58 +0000 (17:08 +0100)
committerJason Merrill <jason@redhat.com>
Wed, 10 Jul 2024 15:17:33 +0000 (11:17 -0400)
During contract parsing, in grok_contract(), we proceed even if the
condition contains errors. This results in contracts with embedded errors
which eventually confuse gimplify. Checks for errors have been added in
grok_contract() to exit early if an error is encountered.

PR c++/113968

gcc/cp/ChangeLog:

* contracts.cc (grok_contract): Check for error_mark_node early
exit.

gcc/testsuite/ChangeLog:

* g++.dg/contracts/pr113968.C: New test.

Signed-off-by: Nina Ranns <dinka.ranns@gmail.com>
gcc/cp/contracts.cc
gcc/testsuite/g++.dg/contracts/pr113968.C [new file with mode: 0644]

index 634e3cf4fa9a9243721cf116dfc0bdcea45dd6f3..a7d0fdacf6ecb4c54288ab560e420a842c89d380 100644 (file)
@@ -750,6 +750,9 @@ tree
 grok_contract (tree attribute, tree mode, tree result, cp_expr condition,
               location_t loc)
 {
+  if (condition == error_mark_node)
+    return error_mark_node;
+
   tree_code code;
   if (is_attribute_p ("assert", attribute))
     code = ASSERTION_STMT;
@@ -785,6 +788,10 @@ grok_contract (tree attribute, tree mode, tree result, cp_expr condition,
 
   /* The condition is converted to bool.  */
   condition = finish_contract_condition (condition);
+
+  if (condition == error_mark_node)
+    return error_mark_node;
+
   CONTRACT_CONDITION (contract) = condition;
 
   return contract;
diff --git a/gcc/testsuite/g++.dg/contracts/pr113968.C b/gcc/testsuite/g++.dg/contracts/pr113968.C
new file mode 100644 (file)
index 0000000..fbaad1c
--- /dev/null
@@ -0,0 +1,29 @@
+// check that an invalid contract condition doesn't cause an ICE
+// { dg-do compile }
+// { dg-options "-std=c++2a -fcontracts " }
+
+struct A
+{
+  A (A&);
+};
+struct S
+{
+  void f(A a)
+    [[ pre : a]] // { dg-error "could not convert" }
+    [[ pre : a.b]]// { dg-error "has no member" }
+    {
+
+    }
+};
+void f(A a)
+  [[ pre : a]] // { dg-error "could not convert" }
+  [[ pre : a.b]]// { dg-error "has no member" }
+  {
+    [[ assert : a ]]; // { dg-error "could not convert" }
+    [[ assert : a.b ]];// { dg-error "has no member" }
+  }
+
+int
+main ()
+{
+}