]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++,coroutines: Handle await expressions in assume attributes.
authorIain Sandoe <iain@sandoe.co.uk>
Mon, 9 Jun 2025 10:26:01 +0000 (11:26 +0100)
committerIain Sandoe <iain@sandoe.co.uk>
Tue, 17 Jun 2025 15:07:09 +0000 (18:07 +0300)
Here we have an expression that is not evaluated but is still seen
as potentially-evaluated.  We handle this by determining if the
operand has side-effects, producing a warning that the assume has
been ignored and eliding it.

gcc/cp/ChangeLog:

* coroutines.cc (analyze_expression_awaits): Elide assume
attributes containing await expressions, since these have
side effects.  Emit a diagnostic that this has been done.

gcc/testsuite/ChangeLog:

* g++.dg/coroutines/assume.C: New test.

gcc/cp/coroutines.cc
gcc/testsuite/g++.dg/coroutines/assume.C [new file with mode: 0644]

index 276c6c40c78555e0306b1fee01b5ab9e70a6b9d4..f97bd9deae33d5fa8ef4a5dfa60e93814e12462d 100644 (file)
@@ -3479,6 +3479,19 @@ analyze_expression_awaits (tree *stmt, int *do_subtree, void *d)
                }
              *do_subtree = 0;
            }
+         else if (!fn && CALL_EXPR_IFN (*stmt) == IFN_ASSUME)
+           {
+             tree expr = CALL_EXPR_ARG (*stmt, 0);
+             if (TREE_SIDE_EFFECTS (expr))
+               {
+                 location_t loc_e = cp_expr_location (expr);
+                 location_t loc_s = cp_expr_location (*stmt);
+                 location_t loc_n = make_location (loc_e, loc_s, loc_s);
+                 warning_at (loc_n, OPT_Wattributes,"assumption ignored"
+                             " because it contains an await-expression");
+                 *stmt = build_empty_stmt (loc_n);
+               }
+           }
        }
        break;
       case CO_YIELD_EXPR:
diff --git a/gcc/testsuite/g++.dg/coroutines/assume.C b/gcc/testsuite/g++.dg/coroutines/assume.C
new file mode 100644 (file)
index 0000000..d007386
--- /dev/null
@@ -0,0 +1,40 @@
+// { dg-additional-options "-fsyntax-only -Wattributes" }
+
+#include <coroutine>
+
+struct awaitable {
+    awaitable (int n) : delay{n} {}
+
+    constexpr bool await_ready () const noexcept { return false; }
+    auto await_suspend (std::coroutine_handle<> h) const {
+        __builtin_abort ();
+        return false;
+    }
+    int await_resume() const noexcept {
+        return delay;
+    }
+
+    int delay;
+};
+
+struct Task {
+    struct promise_type {
+        promise_type() = default;
+        Task get_return_object() { return {}; }
+        std::suspend_never initial_suspend() { return {}; }
+        std::suspend_always final_suspend() noexcept { return {}; }
+        void unhandled_exception() {}
+        void return_void () {}
+        awaitable yield_value (int v) { return {v}; }
+    };
+};
+
+int h () { return 5; }
+
+Task foo() noexcept {
+    int x = 5;
+    [[assume (x == 5)]];
+    [[assume (co_await awaitable{10})]]; // { dg-warning {assumption ignored because it contains an await-expression} }
+    [[assume ((h(),co_await awaitable{11}))]]; // { dg-warning {assumption ignored because it contains an await-expression} }
+    co_return;
+}