@@ -4038,7 +4038,8 @@ lower_rec_input_clauses (tree clauses, g
x = NULL;
do_private:
tree nx;
- nx = lang_hooks.decls.omp_clause_default_ctor (c, new_var, x);
+ nx = lang_hooks.decls.omp_clause_default_ctor
+ (c, unshare_expr (new_var), x);
if (is_simd)
{
tree y = lang_hooks.decls.omp_clause_dtor (c, new_var);
@@ -4192,7 +4193,8 @@ lower_rec_input_clauses (tree clauses, g
break;
}
}
- x = lang_hooks.decls.omp_clause_copy_ctor (c, new_var, x);
+ x = lang_hooks.decls.omp_clause_copy_ctor
+ (c, unshare_expr (new_var), x);
gimplify_and_add (x, ilist);
goto do_dtor;
@@ -1716,16 +1716,7 @@ cxx_omp_finish_clause (tree c, gimple_se
if (decl == error_mark_node)
make_shared = true;
else if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
- {
- if (is_invisiref_parm (decl))
- inner_type = TREE_TYPE (inner_type);
- else
- {
- error ("%qE implicitly determined as %<firstprivate%> has reference type",
- decl);
- make_shared = true;
- }
- }
+ inner_type = TREE_TYPE (inner_type);
/* We're interested in the base element, not arrays. */
while (TREE_CODE (inner_type) == ARRAY_TYPE)
@@ -5330,14 +5330,19 @@ finish_omp_clauses (tree clauses)
goto check_dup_generic;
case OMP_CLAUSE_LINEAR:
t = OMP_CLAUSE_DECL (c);
- if (!type_dependent_expression_p (t)
- && !INTEGRAL_TYPE_P (TREE_TYPE (t))
- && TREE_CODE (TREE_TYPE (t)) != POINTER_TYPE)
+ if (!type_dependent_expression_p (t))
{
- error ("linear clause applied to non-integral non-pointer "
- "variable with %qT type", TREE_TYPE (t));
- remove = true;
- break;
+ tree type = TREE_TYPE (t);
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ if (!INTEGRAL_TYPE_P (type)
+ && TREE_CODE (type) != POINTER_TYPE)
+ {
+ error ("linear clause applied to non-integral non-pointer "
+ "variable with %qT type", TREE_TYPE (t));
+ remove = true;
+ break;
+ }
}
t = OMP_CLAUSE_LINEAR_STEP (c);
if (t == NULL_TREE)
@@ -5362,14 +5367,16 @@ finish_omp_clauses (tree clauses)
if (TREE_CODE (OMP_CLAUSE_DECL (c)) == PARM_DECL)
t = maybe_constant_value (t);
t = fold_build_cleanup_point_expr (TREE_TYPE (t), t);
- if (TREE_CODE (TREE_TYPE (OMP_CLAUSE_DECL (c)))
- == POINTER_TYPE)
+ tree type = TREE_TYPE (OMP_CLAUSE_DECL (c));
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) == POINTER_TYPE)
{
+ tree d = convert_from_reference (OMP_CLAUSE_DECL (c));
t = pointer_int_sum (OMP_CLAUSE_LOCATION (c), PLUS_EXPR,
- OMP_CLAUSE_DECL (c), t);
+ d, t);
t = fold_build2_loc (OMP_CLAUSE_LOCATION (c),
- MINUS_EXPR, sizetype, t,
- OMP_CLAUSE_DECL (c));
+ MINUS_EXPR, sizetype, t, d);
if (t == error_mark_node)
{
remove = true;
@@ -5377,7 +5384,7 @@ finish_omp_clauses (tree clauses)
}
}
else
- t = fold_convert (TREE_TYPE (OMP_CLAUSE_DECL (c)), t);
+ t = fold_convert (type, t);
}
OMP_CLAUSE_LINEAR_STEP (c) = t;
}
@@ -6019,7 +6026,7 @@ finish_omp_clauses (tree clauses)
{
enum omp_clause_code c_kind = OMP_CLAUSE_CODE (c);
bool remove = false;
- bool need_complete_non_reference = false;
+ bool need_complete_type = false;
bool need_default_ctor = false;
bool need_copy_ctor = false;
bool need_copy_assignment = false;
@@ -6033,19 +6040,19 @@ finish_omp_clauses (tree clauses)
need_implicitly_determined = true;
break;
case OMP_CLAUSE_PRIVATE:
- need_complete_non_reference = true;
+ need_complete_type = true;
need_default_ctor = true;
need_dtor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_FIRSTPRIVATE:
- need_complete_non_reference = true;
+ need_complete_type = true;
need_copy_ctor = true;
need_dtor = true;
need_implicitly_determined = true;
break;
case OMP_CLAUSE_LASTPRIVATE:
- need_complete_non_reference = true;
+ need_complete_type = true;
need_copy_assignment = true;
need_implicitly_determined = true;
break;
@@ -6125,18 +6132,14 @@ finish_omp_clauses (tree clauses)
break;
}
- if (need_complete_non_reference || need_copy_assignment)
+ if (need_complete_type || need_copy_assignment)
{
t = require_complete_type (t);
if (t == error_mark_node)
remove = true;
else if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE
- && need_complete_non_reference)
- {
- error ("%qE has reference type for %qs", t,
- omp_clause_code_name[OMP_CLAUSE_CODE (c)]);
- remove = true;
- }
+ && !complete_type_or_else (TREE_TYPE (TREE_TYPE (t)), t))
+ remove = true;
}
if (need_implicitly_determined)
{
@@ -6171,12 +6174,13 @@ finish_omp_clauses (tree clauses)
/* We're interested in the base element, not arrays. */
inner_type = type = TREE_TYPE (t);
- while (TREE_CODE (inner_type) == ARRAY_TYPE)
- inner_type = TREE_TYPE (inner_type);
-
- if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ if ((need_complete_type
+ || need_copy_assignment
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION)
&& TREE_CODE (inner_type) == REFERENCE_TYPE)
inner_type = TREE_TYPE (inner_type);
+ while (TREE_CODE (inner_type) == ARRAY_TYPE)
+ inner_type = TREE_TYPE (inner_type);
/* Check for special function availability by building a call to one.
Save the results, because later we won't be in the right context
@@ -10,8 +10,8 @@ const A a;
void foo (A &p)
{
const A &q = a;
-#pragma omp task // { dg-error "has reference type" }
+#pragma omp task
bar (p);
-#pragma omp task // { dg-error "has reference type" }
+#pragma omp task
bar (q);
}
@@ -0,0 +1,26 @@
+// { dg-do compile }
+
+struct S; // { dg-message "forward declaration" }
+void foo (S &);
+
+void
+f1 (S &x) // { dg-error "has incomplete type" }
+{
+#pragma omp parallel private (x)
+ foo (x);
+}
+
+void
+f2 (S &x) // { dg-error "has incomplete type" }
+{
+#pragma omp parallel firstprivate (x)
+ foo (x);
+}
+
+void
+f3 (S &x) // { dg-error "has incomplete type" }
+{
+#pragma omp parallel for lastprivate (x)
+ for (int i = 0; i < 10; i++)
+ foo (x);
+}
@@ -0,0 +1,242 @@
+// { dg-do run }
+
+#include <omp.h>
+#include <assert.h>
+
+struct B
+{
+ static int ic, dc, xc, ac, cc;
+
+ B();
+ B(const B &);
+ ~B();
+ B& operator=(const B &);
+ void doit();
+ static void clear();
+};
+
+int B::ic;
+int B::dc;
+int B::xc;
+int B::cc;
+int B::ac;
+
+B::B()
+{
+ #pragma omp atomic
+ ic++;
+}
+
+B::~B()
+{
+ #pragma omp atomic
+ dc++;
+}
+
+B::B(const B &)
+{
+ #pragma omp atomic
+ cc++;
+}
+
+B& B::operator=(const B &)
+{
+ #pragma omp atomic
+ ac++;
+ return *this;
+}
+
+void B::doit()
+{
+ #pragma omp atomic
+ xc++;
+}
+
+void B::clear()
+{
+ ic = 0;
+ dc = 0;
+ cc = 0;
+ ac = 0;
+ xc = 0;
+}
+
+static int n;
+
+void f1(B &a)
+{
+ B b;
+ B &c = b;
+ #pragma omp parallel default(none) private(a, c) shared (n)
+ {
+ #pragma omp master
+ n = omp_get_num_threads ();
+ a.doit();
+ c.doit();
+ }
+}
+
+void f2(B &a)
+{
+ B b;
+ B &c = b;
+ #pragma omp parallel default(none) firstprivate(a, c) shared(n)
+ {
+ #pragma omp master
+ n = omp_get_num_threads ();
+ a.doit();
+ c.doit();
+ }
+}
+
+void f3(B &a)
+{
+ B b;
+ B &c = b;
+ #pragma omp parallel default(none) shared(n, a, c)
+ {
+ #pragma omp master
+ n = omp_get_num_threads ();
+ #pragma omp for lastprivate (a, c)
+ for (int i = 0; i < omp_get_num_threads (); i++)
+ {
+ a.doit();
+ c.doit();
+ }
+ }
+}
+
+void f4()
+{
+ B b;
+ B &c = b;
+ #pragma omp parallel default(none) private (c) shared (n)
+ {
+ B d;
+ B &e = d;
+ #pragma omp single copyprivate (c, e)
+ {
+ c.doit();
+ e.doit();
+ }
+ c.doit();
+ e.doit();
+ }
+}
+
+void f5(B (&a)[2])
+{
+ B b[2];
+ B (&c)[2] = b;
+ #pragma omp parallel default(none) private(a, c) shared (n)
+ {
+ #pragma omp master
+ n = omp_get_num_threads ();
+ a[0].doit();
+ a[1].doit();
+ c[0].doit();
+ c[1].doit();
+ }
+}
+
+void f6(B (&a)[2])
+{
+ B b[2];
+ B (&c)[2] = b;
+ #pragma omp parallel default(none) firstprivate(a, c) shared (n)
+ {
+ #pragma omp master
+ n = omp_get_num_threads ();
+ a[0].doit();
+ a[1].doit();
+ c[0].doit();
+ c[1].doit();
+ }
+}
+
+void f7(B (&a)[2])
+{
+ B b[2];
+ B (&c)[2] = b;
+ #pragma omp parallel default(none) shared(n, a, c)
+ {
+ #pragma omp master
+ n = omp_get_num_threads ();
+ #pragma omp for lastprivate (a, c)
+ for (int i = 0; i < omp_get_num_threads (); i++)
+ {
+ a[0].doit();
+ a[1].doit();
+ c[0].doit();
+ c[1].doit();
+ }
+ }
+}
+
+void f8()
+{
+ B b[2];
+ B (&c)[2] = b;
+ #pragma omp parallel default(none) private (c) shared (n)
+ {
+ B d[2];
+ B (&e)[2] = d;
+ #pragma omp single copyprivate (c, e)
+ {
+ c[0].doit();
+ c[1].doit();
+ e[0].doit();
+ e[1].doit();
+ }
+ c[0].doit();
+ c[1].doit();
+ e[0].doit();
+ e[1].doit();
+ }
+}
+
+int main()
+{
+ {
+ B a;
+ f1(a);
+ }
+ assert (B::xc == 2*n && B::ic == 2*n+2 && B::dc == 2*n+2 && B::ac == 0 && B::cc == 0);
+ B::clear();
+ {
+ B a;
+ f2(a);
+ }
+ assert (B::xc == 2*n && B::ic == 2 && B::dc == 2*n+2 && B::ac == 0 && B::cc == 2*n);
+ B::clear();
+ {
+ B a;
+ f3(a);
+ }
+ assert (B::xc == 2*n && B::ic == 2*n+2 && B::dc == 2*n+2 && B::ac == 2 && B::cc == 0);
+ B::clear();
+ f4();
+ assert (B::xc == 2*n+2 && B::ic == 2*n+1 && B::dc == 2*n+1 && B::ac == 2*n-2 && B::cc == 0);
+ B::clear();
+ {
+ B a[2];
+ f5(a);
+ }
+ assert (B::xc == 4*n && B::ic == 4*n+4 && B::dc == 4*n+4 && B::ac == 0 && B::cc == 0);
+ B::clear();
+ {
+ B a[2];
+ f6(a);
+ }
+ assert (B::xc == 4*n && B::ic == 4 && B::dc == 4*n+4 && B::ac == 0 && B::cc == 4*n);
+ B::clear();
+ {
+ B a[2];
+ f7(a);
+ }
+ assert (B::xc == 4*n && B::ic == 4*n+4 && B::dc == 4*n+4 && B::ac == 4 && B::cc == 0);
+ B::clear();
+ f8();
+ assert (B::xc == 4*n+4 && B::ic == 4*n+2 && B::dc == 4*n+2 && B::ac == 4*n-4 && B::cc == 0);
+ return 0;
+}
@@ -0,0 +1,43 @@
+// { dg-do run }
+// { dg-options "-O2" }
+// { dg-additional-options "-msse2" { target sse2_runtime } }
+// { dg-additional-options "-mavx" { target avx_runtime } }
+
+int a[1024];
+short b[2048];
+
+static inline void
+bar (int &x, unsigned long long &y, short *&z)
+{
+ a[x] = x + y + *z;
+ x++;
+ y += 17;
+ z += 2;
+}
+
+__attribute__((noinline, noclone)) int
+foo (unsigned long long &s, short *&t)
+{
+ int i, j = 0;
+ int &r = j;
+#pragma omp parallel for simd linear(r) linear(s:17ULL) linear(t:2)
+ for (i = 0; i < 1024; i++)
+ bar (r, s, t);
+ return j;
+}
+
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 2048; i++)
+ b[i] = 3 * i;
+ unsigned long long s = 12;
+ short *t = b;
+ int j = foo (s, t);
+ for (i = 0; i < 1024; i++)
+ if (a[i] != 12 + 24 * i)
+ __builtin_abort ();
+ if (j != 1024 || s != 12 + 1024 * 17ULL || t != &b[2048])
+ __builtin_abort ();
+}
@@ -0,0 +1,57 @@
+// { dg-do run }
+
+#include <omp.h>
+
+__attribute__((noinline, noclone)) void
+foo (int &a, short &d, char &g)
+{
+ unsigned long b = 12;
+ unsigned long &c = b;
+ long long e = 21;
+ long long &f = e;
+ unsigned int h = 12;
+ unsigned int &k = h;
+ #pragma omp parallel default(none) private(a, c) firstprivate(d, f) shared(g, k)
+ {
+ int i = omp_get_thread_num ();
+ a = i;
+ c = 2 * i;
+ if (d != 27 || f != 21)
+ __builtin_abort ();
+ d = 3 * (i & 0xfff);
+ f = 4 * i;
+ #pragma omp barrier
+ if (a != i || c != 2 * i || d != 3 * (i & 0xfff) || f != 4 * i)
+ __builtin_abort ();
+ #pragma omp for lastprivate(g, k)
+ for (int j = 0; j < 32; j++)
+ {
+ g = j;
+ k = 3 * j;
+ }
+ }
+ if (g != 31 || k != 31 * 3)
+ __builtin_abort ();
+ #pragma omp parallel for firstprivate (g, k) lastprivate (g, k)
+ for (int j = 0; j < 32; j++)
+ {
+ if (g != 31 || k != 31 * 3)
+ __builtin_abort ();
+ if (j == 31)
+ {
+ g = 29;
+ k = 138;
+ }
+ }
+ if (g != 29 || k != 138)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ int a = 5;
+ short d = 27;
+ char g = ' ';
+ foo (a, d, g);
+}