From patchwork Thu Nov 25 14:10:13 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Julian Brown X-Patchwork-Id: 48152 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 D33A03858017 for ; Thu, 25 Nov 2021 14:17:32 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from esa2.mentor.iphmx.com (esa2.mentor.iphmx.com [68.232.141.98]) by sourceware.org (Postfix) with ESMTPS id 46A4C385803B for ; Thu, 25 Nov 2021 14:10:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 46A4C385803B 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: gQb0DTOAFNerhOvgMxNYG+M7GSTrgVNJdphYcZGDvVV1nS+afSE7PVNHkO3MQRGWwnOadSdkHt ZFckgDMN5OFNvpb8FaAsj7qEyTsjIZC9dCb7Pe5zWxZeNzOBcSPUD1Vy9tnZPi1DCL8EDD1HjY pUXQdIZj44oSd5PXfR3QV2PWiL3c3sqKyCKWWC4SFIsQMlb9MGOSBtHveVha2vqd5eFFCceDyQ ot4u8hDNo/iuZnd49a20Sg86DR3nnmxu8jaGmx+jmWmitz5I1EsDxlJrE2kAerKrE9sId68qmB zB/GarpDa6e1YgxcS/CWTyCF X-IronPort-AV: E=Sophos;i="5.87,263,1631606400"; d="scan'208";a="68920873" Received: from orw-gwy-02-in.mentorg.com ([192.94.38.167]) by esa2.mentor.iphmx.com with ESMTP; 25 Nov 2021 06:10:32 -0800 IronPort-SDR: FB+ZCkXF4KyO6BJCZu1ncOJGfbZIQWke/RK49Uw7Y6FAayqb12x/hnkHJ353NtTqdeURRvpSht eMxMXD9klBntSnEJi7VrVVDJp5SZ2a9STsfOgQ8p0tPzkVUWpAuUkDzs8EuQ7nJhmBeZB3RBXv cl89Ka9RCJbgaBQcjTftUzu1XFN3S+4F7aw0YtrnedB2mIl+3TYh6cHZs/xgeLsaI+ym4BfZA6 F80L7MBowaI54uk9+Fgzt0omN5wU0wdDZNIBvMRxgHkqpTn8o369YlcOSfDICe8hVnMBdLUjJD rnw= From: Julian Brown To: Subject: [PATCH 14/16] OpenMP: Add inspector class to unify mapped address analysis Date: Thu, 25 Nov 2021 06:10:13 -0800 Message-ID: <20211125141013.113782-5-julian@codesourcery.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20211125141013.113782-1-julian@codesourcery.com> References: <20211125141013.113782-1-julian@codesourcery.com> MIME-Version: 1.0 X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-15.mgc.mentorg.com (139.181.222.15) 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 , Thomas Schwinge 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. (The adjacent "c_omp_decompose_attachable_address" function could also be moved into the address inspector class, perhaps. That's not been done yet.) 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 | 252 ++++++------------ .../g++.dg/gomp/unmappable-component-1.C | 21 ++ 5 files changed, 338 insertions(+), 324 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 dd103d8eecd..05d479e4d2f 100644 --- a/gcc/c-family/c-common.h +++ b/gcc/c-family/c-common.h @@ -1253,6 +1253,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 a90696fe706..5b2fbf6809b 100644 --- a/gcc/c-family/c-omp.c +++ b/gcc/c-family/c-omp.c @@ -3113,6 +3113,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 cfac7d0a2b5..3a9f129181b 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -13208,6 +13208,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 @@ -13217,59 +13219,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)) @@ -14917,23 +14875,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) @@ -15001,96 +14952,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 6d30a9ed97d..a95eb1adcb5 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4996,6 +4996,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 @@ -5026,59 +5059,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) @@ -7907,27 +7899,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) @@ -7995,106 +7975,38 @@ 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; - } - } - if (!processing_template_decl - && TREE_CODE (t) == FIELD_DECL) + } + 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, 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; +}