openmp: Allow private or firstprivate arguments to default clause even for C/C++
OpenMP 5.1 allows default(private) or default(firstprivate) even in C/C++, but it behaves the same way as in Fortran only for variables not declared at namespace or file scope. For the namespace/file scope variables it instead behaves as default(none). 2021-09-18 Jakub Jelinek <jakub@redhat.com> gcc/ * gimplify.c (omp_default_clause): For C/C++ default({,first}private), if file/namespace scope variable doesn't have predetermined sharing, treat it as if there was default(none). gcc/c/ * c-parser.c (c_parser_omp_clause_default): Handle private and firstprivate arguments, adjust diagnostics on unknown argument. gcc/cp/ * parser.c (cp_parser_omp_clause_default): Handle private and firstprivate arguments, adjust diagnostics on unknown argument. * cp-gimplify.c (cxx_omp_finish_clause): Handle OMP_CLAUSE_PRIVATE. gcc/testsuite/ * c-c++-common/gomp/default-2.c: New test. * c-c++-common/gomp/default-3.c: New test. * g++.dg/gomp/default-1.C: New test. libgomp/ * testsuite/libgomp.c++/default-1.C: New test. * testsuite/libgomp.c-c++-common/default-1.c: New test. * libgomp.texi (OpenMP 5.1): Mark "private and firstprivate argument to default clause in C and C++" as implemented.
This commit is contained in:
parent
d07c750cc6
commit
e5597f2ad5
10 changed files with 302 additions and 7 deletions
|
@ -13420,6 +13420,9 @@ c_parser_omp_clause_copyprivate (c_parser *parser, tree list)
|
|||
/* OpenMP 2.5:
|
||||
default ( none | shared )
|
||||
|
||||
OpenMP 5.1:
|
||||
default ( private | firstprivate )
|
||||
|
||||
OpenACC:
|
||||
default ( none | present ) */
|
||||
|
||||
|
@ -13446,9 +13449,24 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
|
|||
break;
|
||||
|
||||
case 'p':
|
||||
if (strcmp ("present", p) != 0 || !is_oacc)
|
||||
if (is_oacc)
|
||||
{
|
||||
if (strcmp ("present", p) != 0)
|
||||
goto invalid_kind;
|
||||
kind = OMP_CLAUSE_DEFAULT_PRESENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (strcmp ("private", p) != 0)
|
||||
goto invalid_kind;
|
||||
kind = OMP_CLAUSE_DEFAULT_PRIVATE;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (strcmp ("firstprivate", p) != 0 || is_oacc)
|
||||
goto invalid_kind;
|
||||
kind = OMP_CLAUSE_DEFAULT_PRESENT;
|
||||
kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
|
@ -13469,7 +13487,8 @@ c_parser_omp_clause_default (c_parser *parser, tree list, bool is_oacc)
|
|||
if (is_oacc)
|
||||
c_parser_error (parser, "expected %<none%> or %<present%>");
|
||||
else
|
||||
c_parser_error (parser, "expected %<none%> or %<shared%>");
|
||||
c_parser_error (parser, "expected %<none%>, %<shared%>, "
|
||||
"%<private%> or %<firstprivate%>");
|
||||
}
|
||||
parens.skip_until_found_close (parser);
|
||||
|
||||
|
|
|
@ -2060,6 +2060,7 @@ cxx_omp_finish_clause (tree c, gimple_seq *, bool /* openacc */)
|
|||
bool make_shared = false;
|
||||
|
||||
if (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_FIRSTPRIVATE
|
||||
&& OMP_CLAUSE_CODE (c) != OMP_CLAUSE_PRIVATE
|
||||
&& (OMP_CLAUSE_CODE (c) != OMP_CLAUSE_LASTPRIVATE
|
||||
|| !OMP_CLAUSE_LASTPRIVATE_LOOP_IV (c)))
|
||||
return;
|
||||
|
@ -2080,9 +2081,10 @@ cxx_omp_finish_clause (tree c, gimple_seq *, bool /* openacc */)
|
|||
Save the results, because later we won't be in the right context
|
||||
for making these queries. */
|
||||
bool first = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE;
|
||||
bool last = OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE;
|
||||
if (!make_shared
|
||||
&& CLASS_TYPE_P (inner_type)
|
||||
&& cxx_omp_create_clause_info (c, inner_type, !first, first, !first,
|
||||
&& cxx_omp_create_clause_info (c, inner_type, !first, first, last,
|
||||
true))
|
||||
make_shared = true;
|
||||
|
||||
|
|
|
@ -36988,6 +36988,9 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location
|
|||
/* OpenMP 2.5:
|
||||
default ( none | shared )
|
||||
|
||||
OpenMP 5.1:
|
||||
default ( private | firstprivate )
|
||||
|
||||
OpenACC:
|
||||
default ( none | present ) */
|
||||
|
||||
|
@ -37001,7 +37004,12 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
|
|||
matching_parens parens;
|
||||
if (!parens.require_open (parser))
|
||||
return list;
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
|
||||
if (!is_oacc && cp_lexer_next_token_is_keyword (parser->lexer, RID_PRIVATE))
|
||||
{
|
||||
kind = OMP_CLAUSE_DEFAULT_PRIVATE;
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
|
||||
{
|
||||
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
|
||||
const char *p = IDENTIFIER_POINTER (id);
|
||||
|
@ -37020,6 +37028,12 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
|
|||
kind = OMP_CLAUSE_DEFAULT_PRESENT;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
if (strcmp ("firstprivate", p) != 0 || is_oacc)
|
||||
goto invalid_kind;
|
||||
kind = OMP_CLAUSE_DEFAULT_FIRSTPRIVATE;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
if (strcmp ("shared", p) != 0 || is_oacc)
|
||||
goto invalid_kind;
|
||||
|
@ -37038,7 +37052,8 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list,
|
|||
if (is_oacc)
|
||||
cp_parser_error (parser, "expected %<none%> or %<present%>");
|
||||
else
|
||||
cp_parser_error (parser, "expected %<none%> or %<shared%>");
|
||||
cp_parser_error (parser, "expected %<none%>, %<shared%>, "
|
||||
"%<private%> or %<firstprivate%>");
|
||||
}
|
||||
|
||||
if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED
|
||||
|
|
|
@ -7369,6 +7369,18 @@ omp_default_clause (struct gimplify_omp_ctx *ctx, tree decl,
|
|||
default_kind = kind;
|
||||
else if (VAR_P (decl) && TREE_STATIC (decl) && DECL_IN_CONSTANT_POOL (decl))
|
||||
default_kind = OMP_CLAUSE_DEFAULT_SHARED;
|
||||
/* For C/C++ default({,first}private), variables with static storage duration
|
||||
declared in a namespace or global scope and referenced in construct
|
||||
must be explicitly specified, i.e. acts as default(none). */
|
||||
else if ((default_kind == OMP_CLAUSE_DEFAULT_PRIVATE
|
||||
|| default_kind == OMP_CLAUSE_DEFAULT_FIRSTPRIVATE)
|
||||
&& VAR_P (decl)
|
||||
&& is_global_var (decl)
|
||||
&& (DECL_FILE_SCOPE_P (decl)
|
||||
|| (DECL_CONTEXT (decl)
|
||||
&& TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL))
|
||||
&& !lang_GNU_Fortran ())
|
||||
default_kind = OMP_CLAUSE_DEFAULT_NONE;
|
||||
|
||||
switch (default_kind)
|
||||
{
|
||||
|
|
67
gcc/testsuite/c-c++-common/gomp/default-2.c
Normal file
67
gcc/testsuite/c-c++-common/gomp/default-2.c
Normal file
|
@ -0,0 +1,67 @@
|
|||
int x;
|
||||
extern int z;
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
int y = 0, i;
|
||||
static int w;
|
||||
#pragma omp task default(firstprivate) /* { dg-message "note: enclosing 'task'" } */
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
|
||||
}
|
||||
#pragma omp taskloop default(firstprivate) /* { dg-message "note: enclosing 'taskloop'" } */
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
|
||||
}
|
||||
#pragma omp teams default(firstprivate) /* { dg-message "note: enclosing 'teams'" } */
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
|
||||
}
|
||||
#pragma omp parallel default(firstprivate) /* { dg-message "note: enclosing 'parallel'" } */
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
|
||||
}
|
||||
#pragma omp task default(private) /* { dg-message "note: enclosing 'task'" } */
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
|
||||
w = 1; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
|
||||
}
|
||||
#pragma omp taskloop default(private) /* { dg-message "note: enclosing 'taskloop'" } */
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
|
||||
w = 1; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
|
||||
}
|
||||
#pragma omp teams default(private) /* { dg-message "note: enclosing 'teams'" } */
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
|
||||
w = 1; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
|
||||
}
|
||||
#pragma omp parallel default(private) /* { dg-message "note: enclosing 'parallel'" } */
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
|
||||
x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
|
||||
z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
|
||||
}
|
||||
}
|
14
gcc/testsuite/c-c++-common/gomp/default-3.c
Normal file
14
gcc/testsuite/c-c++-common/gomp/default-3.c
Normal file
|
@ -0,0 +1,14 @@
|
|||
void
|
||||
foo (void)
|
||||
{
|
||||
int i;
|
||||
#pragma omp task default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
|
||||
;
|
||||
#pragma omp taskloop default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
|
||||
for (i = 0; i < 64; i++)
|
||||
;
|
||||
#pragma omp teams default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
|
||||
;
|
||||
#pragma omp parallel default(copyprivate) /* { dg-error "expected 'none', 'shared', 'private' or 'firstprivate' before 'copyprivate'" } */
|
||||
;
|
||||
}
|
112
gcc/testsuite/g++.dg/gomp/default-1.C
Normal file
112
gcc/testsuite/g++.dg/gomp/default-1.C
Normal file
|
@ -0,0 +1,112 @@
|
|||
namespace N
|
||||
{
|
||||
int x;
|
||||
extern int z;
|
||||
}
|
||||
|
||||
struct S
|
||||
{
|
||||
static int s;
|
||||
};
|
||||
|
||||
#if __cpp_variable_templates >= 201304
|
||||
template <int N>
|
||||
int t = N;
|
||||
#endif
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
int y = 0, i;
|
||||
static int w;
|
||||
#pragma omp task default(firstprivate) /* { dg-message "note: enclosing 'task'" } */
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
|
||||
S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'task'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'task'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
#pragma omp taskloop default(firstprivate) /* { dg-message "note: enclosing 'taskloop'" } */
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
|
||||
S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'taskloop'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'taskloop'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
#pragma omp teams default(firstprivate) /* { dg-message "note: enclosing 'teams'" } */
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
|
||||
S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'teams'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'teams'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
#pragma omp parallel default(firstprivate) /* { dg-message "note: enclosing 'parallel'" } */
|
||||
{
|
||||
y++; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
|
||||
w++; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
|
||||
S::s++; /* { dg-bogus "'S::s' not specified in enclosing 'parallel'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'parallel'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
#pragma omp task default(private) /* { dg-message "note: enclosing 'task'" } */
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'task'" } */
|
||||
w = 1; /* { dg-bogus "'w' not specified in enclosing 'task'" } */
|
||||
S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'task'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'task'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'task'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'task'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
#pragma omp taskloop default(private) /* { dg-message "note: enclosing 'taskloop'" } */
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'taskloop'" } */
|
||||
w = 1; /* { dg-bogus "'w' not specified in enclosing 'taskloop'" } */
|
||||
S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'taskloop'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'taskloop'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'taskloop'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'taskloop'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
#pragma omp teams default(private) /* { dg-message "note: enclosing 'teams'" } */
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'teams'" } */
|
||||
w = 1; /* { dg-bogus "'w' not specified in enclosing 'teams'" } */
|
||||
S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'teams'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'teams'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'teams'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'teams'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
#pragma omp parallel default(private) /* { dg-message "note: enclosing 'parallel'" } */
|
||||
{
|
||||
y = 1; /* { dg-bogus "'y' not specified in enclosing 'parallel'" } */
|
||||
w = 1; /* { dg-bogus "'w' not specified in enclosing 'parallel'" } */
|
||||
S::s = 1; /* { dg-bogus "'S::s' not specified in enclosing 'parallel'" } */
|
||||
N::x++; /* { dg-error "'x' not specified in enclosing 'parallel'" } */
|
||||
N::z++; /* { dg-error "'z' not specified in enclosing 'parallel'" } */
|
||||
#if __cpp_variable_templates >= 201304
|
||||
t<5>++; /* { dg-error "'t' not specified in enclosing 'parallel'" "" { target c++14 } } */
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -305,7 +305,7 @@ The OpenMP 4.5 specification is fully supported.
|
|||
@item @code{seq_cst} clause on a @code{flush} construct @tab Y @tab
|
||||
@item @code{inoutset} argument to the @code{depend} clause @tab N @tab
|
||||
@item @code{private} and @code{firstprivate} argument to @code{default}
|
||||
clause in C and C++ @tab N @tab
|
||||
clause in C and C++ @tab Y @tab
|
||||
@item @code{present} argument to @code{defaultmap} clause @tab N @tab
|
||||
@item @code{omp_set_num_teams}, @code{omp_set_teams_thread_limit},
|
||||
@code{omp_get_max_teams}, @code{omp_get_teams_thread_limit} runtime
|
||||
|
|
29
libgomp/testsuite/libgomp.c++/default-1.C
Normal file
29
libgomp/testsuite/libgomp.c++/default-1.C
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <omp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
struct S { S () : s (42) {} S (const S &x) : s (x.s) {}; ~S () {} int s; };
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
S s;
|
||||
s.s = 113;
|
||||
#pragma omp parallel num_threads(4) default(firstprivate)
|
||||
{
|
||||
if (s.s != 113)
|
||||
abort ();
|
||||
s.s = omp_get_thread_num ();
|
||||
#pragma omp barrier
|
||||
if (s.s != omp_get_thread_num ())
|
||||
abort ();
|
||||
}
|
||||
#pragma omp parallel num_threads(4) default(private)
|
||||
{
|
||||
if (s.s != 42)
|
||||
abort ();
|
||||
s.s = omp_get_thread_num () + 13;
|
||||
#pragma omp barrier
|
||||
if (s.s != omp_get_thread_num () + 13)
|
||||
abort ();
|
||||
}
|
||||
}
|
25
libgomp/testsuite/libgomp.c-c++-common/default-1.c
Normal file
25
libgomp/testsuite/libgomp.c-c++-common/default-1.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include <omp.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int
|
||||
main ()
|
||||
{
|
||||
int v = 42;
|
||||
#pragma omp parallel num_threads(4) default(firstprivate)
|
||||
{
|
||||
if (v != 42)
|
||||
abort ();
|
||||
v = omp_get_thread_num ();
|
||||
#pragma omp barrier
|
||||
if (v != omp_get_thread_num ())
|
||||
abort ();
|
||||
}
|
||||
#pragma omp parallel num_threads(4) default(private)
|
||||
{
|
||||
v = omp_get_thread_num () + 13;
|
||||
#pragma omp barrier
|
||||
if (v != omp_get_thread_num () + 13)
|
||||
abort ();
|
||||
}
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue