From patchwork Mon Jan 20 05:18:08 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: JunMa X-Patchwork-Id: 1225628 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-517708-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=linux.alibaba.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha1 header.s=default header.b=X7A+00hs; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 481Kh16RKsz9sPJ for ; Mon, 20 Jan 2020 16:18:23 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=cX/zur5GMbWO52dy2792rkmPc4H9J7bxZtTj5EhCfFphdUtqhb ivVfhU65pcGN2aTpI/BYgrf0M2qMo5M0TArxV4aoY4YOEQ7pr8ORvRdwIv4MXm4G XHttMgZa31YJBl92z5jpqAXhf8157i0nRN2bESX3L6S/2Go4EJGVqIYB4= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:to:cc :from:subject:message-id:date:mime-version:content-type; s= default; bh=n03LzFjlMH9uZUdbmXHWwSekUdQ=; b=X7A+00hswws4xOH26/3+ QB7NG7bVoXlH06gIB2TVC+FVrv3aEcgQ5qsh2ePr05DXrRoiYw4cR+4WEaQKX73f CG9OAeyNOiD6se7E8OP497BadBG5CXmBJtjmIqc3ajVdsHkZzw/3GuGU7APWOv9q ot4ojA8jVcH0Kid087+eyUw= Received: (qmail 97431 invoked by alias); 20 Jan 2020 05:18:15 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 97423 invoked by uid 89); 20 Jan 2020 05:18:15 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.7 required=5.0 tests=AWL, BAYES_00, ENV_AND_HDR_SPF_MATCH, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS, UNPARSEABLE_RELAY, USER_IN_DEF_SPF_WL autolearn=ham version=3.3.1 spammy=junma X-HELO: out30-57.freemail.mail.aliyun.com Received: from out30-57.freemail.mail.aliyun.com (HELO out30-57.freemail.mail.aliyun.com) (115.124.30.57) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 20 Jan 2020 05:18:13 +0000 X-Alimail-AntiSpam: AC=PASS; BC=-1|-1; BR=01201311R101e4; CH=green; DM=||false|; DS=||; FP=0|-1|-1|-1|0|-1|-1|-1; HT=e01f04397; MF=junma@linux.alibaba.com; NM=1; PH=DS; RN=2; SR=0; TI=SMTPD_---0To9H4sy_1579497489; Received: from MacBook-Pro-6.local(mailfrom:JunMa@linux.alibaba.com fp:SMTPD_---0To9H4sy_1579497489) by smtp.aliyun-inc.com(127.0.0.1); Mon, 20 Jan 2020 13:18:09 +0800 To: gcc-patches Cc: Iain Sandoe From: JunMa Subject: [PATCH Coroutines] Add error messages for missing methods of awaitable class Message-ID: <661fe9cf-23eb-5d33-4fce-8edfab8a3d2a@linux.alibaba.com> Date: Mon, 20 Jan 2020 13:18:08 +0800 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:60.0) Gecko/20100101 Thunderbird/60.9.1 MIME-Version: 1.0 X-IsSubscribed: yes Hi This patch adds lookup_awaitable_member, it outputs error messages when any of the await_ready/suspend/resume functions are missing in awaitable class. This patch also add some error check on return value of build_co_await since we may failed to build co_await_expr. Bootstrap and test on X86_64, is it OK? Regards JunMa gcc/cp 2020-01-20  Jun Ma         * coroutines.cc (lookup_awaitable_member): Lookup an awaitable member.         (build_co_await): Use lookup_awaitable_member instead of lookup_member.         (finish_co_yield_expr, finish_co_await_expr): Add error check on return         value of build_co_await. gcc/testsuite 2020-01-20  Jun Ma         * g++.dg/coroutines/coro1-missing-await-method.C: New test. From 3979b29dcdb1000bbc819f69c1dc3ce7616f87cd Mon Sep 17 00:00:00 2001 From: "liangbin.mj" Date: Thu, 21 Nov 2019 08:51:22 +0800 Subject: [PATCH] to #23584419 Add some error messages when can not find method of awaitable class. --- gcc/cp/coroutines.cc | 49 ++++++++++++------- .../coroutines/coro1-missing-await-method.C | 21 ++++++++ .../coroutines/coro1-ret-int-yield-int.h | 9 ++++ 3 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C diff --git a/gcc/cp/coroutines.cc b/gcc/cp/coroutines.cc index d3aacd7ad3b..49e509f4384 100644 --- a/gcc/cp/coroutines.cc +++ b/gcc/cp/coroutines.cc @@ -505,6 +505,23 @@ lookup_promise_method (tree fndecl, tree member_id, location_t loc, return pm_memb; } +/* Lookup an Awaitable member, which should be await_ready, await_suspend + or await_resume */ + +static tree +lookup_awaitable_member (tree await_type, tree member_id, location_t loc) +{ + tree aw_memb + = lookup_member (await_type, member_id, + /*protect*/ 1, /*want_type*/ 0, tf_warning_or_error); + if (aw_memb == NULL_TREE || aw_memb == error_mark_node) + { + error_at (loc, "no member named %qE in %qT", member_id, await_type); + return error_mark_node; + } + return aw_memb; +} + /* Here we check the constraints that are common to all keywords (since the presence of a coroutine keyword makes the function into a coroutine). */ @@ -643,25 +660,18 @@ build_co_await (location_t loc, tree a, suspend_point_kind suspend_kind) /* Check for required awaitable members and their types. */ tree awrd_meth - = lookup_member (o_type, coro_await_ready_identifier, - /* protect */ 1, /*want_type=*/0, tf_warning_or_error); - + = lookup_awaitable_member (o_type, coro_await_ready_identifier, loc); if (!awrd_meth || awrd_meth == error_mark_node) return error_mark_node; - tree awsp_meth - = lookup_member (o_type, coro_await_suspend_identifier, - /* protect */ 1, /*want_type=*/0, tf_warning_or_error); - + = lookup_awaitable_member (o_type, coro_await_suspend_identifier, loc); if (!awsp_meth || awsp_meth == error_mark_node) return error_mark_node; /* The type of the co_await is the return type of the awaitable's - co_resume(), so we need to look that up. */ + await_resume(), so we need to look that up. */ tree awrs_meth - = lookup_member (o_type, coro_await_resume_identifier, - /* protect */ 1, /*want_type=*/0, tf_warning_or_error); - + = lookup_awaitable_member (o_type, coro_await_resume_identifier, loc); if (!awrs_meth || awrs_meth == error_mark_node) return error_mark_node; @@ -800,9 +810,11 @@ finish_co_await_expr (location_t kw, tree expr) /* Now we want to build co_await a. */ tree op = build_co_await (kw, a, CO_AWAIT_SUSPEND_POINT); - TREE_SIDE_EFFECTS (op) = 1; - SET_EXPR_LOCATION (op, kw); - + if (op != error_mark_node) + { + TREE_SIDE_EFFECTS (op) = 1; + SET_EXPR_LOCATION (op, kw); + } return op; } @@ -864,10 +876,11 @@ finish_co_yield_expr (location_t kw, tree expr) promise transform_await(). */ tree op = build_co_await (kw, yield_call, CO_YIELD_SUSPEND_POINT); - - op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op); - TREE_SIDE_EFFECTS (op) = 1; - + if (op != error_mark_node) + { + op = build2_loc (kw, CO_YIELD_EXPR, TREE_TYPE (op), expr, op); + TREE_SIDE_EFFECTS (op) = 1; + } return op; } diff --git a/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C b/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C new file mode 100644 index 00000000000..c1869e0654c --- /dev/null +++ b/gcc/testsuite/g++.dg/coroutines/coro1-missing-await-method.C @@ -0,0 +1,21 @@ +// { dg-additional-options "-fsyntax-only -w" } +#include "coro.h" + +#define MISSING_AWAIT_READY +#define MISSING_AWAIT_SUSPEND +#define MISSING_AWAIT_RESUME +#include "coro1-ret-int-yield-int.h" + +coro1 +bar0 () // { dg-error {no member named 'await_suspend' in 'coro1::suspend_always_prt'} } +{ + co_await coro1::suspend_never_prt{}; // { dg-error {no member named 'await_ready' in 'coro1::suspend_never_prt'} } + co_yield 5; // { dg-error {no member named 'await_suspend' in 'coro1::suspend_always_prt'} } + co_await coro1::suspend_always_intprt(5); // { dg-error {no member named 'await_resume' in 'coro1::suspend_always_intprt'} } + co_return 0; +} + +int main (int ac, char *av[]) { + struct coro1 x0 = bar0 (); + return 0; +} diff --git a/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h b/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h index b961755e472..abf625869fa 100644 --- a/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h +++ b/gcc/testsuite/g++.dg/coroutines/coro1-ret-int-yield-int.h @@ -27,14 +27,20 @@ struct coro1 { // Some awaitables to use in tests. // With progress printing for debug. struct suspend_never_prt { +#ifdef MISSING_AWAIT_READY +#else bool await_ready() const noexcept { return true; } +#endif void await_suspend(handle_type) const noexcept { PRINT ("susp-never-susp");} void await_resume() const noexcept { PRINT ("susp-never-resume");} }; struct suspend_always_prt { bool await_ready() const noexcept { return false; } +#ifdef MISSING_AWAIT_SUSPEND +#else void await_suspend(handle_type) const noexcept { PRINT ("susp-always-susp");} +#endif void await_resume() const noexcept { PRINT ("susp-always-resume");} ~suspend_always_prt() { PRINT ("susp-always-dtor"); } }; @@ -46,7 +52,10 @@ struct coro1 { ~suspend_always_intprt() {} bool await_ready() const noexcept { return false; } void await_suspend(coro::coroutine_handle<>) const noexcept { PRINT ("susp-always-susp-intprt");} +#ifdef MISSING_AWAIT_RESUME +#else int await_resume() const noexcept { PRINT ("susp-always-resume-intprt"); return x;} +#endif }; /* This returns the square of the int that it was constructed with. */