Hi! My clarification request for ambiguity in the new OpenMP 3.1 standard http://www.openmp.org/forum/viewtopic.php?f=10&t=1198 has been resolved in that const qualified static data members with no mutable members should be allowed in firstprivate clauses. The following patch implements it, regtested on x86_64-linux, committed to gomp-3_1-branch.
2011-07-29 Jakub Jelinek <ja...@redhat.com> * cp-tree.h (cxx_omp_const_qual_no_mutable): New prototype. * cp-gimplify.c (cxx_omp_const_qual_no_mutable): New function. (cxx_omp_predetermined_sharing): Use it. * semantics.c (finish_omp_clauses): Allow const qualified static data members having no mutable member in firstprivate clauses. * g++.dg/gomp/sharing-2.C: New test. --- gcc/cp/cp-tree.h.jj 2011-07-11 17:43:48.000000000 +0200 +++ gcc/cp/cp-tree.h 2011-07-29 18:34:03.000000000 +0200 @@ -5761,6 +5761,7 @@ extern void init_shadowed_var_for_decl extern int cp_gimplify_expr (tree *, gimple_seq *, gimple_seq *); extern void cp_genericize (tree); +extern bool cxx_omp_const_qual_no_mutable (tree); extern enum omp_clause_default_kind cxx_omp_predetermined_sharing (tree); extern tree cxx_omp_clause_default_ctor (tree, tree, tree); extern tree cxx_omp_clause_copy_ctor (tree, tree, tree); --- gcc/cp/cp-gimplify.c.jj 2011-07-11 19:57:49.000000000 +0200 +++ gcc/cp/cp-gimplify.c 2011-07-29 18:33:14.000000000 +0200 @@ -1367,26 +1367,15 @@ cxx_omp_privatize_by_reference (const_tr return is_invisiref_parm (decl); } -/* True if OpenMP sharing attribute of DECL is predetermined. */ - -enum omp_clause_default_kind -cxx_omp_predetermined_sharing (tree decl) +/* Return true if DECL is const qualified var having no mutable member. */ +bool +cxx_omp_const_qual_no_mutable (tree decl) { - tree type; - - /* Static data members are predetermined as shared. */ - if (TREE_STATIC (decl)) - { - tree ctx = CP_DECL_CONTEXT (decl); - if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) - return OMP_CLAUSE_DEFAULT_SHARED; - } - - type = TREE_TYPE (decl); + tree type = TREE_TYPE (decl); if (TREE_CODE (type) == REFERENCE_TYPE) { if (!is_invisiref_parm (decl)) - return OMP_CLAUSE_DEFAULT_UNSPECIFIED; + return false; type = TREE_TYPE (type); if (TREE_CODE (decl) == RESULT_DECL && DECL_NAME (decl)) @@ -1410,11 +1399,32 @@ cxx_omp_predetermined_sharing (tree decl } if (type == error_mark_node) - return OMP_CLAUSE_DEFAULT_UNSPECIFIED; + return false; /* Variables with const-qualified type having no mutable member are predetermined shared. */ if (TYPE_READONLY (type) && !cp_has_mutable_p (type)) + return true; + + return false; +} + +/* True if OpenMP sharing attribute of DECL is predetermined. */ + +enum omp_clause_default_kind +cxx_omp_predetermined_sharing (tree decl) +{ + /* Static data members are predetermined shared. */ + if (TREE_STATIC (decl)) + { + tree ctx = CP_DECL_CONTEXT (decl); + if (TYPE_P (ctx) && MAYBE_CLASS_TYPE_P (ctx)) + return OMP_CLAUSE_DEFAULT_SHARED; + } + + /* Const qualified vars having no mutable member are predetermined + shared. */ + if (cxx_omp_const_qual_no_mutable (decl)) return OMP_CLAUSE_DEFAULT_SHARED; return OMP_CLAUSE_DEFAULT_UNSPECIFIED; --- gcc/cp/semantics.c.jj 2011-07-11 21:43:48.000000000 +0200 +++ gcc/cp/semantics.c 2011-07-29 18:34:34.000000000 +0200 @@ -4085,12 +4085,9 @@ finish_omp_clauses (tree clauses) case OMP_CLAUSE_DEFAULT_UNSPECIFIED: break; case OMP_CLAUSE_DEFAULT_SHARED: - /* const vars may be specified in firstprivate clause, - but don't allow static data members. */ + /* const vars may be specified in firstprivate clause. */ if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE - && (!TREE_STATIC (t) - || !TYPE_P (CP_DECL_CONTEXT (t)) - || !MAYBE_CLASS_TYPE_P (CP_DECL_CONTEXT (t)))) + && cxx_omp_const_qual_no_mutable (t)) break; share_name = "shared"; break; --- gcc/testsuite/g++.dg/gomp/sharing-2.C.jj 2011-07-29 18:48:33.000000000 +0200 +++ gcc/testsuite/g++.dg/gomp/sharing-2.C 2011-07-29 18:48:23.000000000 +0200 @@ -0,0 +1,47 @@ +// { dg-do compile } + +struct T +{ + int i; + mutable int j; +}; +struct S +{ + const static int d = 1; + const static T e; + void foo (int, T); +}; + +const int S::d; +const T S::e = { 2, 3 }; + +void bar (const int &); + +void +S::foo (const int x, const T y) +{ + #pragma omp parallel firstprivate (x) + bar (x); + #pragma omp parallel firstprivate (d) + bar (d); + #pragma omp parallel firstprivate (y) + bar (y.i); + #pragma omp parallel firstprivate (e) // { dg-error "is predetermined" } + bar (e.i); + #pragma omp parallel shared (x) // { dg-error "is predetermined" } + bar (x); + #pragma omp parallel shared (d) // { dg-error "is predetermined" } + bar (d); + #pragma omp parallel shared (e) // { dg-error "is predetermined" } + bar (e.i); + #pragma omp parallel shared (y) + bar (y.i); + #pragma omp parallel private (x) // { dg-error "is predetermined" } + bar (x); + #pragma omp parallel private (d) // { dg-error "is predetermined" } + bar (d); + #pragma omp parallel private (y) + bar (y.i); + #pragma omp parallel private (e) // { dg-error "is predetermined" } + bar (e.i); +} Jakub