From: Julian Brown <julian@codesourcery.com>
To: <gcc-patches@gcc.gnu.org>
Cc: Jakub Jelinek <jakub@redhat.com>,
Thomas Schwinge <thomas@codesourcery.com>,
Tobias Burnus <tobias@codesourcery.com>,
Fortran List <fortran@gcc.gnu.org>
Subject: [PATCH v2 07/11] OpenMP: lvalue parsing for map clauses (C)
Date: Fri, 18 Mar 2022 09:26:48 -0700 [thread overview]
Message-ID: <32bdcb99b5c6d3798b5d24e2c60d6ff423ebf30a.1647619144.git.julian@codesourcery.com> (raw)
In-Reply-To: <cover.1647619144.git.julian@codesourcery.com>
This patch adds support for parsing general lvalues for OpenMP "map"
clauses to the C front-end, similar to the previous patch for C++.
This version of the patch has been adjusted for changes to the address
inspector patch, but is otherwise the same as the last posted version.
2022-03-17 Julian Brown <julian@codesourcery.com>
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_1): Handle more kinds of expressions.
(c_finish_omp_clauses): Check for supported expression types. Support
non-DECL_P root term for map clauses.
gcc/testsuite/
* c-c++-common/gomp/map-1.c: Adjust expected output.
* c-c++-common/gomp/map-6.c: Likewise.
libgomp/
* testsuite/libgomp.c-c++-common/ind-base-4.c: New test.
* testsuite/libgomp.c-c++-common/unary-ptr-1.c: New test.
---
gcc/c/c-parser.cc | 150 +++++++++++++++---
gcc/c/c-tree.h | 1 +
gcc/c/c-typeck.cc | 38 ++++-
gcc/testsuite/c-c++-common/gomp/map-1.c | 3 +-
gcc/testsuite/c-c++-common/gomp/map-6.c | 2 +
.../libgomp.c-c++-common/ind-base-4.c | 50 ++++++
.../libgomp.c-c++-common/unary-ptr-1.c | 16 ++
7 files changed, 236 insertions(+), 24 deletions(-)
create mode 100644 libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c
create mode 100644 libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index e9086c58524..cc590e56e75 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -10486,7 +10486,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;
@@ -10505,15 +10505,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. */
@@ -13009,7 +13038,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<omp_dim> dims;
bool array_section_p;
@@ -13019,6 +13048,8 @@ c_parser_omp_variable_list (c_parser *parser,
while (1)
{
+ tree t = NULL_TREE;
+
if (kind == OMP_CLAUSE_DEPEND || kind == OMP_CLAUSE_AFFINITY)
{
if (c_parser_next_token_is_not (parser, CPP_NAME)
@@ -13087,8 +13118,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)
@@ -13139,8 +13246,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))
@@ -13227,9 +13333,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++)
{
@@ -13289,6 +13393,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;
@@ -13305,7 +13411,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;
@@ -13313,7 +13419,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;
@@ -13382,7 +13488,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);
@@ -16490,7 +16596,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:
@@ -16499,7 +16605,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 c70f0ba5ab6..962b9b23ed6 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -673,6 +673,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.cc b/gcc/c/c-typeck.cc
index 20dd938bdf1..162ed0a18a2 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -75,6 +75,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;
@@ -2020,6 +2023,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;
}
@@ -13233,7 +13243,9 @@ handle_omp_array_sections_1 (tree c, tree t, vec<tree> &types,
t = t_insp.get_deref_origin ();
if (t == error_mark_node)
return error_mark_node;
- if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
+ if (!VAR_P (t)
+ && (ort == C_ORT_ACC || !EXPR_P (t))
+ && TREE_CODE (t) != PARM_DECL)
{
if (DECL_P (t))
error_at (OMP_CLAUSE_LOCATION (c),
@@ -14901,6 +14913,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (!DECL_P (rt))
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 (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
&& OMP_CLAUSE_MAP_IMPLICIT (c)
&& (bitmap_bit_p (&map_head, DECL_UID (rt))
@@ -14951,6 +14972,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;
}
@@ -14979,6 +15003,15 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
else
t = t_insp.get_deref_origin ();
+ 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;
@@ -14999,6 +15032,9 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
if (!VAR_P (t) && TREE_CODE (t) != PARM_DECL)
{
+ if (ort != C_ORT_ACC && EXPR_P (t))
+ break;
+
error_at (OMP_CLAUSE_LOCATION (c),
"%qE is not a variable in %qs clause", t,
omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
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)
diff --git a/libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c b/libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c
new file mode 100644
index 00000000000..91549ac4d24
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/ind-base-4.c
@@ -0,0 +1,50 @@
+// { dg-do run }
+// { dg-options "-fopenmp" }
+
+#include <assert.h>
+#include <stdlib.h>
+
+typedef struct
+{
+ int x[10];
+} S;
+
+typedef struct
+{
+ S ***s;
+} T;
+
+typedef struct
+{
+ T **t;
+} U;
+
+void
+foo (void)
+{
+ U *u = (U *) malloc (sizeof (U));
+ T *real_t = (T *) malloc (sizeof (T));
+ S *real_s = (S *) malloc (sizeof (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);
+ free (real_s);
+ free (real_t);
+ free (u);
+}
+
+int main (int argc, char *argv[])
+{
+ foo ();
+ return 0;
+}
diff --git a/libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c b/libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c
new file mode 100644
index 00000000000..3623b269576
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c-c++-common/unary-ptr-1.c
@@ -0,0 +1,16 @@
+#include <assert.h>
+
+int main (int argc, char *argv[])
+{
+ int y = 0;
+ int *x = &y;
+
+#pragma omp target map(*x)
+ {
+ (*x)++;
+ }
+
+ assert (y == 1);
+
+ return 0;
+}
--
2.29.2
next prev parent reply other threads:[~2022-03-18 16:27 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-03-18 16:24 [PATCH v2 00/11] OpenMP 5.0: C & C++ "declare mapper" support (plus struct rework, etc.) Julian Brown
2022-03-18 16:24 ` [PATCH v2 01/11] OpenMP 5.0: Clause ordering for OpenMP 5.0 (topological sorting by base pointer) Julian Brown
2022-05-24 13:03 ` Jakub Jelinek
2022-06-08 15:00 ` Julian Brown
2022-06-09 14:45 ` Jakub Jelinek
2022-03-18 16:24 ` [PATCH v2 02/11] Remove omp_target_reorder_clauses Julian Brown
2022-05-24 13:05 ` Jakub Jelinek
2022-03-18 16:24 ` [PATCH v2 03/11] OpenMP/OpenACC struct sibling list gimplification extension and rework Julian Brown
2022-05-24 13:17 ` Jakub Jelinek
2022-03-18 16:24 ` [PATCH v2 04/11] OpenMP/OpenACC: Add inspector class to unify mapped address analysis Julian Brown
2022-05-24 13:32 ` Jakub Jelinek
2022-03-18 16:26 ` [PATCH v2 05/11] OpenMP: Handle reference-typed struct members Julian Brown
2022-05-24 13:39 ` Jakub Jelinek
2022-03-18 16:26 ` [PATCH v2 06/11] OpenMP: lvalue parsing for map clauses (C++) Julian Brown
2022-05-24 14:15 ` Jakub Jelinek
2022-11-01 21:50 ` Julian Brown
2022-11-01 21:54 ` [PATCH 2/2] OpenMP: Use OMP_ARRAY_SECTION instead of TREE_LIST in C++ FE Julian Brown
2022-11-02 11:58 ` [PATCH v2 06/11] OpenMP: lvalue parsing for map clauses (C++) Jakub Jelinek
2022-11-02 12:20 ` Julian Brown
2022-11-02 12:35 ` Jakub Jelinek
2022-11-08 14:36 ` Julian Brown
2022-11-25 13:22 ` Jakub Jelinek
2022-03-18 16:26 ` Julian Brown [this message]
2022-03-18 16:26 ` [PATCH v2 08/11] Use OMP_ARRAY_SECTION instead of TREE_LIST in C++ FE Julian Brown
2022-05-24 14:19 ` Jakub Jelinek
2022-03-18 16:26 ` [PATCH v2 09/11] OpenMP 5.0 "declare mapper" support for C++ Julian Brown
2022-05-24 14:48 ` Jakub Jelinek
2022-05-25 13:37 ` Jakub Jelinek
2022-03-18 16:28 ` [PATCH v2 10/11] OpenMP: Use OMP_ARRAY_SECTION instead of TREE_LIST for array sections in C FE Julian Brown
2022-03-18 16:28 ` [PATCH v2 11/11] OpenMP: Support OpenMP 5.0 "declare mapper" directives for C Julian Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=32bdcb99b5c6d3798b5d24e2c60d6ff423ebf30a.1647619144.git.julian@codesourcery.com \
--to=julian@codesourcery.com \
--cc=fortran@gcc.gnu.org \
--cc=gcc-patches@gcc.gnu.org \
--cc=jakub@redhat.com \
--cc=thomas@codesourcery.com \
--cc=tobias@codesourcery.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).