aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2022-05-12 08:31:20 +0200
committerJakub Jelinek <jakub@redhat.com>2022-05-12 08:31:20 +0200
commit7f78783dbedca0183d193e475262ca3c489fd365 (patch)
tree894cab7fc78808ee0b5e59ac3f2bb8a3eee01e90 /gcc
parent8585185cc4de3a9268af6afc42a0e86b7ba72b12 (diff)
downloadgcc-7f78783dbedca0183d193e475262ca3c489fd365.zip
gcc-7f78783dbedca0183d193e475262ca3c489fd365.tar.gz
gcc-7f78783dbedca0183d193e475262ca3c489fd365.tar.bz2
openmp: Add omp_all_memory support (C/C++ only so far)
The ugly part is that OpenMP 5.1 made omp_all_memory a reserved identifier which isn't allowed to be used anywhere but in the depend clause, this is against how everything else has been handled in OpenMP so far (where some identifiers could have special meaning in some OpenMP clauses or pragmas but not elsewhere). The patch handles it by making it a conditional keyword (for -fopenmp only) and emitting a better diagnostics when it is used in a primary expression. Having a nicer diagnostics when e.g. trying to do int omp_all_memory; or int *omp_all_memory[10]; etc. would mean changing too many spots and hooking into name lookups to reject declaring any such symbols would be too ugly and I'm afraid there are way too many spots where one can introduce a name (variables, functions, namespaces, struct, enum, enumerators, template arguments, ...). Otherwise, the handling is quite simple, normal depend clauses lower into addresses of variables being handed over to the library, for omp_all_memory I'm using NULL pointers. omp_all_memory can only be used with inout or out depend kinds and means that a task is dependent on all previously created sibling tasks that have any dependency (of any depend kind) and that any later created sibling tasks will be dependent on it if they have any dependency. 2022-05-12 Jakub Jelinek <jakub@redhat.com> gcc/ * gimplify.cc (gimplify_omp_depend): Don't build_fold_addr_expr if null_pointer_node. (gimplify_scan_omp_clauses): Likewise. * tree-pretty-print.cc (dump_omp_clause): Print null_pointer_node as omp_all_memory. gcc/c-family/ * c-common.h (enum rid): Add RID_OMP_ALL_MEMORY. * c-omp.cc (c_finish_omp_depobj): Don't build_fold_addr_expr if null_pointer_node. gcc/c/ * c-parser.cc (c_parse_init): Register omp_all_memory as keyword if flag_openmp. (c_parser_postfix_expression): Diagnose uses of omp_all_memory in postfix expressions. (c_parser_omp_variable_list): Handle omp_all_memory in depend clause. * c-typeck.cc (c_finish_omp_clauses): Handle omp_all_memory keyword in depend clause as null_pointer_node, diagnose invalid uses. gcc/cp/ * lex.cc (init_reswords): Register omp_all_memory as keyword if flag_openmp. * parser.cc (cp_parser_primary_expression): Diagnose uses of omp_all_memory in postfix expressions. (cp_parser_omp_var_list_no_open): Handle omp_all_memory in depend clause. * semantics.cc (finish_omp_clauses): Handle omp_all_memory keyword in depend clause as null_pointer_node, diagnose invalid uses. * pt.cc (tsubst_omp_clause_decl): Pass through omp_all_memory. gcc/testsuite/ * c-c++-common/gomp/all-memory-1.c: New test. * c-c++-common/gomp/all-memory-2.c: New test. * c-c++-common/gomp/all-memory-3.c: New test. * g++.dg/gomp/all-memory-1.C: New test. * g++.dg/gomp/all-memory-2.C: New test. libgomp/ * libgomp.h (struct gomp_task): Add depend_all_memory member. * task.c (gomp_init_task): Initialize depend_all_memory. (gomp_task_handle_depend): Handle omp_all_memory. (gomp_task_run_post_handle_depend_hash): Clear parent->depend_all_memory if equal to current task. (gomp_task_maybe_wait_for_dependencies): Handle omp_all_memory. * testsuite/libgomp.c-c++-common/depend-1.c: New test. * testsuite/libgomp.c-c++-common/depend-2.c: New test. * testsuite/libgomp.c-c++-common/depend-3.c: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/c-common.h3
-rw-r--r--gcc/c-family/c-omp.cc2
-rw-r--r--gcc/c/c-parser.cc29
-rw-r--r--gcc/c/c-typeck.cc44
-rw-r--r--gcc/cp/lex.cc8
-rw-r--r--gcc/cp/parser.cc17
-rw-r--r--gcc/cp/pt.cc4
-rw-r--r--gcc/cp/semantics.cc44
-rw-r--r--gcc/gimplify.cc19
-rw-r--r--gcc/testsuite/c-c++-common/gomp/all-memory-1.c52
-rw-r--r--gcc/testsuite/c-c++-common/gomp/all-memory-2.c55
-rw-r--r--gcc/testsuite/c-c++-common/gomp/all-memory-3.c22
-rw-r--r--gcc/testsuite/g++.dg/gomp/all-memory-1.C24
-rw-r--r--gcc/testsuite/g++.dg/gomp/all-memory-2.C26
-rw-r--r--gcc/tree-pretty-print.cc5
15 files changed, 319 insertions, 35 deletions
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index aa043de..47442c9 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -219,6 +219,9 @@ enum rid
RID_AT_INTERFACE,
RID_AT_IMPLEMENTATION,
+ /* OpenMP */
+ RID_OMP_ALL_MEMORY,
+
/* Named address support, mapping the keyword to a particular named address
number. Named address space 0 is reserved for the generic address. If
there are more than 254 named addresses, the addr_space_t type will need
diff --git a/gcc/c-family/c-omp.cc b/gcc/c-family/c-omp.cc
index 777cdc6..987ba7d 100644
--- a/gcc/c-family/c-omp.cc
+++ b/gcc/c-family/c-omp.cc
@@ -757,7 +757,7 @@ c_finish_omp_depobj (location_t loc, tree depobj,
t = build2 (COMPOUND_EXPR, TREE_TYPE (t1), TREE_OPERAND (t, 0),
t1);
}
- else
+ else if (t != null_pointer_node)
t = build_fold_addr_expr (t);
break;
default:
diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc
index d431d5f..51a0725 100644
--- a/gcc/c/c-parser.cc
+++ b/gcc/c/c-parser.cc
@@ -165,6 +165,14 @@ c_parse_init (void)
C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
C_IS_RESERVED_WORD (id) = 1;
}
+
+ if (flag_openmp)
+ {
+ id = get_identifier ("omp_all_memory");
+ C_SET_RID_CODE (id, RID_OMP_ALL_MEMORY);
+ C_IS_RESERVED_WORD (id) = 1;
+ ridpointers [RID_OMP_ALL_MEMORY] = id;
+ }
}
/* A parser structure recording information about the state and
@@ -10202,6 +10210,13 @@ c_parser_postfix_expression (c_parser *parser)
case RID_GENERIC:
expr = c_parser_generic_selection (parser);
break;
+ case RID_OMP_ALL_MEMORY:
+ gcc_assert (flag_openmp);
+ c_parser_consume_token (parser);
+ error_at (loc, "%<omp_all_memory%> may only be used in OpenMP "
+ "%<depend%> clause");
+ expr.set_error ();
+ break;
default:
c_parser_error (parser, "expected expression");
expr.set_error ();
@@ -13025,7 +13040,19 @@ c_parser_omp_variable_list (c_parser *parser,
if (c_parser_next_token_is_not (parser, CPP_NAME)
|| c_parser_peek_token (parser)->id_kind != C_ID_ID)
{
- struct c_expr expr = c_parser_expr_no_commas (parser, NULL);
+ struct c_expr expr;
+ if (kind == OMP_CLAUSE_DEPEND
+ && c_parser_next_token_is_keyword (parser,
+ RID_OMP_ALL_MEMORY)
+ && (c_parser_peek_2nd_token (parser)->type == CPP_COMMA
+ || (c_parser_peek_2nd_token (parser)->type
+ == CPP_CLOSE_PAREN)))
+ {
+ expr.value = ridpointers[RID_OMP_ALL_MEMORY];
+ c_parser_consume_token (parser);
+ }
+ else
+ expr = c_parser_expr_no_commas (parser, NULL);
if (expr.value != error_mark_node)
{
tree u = build_omp_clause (clause_loc, kind);
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index e130196..bcfe08b 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -14832,6 +14832,18 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
if (t == error_mark_node)
remove = true;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && t == ridpointers[RID_OMP_ALL_MEMORY])
+ {
+ if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_OUT
+ && OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_INOUT)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<omp_all_memory%> used with %<depend%> kind "
+ "other than %<out%> or %<inout%>");
+ remove = true;
+ }
+ }
else if (!lvalue_p (t))
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -14873,24 +14885,32 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
if (!remove)
{
- tree addr = build_unary_op (OMP_CLAUSE_LOCATION (c), ADDR_EXPR,
- t, false);
- if (addr == error_mark_node)
- remove = true;
+ if (t == ridpointers[RID_OMP_ALL_MEMORY])
+ t = null_pointer_node;
else
{
+ tree addr = build_unary_op (OMP_CLAUSE_LOCATION (c),
+ ADDR_EXPR, t, false);
+ if (addr == error_mark_node)
+ {
+ remove = true;
+ break;
+ }
t = build_indirect_ref (OMP_CLAUSE_LOCATION (c), addr,
RO_UNARY_STAR);
if (t == error_mark_node)
- remove = true;
- else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
- && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
- && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
- == TREE_VEC))
- TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
- else
- OMP_CLAUSE_DECL (c) = t;
+ {
+ remove = true;
+ break;
+ }
}
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+ && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+ && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+ == TREE_VEC))
+ TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+ else
+ OMP_CLAUSE_DECL (c) = t;
}
break;
diff --git a/gcc/cp/lex.cc b/gcc/cp/lex.cc
index 784debc..0b121a9 100644
--- a/gcc/cp/lex.cc
+++ b/gcc/cp/lex.cc
@@ -273,6 +273,14 @@ init_reswords (void)
C_SET_RID_CODE (id, RID_FIRST_INT_N + i);
set_identifier_kind (id, cik_keyword);
}
+
+ if (flag_openmp)
+ {
+ id = get_identifier ("omp_all_memory");
+ C_SET_RID_CODE (id, RID_OMP_ALL_MEMORY);
+ set_identifier_kind (id, cik_keyword);
+ ridpointers [RID_OMP_ALL_MEMORY] = id;
+ }
}
static void
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index d09d5b7..84f379c 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -5876,6 +5876,14 @@ cp_parser_primary_expression (cp_parser *parser,
case RID_AT_SELECTOR:
return cp_parser_objc_expression (parser);
+ case RID_OMP_ALL_MEMORY:
+ gcc_assert (flag_openmp);
+ cp_lexer_consume_token (parser->lexer);
+ error_at (token->location,
+ "%<omp_all_memory%> may only be used in OpenMP "
+ "%<depend%> clause");
+ return error_mark_node;
+
case RID_TEMPLATE:
if (parser->in_function_body
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
@@ -36735,6 +36743,15 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
decl = cp_parser_primary_expression (parser, false, false, false,
&idk);
}
+ else if (kind == OMP_CLAUSE_DEPEND
+ && cp_parser_is_keyword (token, RID_OMP_ALL_MEMORY)
+ && (cp_lexer_nth_token_is (parser->lexer, 2, CPP_COMMA)
+ || cp_lexer_nth_token_is (parser->lexer, 2,
+ CPP_CLOSE_PAREN)))
+ {
+ decl = ridpointers[RID_OMP_ALL_MEMORY];
+ cp_lexer_consume_token (parser->lexer);
+ }
else
{
name = cp_parser_id_expression (parser, /*template_p=*/false,
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 2c7c5f8..06b4a7d 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -17601,8 +17601,8 @@ static tree
tsubst_omp_clause_decl (tree decl, tree args, tsubst_flags_t complain,
tree in_decl, tree *iterator_cache)
{
- if (decl == NULL_TREE)
- return NULL_TREE;
+ if (decl == NULL_TREE || decl == ridpointers[RID_OMP_ALL_MEMORY])
+ return decl;
/* Handle OpenMP iterators. */
if (TREE_CODE (decl) == TREE_LIST
diff --git a/gcc/cp/semantics.cc b/gcc/cp/semantics.cc
index 10478d1..61f49be 100644
--- a/gcc/cp/semantics.cc
+++ b/gcc/cp/semantics.cc
@@ -7815,6 +7815,20 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
if (t == error_mark_node)
remove = true;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_DEPEND
+ && t == ridpointers[RID_OMP_ALL_MEMORY])
+ {
+ if (OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_OUT
+ && OMP_CLAUSE_DEPEND_KIND (c) != OMP_CLAUSE_DEPEND_INOUT)
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "%<omp_all_memory%> used with %<depend%> kind "
+ "other than %<out%> or %<inout%>");
+ remove = true;
+ }
+ if (processing_template_decl)
+ break;
+ }
else if (processing_template_decl && TREE_CODE (t) != OVERLOAD)
break;
else if (!lvalue_p (t))
@@ -7867,24 +7881,32 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
}
if (!remove)
{
- tree addr = cp_build_addr_expr (t, tf_warning_or_error);
- if (addr == error_mark_node)
- remove = true;
+ if (t == ridpointers[RID_OMP_ALL_MEMORY])
+ t = null_pointer_node;
else
{
+ tree addr = cp_build_addr_expr (t, tf_warning_or_error);
+ if (addr == error_mark_node)
+ {
+ remove = true;
+ break;
+ }
t = cp_build_indirect_ref (OMP_CLAUSE_LOCATION (c),
addr, RO_UNARY_STAR,
tf_warning_or_error);
if (t == error_mark_node)
- remove = true;
- else if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
- && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
- && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
- == TREE_VEC))
- TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
- else
- OMP_CLAUSE_DECL (c) = t;
+ {
+ remove = true;
+ break;
+ }
}
+ if (TREE_CODE (OMP_CLAUSE_DECL (c)) == TREE_LIST
+ && TREE_PURPOSE (OMP_CLAUSE_DECL (c))
+ && (TREE_CODE (TREE_PURPOSE (OMP_CLAUSE_DECL (c)))
+ == TREE_VEC))
+ TREE_VALUE (OMP_CLAUSE_DECL (c)) = t;
+ else
+ OMP_CLAUSE_DECL (c) = t;
}
break;
case OMP_CLAUSE_DETACH:
diff --git a/gcc/gimplify.cc b/gcc/gimplify.cc
index 822e0cf..13413d0 100644
--- a/gcc/gimplify.cc
+++ b/gcc/gimplify.cc
@@ -8623,7 +8623,8 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
}
if (error_operand_p (TREE_VALUE (t)))
return 2;
- TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
+ if (TREE_VALUE (t) != null_pointer_node)
+ TREE_VALUE (t) = build_fold_addr_expr (TREE_VALUE (t));
r = build4 (ARRAY_REF, ptr_type_node, array, cnts[i],
NULL_TREE, NULL_TREE);
tem = build2_loc (OMP_CLAUSE_LOCATION (c), MODIFY_EXPR,
@@ -8650,7 +8651,8 @@ gimplify_omp_depend (tree *list_p, gimple_seq *pre_p)
}
if (error_operand_p (OMP_CLAUSE_DECL (c)))
return 2;
- OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
+ if (OMP_CLAUSE_DECL (c) != null_pointer_node)
+ OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
is_gimple_val, fb_rvalue) == GS_ERROR)
return 2;
@@ -10346,12 +10348,15 @@ gimplify_scan_omp_clauses (tree *list_p, gimple_seq *pre_p,
remove = true;
break;
}
- OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
- if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
- is_gimple_val, fb_rvalue) == GS_ERROR)
+ if (OMP_CLAUSE_DECL (c) != null_pointer_node)
{
- remove = true;
- break;
+ OMP_CLAUSE_DECL (c) = build_fold_addr_expr (OMP_CLAUSE_DECL (c));
+ if (gimplify_expr (&OMP_CLAUSE_DECL (c), pre_p, NULL,
+ is_gimple_val, fb_rvalue) == GS_ERROR)
+ {
+ remove = true;
+ break;
+ }
}
if (code == OMP_TASK)
ctx->has_depend = true;
diff --git a/gcc/testsuite/c-c++-common/gomp/all-memory-1.c b/gcc/testsuite/c-c++-common/gomp/all-memory-1.c
new file mode 100644
index 0000000..5d63e0d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/all-memory-1.c
@@ -0,0 +1,52 @@
+int omp_all_memory; /* { dg-error "expected" } */
+
+void
+foo (void)
+{
+ int p = (&omp_all_memory)[0]; /* { dg-error "'omp_all_memory' may only be used in OpenMP 'depend' clause" } */
+}
+
+void
+bar (void)
+{
+ int *omp_all_memory; /* { dg-error "expected" } */
+}
+
+void
+baz (void)
+{
+ struct omp_all_memory { int a; }; /* { dg-error "expected" } */
+}
+
+void
+qux (void)
+{
+ union omp_all_memory { int a; }; /* { dg-error "expected" } */
+}
+
+void
+corge (void)
+{
+ enum omp_all_memory { OAM; }; /* { dg-error "expected" } */
+}
+
+void
+garply (void)
+{
+ enum E { omp_all_memory }; } /* { dg-error "expected" } */
+
+void
+boo (void)
+{
+ int x, y;
+ #pragma omp task private (omp_all_memory) /* { dg-error "expected" } */
+ ;
+ #pragma omp task depend(inout: *&omp_all_memory) /* { dg-error "'omp_all_memory' may only be used in OpenMP 'depend' clause" } */
+ ;
+ #pragma omp task depend(inout: omp_all_memory[0]) /* { dg-error "'omp_all_memory' may only be used in OpenMP 'depend' clause" } */
+ ;
+ #pragma omp task depend(in: omp_all_memory) /* { dg-error "'omp_all_memory' used with 'depend' kind other than 'out' or 'inout'" } */
+ ;
+ #pragma omp task depend(mutexinoutset: omp_all_memory) /* { dg-error "'omp_all_memory' used with 'depend' kind other than 'out' or 'inout'" } */
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/all-memory-2.c b/gcc/testsuite/c-c++-common/gomp/all-memory-2.c
new file mode 100644
index 0000000..6f5d31b
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/all-memory-2.c
@@ -0,0 +1,55 @@
+/* { dg-options "-fno-openmp" } */
+
+int omp_all_memory; /* { dg-bogus "expected" } */
+
+void
+foo (void)
+{
+ int p = (&omp_all_memory)[0]; /* { dg-bogus "'omp_all_memory' may only be used in OpenMP 'depend' clause" } */
+}
+
+void
+bar (void)
+{
+ int *omp_all_memory; /* { dg-bogus "expected" } */
+}
+
+void
+baz (void)
+{
+ struct omp_all_memory { int a; }; /* { dg-bogus "expected" } */
+}
+
+void
+qux (void)
+{
+ union omp_all_memory { int a; }; /* { dg-bogus "expected" } */
+}
+
+void
+corge (void)
+{
+ enum omp_all_memory { OAM }; /* { dg-bogus "expected" } */
+}
+
+void
+garply (void)
+{
+ enum E { omp_all_memory }; /* { dg-bogus "expected" } */
+}
+
+void
+boo (void)
+{
+ int x, y;
+ #pragma omp task private (omp_all_memory)
+ ;
+ #pragma omp task depend(inout: *&omp_all_memory)
+ ;
+ #pragma omp task depend(inout: omp_all_memory[0])
+ ;
+ #pragma omp task depend(in: omp_all_memory)
+ ;
+ #pragma omp task depend(mutexinoutset: omp_all_memory)
+ ;
+}
diff --git a/gcc/testsuite/c-c++-common/gomp/all-memory-3.c b/gcc/testsuite/c-c++-common/gomp/all-memory-3.c
new file mode 100644
index 0000000..f178b8d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/gomp/all-memory-3.c
@@ -0,0 +1,22 @@
+typedef struct __attribute__((__aligned__ (sizeof (void *)))) omp_depend_t {
+ char __omp_depend_t__[2 * sizeof (void *)];
+} omp_depend_t;
+
+omp_depend_t z;
+
+void
+foo (void)
+{
+ int x = 0, y = 0;
+ #pragma omp task depend(out: omp_all_memory)
+ ;
+ #pragma omp task depend(inout: omp_all_memory)
+ ;
+ #pragma omp task depend(out: x, omp_all_memory, y)
+ ;
+ #pragma omp task depend(inout: omp_all_memory, y)
+ ;
+ #pragma omp task depend(out: x, omp_all_memory)
+ ;
+ #pragma omp depobj (z) depend (inout: omp_all_memory)
+}
diff --git a/gcc/testsuite/g++.dg/gomp/all-memory-1.C b/gcc/testsuite/g++.dg/gomp/all-memory-1.C
new file mode 100644
index 0000000..8f3358d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/all-memory-1.C
@@ -0,0 +1,24 @@
+namespace A
+{
+ namespace omp_all_memory // { dg-error "expected" }
+ {
+ }
+}
+
+namespace B
+{
+ template <int N>
+ void omp_all_memory () {} // { dg-error "expected" }
+}
+
+namespace C
+{
+ template <int N>
+ struct omp_all_memory {}; // { dg-error "expected" }
+}
+
+namespace D
+{
+ template <int omp_all_memory> // { dg-error "expected" }
+ struct S {};
+}
diff --git a/gcc/testsuite/g++.dg/gomp/all-memory-2.C b/gcc/testsuite/g++.dg/gomp/all-memory-2.C
new file mode 100644
index 0000000..1acf391
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/all-memory-2.C
@@ -0,0 +1,26 @@
+// { dg-options "-fno-openmp" }
+
+namespace A
+{
+ namespace omp_all_memory // { dg-bogus "expected" }
+ {
+ }
+}
+
+namespace B
+{
+ template <int N>
+ void omp_all_memory () {} // { dg-bogus "expected" }
+}
+
+namespace C
+{
+ template <int N>
+ struct omp_all_memory {}; // { dg-bogus "expected" }
+}
+
+namespace D
+{
+ template <int omp_all_memory> // { dg-bogus "expected" }
+ struct S {};
+}
diff --git a/gcc/tree-pretty-print.cc b/gcc/tree-pretty-print.cc
index 99af977..d7615aa 100644
--- a/gcc/tree-pretty-print.cc
+++ b/gcc/tree-pretty-print.cc
@@ -850,7 +850,10 @@ dump_omp_clause (pretty_printer *pp, tree clause, int spc, dump_flags_t flags)
pp_string (pp, name);
pp_colon (pp);
}
- dump_generic_node (pp, t, spc, flags, false);
+ if (t == null_pointer_node)
+ pp_string (pp, "omp_all_memory");
+ else
+ dump_generic_node (pp, t, spc, flags, false);
pp_right_paren (pp);
}
break;