@@ -6336,7 +6336,7 @@ extern void finish_omp_taskwait (void)
extern void finish_omp_taskyield (void);
extern void finish_omp_cancel (tree);
extern void finish_omp_cancellation_point (tree);
-extern tree omp_privatize_field (tree);
+extern tree omp_privatize_field (tree, bool);
extern tree begin_transaction_stmt (location_t, tree *, int);
extern void finish_transaction_stmt (tree, tree, int, tree);
extern tree build_transaction_expr (location_t, tree, int, tree);
@@ -32634,7 +32634,7 @@ cp_parser_omp_for_loop_init (cp_parser *
decl = cp_parser_lookup_name_simple (parser, name,
token->location);
if (TREE_CODE (decl) == FIELD_DECL)
- add_private_clause = omp_privatize_field (decl);
+ add_private_clause = omp_privatize_field (decl, false);
}
cp_parser_abort_tentative_parse (parser);
cp_parser_parse_tentatively (parser);
@@ -14465,6 +14465,7 @@ tsubst_omp_clauses (tree clauses, bool d
if (allow_fields)
switch (OMP_CLAUSE_CODE (nc))
{
+ case OMP_CLAUSE_SHARED:
case OMP_CLAUSE_PRIVATE:
case OMP_CLAUSE_FIRSTPRIVATE:
case OMP_CLAUSE_LASTPRIVATE:
@@ -14644,7 +14645,7 @@ tsubst_omp_for_iterator (tree t, int i,
&& DECL_NAME (v) == this_identifier)
{
decl = TREE_OPERAND (decl, 1);
- decl = omp_privatize_field (decl);
+ decl = omp_privatize_field (decl, false);
}
/* FALLTHRU */
default:
@@ -4326,19 +4326,20 @@ omp_note_field_privatization (tree f, tr
dummy VAR_DECL. */
tree
-omp_privatize_field (tree t)
+omp_privatize_field (tree t, bool shared)
{
tree m = finish_non_static_data_member (t, NULL_TREE, NULL_TREE);
if (m == error_mark_node)
return error_mark_node;
- if (!omp_private_member_map)
+ if (!omp_private_member_map && !shared)
omp_private_member_map = new hash_map<tree, tree>;
if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
{
gcc_assert (TREE_CODE (m) == INDIRECT_REF);
m = TREE_OPERAND (m, 0);
}
- tree &v = omp_private_member_map->get_or_insert (t);
+ tree vb = NULL_TREE;
+ tree &v = shared ? vb : omp_private_member_map->get_or_insert (t);
if (v == NULL_TREE)
{
v = create_temporary_var (TREE_TYPE (m));
@@ -4347,7 +4348,8 @@ omp_privatize_field (tree t)
DECL_OMP_PRIVATIZED_MEMBER (v) = 1;
SET_DECL_VALUE_EXPR (v, m);
DECL_HAS_VALUE_EXPR_P (v) = 1;
- omp_private_member_vec.safe_push (t);
+ if (!shared)
+ omp_private_member_vec.safe_push (t);
}
return v;
}
@@ -4450,7 +4452,7 @@ handle_omp_array_sections_1 (tree c, tre
if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
&& TREE_CODE (TREE_CHAIN (t)) == FIELD_DECL)
- TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t));
+ TREE_CHAIN (t) = omp_privatize_field (TREE_CHAIN (t), false);
ret = handle_omp_array_sections_1 (c, TREE_CHAIN (t), types,
maybe_zero_len, first_non_one, is_omp);
if (ret == error_mark_node || ret == NULL_TREE)
@@ -5681,6 +5683,7 @@ finish_omp_clauses (tree clauses, bool a
switch (OMP_CLAUSE_CODE (c))
{
case OMP_CLAUSE_SHARED:
+ field_ok = allow_fields;
goto check_dup_generic;
case OMP_CLAUSE_PRIVATE:
field_ok = allow_fields;
@@ -5851,7 +5854,7 @@ finish_omp_clauses (tree clauses, bool a
t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
if (t)
{
- if (!remove)
+ if (!remove && OMP_CLAUSE_CODE (c) != OMP_CLAUSE_SHARED)
omp_note_field_privatization (t, OMP_CLAUSE_DECL (c));
}
else
@@ -5896,7 +5899,9 @@ finish_omp_clauses (tree clauses, bool a
&& TREE_CODE (t) == FIELD_DECL
&& t == OMP_CLAUSE_DECL (c))
{
- OMP_CLAUSE_DECL (c) = omp_privatize_field (t);
+ OMP_CLAUSE_DECL (c)
+ = omp_privatize_field (t, (OMP_CLAUSE_CODE (c)
+ == OMP_CLAUSE_SHARED));
if (OMP_CLAUSE_DECL (c) == error_mark_node)
remove = true;
}
@@ -7002,6 +7007,15 @@ finish_omp_clauses (tree clauses, bool a
need_dtor))
remove = true;
+ if (!remove
+ && c_kind == OMP_CLAUSE_SHARED
+ && processing_template_decl)
+ {
+ t = omp_clause_decl_field (OMP_CLAUSE_DECL (c));
+ if (t)
+ OMP_CLAUSE_DECL (c) = t;
+ }
+
if (remove)
*pc = OMP_CLAUSE_CHAIN (c);
else
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fopenmp" } */
+
+struct S { int a; };
+
+void
+foo (struct S *x)
+{
+ struct S b;
+ #pragma omp parallel private (b.a) /* { dg-error "expected .\\). before .\\.. token" } */
+ ;
+ #pragma omp parallel private (x->a) /* { dg-error "expected .\\). before .->. token" } */
+ ;
+}
@@ -12,7 +12,8 @@ void T::test()
#pragma omp parallel private(n)
n = 1;
- #pragma omp parallel shared(n) // { dg-error "T::n" }
+ #pragma omp parallel shared(n)
+ #pragma omp single
n = 1;
#pragma omp parallel firstprivate(n)
@@ -76,19 +76,19 @@ B::m2 ()
#pragma omp parallel for reduction (+:g) // { dg-error "has const type for .reduction." }
for (int i = 0; i < 10; i++)
;
- #pragma omp parallel shared (a) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (a)
;
- #pragma omp parallel shared (b) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (b)
;
- #pragma omp parallel shared (c) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (c)
;
- #pragma omp parallel shared (e) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (e)
;
- #pragma omp parallel shared (f) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (f)
;
- #pragma omp parallel shared (g) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (g)
;
- #pragma omp parallel shared (h) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (h) // { dg-error "is predetermined .shared. for .shared." }
;
return 0;
}
@@ -150,19 +150,19 @@ B::m4 () const
#pragma omp parallel for reduction (+:g) // { dg-error "has const type for .reduction." }
for (int i = 0; i < 10; i++)
;
- #pragma omp parallel shared (a) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (a) // { dg-error "is predetermined .shared. for .shared." }
;
- #pragma omp parallel shared (b) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (b)
;
- #pragma omp parallel shared (c) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (c)
;
- #pragma omp parallel shared (e) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (e)
;
- #pragma omp parallel shared (f) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (f)
;
- #pragma omp parallel shared (g) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (g)
;
- #pragma omp parallel shared (h) // { dg-error "is not a variable in clause" }
+ #pragma omp parallel shared (h) // { dg-error "is predetermined .shared. for .shared." }
;
return 0;
}
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct S { int a; void foo (S *); static S &bar (); };
+
+void
+S::foo (S *x)
+{
+ S &b = bar ();
+ S c;
+ #pragma omp parallel private (b.a) // { dg-error "expected .\\). before .\\.. token" }
+ ;
+ #pragma omp parallel private (c.a) // { dg-error "expected .\\). before .\\.. token" }
+ ;
+ #pragma omp parallel private (x->a) // { dg-error "expected .\\). before .->. token" }
+ ;
+}
@@ -0,0 +1,22 @@
+// { dg-do compile }
+
+class C { int a; char b; void foo (); };
+
+void
+C::foo ()
+{
+ #pragma omp parallel shared (a, a) // { dg-error "appears more than once in data clauses" }
+ ;
+ #pragma omp parallel shared (a) private (b) shared(C::a) // { dg-error "appears more than once in data clauses" }
+ ;
+ #pragma omp task private (a) private (b)
+ ;
+ #pragma omp task firstprivate (a) shared (C::a) // { dg-error "appears more than once in data clauses" }
+ ;
+ #pragma omp parallel for lastprivate (b) firstprivate (a) lastprivate (b) // { dg-error "appears more than once in data clauses" }
+ for (int i = 0; i < 64; i++)
+ ;
+ #pragma omp parallel for lastprivate (b) firstprivate (b)
+ for (int i = 0; i < 64; i++)
+ ;
+}
@@ -0,0 +1,119 @@
+// { dg-do run }
+
+#include <omp.h>
+
+int c, d, e;
+struct R { R () {}; ~R () {}; int r; };
+template <typename Q>
+struct T { T () : t(d) {}; virtual ~T () {}; Q t; };
+template <typename Q>
+struct A : public R, virtual public T<Q> { A () : b(c), a(e) {} Q a; int &b; void m1 (); };
+
+void
+take (int &a, int &b, int &c, int &d)
+{
+ asm volatile ("" : : "g" (&a), "g" (&b), "g" (&c), "g" (&d) : "memory");
+}
+
+template <typename Q>
+void
+A<Q>::m1 ()
+{
+ #pragma omp parallel private (a, T<Q>::t) shared (r, A::b) default(none)
+ {
+ int q = omp_get_thread_num (), q2;
+ a = q;
+ T<Q>::t = 3 * q;
+ #pragma omp single copyprivate (q2)
+ {
+ r = 2 * q;
+ b = 4 * q;
+ q2 = q;
+ }
+ take (a, r, T<Q>::t, b);
+ #pragma omp barrier
+ if (A::a != q || R::r != 2 * q2 || T<Q>::t != 3 * q || A::b != 4 * q2)
+ __builtin_abort ();
+ }
+ a = 7;
+ r = 8;
+ T<Q>::t = 9;
+ b = 10;
+ #pragma omp parallel shared (A::a) default (none) firstprivate (R::r, b) shared (T<Q>::t)
+ {
+ int q = omp_get_thread_num (), q2;
+ take (A::a, R::r, T<Q>::t, A::b);
+ if (a != 7 || r != 8 || T<Q>::t != 9 || b != 10)
+ __builtin_abort ();
+ R::r = 6 * q;
+ #pragma omp barrier
+ #pragma omp single copyprivate (q2)
+ {
+ A::a = 5 * q;
+ T<Q>::t = 7 * q;
+ q2 = q;
+ }
+ A::b = 8 * q;
+ take (a, r, T<Q>::t, b);
+ #pragma omp barrier
+ if (a != 5 * q2 || r != 6 * q || T<Q>::t != 7 * q2 || b != 8 * q)
+ __builtin_abort ();
+ }
+ a = 1;
+ b = 2;
+ R::r = 3;
+ T<Q>::t = 4;
+ bool f = false;
+ #pragma omp parallel private (f)
+ {
+ f = false;
+ #pragma omp single
+ #pragma omp taskloop default(none) firstprivate (r, A::a, f) shared (T<Q>::t, b)
+ for (int i = 0; i < 30; i++)
+ {
+ int q = omp_get_thread_num ();
+ int tv, bv;
+ #pragma omp atomic read
+ tv = T<Q>::t;
+ #pragma omp atomic read
+ bv = A::b;
+ if (i == 16)
+ {
+ if (bv != 2 || tv != 4)
+ __builtin_abort ();
+ }
+ else
+ {
+ if ((bv != 2 && bv != 8) || (tv != 4 && tv != 9))
+ __builtin_abort ();
+ }
+ if (!f)
+ {
+ if (A::a != 1 || R::r != 3)
+ __builtin_abort ();
+ }
+ else if (a != 7 * q || r != 9 * q)
+ __builtin_abort ();
+ take (a, r, T<Q>::t, b);
+ A::a = 7 * q;
+ R::r = 9 * q;
+ if (i == 16)
+ {
+ #pragma omp atomic write
+ A::b = 8;
+ #pragma omp atomic write
+ T<Q>::t = 9;
+ }
+ f = true;
+ }
+ }
+}
+
+int
+main ()
+{
+ A<int> a;
+ a.m1 ();
+ A<int &> b;
+ b.m1 ();
+}
@@ -0,0 +1,114 @@
+// { dg-do run }
+
+#include <omp.h>
+
+struct R { R () {}; ~R () {}; int r; };
+struct T { T () {}; virtual ~T () {}; int t; };
+int c;
+struct A : public R, virtual public T { A () : b(c) {} int a; int &b; void m1 (); };
+
+void
+take (int &a, int &b, int &c, int &d)
+{
+ asm volatile ("" : : "g" (&a), "g" (&b), "g" (&c), "g" (&d) : "memory");
+}
+
+void
+A::m1 ()
+{
+ #pragma omp parallel private (a, T::t) shared (r, A::b) default(none)
+ {
+ int q = omp_get_thread_num (), q2;
+ a = q;
+ t = 3 * q;
+ #pragma omp single copyprivate (q2)
+ {
+ r = 2 * q;
+ b = 4 * q;
+ q2 = q;
+ }
+ take (a, r, t, b);
+ #pragma omp barrier
+ if (A::a != q || R::r != 2 * q2 || T::t != 3 * q || A::b != 4 * q2)
+ __builtin_abort ();
+ }
+ a = 7;
+ r = 8;
+ t = 9;
+ b = 10;
+ #pragma omp parallel shared (A::a) default (none) firstprivate (R::r, b) shared (t)
+ {
+ int q = omp_get_thread_num (), q2;
+ take (A::a, R::r, T::t, A::b);
+ if (a != 7 || r != 8 || t != 9 || b != 10)
+ __builtin_abort ();
+ R::r = 6 * q;
+ #pragma omp barrier
+ #pragma omp single copyprivate (q2)
+ {
+ A::a = 5 * q;
+ T::t = 7 * q;
+ q2 = q;
+ }
+ A::b = 8 * q;
+ take (a, r, t, b);
+ #pragma omp barrier
+ if (a != 5 * q2 || r != 6 * q || t != 7 * q2 || b != 8 * q)
+ __builtin_abort ();
+ }
+ a = 1;
+ b = 2;
+ R::r = 3;
+ t = 4;
+ bool f = false;
+ #pragma omp parallel private (f)
+ {
+ f = false;
+ #pragma omp single
+ #pragma omp taskloop default(none) firstprivate (r, A::a, f) shared (T::t, b)
+ for (int i = 0; i < 30; i++)
+ {
+ int q = omp_get_thread_num ();
+ int tv, bv;
+ #pragma omp atomic read
+ tv = t;
+ #pragma omp atomic read
+ bv = A::b;
+ if (i == 16)
+ {
+ if (bv != 2 || tv != 4)
+ __builtin_abort ();
+ }
+ else
+ {
+ if ((bv != 2 && bv != 8) || (tv != 4 && tv != 9))
+ __builtin_abort ();
+ }
+ if (!f)
+ {
+ if (A::a != 1 || R::r != 3)
+ __builtin_abort ();
+ }
+ else if (a != 7 * q || r != 9 * q)
+ __builtin_abort ();
+ take (a, r, t, b);
+ A::a = 7 * q;
+ R::r = 9 * q;
+ if (i == 16)
+ {
+ #pragma omp atomic write
+ A::b = 8;
+ #pragma omp atomic write
+ T::t = 9;
+ }
+ f = true;
+ }
+ }
+}
+
+int
+main ()
+{
+ A a;
+ a.m1 ();
+}