@@ -519,12 +519,7 @@ c_split_parallel_clauses (location_t loc
/* True if OpenMP sharing attribute of DECL is predetermined. */
enum omp_clause_default_kind
-c_omp_predetermined_sharing (tree decl)
+c_omp_predetermined_sharing (tree decl ATTRIBUTE_UNUSED)
{
- /* Variables with const-qualified type having no mutable member
- are predetermined shared. */
- if (TREE_READONLY (decl))
- return OMP_CLAUSE_DEFAULT_SHARED;
-
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
@@ -10406,6 +10406,7 @@ c_finish_omp_clauses (tree clauses)
bool remove = false;
bool need_complete = false;
bool need_implicitly_determined = false;
+ bool no_const = false;
switch (OMP_CLAUSE_CODE (c))
{
@@ -10418,11 +10419,13 @@ c_finish_omp_clauses (tree clauses)
name = "private";
need_complete = true;
need_implicitly_determined = true;
+ no_const = true;
goto check_dup_generic;
case OMP_CLAUSE_REDUCTION:
name = "reduction";
need_implicitly_determined = true;
+ no_const = true;
t = OMP_CLAUSE_DECL (c);
if (AGGREGATE_TYPE_P (TREE_TYPE (t))
|| POINTER_TYPE_P (TREE_TYPE (t)))
@@ -10534,6 +10537,7 @@ c_finish_omp_clauses (tree clauses)
t = OMP_CLAUSE_DECL (c);
need_complete = true;
need_implicitly_determined = true;
+ no_const = true;
if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
{
error_at (OMP_CLAUSE_LOCATION (c),
@@ -10603,6 +10607,13 @@ c_finish_omp_clauses (tree clauses)
t, share_name, name);
remove = true;
}
+ else if (no_const && TREE_READONLY (t))
+ {
+ error_at (OMP_CLAUSE_LOCATION (c),
+ "const-qualified %qE cannot appear in %qs clause",
+ t, name);
+ remove = true;
+ }
}
}
@@ -1184,8 +1184,6 @@ cxx_omp_privatize_by_reference (const_tr
enum omp_clause_default_kind
cxx_omp_predetermined_sharing (tree decl)
{
- tree type;
-
/* Static data members are predetermined as shared. */
if (TREE_STATIC (decl))
{
@@ -1194,41 +1192,6 @@ cxx_omp_predetermined_sharing (tree decl
return OMP_CLAUSE_DEFAULT_SHARED;
}
- type = TREE_TYPE (decl);
- if (TREE_CODE (type) == REFERENCE_TYPE)
- {
- if (!is_invisiref_parm (decl))
- return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
- type = TREE_TYPE (type);
-
- if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl))
- {
- /* NVR doesn't preserve const qualification of the
- variable's type. */
- tree outer = outer_curly_brace_block (current_function_decl);
- tree var;
-
- if (outer)
- for (var = BLOCK_VARS (outer); var; var = DECL_CHAIN (var))
- if (DECL_NAME (decl) == DECL_NAME (var)
- && (TYPE_MAIN_VARIANT (type)
- == TYPE_MAIN_VARIANT (TREE_TYPE (var))))
- {
- if (TYPE_READONLY (TREE_TYPE (var)))
- type = TREE_TYPE (var);
- break;
- }
- }
- }
-
- if (type == error_mark_node)
- return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
-
- /* Variables with const-qualified type having no mutable member
- are predetermined shared. */
- if (TYPE_READONLY (type) && !cp_has_mutable_p (type))
- return OMP_CLAUSE_DEFAULT_SHARED;
-
return OMP_CLAUSE_DEFAULT_UNSPECIFIED;
}
@@ -3820,6 +3820,7 @@ finish_omp_clauses (tree clauses)
bool need_copy_ctor = false;
bool need_copy_assignment = false;
bool need_implicitly_determined = false;
+ bool no_const = false;
tree type, inner_type;
switch (c_kind)
@@ -3833,6 +3834,7 @@ finish_omp_clauses (tree clauses)
need_complete_non_reference = true;
need_default_ctor = true;
need_implicitly_determined = true;
+ no_const = true;
break;
case OMP_CLAUSE_FIRSTPRIVATE:
name = "firstprivate";
@@ -3845,10 +3847,12 @@ finish_omp_clauses (tree clauses)
need_complete_non_reference = true;
need_copy_assignment = true;
need_implicitly_determined = true;
+ no_const = true;
break;
case OMP_CLAUSE_REDUCTION:
name = "reduction";
need_implicitly_determined = true;
+ no_const = true;
break;
case OMP_CLAUSE_COPYPRIVATE:
name = "copyprivate";
@@ -3952,6 +3956,23 @@ finish_omp_clauses (tree clauses)
t, share_name, name);
remove = true;
}
+ else if (no_const)
+ {
+ type = TREE_TYPE (t);
+ if (type != error_mark_node
+ && TYPE_READONLY (type)
+ && (c_kind == OMP_CLAUSE_REDUCTION
+ || !cp_has_mutable_p (type)))
+ {
+ if (c_kind == OMP_CLAUSE_REDUCTION)
+ error ("const-qualified %qE cannot appear in "
+ "%<reduction%> clause", t);
+ else
+ error ("const-qualified %qE with no mutable member "
+ "cannot appear in %qs clause", t, name);
+ remove = true;
+ }
+ }
}
/* We're interested in the base element, not arrays. */
@@ -17,7 +17,7 @@ a24 (int a)
/* O.K. - a is listed in private clause */
/* - z is listed in shared clause */
x = c; /* O.K. - x is threadprivate */
- /* - c has const-qualified type */
+ /* { dg-error "'c' not specified" "" { target *-*-* } 19 } */
z[i] = y;
/* { dg-error "'i' not specified" "" { target *-*-* } 21 } */
/* { dg-error "enclosing parallel" "" { target *-*-* } 13 } */
@@ -44,7 +44,7 @@ main (void)
thrglobalvar++; /* Predetermined - threadprivate. */
thrlocvar++; /* Predetermined - threadprivate. */
foo (i); /* Predetermined - private (omp for loop variable). */
- foo (constvar); /* Predetermined - shared (const qualified type). */
+ foo (constvar); /* { dg-error "not specified in" } */
foo (*p); /* *p predetermined - shared (heap allocated */
(*p)++; /* storage). */
bar (p); /* Explicitly determined - private. */
@@ -80,15 +80,15 @@ foo (int x)
;
#pragma omp p reduction (*:t) /* { dg-error "predetermined 'threadprivate" } */
;
-#pragma omp p shared (c) /* { dg-error "predetermined 'shared'" } */
+#pragma omp p shared (c)
;
-#pragma omp p private (c) /* { dg-error "predetermined 'shared'" } */
+#pragma omp p private (c) /* { dg-error "cannot appear in 'private'" } */
;
-#pragma omp p firstprivate (c) /* { dg-error "predetermined 'shared'" } */
+#pragma omp p firstprivate (c)
;
-#pragma omp p for lastprivate (c) /* { dg-error "predetermined 'shared'" } */
+#pragma omp p for lastprivate (c) /* { dg-error "cannot appear in 'lastprivate'" } */
for (i = 0; i < 10; i++)
;
-#pragma omp p reduction (*:c) /* { dg-error "predetermined 'shared'" } */
+#pragma omp p reduction (*:c) /* { dg-error "cannot appear in 'reduction'" } */
;
}
@@ -0,0 +1,33 @@
+// { dg-do compile }
+// { dg-options "-fopenmp" }
+
+struct A { int i; A (); ~A (); };
+struct B { int i; };
+struct C { int i; mutable int j; C (); ~C (); };
+
+template <typename T> void bar (const T *);
+
+const A a;
+const C c;
+
+const A foo (const A d, const C e)
+{
+ const A f;
+ const B b = { 4 };
+ A g;
+ #pragma omp parallel private (a) // { dg-error "cannot appear in 'private'" }
+ bar (&a);
+ #pragma omp parallel private (b) // { dg-error "cannot appear in 'private'" }
+ bar (&b);
+ #pragma omp parallel private (c)
+ bar (&c);
+ #pragma omp parallel private (d) // { dg-error "cannot appear in 'private'" }
+ bar (&d);
+ #pragma omp parallel private (e)
+ bar (&e);
+ #pragma omp parallel private (f) // { dg-error "cannot appear in 'private'" }
+ bar (&f);
+ #pragma omp parallel private (g)
+ bar (&g);
+ return f;
+}
@@ -61,7 +61,7 @@ main (void)
thrglobalvar++; /* Predetermined - threadprivate. */
thrlocvar++; /* Predetermined - threadprivate. */
foo (i); /* Predetermined - private (omp for loop variable). */
- foo (constvar.x); /* Predetermined - shared (const qualified type). */
+ foo (constvar.x); /* { dg-error "not specified in" } */
foo (T::t.i); /* Predetermined - shared (static data member). */
foo (*p); /* *p predetermined - shared (heap allocated */
(*p)++; /* storage). */
@@ -80,15 +80,15 @@ foo (int x)
;
#pragma omp p reduction (*:t) // { dg-error "predetermined 'threadprivate'" }
;
-#pragma omp p shared (c) // { dg-error "predetermined 'shared'" }
+#pragma omp p shared (c)
;
-#pragma omp p private (c) // { dg-error "predetermined 'shared'" }
+#pragma omp p private (c) // { dg-error "cannot appear in 'private'" }
;
-#pragma omp p firstprivate (c) // { dg-error "predetermined 'shared'" }
+#pragma omp p firstprivate (c)
;
-#pragma omp p for lastprivate (c) // { dg-error "predetermined 'shared'" }
+#pragma omp p for lastprivate (c) // { dg-error "cannot appear in 'lastprivate'" }
for (i = 0; i < 10; i++)
;
-#pragma omp p reduction (*:c) // { dg-error "predetermined 'shared'" }
+#pragma omp p reduction (*:c) // { dg-error "cannot appear in 'reduction'" }
;
}
@@ -15,18 +15,18 @@ const A foo (const A d, const C e)
const A f;
const B b = { 4 };
A g;
- #pragma omp parallel default (none)
- bar (&a);
- #pragma omp parallel default (none)
- bar (&b);
+ #pragma omp parallel default (none) // { dg-error "enclosing parallel" }
+ bar (&a); // { dg-error "not specified" }
+ #pragma omp parallel default (none) // { dg-error "enclosing parallel" }
+ bar (&b); // { dg-error "not specified" }
#pragma omp parallel default (none) // { dg-error "enclosing parallel" }
bar (&c); // { dg-error "not specified" }
- #pragma omp parallel default (none)
- bar (&d);
+ #pragma omp parallel default (none) // { dg-error "enclosing parallel" }
+ bar (&d); // { dg-error "not specified" }
#pragma omp parallel default (none) // { dg-error "enclosing parallel" }
bar (&e); // { dg-error "not specified" }
- #pragma omp parallel default (none)
- bar (&f);
+ #pragma omp parallel default (none) // { dg-error "enclosing parallel" }
+ bar (&f); // { dg-error "not specified" }
#pragma omp parallel default (none) // { dg-error "enclosing parallel" }
bar (&g); // { dg-error "not specified" }
return f;