From patchwork Mon Nov 15 11:18:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 47660 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id D5E4F3858036 for ; Mon, 15 Nov 2021 11:19:22 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id 2D95D3858D39 for ; Mon, 15 Nov 2021 11:18:38 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 2D95D3858D39 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com IronPort-SDR: cKQZHWIIpUmFDg533oHKEvNJU0d5rq2srHxSO+lNEu9Gf93dGNwC4NqVetqQkf3WWzkM0n++7T sKArt4zShAv1mP0Ks2fuyc6ZpsntznhAo32CwgKuDElCHhgNRonweC+4VoLZpwoDcxfCr8Yqml hosVWrTY39udd4LxQE2PIDYfXY0aePexLzSL7r0I2m2cZ7rrN0nYHizzTXBGxZfOyTsGE9C+Vm RYixz0zBO7ywxJnwLdCmOJobutqMuCcPc51I/rcVxy1QLVEkFbJyHaDVl9HSVgL7M84JCRKjj5 JLyOCOWvlFKVYWcDM36+3gsb X-IronPort-AV: E=Sophos;i="5.87,236,1631606400"; d="scan'208";a="68329811" Received: from orw-gwy-02-in.mentorg.com ([192.94.38.167]) by esa3.mentor.iphmx.com with ESMTP; 15 Nov 2021 03:18:38 -0800 IronPort-SDR: 5bl5jP/6RfMVFqefAEux8ty+SJrdD8dX1iYxA115K6s2IEqMwK2/2SWRUnk6DjhNktD/DCSs5M iLjs6qEbHL4zsAN6H4rgtzDoJCKY6TR2fA9C4LG0QJNdvH4BRjbPn2aDKZnKdW5/QEogHQ/Hoq XoHAE97IurlvuYcvmmgIv7YX2T3MqwOQc2YGzuf7BcA2EJ4ATcAWXuep7RuCBHhK6ChkZyE7G9 hvua89MVVc2bMZffvCzGJb2KRvOFAQu2k8i/eimwuz7Pkb1ysgXox40+aDcLU/3asfpOnwQ+gw YUQ= From: Julian Brown To: Subject: [PATCH 1/4] Add debug_omp_expr Date: Mon, 15 Nov 2021 03:18:23 -0800 Message-ID: <611b69f78a05e9a4498cfb0decce9482d3088840.1636974589.git.julian@codesourcery.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-10.mgc.mentorg.com (139.181.222.10) To SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" The C and C++ front-ends use a TREE_LIST as a 3-tuple representing an OpenMP array section, which tends to crash debug_generic_expr if one wants to print such an expression in the debugger. This little helper function works around that. We might want to adjust the representation of array sections to use the soon-to-be-introduced OMP_ARRAY_SECTION tree code throughout instead, at which point this patch will no longer be necessary. OK? Thanks, Julian 2021-11-15 Julian Brown gcc/ * tree-pretty-print.c (print_omp_expr, debug_omp_expr): New functions. * tree-pretty-print.h (debug_omp_expr): Add prototype. --- gcc/tree-pretty-print.c | 31 +++++++++++++++++++++++++++++++ gcc/tree-pretty-print.h | 1 + 2 files changed, 32 insertions(+) diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index 9d631817c59..b213bb9cec5 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -103,6 +103,37 @@ debug_generic_stmt (tree t) fprintf (stderr, "\n"); } +static void +print_omp_expr (tree t) +{ + if (TREE_CODE (t) == TREE_LIST) + { + tree low = TREE_PURPOSE (t); + tree len = TREE_VALUE (t); + tree base = TREE_CHAIN (t); + if (TREE_CODE (base) == TREE_LIST) + print_omp_expr (base); + else + print_generic_expr (stderr, base, TDF_VOPS|TDF_MEMSYMS); + fprintf (stderr, "["); + if (low) + print_generic_expr (stderr, low, TDF_VOPS|TDF_MEMSYMS); + fprintf (stderr, ":"); + if (len) + print_generic_expr (stderr, len, TDF_VOPS|TDF_MEMSYMS); + fprintf (stderr, "]"); + } + else + print_generic_expr (stderr, t, TDF_VOPS|TDF_MEMSYMS); +} + +DEBUG_FUNCTION void +debug_omp_expr (tree t) +{ + print_omp_expr (t); + fprintf (stderr, "\n"); +} + /* Debugging function to print out a chain of trees . */ DEBUG_FUNCTION void diff --git a/gcc/tree-pretty-print.h b/gcc/tree-pretty-print.h index dacd256302b..bc910f9a1b1 100644 --- a/gcc/tree-pretty-print.h +++ b/gcc/tree-pretty-print.h @@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see extern void debug_generic_expr (tree); extern void debug_generic_stmt (tree); +extern void debug_omp_expr (tree); extern void debug_tree_chain (tree); extern void print_generic_decl (FILE *, tree, dump_flags_t); extern void print_generic_stmt (FILE *, tree, dump_flags_t = TDF_NONE); From patchwork Mon Nov 15 11:18:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 47661 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 594733857C74 for ; Mon, 15 Nov 2021 11:19:52 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id E8B403858020 for ; Mon, 15 Nov 2021 11:18:41 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E8B403858020 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com IronPort-SDR: SrzLK4TXjRF1EhDRI9iymWrjSBdPFUVVyMnlMbAD4re7DcnEdoSaRQdVgayIwoEs04U/pXW3uz UkHhh/WkjPgIvPvLZJ8TjOe7PSLg2cbE9KLEGluihbAkvLJi3OphjVlvpit2a3rF3yWtSbhYt6 QZsiTZtUmTuG3fvjicZygzQNsZrKqQojSLzujV/fjxW2cm2tSIhchdPQGw/LPcn/9DvE0Iyt8c 1VfQvOyNhgRPjJDDW98XTEahqz21xwYaptzGDtMeG55CCdV01C1PFljZwIsHyG0rQoP5Egnkd1 GCQrBppUI/GW2CBFIoH7+Lvx X-IronPort-AV: E=Sophos;i="5.87,236,1631606400"; d="scan'208";a="68329815" Received: from orw-gwy-02-in.mentorg.com ([192.94.38.167]) by esa3.mentor.iphmx.com with ESMTP; 15 Nov 2021 03:18:42 -0800 IronPort-SDR: VdyvhhX78DYrV+3xXf5MgDBfCtPMj+3HNPCTekUYy5WjJpr8u9fFiPkdpdqPDBl8b5DBS8q+WQ 6i4lxbcj7aHr6pTNQrWkXAi35QvORIOOaG0yfjTJGcTvyKRjeVW17HooJL47U85/4ydErqsrRu 2zMTs7p608BHg03IReCBzdMDiBwrUqn6npJ9PCSc8nEu+qxrBPbh6PEZBqQizAr737LciCkIsu +7a1+Wz7w4ndQcJE8JcMnnbZzcWaR2lVvPFWR596YrkKRedX4KvJltJ57wDQUC9qb07kSviYj3 xDo= From: Julian Brown To: Subject: [PATCH 2/4] OpenMP: Add inspector class to unify mapped address analysis Date: Mon, 15 Nov 2021 03:18:24 -0800 Message-ID: <68476169eeb72f35a10ae16245dc60ba8f35d94f.1636974589.git.julian@codesourcery.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-10.mgc.mentorg.com (139.181.222.10) To SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" Several places in the C and C++ front-ends dig through OpenMP addresses from "map" clauses (etc.) in order to determine whether they are component accesses that need "attach" operations, check duplicate mapping clauses, and so on. When we're extending support for more kinds of lvalues in map clauses, it seems helpful to bring these all into one place in order to keep all the analyses in sync, and to make it easier to reason about which kinds of expressions are supported. This patch introduces an "address inspector" class for that purpose, and adjusts the C and C++ front-ends to use it. OK? Thanks, Julian 2021-11-15 Julian Brown gcc/c-family/ * c-common.h (c_omp_address_inspector): New class. * c-omp.c (c_omp_address_inspector::init, c_omp_address_inspector::analyze_components, c_omp_address_inspector::map_supported_p, c_omp_address_inspector::mappable_type): New methods. gcc/c/ * c-typeck.c (handle_omp_array_sections_1, c_finish_omp_clauses): Use c_omp_address_inspector class. gcc/cp/ * semantics.c (cp_omp_address_inspector): New class, derived from c_omp_address_inspector. (handle_omp_array_sections_1): Use cp_omp_address_inspector class to analyze OpenMP map clause expressions. Support POINTER_PLUS_EXPR. (finish_omp_clauses): Likewise. Support some additional kinds of lvalues in map clauses. gcc/testsuite/ * g++.dg/gomp/unmappable-component-1.C: New test. --- gcc/c-family/c-common.h | 44 ++++ gcc/c-family/c-omp.c | 147 +++++++++++ gcc/c/c-typeck.c | 198 ++++---------- gcc/cp/semantics.c | 249 ++++++------------ .../g++.dg/gomp/unmappable-component-1.C | 21 ++ 5 files changed, 337 insertions(+), 322 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gomp/unmappable-component-1.C diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h index 0fd07d107a9..1fa81932d90 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1251,6 +1251,50 @@ extern const char *c_omp_map_clause_name (tree, bool); extern void c_omp_adjust_map_clauses (tree, bool); extern tree c_omp_decompose_attachable_address (tree t, tree *virtbase); +class c_omp_address_inspector +{ + tree clause; + tree orig; + tree deref_toplevel; + tree outer_virtual_base; + tree root_term; + bool component_access; + bool indirections; + int map_supported; + +protected: + virtual bool reference_ref_p (tree) { return false; } + virtual bool processing_template_decl_p () { return false; } + virtual bool mappable_type (tree t); + virtual void emit_unmappable_type_notes (tree) { } + +public: + c_omp_address_inspector (tree c, tree t) + : clause (c), orig (t), deref_toplevel (NULL_TREE), + outer_virtual_base (NULL_TREE), root_term (NULL_TREE), + component_access (false), indirections (false), map_supported (-1) + { } + + ~c_omp_address_inspector () {} + + virtual void init (); + + tree analyze_components (bool); + + tree get_deref_toplevel () { return deref_toplevel; } + tree get_outer_virtual_base () { return outer_virtual_base; } + tree get_root_term () { gcc_assert (root_term); return root_term; } + bool component_access_p () { return component_access; } + + bool indir_component_ref_p () + { + gcc_assert (!component_access || root_term != NULL_TREE); + return component_access && indirections; + } + + bool map_supported_p (); +}; + enum c_omp_directive_kind { C_OMP_DIR_STANDALONE, C_OMP_DIR_CONSTRUCT, diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index aa59171b382..9b85d47f78a 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -3171,6 +3171,153 @@ c_omp_adjust_map_clauses (tree clauses, bool is_target) } } +/* This could just be done in the constructor, but we need to call the + subclass's version of reference_ref_p, etc. */ + +void +c_omp_address_inspector::init () +{ + tree t = orig; + + gcc_assert (TREE_CODE (t) != ARRAY_REF); + + /* We may have a reference-typed component access at the outermost level + that has had convert_from_reference called on it. Look through that + access. */ + if (reference_ref_p (t) + && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) + { + t = TREE_OPERAND (t, 0); + deref_toplevel = t; + } + else + deref_toplevel = t; + + /* Strip off expression nodes that may enclose a COMPONENT_REF. Look through + references, but not indirections through pointers. */ + while (1) + { + if (TREE_CODE (t) == COMPOUND_EXPR) + { + t = TREE_OPERAND (t, 1); + STRIP_NOPS (t); + } + else if (TREE_CODE (t) == POINTER_PLUS_EXPR + || TREE_CODE (t) == SAVE_EXPR) + t = TREE_OPERAND (t, 0); + else if (reference_ref_p (t)) + t = TREE_OPERAND (t, 0); + else + break; + } + + outer_virtual_base = t; + + if (TREE_CODE (t) == COMPONENT_REF) + component_access = true; +} + +tree +c_omp_address_inspector::analyze_components (bool checking) +{ + if (root_term) + return root_term; + + gcc_assert (TREE_CODE (outer_virtual_base) == COMPONENT_REF); + + tree t = outer_virtual_base; + + if (checking + && TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL + && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) + { + error_at (OMP_CLAUSE_LOCATION (clause), + "bit-field %qE in %qs clause", + t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]); + return error_mark_node; + } + else if (checking + && !processing_template_decl_p () + && !mappable_type (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (clause), + "%qE does not have a mappable type in %qs clause", + t, omp_clause_code_name[OMP_CLAUSE_CODE (clause)]); + emit_unmappable_type_notes (TREE_TYPE (t)); + return error_mark_node; + } + else if (checking && TREE_TYPE (t) && TYPE_ATOMIC (TREE_TYPE (t))) + { + error_at (OMP_CLAUSE_LOCATION (clause), + "%<_Atomic%> %qE in %qs clause", t, + omp_clause_code_name[OMP_CLAUSE_CODE (clause)]); + return error_mark_node; + } + + while (TREE_CODE (t) == COMPONENT_REF) + { + if (checking + && TREE_TYPE (TREE_OPERAND (t, 0)) + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE) + { + error_at (OMP_CLAUSE_LOCATION (clause), + "%qE is a member of a union", t); + return error_mark_node; + } + t = TREE_OPERAND (t, 0); + while (TREE_CODE (t) == MEM_REF + || TREE_CODE (t) == INDIRECT_REF + || TREE_CODE (t) == ARRAY_REF) + { + if (TREE_CODE (t) == MEM_REF + || TREE_CODE (t) == INDIRECT_REF) + indirections = true; + t = TREE_OPERAND (t, 0); + STRIP_NOPS (t); + if (TREE_CODE (t) == POINTER_PLUS_EXPR) + t = TREE_OPERAND (t, 0); + } + } + + root_term = t; + + return t; +} + +bool +c_omp_address_inspector::map_supported_p () +{ + /* If we've already decided if the mapped address is supported, return + that. */ + if (map_supported != -1) + return map_supported; + + /* Get the innermost point recorded so far. */ + tree t = root_term ? root_term : outer_virtual_base; + + while (TREE_CODE (t) == INDIRECT_REF + || TREE_CODE (t) == MEM_REF + || TREE_CODE (t) == ARRAY_REF + || TREE_CODE (t) == COMPONENT_REF + || TREE_CODE (t) == COMPOUND_EXPR + || TREE_CODE (t) == SAVE_EXPR + || TREE_CODE (t) == POINTER_PLUS_EXPR) + if (TREE_CODE (t) == COMPOUND_EXPR) + t = TREE_OPERAND (t, 1); + else + t = TREE_OPERAND (t, 0); + + map_supported = DECL_P (t); + + return map_supported; +} + +bool +c_omp_address_inspector::mappable_type (tree t) +{ + return lang_hooks.types.omp_mappable_type (t); +} + tree c_omp_decompose_attachable_address (tree t, tree *virtbase) { diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index e0e90a249c9..0dbb78d6e7e 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -13191,6 +13191,8 @@ handle_omp_array_sections_1 (tree c, tree t, vec &types, { if (error_operand_p (t)) return error_mark_node; + c_omp_address_inspector t_insp (c, t); + t_insp.init (); ret = t; if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_AFFINITY && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_DEPEND @@ -13200,59 +13202,15 @@ handle_omp_array_sections_1 (tree c, tree t, vec &types, t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); return error_mark_node; } - while (TREE_CODE (t) == INDIRECT_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == COMPOUND_EXPR) - { - t = TREE_OPERAND (t, 1); - STRIP_NOPS (t); - } - if (TREE_CODE (t) == COMPONENT_REF + if (t_insp.component_access_p () && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)) - { - if (DECL_BIT_FIELD (TREE_OPERAND (t, 1))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - while (TREE_CODE (t) == COMPONENT_REF) - { - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is a member of a union", t); - return error_mark_node; - } - t = TREE_OPERAND (t, 0); - while (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - if (ort == C_ORT_ACC && TREE_CODE (t) == MEM_REF) - { - if (maybe_ne (mem_ref_offset (t), 0)) - error_at (OMP_CLAUSE_LOCATION (c), - "cannot dereference %qE in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - t = TREE_OPERAND (t, 0); - } - } - } + t = t_insp.analyze_components (true); + else + t = t_insp.get_outer_virtual_base (); + if (t == error_mark_node) + return error_mark_node; if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { if (DECL_P (t)) @@ -14900,23 +14858,16 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } while (TREE_CODE (t) == ARRAY_REF) t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) + + c_omp_address_inspector t_insp (c, t); + t_insp.init (); + + tree ovb = t_insp.get_outer_virtual_base (); + + if (TREE_CODE (ovb) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (ovb)) == ARRAY_TYPE) { - do - { - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - } - while (TREE_CODE (t) == COMPONENT_REF); + t = t_insp.analyze_components (false); if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && OMP_CLAUSE_MAP_IMPLICIT (c) @@ -14985,96 +14936,35 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bias) to zero here, so it is not set erroneously to the pointer size later on in gimplify.c. */ OMP_CLAUSE_SIZE (c) = size_zero_node; - while (TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == COMPOUND_EXPR) - { - t = TREE_OPERAND (t, 1); - STRIP_NOPS (t); - } - indir_component_ref_p = false; - if (TREE_CODE (t) == COMPONENT_REF - && (TREE_CODE (TREE_OPERAND (t, 0)) == MEM_REF - || TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF - || TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF)) - { - t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); - indir_component_ref_p = true; - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - if (TREE_CODE (t) == COMPONENT_REF - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_) - { - if (DECL_BIT_FIELD (TREE_OPERAND (t, 1))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE does not have a mappable type in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (TYPE_ATOMIC (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%<_Atomic%> %qE in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - while (TREE_CODE (t) == COMPONENT_REF) - { - if (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) - == UNION_TYPE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is a member of a union", t); - remove = true; - break; - } - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == MEM_REF) - { - if (maybe_ne (mem_ref_offset (t), 0)) - error_at (OMP_CLAUSE_LOCATION (c), - "cannot dereference %qE in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - } - if (remove) + { + c_omp_address_inspector t_insp (c, t); + t_insp.init (); + + if (t_insp.component_access_p () + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_) + t = t_insp.analyze_components (true); + else + t = t_insp.get_outer_virtual_base (); + + if (t == error_mark_node) + { + remove = true; break; - if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) - { - if (bitmap_bit_p (&map_field_head, DECL_UID (t)) - || (ort != C_ORT_ACC - && bitmap_bit_p (&map_head, DECL_UID (t)))) - break; - } - } + } + + indir_component_ref_p = t_insp.indir_component_ref_p (); + + if (t_insp.component_access_p () + && (VAR_P (t) || TREE_CODE (t) == PARM_DECL)) + { + if (bitmap_bit_p (&map_field_head, DECL_UID (t)) + || (ort != C_ORT_ACC + && bitmap_bit_p (&map_head, DECL_UID (t)))) + break; + } + } + if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) { error_at (OMP_CLAUSE_LOCATION (c), diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index bb8577d0d36..1499e565a61 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4969,6 +4969,39 @@ omp_privatize_field (tree t, bool shared) return v; } +/* C++ specialisation of the c_omp_address_inspector class. */ + +class cp_omp_address_inspector : public c_omp_address_inspector +{ +protected: + bool reference_ref_p (tree t) + { + return REFERENCE_REF_P (t); + } + + bool processing_template_decl_p () + { + return processing_template_decl; + } + + bool mappable_type (tree t) + { + return cp_omp_mappable_type (t); + } + + void emit_unmappable_type_notes (tree t) + { + cp_omp_emit_unmappable_type_notes (t); + } + +public: + cp_omp_address_inspector (tree c, tree t) : c_omp_address_inspector (c, t) + { } + + ~cp_omp_address_inspector () + { } +}; + /* Helper function for handle_omp_array_sections. Called recursively to handle multiple array-section-subscripts. C is the clause, T current expression (initially OMP_CLAUSE_DECL), which is either @@ -4999,59 +5032,18 @@ handle_omp_array_sections_1 (tree c, tree t, vec &types, { if (error_operand_p (t)) return error_mark_node; - if (REFERENCE_REF_P (t) - && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) - t = TREE_OPERAND (t, 0); - ret = t; - while (TREE_CODE (t) == INDIRECT_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == COMPOUND_EXPR) - { - t = TREE_OPERAND (t, 1); - STRIP_NOPS (t); - } - if (TREE_CODE (t) == COMPONENT_REF + cp_omp_address_inspector t_insp (c, t); + t_insp.init (); + if (t_insp.component_access_p () && (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_TO - || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM) - && !type_dependent_expression_p (t)) - { - if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL - && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - return error_mark_node; - } - while (TREE_CODE (t) == COMPONENT_REF) - { - if (TREE_TYPE (TREE_OPERAND (t, 0)) - && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == UNION_TYPE) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is a member of a union", t); - return error_mark_node; - } - t = TREE_OPERAND (t, 0); - while (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - } - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - } + || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FROM)) + t = t_insp.analyze_components (true); + else + t = t_insp.get_outer_virtual_base (); + if (t == error_mark_node) + return error_mark_node; + ret = t_insp.get_deref_toplevel (); if (TREE_CODE (t) == FIELD_DECL) ret = finish_non_static_data_member (t, NULL_TREE, NULL_TREE); else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) @@ -7846,27 +7838,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } while (TREE_CODE (t) == ARRAY_REF) t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == COMPONENT_REF - && TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) + + cp_omp_address_inspector t_insp (c, t); + t_insp.init (); + tree ovb = t_insp.get_outer_virtual_base (); + + if (TREE_CODE (ovb) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (ovb)) == ARRAY_TYPE) { - do - { - t = TREE_OPERAND (t, 0); - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - } - } - while (TREE_CODE (t) == COMPONENT_REF); + t = t_insp.analyze_components (false); if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && OMP_CLAUSE_MAP_IMPLICIT (c) @@ -7935,104 +7915,37 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) bias) to zero here, so it is not set erroneously to the pointer size later on in gimplify.c. */ OMP_CLAUSE_SIZE (c) = size_zero_node; - if (REFERENCE_REF_P (t) - && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF) - { - t = TREE_OPERAND (t, 0); - if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP - && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH) - OMP_CLAUSE_DECL (c) = t; - } - while (TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == COMPOUND_EXPR) - { - t = TREE_OPERAND (t, 1); - STRIP_NOPS (t); - } - indir_component_ref_p = false; - if (TREE_CODE (t) == COMPONENT_REF - && (TREE_CODE (TREE_OPERAND (t, 0)) == INDIRECT_REF - || TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF)) - { - t = TREE_OPERAND (TREE_OPERAND (t, 0), 0); - indir_component_ref_p = true; - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - if (TREE_CODE (t) == COMPONENT_REF - && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_) - { - if (type_dependent_expression_p (t)) + + { + cp_omp_address_inspector t_insp (c, t); + t_insp.init (); + + if (t_insp.component_access_p () + && OMP_CLAUSE_CODE (c) != OMP_CLAUSE__CACHE_) + t = t_insp.analyze_components (true); + else + t = t_insp.get_outer_virtual_base (); + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP + && OMP_CLAUSE_MAP_KIND (c) != GOMP_MAP_ATTACH_DETACH) + OMP_CLAUSE_DECL (c) = t_insp.get_deref_toplevel (); + if (type_dependent_expression_p (t_insp.get_deref_toplevel ())) + break; + if (t == error_mark_node) + { + remove = true; break; - if (TREE_CODE (TREE_OPERAND (t, 1)) == FIELD_DECL - && DECL_BIT_FIELD (TREE_OPERAND (t, 1))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "bit-field %qE in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - remove = true; - } - else if (!cp_omp_mappable_type (TREE_TYPE (t))) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE does not have a mappable type in %qs clause", - t, omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - cp_omp_emit_unmappable_type_notes (TREE_TYPE (t)); - remove = true; - } - while (TREE_CODE (t) == COMPONENT_REF) - { - if (TREE_TYPE (TREE_OPERAND (t, 0)) - && (TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) - == UNION_TYPE)) - { - error_at (OMP_CLAUSE_LOCATION (c), - "%qE is a member of a union", t); - remove = true; - break; - } - t = TREE_OPERAND (t, 0); - if (TREE_CODE (t) == MEM_REF) - { - if (maybe_ne (mem_ref_offset (t), 0)) - error_at (OMP_CLAUSE_LOCATION (c), - "cannot dereference %qE in %qs clause", t, - omp_clause_code_name[OMP_CLAUSE_CODE (c)]); - else - t = TREE_OPERAND (t, 0); - } - while (TREE_CODE (t) == MEM_REF - || TREE_CODE (t) == INDIRECT_REF - || TREE_CODE (t) == ARRAY_REF) - { - t = TREE_OPERAND (t, 0); - STRIP_NOPS (t); - if (TREE_CODE (t) == POINTER_PLUS_EXPR) - t = TREE_OPERAND (t, 0); - } - } - if (remove) - break; - if (REFERENCE_REF_P (t)) - t = TREE_OPERAND (t, 0); - if (VAR_P (t) || TREE_CODE (t) == PARM_DECL) - { - if (bitmap_bit_p (&map_field_head, DECL_UID (t)) - || (ort != C_ORT_ACC - && bitmap_bit_p (&map_head, DECL_UID (t)))) - goto handle_map_references; - } - } + } + indir_component_ref_p = t_insp.indir_component_ref_p (); + if (t_insp.component_access_p () + && (VAR_P (t) || TREE_CODE (t) == PARM_DECL)) + { + if (bitmap_bit_p (&map_field_head, DECL_UID (t)) + || (ort != C_ORT_ACC + && bitmap_bit_p (&map_head, DECL_UID (t)))) + goto handle_map_references; + } + } + if (!processing_template_decl && TREE_CODE (t) == FIELD_DECL) { OMP_CLAUSE_DECL (c) = finish_non_static_data_member (t, NULL_TREE, diff --git a/gcc/testsuite/g++.dg/gomp/unmappable-component-1.C b/gcc/testsuite/g++.dg/gomp/unmappable-component-1.C new file mode 100644 index 00000000000..6fbc49616b1 --- /dev/null +++ b/gcc/testsuite/g++.dg/gomp/unmappable-component-1.C @@ -0,0 +1,21 @@ +/* { dg-do compile } */ + +struct A { + static int x[10]; +}; + +struct B { + A a; +}; + +int +main (int argc, char *argv[]) +{ + B *b = new B; +#pragma omp target map(b->a) // { dg-error "'b->B::a' does not have a mappable type in 'map' clause" } + ; + B bb; +#pragma omp target map(bb.a) // { dg-error "'bb\.B::a' does not have a mappable type in 'map' clause" } + ; + delete b; +} From patchwork Mon Nov 15 11:18:25 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 47662 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 5F06D3857404 for ; Mon, 15 Nov 2021 11:20:28 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id 7BEDA3858027 for ; Mon, 15 Nov 2021 11:18:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7BEDA3858027 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com IronPort-SDR: /AknZDeM6OwPjW3sENbEaV0P+Pa1wIZQQ2p4mufMPp4Lu031o+hG5oSsQeyIGix8zRe+DgIVtg +VZksJg/lhinBj0ptkPRTwCMsyv5B/10hhtkIbzb1NduIOPpO+fWDZ6L1Yq3+kM9WSI4uQ6vve VO/eI1HFPewUrBvtuaBYa8oA23WUNfDfI7/F/gKokI9OPZGIHtKxiQ+b26ABdoB9LlPdTmfYji 1L8Vf5z4P6C4phic6BXtBIlqaRT8yKa2Nskx6xiWAaz+4kIDxvctvTs9wnFrCIFwR5W9cbvwyx U7WS+1DAK+Ftci5u0f3BfEoK X-IronPort-AV: E=Sophos;i="5.87,236,1631606400"; d="scan'208";a="68329817" Received: from orw-gwy-02-in.mentorg.com ([192.94.38.167]) by esa3.mentor.iphmx.com with ESMTP; 15 Nov 2021 03:18:42 -0800 IronPort-SDR: i9CkenTk2v+3dCAb13C0SNe5L6r8DazkQ0E3JvCWzmt7CtdHKfMlvY2MtYLyYbsoVhDGSiHJyy HODr2XtpdQzghnZliJyCgB2Nrc9LywHFtbwOdCYvz7lVE9jBa+kl02lUNnO7hgc4obrB6gA3Qd wfS5tJTf3faWW+EVKT1sOp4SS+itPCp6Z84TboZqzLBX0gpX4quRlGc7DXvX7MDs5h8XqgI8P1 j5FTR25/LlpAPSYizrhuOCn3dKHDruayLhl+ylmZ77UOP9f+J73FjenoAfhipaR/iCGWLYFU04 sGc= From: Julian Brown To: Subject: [PATCH 3/4] OpenMP: lvalue parsing for map clauses (C++) Date: Mon, 15 Nov 2021 03:18:25 -0800 Message-ID: <6c491905cd64b5b6a53d762d27afd9b875866323.1636974589.git.julian@codesourcery.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-10.mgc.mentorg.com (139.181.222.10) To SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch changes parsing for OpenMP map clauses in C++ to use the generic expression parser, hence adds support for parsing general lvalues (as required by OpenMP 5.0+). So far only a few new types of expression are actually supported throughout compilation (including everything in the testsuite of course, and newly-added tests), and we attempt to reject unsupported expressions in order to avoid surprises for the user. The intention is to incrementally add support for further kinds of lvalues on top of this patch. OK? Thanks, Julian 2021-11-15 Julian Brown gcc/c-family/ * c-omp.c (c_omp_decompose_attachable_address): Handle more types of expressions. gcc/cp/ * error.c (dump_expr): Handle OMP_ARRAY_SECTION. * parser.c (cp_parser_new): Initialize parser->omp_array_section_p. (cp_parser_postfix_open_square_expression): Support OMP_ARRAY_SECTION parsing. (cp_parser_omp_var_list_no_open): Remove ALLOW_DEREF parameter, add MAP_LVALUE in its place. Supported generalised lvalue parsing for map clauses. (cp_parser_omp_var_list): Remove ALLOW_DEREF parameter, add MAP_LVALUE. Pass to cp_parser_omp_var_list_no_open. (cp_parser_oacc_data_clause, cp_parser_omp_all_clauses): Update calls to cp_parser_omp_var_list. * parser.h (cp_parser): Add omp_array_section_p field. * semantics.c (handle_omp_array_sections_1): Handle more types of map expression. (handle_omp_array_section): Handle non-DECL_P attachment points. (finish_omp_clauses): Check for supported types of expression. gcc/ * gimplify.c (build_struct_group): Handle reference-typed component accesses. Fix support for non-DECL_P struct bases. (omp_build_struct_sibling_lists): Support length-two group for synthesized inner struct mapping. * tree-pretty-print.c (dump_generic_node): Support OMP_ARRAY_SECTION. * tree.def (OMP_ARRAY_SECTION): New tree code. gcc/testsuite/ * c-c++-common/gomp/map-6.c: Update expected output. * g++.dg/gomp/pr67522.C: Likewise. libgomp/ * testsuite/libgomp.c++/ind-base-1.C: New test. * testsuite/libgomp.c++/ind-base-2.C: New test. * testsuite/libgomp.c++/struct-ref-1.C: New test. --- gcc/c-family/c-omp.c | 25 ++- gcc/cp/error.c | 9 ++ gcc/cp/parser.c | 141 ++++++++++++++-- gcc/cp/parser.h | 3 + gcc/cp/semantics.c | 35 +++- gcc/gimplify.c | 37 ++++- gcc/testsuite/c-c++-common/gomp/map-6.c | 4 +- gcc/testsuite/g++.dg/gomp/pr67522.C | 2 +- gcc/tree-pretty-print.c | 14 ++ gcc/tree.def | 3 + libgomp/testsuite/libgomp.c++/ind-base-1.C | 162 +++++++++++++++++++ libgomp/testsuite/libgomp.c++/ind-base-2.C | 49 ++++++ libgomp/testsuite/libgomp.c++/struct-ref-1.C | 97 +++++++++++ 13 files changed, 553 insertions(+), 28 deletions(-) create mode 100644 libgomp/testsuite/libgomp.c++/ind-base-1.C create mode 100644 libgomp/testsuite/libgomp.c++/ind-base-2.C create mode 100644 libgomp/testsuite/libgomp.c++/struct-ref-1.C diff --git a/gcc/c-family/c-omp.c b/gcc/c-family/c-omp.c index 9b85d47f78a..3834bd50cc9 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -3323,12 +3323,18 @@ c_omp_decompose_attachable_address (tree t, tree *virtbase) { *virtbase = t; - /* It's already a pointer. Just use that. */ - if (POINTER_TYPE_P (TREE_TYPE (t))) + /* It's already a non-offset pointer. Just use that. */ + if (POINTER_TYPE_P (TREE_TYPE (t)) + && (DECL_P (t) + || TREE_CODE (t) == COMPONENT_REF + || TREE_CODE (t) == ARRAY_REF)) return NULL_TREE; /* Otherwise, look for a base pointer deeper within the expression. */ + while (TREE_CODE (t) == COMPOUND_EXPR) + t = TREE_OPERAND (t, 1); + while (TREE_CODE (t) == COMPONENT_REF && (TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF || TREE_CODE (TREE_OPERAND (t, 0)) == ARRAY_REF)) @@ -3338,9 +3344,24 @@ c_omp_decompose_attachable_address (tree t, tree *virtbase) t = TREE_OPERAND (t, 0); } + if (TREE_CODE (t) == POINTER_PLUS_EXPR) + { + t = TREE_OPERAND (t, 0); + if (TREE_CODE (t) == SAVE_EXPR) + t = TREE_OPERAND (t, 0); + } + + if (TREE_CODE (t) == INDIRECT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == REFERENCE_TYPE) + t = TREE_OPERAND (t, 0); *virtbase = t; + /* If we have a pointer now (e.g. after we've stripped POINTER_PLUS_EXPR), + we have an offset pointer. That's the attachment point. */ + if (POINTER_TYPE_P (TREE_TYPE (t))) + return t; + if (TREE_CODE (t) != COMPONENT_REF) return NULL_TREE; diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 012a4ecddf4..141c959d1bb 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -2415,6 +2415,15 @@ dump_expr (cxx_pretty_printer *pp, tree t, int flags) pp_cxx_right_bracket (pp); break; + case OMP_ARRAY_SECTION: + dump_expr (pp, TREE_OPERAND (t, 0), flags); + pp_cxx_left_bracket (pp); + dump_expr (pp, TREE_OPERAND (t, 1), flags); + pp_colon (pp); + dump_expr (pp, TREE_OPERAND (t, 2), flags); + pp_cxx_right_bracket (pp); + break; + case UNARY_PLUS_EXPR: dump_unary_op (pp, "+", t, flags); break; diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 4f9e364aa95..2b2ad9b77d2 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -4241,6 +4241,9 @@ cp_parser_new (cp_lexer *lexer) parser->omp_declare_simd = NULL; parser->oacc_routine = NULL; + /* Allow array slice in expression. */ + parser->omp_array_section_p = false; + /* Not declaring an implicit function template. */ parser->auto_is_implicit_function_template_parm_p = false; parser->fully_implicit_function_template_p = false; @@ -7898,6 +7901,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, tree index = NULL_TREE; location_t loc = cp_lexer_peek_token (parser->lexer)->location; bool saved_greater_than_is_operator_p; + bool saved_colon_corrects_to_scope_p; /* Consume the `[' token. */ cp_lexer_consume_token (parser->lexer); @@ -7905,6 +7909,9 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, saved_greater_than_is_operator_p = parser->greater_than_is_operator_p; parser->greater_than_is_operator_p = true; + saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p; + parser->colon_corrects_to_scope_p = false; + /* Parse the index expression. */ /* ??? For offsetof, there is a question of what to allow here. If offsetof is not being used in an integral constant expression context, @@ -7915,7 +7922,8 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, constant expressions here. */ if (for_offsetof) index = cp_parser_constant_expression (parser); - else + else if (!parser->omp_array_section_p + || cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)) { if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) { @@ -7932,6 +7940,32 @@ cp_parser_postfix_open_square_expression (cp_parser *parser, parser->greater_than_is_operator_p = saved_greater_than_is_operator_p; + if (parser->omp_array_section_p + && cp_lexer_next_token_is (parser->lexer, CPP_COLON)) + { + cp_lexer_consume_token (parser->lexer); + tree length = NULL_TREE; + if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE)) + length = cp_parser_expression (parser); + + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + + if ((index && error_operand_p (index)) + || (length && error_operand_p (length))) + return error_mark_node; + + cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); + + /* NOTE: We are reusing using the type of the whole array as the type of + the array section here, which isn't necessarily entirely correct. + Might need revisiting. */ + return build3_loc (input_location, OMP_ARRAY_SECTION, + TREE_TYPE (postfix_expression), + postfix_expression, index, length); + } + + parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p; + /* Look for the closing `]'. */ cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE); @@ -36340,7 +36374,7 @@ struct omp_dim static tree cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, tree list, bool *colon, - bool allow_deref = false) + bool map_lvalue = false) { auto_vec dims; bool array_section_p; @@ -36351,12 +36385,95 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, parser->colon_corrects_to_scope_p = false; *colon = false; } + begin_scope (sk_omp, NULL); while (1) { tree name, decl; if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) cp_parser_parse_tentatively (parser); + else if (map_lvalue && kind == OMP_CLAUSE_MAP) + { + auto s = make_temp_override (parser->omp_array_section_p, true); + token = cp_lexer_peek_token (parser->lexer); + location_t loc = token->location; + decl = cp_parser_assignment_expression (parser); + + dims.truncate (0); + if (TREE_CODE (decl) == OMP_ARRAY_SECTION) + { + while (TREE_CODE (decl) == OMP_ARRAY_SECTION) + { + tree low_bound = TREE_OPERAND (decl, 1); + tree length = TREE_OPERAND (decl, 2); + dims.safe_push (omp_dim (low_bound, length, loc, false)); + decl = TREE_OPERAND (decl, 0); + } + + while (TREE_CODE (decl) == ARRAY_REF + || TREE_CODE (decl) == INDIRECT_REF + || TREE_CODE (decl) == COMPOUND_EXPR) + { + if (REFERENCE_REF_P (decl)) + break; + + if (TREE_CODE (decl) == COMPOUND_EXPR) + { + decl = TREE_OPERAND (decl, 1); + STRIP_NOPS (decl); + } + else if (TREE_CODE (decl) == INDIRECT_REF) + { + dims.safe_push (omp_dim (integer_zero_node, + integer_one_node, loc, true)); + decl = TREE_OPERAND (decl, 0); + } + else /* ARRAY_REF. */ + { + tree index = TREE_OPERAND (decl, 1); + dims.safe_push (omp_dim (index, integer_one_node, loc, + true)); + decl = TREE_OPERAND (decl, 0); + } + } + + /* Bare references have their own special handling, so remove + the explicit dereference added by convert_from_reference. */ + if (REFERENCE_REF_P (decl)) + decl = TREE_OPERAND (decl, 0); + + for (int i = dims.length () - 1; i >= 0; i--) + decl = tree_cons (dims[i].low_bound, dims[i].length, decl); + } + else if (TREE_CODE (decl) == INDIRECT_REF) + { + bool ref_p = REFERENCE_REF_P (decl); + + /* Turn *foo into the representation previously used for + foo[0]. */ + decl = TREE_OPERAND (decl, 0); + STRIP_NOPS (decl); + + /* ...but don't add the [0:1] representation for references + (because they have special handling elsewhere). */ + if (!ref_p) + decl = tree_cons (integer_zero_node, integer_one_node, decl); + } + else if (TREE_CODE (decl) == ARRAY_REF) + { + tree idx = TREE_OPERAND (decl, 1); + + decl = TREE_OPERAND (decl, 0); + STRIP_NOPS (decl); + + decl = tree_cons (idx, integer_one_node, decl); + } + else if (TREE_CODE (decl) == NON_LVALUE_EXPR + || CONVERT_EXPR_P (decl)) + decl = TREE_OPERAND (decl, 0); + + goto build_clause; + } token = cp_lexer_peek_token (parser->lexer); if (kind != 0 && cp_parser_is_keyword (token, RID_THIS)) @@ -36426,8 +36543,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, case OMP_CLAUSE_TO: start_component_ref: while (cp_lexer_next_token_is (parser->lexer, CPP_DOT) - || (allow_deref - && cp_lexer_next_token_is (parser->lexer, CPP_DEREF))) + || cp_lexer_next_token_is (parser->lexer, CPP_DEREF)) { cpp_ttype ttype = cp_lexer_next_token_is (parser->lexer, CPP_DOT) @@ -36513,9 +36629,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, || kind == OMP_CLAUSE_TO) && !array_section_p && (cp_lexer_next_token_is (parser->lexer, CPP_DOT) - || (allow_deref - && cp_lexer_next_token_is (parser->lexer, - CPP_DEREF)))) + || cp_lexer_next_token_is (parser->lexer, CPP_DEREF))) { for (unsigned i = 0; i < dims.length (); i++) { @@ -36551,6 +36665,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, cp_parser_parse_definitely (parser); } + build_clause: tree u = build_omp_clause (token->location, kind); OMP_CLAUSE_DECL (u) = decl; OMP_CLAUSE_CHAIN (u) = list; @@ -36572,6 +36687,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, { *colon = true; cp_parser_require (parser, CPP_COLON, RT_COLON); + finish_scope (); return list; } @@ -36592,6 +36708,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, goto get_comma; } + finish_scope (); return list; } @@ -36600,11 +36717,11 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind, static tree cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list, - bool allow_deref = false) + bool map_lvalue = false) { if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN)) return cp_parser_omp_var_list_no_open (parser, kind, list, NULL, - allow_deref); + map_lvalue); return list; } @@ -36671,7 +36788,7 @@ cp_parser_oacc_data_clause (cp_parser *parser, pragma_omp_clause c_kind, gcc_unreachable (); } tree nl, c; - nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list, true); + nl = cp_parser_omp_var_list (parser, OMP_CLAUSE_MAP, list, false); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_SET_MAP_KIND (c, kind); @@ -40018,12 +40135,12 @@ cp_parser_omp_all_clauses (cp_parser *parser, omp_clause_mask mask, clauses); else clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_TO, clauses, - true); + false); c_name = "to"; break; case PRAGMA_OMP_CLAUSE_FROM: clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FROM, clauses, - true); + false); c_name = "from"; break; case PRAGMA_OMP_CLAUSE_UNIFORM: diff --git a/gcc/cp/parser.h b/gcc/cp/parser.h index 3669587cebd..bebf8e6b16a 100644 --- a/gcc/cp/parser.h +++ b/gcc/cp/parser.h @@ -404,6 +404,9 @@ struct GTY(()) cp_parser { /* TRUE if omp::directive or omp::sequence attributes may not appear. */ bool omp_attrs_forbidden_p; + /* TRUE if an OpenMP array section is allowed. */ + bool omp_array_section_p; + /* Tracks the function's template parameter list when declaring a function using generic type parameters. This is either a new chain in the case of a fully implicit function template or an extension of the function's existing diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 1499e565a61..b02787ccbe5 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -5046,7 +5046,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec &types, ret = t_insp.get_deref_toplevel (); if (TREE_CODE (t) == FIELD_DECL) ret = finish_non_static_data_member (t, NULL_TREE, NULL_TREE); - else if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL) + else if (!VAR_P (t) + && (ort == C_ORT_ACC || !EXPR_P (t)) + && TREE_CODE (t) != PARM_DECL) { if (processing_template_decl && TREE_CODE (t) != OVERLOAD) return NULL_TREE; @@ -5635,7 +5637,9 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) bool reference_always_pointer = true; tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); - if (TREE_CODE (t) == COMPONENT_REF) + if (TREE_CODE (t) == COMPONENT_REF + || (TREE_CODE (t) == POINTER_PLUS_EXPR + && TREE_CODE (TREE_OPERAND (t, 0)) == COMPONENT_REF)) { OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH); @@ -5663,6 +5667,13 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) } OMP_CLAUSE_SET_MAP_KIND (c2, k); } + else if (ort != C_ORT_ACC && attach_pt && !DECL_P (attach_pt)) + { + if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE) + return false; + + OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH); + } else OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER); OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c); @@ -7848,6 +7859,15 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { t = t_insp.analyze_components (false); + if (!t_insp.map_supported_p ()) + { + sorry_at (OMP_CLAUSE_LOCATION (c), + "unsupported map expression %qE", + OMP_CLAUSE_DECL (c)); + remove = true; + break; + } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && OMP_CLAUSE_MAP_IMPLICIT (c) && (bitmap_bit_p (&map_head, DECL_UID (t)) @@ -7930,6 +7950,14 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) OMP_CLAUSE_DECL (c) = t_insp.get_deref_toplevel (); if (type_dependent_expression_p (t_insp.get_deref_toplevel ())) break; + if (!t_insp.map_supported_p ()) + { + sorry_at (OMP_CLAUSE_LOCATION (c), + "unsupported map expression %qE", + OMP_CLAUSE_DECL (c)); + remove = true; + break; + } if (t == error_mark_node) { remove = true; @@ -7959,7 +7987,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort) if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && (OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_POINTER || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ALWAYS_POINTER - || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH)) + || OMP_CLAUSE_MAP_KIND (c) == GOMP_MAP_ATTACH_DETACH + || (ort != C_ORT_ACC && EXPR_P (t)))) break; if (DECL_P (t)) error_at (OMP_CLAUSE_LOCATION (c), diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 4563cce3fc6..8b0d0dbd084 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -10287,6 +10287,7 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code, { tree l = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), OMP_CLAUSE_MAP); gomp_map_kind k = attach ? GOMP_MAP_FORCE_PRESENT : GOMP_MAP_STRUCT; + tree *tail_chain; OMP_CLAUSE_SET_MAP_KIND (l, k); @@ -10315,9 +10316,13 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code, { OMP_CLAUSE_CHAIN (extra_node) = *insert_node_pos; OMP_CLAUSE_CHAIN (alloc_node) = extra_node; + tail_chain = &OMP_CLAUSE_CHAIN (extra_node); } else - OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos; + { + OMP_CLAUSE_CHAIN (alloc_node) = *insert_node_pos; + tail_chain = &OMP_CLAUSE_CHAIN (alloc_node); + } *insert_node_pos = l; } @@ -10325,6 +10330,7 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code, { gcc_assert (*grp_start_p == grp_end); grp_start_p = insert_node_after (l, grp_start_p); + tail_chain = &OMP_CLAUSE_CHAIN (*grp_start_p); } tree noind = strip_indirections (base); @@ -10389,8 +10395,7 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code, || TREE_CODE (sdecl) == POINTER_PLUS_EXPR) sdecl = TREE_OPERAND (sdecl, 0); - if (DECL_P (sdecl) - && POINTER_TYPE_P (TREE_TYPE (sdecl)) + if (POINTER_TYPE_P (TREE_TYPE (sdecl)) && (region_type & ORT_TARGET)) { tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (grp_end), @@ -10404,8 +10409,12 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code, && (TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (base, 0), 0))) == REFERENCE_TYPE)))); - enum gomp_map_kind mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE - : GOMP_MAP_FIRSTPRIVATE_POINTER; + enum gomp_map_kind mkind; + if (DECL_P (sdecl)) + mkind = base_ref ? GOMP_MAP_FIRSTPRIVATE_REFERENCE + : GOMP_MAP_FIRSTPRIVATE_POINTER; + else + mkind = GOMP_MAP_ATTACH; OMP_CLAUSE_SET_MAP_KIND (c2, mkind); OMP_CLAUSE_DECL (c2) = sdecl; tree baddr = build_fold_addr_expr (base); @@ -10421,9 +10430,21 @@ build_struct_group (enum omp_region_type region_type, enum tree_code code, OMP_CLAUSE_SIZE (c2) = fold_build2_loc (OMP_CLAUSE_LOCATION (grp_end), MINUS_EXPR, ptrdiff_type_node, baddr, decladdr); - /* Insert after struct node. */ - OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l); - OMP_CLAUSE_CHAIN (l) = c2; + if (mkind == GOMP_MAP_FIRSTPRIVATE_POINTER + || mkind == GOMP_MAP_FIRSTPRIVATE_REFERENCE) + { + /* Insert after struct node. */ + OMP_CLAUSE_CHAIN (c2) = OMP_CLAUSE_CHAIN (l); + OMP_CLAUSE_CHAIN (l) = c2; + } + else /* GOMP_MAP_ATTACH. */ + { + /* Insert after struct group. */ + OMP_CLAUSE_CHAIN (c2) = *tail_chain; + *tail_chain = c2; + if (*grp_start_p == grp_end) + return &OMP_CLAUSE_CHAIN (*tail_chain); + } } return NULL; diff --git a/gcc/testsuite/c-c++-common/gomp/map-6.c b/gcc/testsuite/c-c++-common/gomp/map-6.c index 6ee59714847..c749db845b0 100644 --- a/gcc/testsuite/c-c++-common/gomp/map-6.c +++ b/gcc/testsuite/c-c++-common/gomp/map-6.c @@ -20,12 +20,12 @@ foo (void) ; #pragma omp target map (close a) /* { dg-error "'close' undeclared" "" { target c } } */ - /* { dg-error "'close' has not been declared" "" { target c++ } .-1 } */ + /* { dg-error "'close' was not declared in this scope" "" { target c++ } .-1 } */ /* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */ ; #pragma omp target map (always a) /* { dg-error "'always' undeclared" "" { target c } } */ - /* { dg-error "'always' has not been declared" "" { target c++ } .-1 } */ + /* { dg-error "'always' was not declared in this scope" "" { target c++ } .-1 } */ /* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */ ; diff --git a/gcc/testsuite/g++.dg/gomp/pr67522.C b/gcc/testsuite/g++.dg/gomp/pr67522.C index da8cb74d1fa..4a901ba68c7 100644 --- a/gcc/testsuite/g++.dg/gomp/pr67522.C +++ b/gcc/testsuite/g++.dg/gomp/pr67522.C @@ -12,7 +12,7 @@ foo (void) for (int i = 0; i < 16; i++) ; - #pragma omp target map (S[0:10]) // { dg-error "is not a variable in" } + #pragma omp target map (S[0:10]) // { dg-error "expected primary-expression before '\\\[' token" } ; #pragma omp task depend (inout: S[0:10]) // { dg-error "is not a variable in" } diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c index b213bb9cec5..3ee27d5d25d 100644 --- a/gcc/tree-pretty-print.c +++ b/gcc/tree-pretty-print.c @@ -2510,6 +2510,20 @@ dump_generic_node (pretty_printer *pp, tree node, int spc, dump_flags_t flags, } break; + case OMP_ARRAY_SECTION: + op0 = TREE_OPERAND (node, 0); + if (op_prio (op0) < op_prio (node)) + pp_left_paren (pp); + dump_generic_node (pp, op0, spc, flags, false); + if (op_prio (op0) < op_prio (node)) + pp_right_paren (pp); + pp_left_bracket (pp); + dump_generic_node (pp, TREE_OPERAND (node, 1), spc, flags, false); + pp_colon (pp); + dump_generic_node (pp, TREE_OPERAND (node, 2), spc, flags, false); + pp_right_bracket (pp); + break; + case CONSTRUCTOR: { unsigned HOST_WIDE_INT ix; diff --git a/gcc/tree.def b/gcc/tree.def index e27bc3e2b1f..9824840ec00 100644 --- a/gcc/tree.def +++ b/gcc/tree.def @@ -1304,6 +1304,9 @@ DEFTREECODE (OMP_ATOMIC_CAPTURE_NEW, "omp_atomic_capture_new", tcc_statement, 2) /* OpenMP clauses. */ DEFTREECODE (OMP_CLAUSE, "omp_clause", tcc_exceptional, 0) +/* An OpenMP array section. */ +DEFTREECODE (OMP_ARRAY_SECTION, "omp_array_section", tcc_expression, 3) + /* TRANSACTION_EXPR tree code. Operand 0: BODY: contains body of the transaction. */ DEFTREECODE (TRANSACTION_EXPR, "transaction_expr", tcc_expression, 1) diff --git a/libgomp/testsuite/libgomp.c++/ind-base-1.C b/libgomp/testsuite/libgomp.c++/ind-base-1.C new file mode 100644 index 00000000000..4566854e60a --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/ind-base-1.C @@ -0,0 +1,162 @@ +// { dg-do run } +// { dg-options "-fopenmp" } + +#include + +struct S +{ + int x[10]; +}; + +struct T +{ + struct S *s; +}; + +struct U +{ + struct T *t; +}; + +void +foo_siblist (void) +{ + U *u = new U; + u->t = new T; + u->t->s = new S; + for (int i = 0; i < 10; i++) + u->t->s->x[i] = 0; +#pragma omp target map(u->t, *(u->t), u->t->s, *u->t->s) + for (int i = 0; i < 10; i++) + u->t->s->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert (u->t->s->x[i] == i * 3); + delete u->t->s; + delete u->t; + delete u; +} + +void +foo (void) +{ + U *u = new U; + u->t = new T; + u->t->s = new S; + for (int i = 0; i < 10; i++) + u->t->s->x[i] = 0; +#pragma omp target map(*u, u->t, *(u->t), u->t->s, *u->t->s) + for (int i = 0; i < 10; i++) + u->t->s->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert (u->t->s->x[i] == i * 3); + delete u->t->s; + delete u->t; + delete u; +} + +void +foo_tofrom (void) +{ + U *u = new U; + u->t = new T; + u->t->s = new S; + for (int i = 0; i < 10; i++) + u->t->s->x[i] = 0; +#pragma omp target map(u, *u, u->t, *(u->t), u->t->s, *u->t->s) + for (int i = 0; i < 10; i++) + u->t->s->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert (u->t->s->x[i] == i * 3); + delete u->t->s; + delete u->t; + delete u; +} + +void +bar (void) +{ + U *u = new U; + U **up = &u; + u->t = new T; + u->t->s = new S; + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = 0; +#pragma omp target map(*up, (*up)->t, *(*up)->t, (*up)->t->s, *(*up)->t->s) + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert ((*up)->t->s->x[i] == i * 3); + delete u->t->s; + delete u->t; + delete u; +} + +void +bar_pp (void) +{ + U *u = new U; + U **up = &u; + u->t = new T; + u->t->s = new S; + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = 0; +#pragma omp target map(*up, **up, (*up)->t, *(*up)->t, (*up)->t->s, *(*up)->t->s) + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert ((*up)->t->s->x[i] == i * 3); + delete u->t->s; + delete u->t; + delete u; +} + +void +bar_tofrom (void) +{ + U *u = new U; + U **up = &u; + u->t = new T; + u->t->s = new S; + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = 0; +#pragma omp target map(*up, up, (*up)->t, *(*up)->t, (*up)->t->s, *(*up)->t->s) + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert ((*up)->t->s->x[i] == i * 3); + delete u->t->s; + delete u->t; + delete u; +} + +void +bar_tofrom_pp (void) +{ + U *u = new U; + U **up = &u; + u->t = new T; + u->t->s = new S; + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = 0; +#pragma omp target map(**up, *up, up, (*up)->t, *(*up)->t, (*up)->t->s, \ + *(*up)->t->s) + for (int i = 0; i < 10; i++) + (*up)->t->s->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert ((*up)->t->s->x[i] == i * 3); + delete u->t->s; + delete u->t; + delete u; +} + +int main (int argc, char *argv[]) +{ + foo_siblist (); + foo (); + foo_tofrom (); + bar (); + bar_pp (); + bar_tofrom (); + bar_tofrom_pp (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/ind-base-2.C b/libgomp/testsuite/libgomp.c++/ind-base-2.C new file mode 100644 index 00000000000..706a1205c00 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/ind-base-2.C @@ -0,0 +1,49 @@ +// { dg-do run } +// { dg-options "-fopenmp" } + +#include + +struct S +{ + int x[10]; +}; + +struct T +{ + struct S ***s; +}; + +struct U +{ + struct T **t; +}; + +void +foo (void) +{ + U *u = new U; + T *real_t = new T; + S *real_s = new S; + T **t_pp = &real_t; + S **s_pp = &real_s; + S ***s_ppp = &s_pp; + u->t = t_pp; + (*u->t)->s = s_ppp; + for (int i = 0; i < 10; i++) + (**((*u->t)->s))->x[i] = 0; +#pragma omp target map(u->t, *u->t, (*u->t)->s, *(*u->t)->s, **(*u->t)->s, \ + (**(*u->t)->s)->x[0:10]) + for (int i = 0; i < 10; i++) + (**((*u->t)->s))->x[i] = i * 3; + for (int i = 0; i < 10; i++) + assert ((**((*u->t)->s))->x[i] == i * 3); + delete real_s; + delete real_t; + delete u; +} + +int main (int argc, char *argv[]) +{ + foo (); + return 0; +} diff --git a/libgomp/testsuite/libgomp.c++/struct-ref-1.C b/libgomp/testsuite/libgomp.c++/struct-ref-1.C new file mode 100644 index 00000000000..d3874650017 --- /dev/null +++ b/libgomp/testsuite/libgomp.c++/struct-ref-1.C @@ -0,0 +1,97 @@ +// { dg-do run } +// { dg-options "-fopenmp" } + +#include + +struct S +{ + int x[10]; +}; + +void +foo (S *s, int x) +{ + S *&r = s; + for (int i = 0; i < x; i++) + s[0].x[i] = s[1].x[i] = 0; + #pragma omp target map (s, x) + ; + #pragma omp target map (s[0], x) + for (int i = 0; i < x; i++) + s[0].x[i] = i; + #pragma omp target map (s[1], x) + for (int i = 0; i < x; i++) + s[1].x[i] = i * 2; + for (int i = 0; i < x; i++) + { + assert (s[0].x[i] == i); + assert (s[1].x[i] == i * 2); + s[0].x[i] = 0; + s[1].x[i] = 0; + } + #pragma omp target map (r, x) + ; + #pragma omp target map (r[0], x) + for (int i = 0; i < x; i++) + r[0].x[i] = i; + #pragma omp target map (r[1], x) + for (int i = 0; i < x; i++) + r[1].x[i] = i * 2; + for (int i = 0; i < x; i++) + { + assert (r[0].x[i] == i); + assert (r[1].x[i] == i * 2); + } +} + +template +struct T +{ + int x[N]; +}; + +template +void +bar (T *t, int x) +{ + T *&r = t; + for (int i = 0; i < x; i++) + t[0].x[i] = t[1].x[i] = 0; + #pragma omp target map (t, x) + ; + #pragma omp target map (t[0], x) + for (int i = 0; i < x; i++) + t[0].x[i] = i; + #pragma omp target map (t[1], x) + for (int i = 0; i < x; i++) + t[1].x[i] = i * 2; + for (int i = 0; i < x; i++) + { + assert (t[0].x[i] == i); + assert (t[1].x[i] == i * 2); + t[0].x[i] = 0; + t[1].x[i] = 0; + } + #pragma omp target map (r, x) + ; + #pragma omp target map (r[0], x) + for (int i = 0; i < x; i++) + r[0].x[i] = i; + #pragma omp target map (r[1], x) + for (int i = 0; i < x; i++) + r[1].x[i] = i * 2; + for (int i = 0; i < x; i++) + { + assert (r[0].x[i] == i); + assert (r[1].x[i] == i * 2); + } +} + +int main (int argc, char *argv[]) +{ + S s[2]; + foo (s, 10); + T<10> t[2]; + bar (t, 10); + return 0; +} From patchwork Mon Nov 15 11:18:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 47663 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 0A0D13857820 for ; Mon, 15 Nov 2021 11:21:04 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa3.mentor.iphmx.com (esa3.mentor.iphmx.com [68.232.137.180]) by sourceware.org (Postfix) with ESMTPS id DA33A3857C73 for ; Mon, 15 Nov 2021 11:18:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DA33A3857C73 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com IronPort-SDR: T0gQCZB7qF+75AsPh7olL/YQ/W1YJiocpttudQrxPfouPmi8buAYd1y+FCFWvTSlC9TjmLrw+s LP874e21ZvedzgdZdtpU/lcCzr8rXKLR2BFNqy6I3CAR5iKOqLPUl4h5kHM5KD5R8qsMLPT+4p soRYXpFH9hZTRAV2VGosDw9r/663ebt+L0mzmcNaAi0JtnL9WIuejAQE9h7Dss+J8JNQgciLRb 1MFPjwpmS4oSSPFyKmcVanPLFfZSvEGLfhoVgmbSZzH9jCftxOhcp/MQlOqhgzMDiRAP9t04uG PXk3Xw6qrwCSVDfgClR4bIi+ X-IronPort-AV: E=Sophos;i="5.87,236,1631606400"; d="scan'208";a="68329820" Received: from orw-gwy-02-in.mentorg.com ([192.94.38.167]) by esa3.mentor.iphmx.com with ESMTP; 15 Nov 2021 03:18:47 -0800 IronPort-SDR: F6n9gEW6kAlpRpTNjlV7s0YbCaHz3rOe1YAJnyIC8AIyvMvtJdj0Q8oLd/DzYgythMW1xbCAJl q93lGfynOBFDmyFF8q88flmIvRy94t+y7FT6zHyj7+SST9cJ9+dR/ruPLbw0cgvn5yNg0CVHzv 6QBRAJkOqjp4vtPibnLSqsNIFY8Udf862MzTrYzhCPwk6LuXZtN3MJy3xeiv7fhlaYYpS6sG6H 67fK9xG7dWroe1lWyls5VlXr2VIh/RaETPDVQGb6qg6n+vaRs8m6RDd8/0svcgxGkhnlcrmUIJ VNI= From: Julian Brown To: Subject: [PATCH 4/4] OpenMP: lvalue parsing for map clauses (C) Date: Mon, 15 Nov 2021 03:18:26 -0800 Message-ID: X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-10.mgc.mentorg.com (139.181.222.10) To SVR-IES-MBX-04.mgc.mentorg.com (139.181.222.4) X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, HEADER_FROM_DIFFERENT_DOMAINS, KAM_DMARC_STATUS, SPF_HELO_PASS, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This patch adds support for parsing general lvalues for OpenMP "map" clauses to the C front-end, similar to the previous patch for C++. OK? Thanks, Julian 2021-11-15 Julian Brown gcc/c/ * c-parser.c (c_parser_postfix_expression_after_primary): Add support for OpenMP array section parsing. (c_parser_omp_variable_list): Change ALLOW_DEREF parameter to MAP_LVALUE. Support parsing of general lvalues in "map" clauses. (c_parser_omp_var_list_parens): Change ALLOW_DEREF parameter to MAP_LVALUE. Update call to c_parser_omp_variable_list. (c_parser_oacc_data_clause, c_parser_omp_clause_to, c_parser_omp_clause_from): Update calls to c_parser_omp_var_list_parens. * c-tree.h (c_omp_array_section_p): Add extern declaration. * c-typeck.c (c_omp_array_section_p): Add flag. (mark_exp_read): Support OMP_ARRAY_SECTION. (handle_omp_array_sections): Handle non-DECL_P attachment points. (c_finish_omp_clauses): Check for supported expression types. gcc/testsuite/ * c-c++-common/gomp/map-1.c: Adjust expected output. * c-c++-common/gomp/map-6.c: Likewise. --- gcc/c/c-parser.c | 150 ++++++++++++++++++++---- gcc/c/c-tree.h | 1 + gcc/c/c-typeck.c | 38 ++++++ gcc/testsuite/c-c++-common/gomp/map-1.c | 3 +- gcc/testsuite/c-c++-common/gomp/map-6.c | 2 + 5 files changed, 171 insertions(+), 23 deletions(-) diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index f7cd49cc58a..58e9fe5079b 100644 --- a/gcc/c/c-parser.c +++ b/gcc/c/c-parser.c @@ -10460,7 +10460,7 @@ c_parser_postfix_expression_after_primary (c_parser *parser, struct c_expr expr) { struct c_expr orig_expr; - tree ident, idx; + tree ident, idx, len; location_t sizeof_arg_loc[3], comp_loc; tree sizeof_arg[3]; unsigned int literal_zero_mask; @@ -10479,15 +10479,44 @@ c_parser_postfix_expression_after_primary (c_parser *parser, case CPP_OPEN_SQUARE: /* Array reference. */ c_parser_consume_token (parser); - idx = c_parser_expression (parser).value; - c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, - "expected %<]%>"); - start = expr.get_start (); - finish = parser->tokens_buf[0].location; - expr.value = build_array_ref (op_loc, expr.value, idx); - set_c_expr_source_range (&expr, start, finish); - expr.original_code = ERROR_MARK; - expr.original_type = NULL; + idx = len = NULL_TREE; + if (!c_omp_array_section_p + || c_parser_next_token_is_not (parser, CPP_COLON)) + idx = c_parser_expression (parser).value; + + if (c_omp_array_section_p + && c_parser_next_token_is (parser, CPP_COLON)) + { + c_parser_consume_token (parser); + if (c_parser_next_token_is_not (parser, CPP_CLOSE_SQUARE)) + len = c_parser_expression (parser).value; + + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + + /* NOTE: We are reusing using the type of the whole array as the + type of the array section here, which isn't necessarily + entirely correct. Might need revisiting. */ + start = expr.get_start (); + finish = parser->tokens_buf[0].location; + expr.value = build3_loc (op_loc, OMP_ARRAY_SECTION, + TREE_TYPE (expr.value), expr.value, + idx, len); + set_c_expr_source_range (&expr, start, finish); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + } + else + { + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, + "expected %<]%>"); + start = expr.get_start (); + finish = parser->tokens_buf[0].location; + expr.value = build_array_ref (op_loc, expr.value, idx); + set_c_expr_source_range (&expr, start, finish); + expr.original_code = ERROR_MARK; + expr.original_type = NULL; + } break; case CPP_OPEN_PAREN: /* Function call. */ @@ -12983,7 +13012,7 @@ static tree c_parser_omp_variable_list (c_parser *parser, location_t clause_loc, enum omp_clause_code kind, tree list, - bool allow_deref = false) + bool map_lvalue = false) { auto_vec tokens; unsigned int tokens_avail = 0; @@ -12993,6 +13022,8 @@ c_parser_omp_variable_list (c_parser *parser, { auto_vec dims; bool array_section_p = false; + tree t = NULL_TREE; + if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY) { if (c_parser_next_token_is_not (parser, CPP_NAME) @@ -13061,8 +13092,84 @@ c_parser_omp_variable_list (c_parser *parser, parser->tokens = tokens.address (); parser->tokens_avail = tokens.length (); } + else if (map_lvalue && kind == OMP_CLAUSE_MAP) + { + location_t loc = c_parser_peek_token (parser)->location; + bool save_c_omp_array_section_p = c_omp_array_section_p; + c_omp_array_section_p = true; + c_expr expr = c_parser_expr_no_commas (parser, NULL); + if (expr.value != error_mark_node) + mark_exp_read (expr.value); + c_omp_array_section_p = save_c_omp_array_section_p; + tree decl = expr.value; - tree t = NULL_TREE; + dims.truncate (0); + if (TREE_CODE (decl) == OMP_ARRAY_SECTION) + { + while (TREE_CODE (decl) == OMP_ARRAY_SECTION) + { + tree low_bound = TREE_OPERAND (decl, 1); + tree length = TREE_OPERAND (decl, 2); + dims.safe_push (omp_dim (low_bound, length, loc, false)); + decl = TREE_OPERAND (decl, 0); + } + + while (TREE_CODE (decl) == ARRAY_REF + || TREE_CODE (decl) == INDIRECT_REF + || TREE_CODE (decl) == COMPOUND_EXPR) + { + if (TREE_CODE (decl) == COMPOUND_EXPR) + { + decl = TREE_OPERAND (decl, 1); + STRIP_NOPS (decl); + } + else if (TREE_CODE (decl) == INDIRECT_REF) + { + dims.safe_push (omp_dim (integer_zero_node, + integer_one_node, loc, true)); + decl = TREE_OPERAND (decl, 0); + } + else /* ARRAY_REF. */ + { + tree index = TREE_OPERAND (decl, 1); + dims.safe_push (omp_dim (index, integer_one_node, loc, + true)); + decl = TREE_OPERAND (decl, 0); + } + } + + for (int i = dims.length () - 1; i >= 0; i--) + decl = tree_cons (dims[i].low_bound, dims[i].length, decl); + } + else if (TREE_CODE (decl) == INDIRECT_REF) + { + /* Turn *foo into the representation previously used for + foo[0]. */ + decl = TREE_OPERAND (decl, 0); + STRIP_NOPS (decl); + + decl = tree_cons (integer_zero_node, integer_one_node, decl); + } + else if (TREE_CODE (decl) == ARRAY_REF) + { + tree idx = TREE_OPERAND (decl, 1); + + decl = TREE_OPERAND (decl, 0); + STRIP_NOPS (decl); + + decl = tree_cons (idx, integer_one_node, decl); + } + else if (TREE_CODE (decl) == NON_LVALUE_EXPR + || CONVERT_EXPR_P (decl)) + decl = TREE_OPERAND (decl, 0); + + tree u = build_omp_clause (clause_loc, kind); + OMP_CLAUSE_DECL (u) = decl; + OMP_CLAUSE_CHAIN (u) = list; + list = u; + + goto next_item; + } if (c_parser_next_token_is (parser, CPP_NAME) && c_parser_peek_token (parser)->id_kind == C_ID_ID) @@ -13113,8 +13220,7 @@ c_parser_omp_variable_list (c_parser *parser, case OMP_CLAUSE_TO: start_component_ref: while (c_parser_next_token_is (parser, CPP_DOT) - || (allow_deref - && c_parser_next_token_is (parser, CPP_DEREF))) + || c_parser_next_token_is (parser, CPP_DEREF)) { location_t op_loc = c_parser_peek_token (parser)->location; if (c_parser_next_token_is (parser, CPP_DEREF)) @@ -13201,9 +13307,7 @@ c_parser_omp_variable_list (c_parser *parser, || kind == OMP_CLAUSE_TO) && !array_section_p && (c_parser_next_token_is (parser, CPP_DOT) - || (allow_deref - && c_parser_next_token_is (parser, - CPP_DEREF)))) + || c_parser_next_token_is (parser, CPP_DEREF))) { for (unsigned i = 0; i < dims.length (); i++) { @@ -13265,6 +13369,8 @@ c_parser_omp_variable_list (c_parser *parser, parser->tokens = &parser->tokens_buf[0]; parser->tokens_avail = tokens_avail; } + + next_item: if (c_parser_next_token_is_not (parser, CPP_COMMA)) break; @@ -13281,7 +13387,7 @@ c_parser_omp_variable_list (c_parser *parser, static tree c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, - tree list, bool allow_deref = false) + tree list, bool map_lvalue = false) { /* The clauses location. */ location_t loc = c_parser_peek_token (parser)->location; @@ -13289,7 +13395,7 @@ c_parser_omp_var_list_parens (c_parser *parser, enum omp_clause_code kind, matching_parens parens; if (parens.require_open (parser)) { - list = c_parser_omp_variable_list (parser, loc, kind, list, allow_deref); + list = c_parser_omp_variable_list (parser, loc, kind, list, map_lvalue); parens.skip_until_found_close (parser); } return list; @@ -13358,7 +13464,7 @@ c_parser_oacc_data_clause (c_parser *parser, pragma_omp_clause c_kind, gcc_unreachable (); } tree nl, c; - nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list, true); + nl = c_parser_omp_var_list_parens (parser, OMP_CLAUSE_MAP, list); for (c = nl; c != list; c = OMP_CLAUSE_CHAIN (c)) OMP_CLAUSE_SET_MAP_KIND (c, kind); @@ -16429,7 +16535,7 @@ c_parser_omp_clause_device_type (c_parser *parser, tree list) static tree c_parser_omp_clause_to (c_parser *parser, tree list) { - return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list, true); + return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_TO, list); } /* OpenMP 4.0: @@ -16438,7 +16544,7 @@ c_parser_omp_clause_to (c_parser *parser, tree list) static tree c_parser_omp_clause_from (c_parser *parser, tree list) { - return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list, true); + return c_parser_omp_var_list_parens (parser, OMP_CLAUSE_FROM, list); } /* OpenMP 4.0: diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h index a046c6b0926..f71cf34505b 100644 --- a/gcc/c/c-tree.h +++ b/gcc/c/c-tree.h @@ -671,6 +671,7 @@ extern int in_alignof; extern int in_sizeof; extern int in_typeof; extern bool c_in_omp_for; +extern bool c_omp_array_section_p; extern tree c_last_sizeof_arg; extern location_t c_last_sizeof_loc; diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 0dbb78d6e7e..5822800109d 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -74,6 +74,9 @@ int in_typeof; /* True when parsing OpenMP loop expressions. */ bool c_in_omp_for; +/* True when parsing OpenMP map clause. */ +bool c_omp_array_section_p; + /* The argument of last parsed sizeof expression, only to be tested if expr.original_code == SIZEOF_EXPR. */ tree c_last_sizeof_arg; @@ -2019,6 +2022,13 @@ mark_exp_read (tree exp) case C_MAYBE_CONST_EXPR: mark_exp_read (TREE_OPERAND (exp, 1)); break; + case OMP_ARRAY_SECTION: + mark_exp_read (TREE_OPERAND (exp, 0)); + if (TREE_OPERAND (exp, 1)) + mark_exp_read (TREE_OPERAND (exp, 1)); + if (TREE_OPERAND (exp, 2)) + mark_exp_read (TREE_OPERAND (exp, 2)); + break; default: break; } @@ -13775,6 +13785,13 @@ handle_omp_array_sections (tree c, enum c_omp_region_type ort) tree c2 = build_omp_clause (OMP_CLAUSE_LOCATION (c), OMP_CLAUSE_MAP); if (TREE_CODE (t) == COMPONENT_REF) OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH); + else if (ort != C_ORT_ACC && attach_pt && !DECL_P (attach_pt)) + { + if (TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE) + return false; + + OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_ATTACH_DETACH); + } else OMP_CLAUSE_SET_MAP_KIND (c2, GOMP_MAP_FIRSTPRIVATE_POINTER); OMP_CLAUSE_MAP_IMPLICIT (c2) = OMP_CLAUSE_MAP_IMPLICIT (c); @@ -14869,6 +14886,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) { t = t_insp.analyze_components (false); + if (!t_insp.map_supported_p ()) + { + sorry_at (OMP_CLAUSE_LOCATION (c), + "unsupported map expression %qE", + OMP_CLAUSE_DECL (c)); + remove = true; + break; + } + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && OMP_CLAUSE_MAP_IMPLICIT (c) && (bitmap_bit_p (&map_head, DECL_UID (t)) @@ -14920,6 +14946,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) } if (t == error_mark_node) { + error_at (OMP_CLAUSE_LOCATION (c), + "unmappable expression in %qs clause", + omp_clause_code_name[OMP_CLAUSE_CODE (c)]); remove = true; break; } @@ -14947,6 +14976,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort) else t = t_insp.get_outer_virtual_base (); + if (!t_insp.map_supported_p ()) + { + sorry_at (OMP_CLAUSE_LOCATION (c), + "unsupported map expression %qE", + OMP_CLAUSE_DECL (c)); + remove = true; + break; + } + if (t == error_mark_node) { remove = true; diff --git a/gcc/testsuite/c-c++-common/gomp/map-1.c b/gcc/testsuite/c-c++-common/gomp/map-1.c index ed88944da7b..57baa4fd285 100644 --- a/gcc/testsuite/c-c++-common/gomp/map-1.c +++ b/gcc/testsuite/c-c++-common/gomp/map-1.c @@ -39,7 +39,8 @@ foo (int g[3][10], int h[4][8], int i[2][10], int j[][9], ; #pragma omp target map(alloc: s1) /* { dg-error "'s1' does not have a mappable type in 'map' clause" } */ ; - #pragma omp target map(alloc: s2) /* { dg-error "'s2' does not have a mappable type in 'map' clause" } */ + #pragma omp target map(alloc: s2) /* { dg-error "'s2' does not have a mappable type in 'map' clause" "" { target c++ } } */ + /* { dg-error "unmappable expression in 'map' clause" "" { target c } .-1 } */ ; #pragma omp target map(to: a[:][:]) /* { dg-error "array type length expression must be specified" } */ bar (&a[0][0]); /* { dg-error "referenced in target region does not have a mappable type" } */ diff --git a/gcc/testsuite/c-c++-common/gomp/map-6.c b/gcc/testsuite/c-c++-common/gomp/map-6.c index c749db845b0..19db264e805 100644 --- a/gcc/testsuite/c-c++-common/gomp/map-6.c +++ b/gcc/testsuite/c-c++-common/gomp/map-6.c @@ -22,11 +22,13 @@ foo (void) #pragma omp target map (close a) /* { dg-error "'close' undeclared" "" { target c } } */ /* { dg-error "'close' was not declared in this scope" "" { target c++ } .-1 } */ /* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */ + /* { dg-error "unmappable expression in 'map' clause" "" { target c } .-3 } */ ; #pragma omp target map (always a) /* { dg-error "'always' undeclared" "" { target c } } */ /* { dg-error "'always' was not declared in this scope" "" { target c++ } .-1 } */ /* { dg-error "expected '\\)' before 'a'" "" { target *-*-* } .-2 } */ + /* { dg-error "unmappable expression in 'map' clause" "" { target c } .-3 } */ ; #pragma omp target map (close to:a)