Compilation fails, if within a template function a const argument is used within an openmp parallel region with default(none). If shared(x) is specified also a "predetermined 'shared'" error is produced. Error: $ g++ -fopenmp pf.cc pf.cc: In function 'void g(T)': pf.cc:11:45: error: 'x' is predetermined 'shared' for 'shared' pf.cc: In function 'void f(T) [with T = int]': pf.cc:5:8: error: 'x' not specified in enclosing parallel pf.cc:5:8: error: enclosing parallel pf.cc: In function 'void g(T) [with T = int]': pf.cc:12:8: error: 'x' not specified in enclosing parallel pf.cc:12:8: error: enclosing parallel Version: $ gcc -v Using built-in specs. COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/home/me/gcc/libexec/gcc/i686-pc-cygwin/4.6.0/lto-wrapper.exe Target: i686-pc-cygwin Configured with: ./configure --enable-languages=c,c++ --prefix=/home/me/gcc --enable-libgomp Thread model: single gcc version 4.6.0 (GCC)
Created attachment 24534 [details] test case
The problem seems to be that x has T const type before instantiation, but int (without const) after instantiation. The spot where the const is lost is: type = type_decays_to (type); TREE_TYPE (r) = type; cp_apply_type_quals_to_decl (cp_type_quals (type), r); Does C++ really mandate stripping the toplevel qualifiers from the PARM_DECLs here? It isn't stripped from VAR_DECLs. OpenMP 2.5/OpenMP 3.0 says that const qualified parameters and variables are predetermined shared. While it hopefully changes in some way in OpenMP 3.1 (though, the current 3.1 draft wording is likely to change, as it is backwards incompatible with default(none)), for older standards the presence/lack of const makes a big difference.
Perhaps the top-level quals from the older type could be used, if the standard doesn't disallow it? Like, if T const arg is instantiated with T int or const int, it would be int const arg, while if it is T arg instantiated with int or const int, it would be int arg.
template <typename T> void f (int const x) { #pragma omp parallel default(none) int y = x; } template <typename T> void g (int const x) { #pragma omp parallel default(none) shared(x) int y = x; } void h () { f<int> (0); g<int> (0); } fails the same way, while after removing template <typename T> and <int> the toplevel qualifier stays and it works as expected. If the current C++ FE behavior is mandated by the standard, i.e. toplevel qualifiers must be always dropped from function arguments when in templates and not otherwise, OpenMP C++ support could just ignore TREE_READONLY on PARM_DECLs in templates or something, but it looks very weird to me.
This is a bug, an unintended consequence of the change to type_decays_to.
Changing the summary to reflect the underlying issue.
Author: jason Date: Tue Jun 21 19:05:25 2011 New Revision: 175271 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175271 Log: PR c++/49418 * call.c (cxx_type_promotes_to): Don't strip cv-quals. * semantics.c (lambda_return_type): Strip them here. Added: trunk/gcc/testsuite/g++.dg/template/param3.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/call.c trunk/gcc/cp/semantics.c trunk/gcc/testsuite/ChangeLog
Fixed on trunk.
Author: jason Date: Fri Jun 24 02:18:42 2011 New Revision: 175368 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175368 Log: PR c++/49418 * typeck2.c (build_functional_cast): Strip cv-quals for value init. * init.c (build_zero_init_1): Not here. Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/init.c trunk/gcc/cp/typeck2.c
Author: jason Date: Mon Jun 27 20:15:49 2011 New Revision: 175557 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=175557 Log: PR c++/49418 * call.c (cxx_type_promotes_to): Don't strip cv-quals. * semantics.c (lambda_return_type): Strip them here. Added: branches/gcc-4_6-branch/gcc/testsuite/g++.dg/template/param3.C Modified: branches/gcc-4_6-branch/gcc/cp/ChangeLog branches/gcc-4_6-branch/gcc/cp/call.c branches/gcc-4_6-branch/gcc/cp/semantics.c branches/gcc-4_6-branch/gcc/testsuite/ChangeLog
Fixed for 4.6.2.