Hi! modules.cc has apparently support for extensions and attempts to ensure that if a module is compiled with those extensions enabled, sources which use the module are compiled with the same extensions. The only extension supported is SE_OPENMP right now. And the use of the extension is keyed on streaming out or in OMP_CLAUSE tree. This is undesirable for several reasons. OMP_CLAUSE is the only tree which can appear in the IL even without -fopenmp/-fopenmp-simd/-fopenacc (when simd ("notinbranch") or simd ("inbranch") attributes are used), and it can appear also in all the 3 modes mentioned above. On the other side, with the exception of arguments of attributes added e.g. for declare simd where no harm should be done if -fopenmp/-fopenmp-simd isn't enabled later on, OMP_CLAUSE appears in OMP_*_CLAUSES of OpenMP/OpenACC construct trees. And those construct trees often have no clauses at all, so keying the extension on OMP_CLAUSE doesn't catch many cases that should be caught. Furthermore, for OpenMP we have 2 modes, -fopenmp-simd which parses some OpenMP but constructs from that mostly OMP_SIMD and a few other cases, and -fopenmp which includes that and far more on top of that; and there is also -fopenacc.
So, this patch stops setting/requesting the extension on OMP_CLAUSE, introduces 3 extensions rather than one (SE_OPENMP_SIMD, SE_OPENMP and SE_OPENACC) and keyes those on OpenMP constructs from the -fopenmp-simd subset, other OpenMP constructs and OpenACC constructs. 2025-03-05 Jakub Jelinek <ja...@redhat.com> PR c++/119102 gcc/cp/ * module.cc (enum streamed_extensions): Add SE_OPENMP_SIMD and SE_OPENACC, change value of SE_OPENMP and SE_BITS. (CASE_OMP_SIMD_CODE, CASE_OMP_CODE, CASE_OACC_CODE): Define. (trees_out::start): Don't set SE_OPENMP extension for OMP_CLAUSE. Set SE_OPENMP_SIMD extension for CASE_OMP_SIMD_CODE, SE_OPENMP for CASE_OMP_CODE and SE_OPENACC for CASE_OACC_CODE. (trees_in::start): Don't fail for OMP_CLAUSE with missing SE_OPENMP extension. Do fail for CASE_OMP_SIMD_CODE and missing SE_OPENMP_SIMD extension, or CASE_OMP_CODE and missing SE_OPENMP extension, or CASE_OACC_CODE and missing SE_OPENACC extension. (module_state::write_readme): Write all of SE_OPENMP_SIMD, SE_OPENMP and SE_OPENACC extensions. (module_state::read_config): Diagnose missing -fopenmp, -fopenmp-simd and/or -fopenacc depending on extensions used. gcc/testsuite/ * g++.dg/modules/pr119102_a.H: New test. * g++.dg/modules/pr119102_b.C: New test. * g++.dg/modules/omp-3_a.C: New test. * g++.dg/modules/omp-3_b.C: New test. * g++.dg/modules/omp-3_c.C: New test. * g++.dg/modules/omp-3_d.C: New test. * g++.dg/modules/oacc-1_a.C: New test. * g++.dg/modules/oacc-1_b.C: New test. * g++.dg/modules/oacc-1_c.C: New test. --- gcc/cp/module.cc.jj 2025-03-03 17:36:37.263748933 +0100 +++ gcc/cp/module.cc 2025-03-04 17:52:16.439987517 +0100 @@ -3613,8 +3613,10 @@ void slurping::release_macros () /* Flags for extensions that end up being streamed. */ enum streamed_extensions { - SE_OPENMP = 1 << 0, - SE_BITS = 1 + SE_OPENMP_SIMD = 1 << 0, + SE_OPENMP = 1 << 1, + SE_OPENACC = 1 << 2, + SE_BITS = 3 }; /* Counter indices. */ @@ -5276,6 +5278,53 @@ trees_in::tree_list (bool has_purpose) return res; } + +#define CASE_OMP_SIMD_CODE \ + case OMP_SIMD: \ + case OMP_STRUCTURED_BLOCK: \ + case OMP_LOOP: \ + case OMP_ORDERED: \ + case OMP_TILE: \ + case OMP_UNROLL +#define CASE_OMP_CODE \ + case OMP_PARALLEL: \ + case OMP_TASK: \ + case OMP_FOR: \ + case OMP_DISTRIBUTE: \ + case OMP_TASKLOOP: \ + case OMP_TEAMS: \ + case OMP_TARGET_DATA: \ + case OMP_TARGET: \ + case OMP_SECTIONS: \ + case OMP_CRITICAL: \ + case OMP_SINGLE: \ + case OMP_SCOPE: \ + case OMP_TASKGROUP: \ + case OMP_MASKED: \ + case OMP_DISPATCH: \ + case OMP_INTEROP: \ + case OMP_MASTER: \ + case OMP_TARGET_UPDATE: \ + case OMP_TARGET_ENTER_DATA: \ + case OMP_TARGET_EXIT_DATA: \ + case OMP_METADIRECTIVE: \ + case OMP_ATOMIC: \ + case OMP_ATOMIC_READ: \ + case OMP_ATOMIC_CAPTURE_OLD: \ + case OMP_ATOMIC_CAPTURE_NEW +#define CASE_OACC_CODE \ + case OACC_PARALLEL: \ + case OACC_KERNELS: \ + case OACC_SERIAL: \ + case OACC_DATA: \ + case OACC_HOST_DATA: \ + case OACC_LOOP: \ + case OACC_CACHE: \ + case OACC_DECLARE: \ + case OACC_ENTER_DATA: \ + case OACC_EXIT_DATA: \ + case OACC_UPDATE + /* Start tree write. Write information to allocate the receiving node. */ @@ -5311,10 +5360,21 @@ trees_out::start (tree t, bool code_stre break; case OMP_CLAUSE: - state->extensions |= SE_OPENMP; u (OMP_CLAUSE_CODE (t)); break; + CASE_OMP_SIMD_CODE: + state->extensions |= SE_OPENMP_SIMD; + break; + + CASE_OMP_CODE: + state->extensions |= SE_OPENMP; + break; + + CASE_OACC_CODE: + state->extensions |= SE_OPENACC; + break; + case STRING_CST: str (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t)); break; @@ -5383,13 +5443,25 @@ trees_in::start (unsigned code) break; case OMP_CLAUSE: - { - if (!(state->extensions & SE_OPENMP)) - goto fail; + t = build_omp_clause (UNKNOWN_LOCATION, omp_clause_code (u ())); + break; - unsigned omp_code = u (); - t = build_omp_clause (UNKNOWN_LOCATION, omp_clause_code (omp_code)); - } + CASE_OMP_SIMD_CODE: + if (!(state->extensions & SE_OPENMP_SIMD)) + goto fail; + t = make_node (tree_code (code)); + break; + + CASE_OMP_CODE: + if (!(state->extensions & SE_OPENMP)) + goto fail; + t = make_node (tree_code (code)); + break; + + CASE_OACC_CODE: + if (!(state->extensions & SE_OPENACC)) + goto fail; + t = make_node (tree_code (code)); break; case STRING_CST: @@ -15402,8 +15474,13 @@ module_state::write_readme (elf_out *to, readme.printf ("source: %s", main_input_filename); readme.printf ("dialect: %s", dialect); if (extensions) - readme.printf ("extensions: %s", - extensions & SE_OPENMP ? "-fopenmp" : ""); + readme.printf ("extensions: %s%s%s", + extensions & SE_OPENMP ? "-fopenmp" + : extensions & SE_OPENMP_SIMD ? "-fopenmp-simd" : "", + (extensions & SE_OPENACC) + && (extensions & (SE_OPENMP | SE_OPENMP_SIMD)) + ? " " : "", + extensions & SE_OPENACC ? "-fopenacc" : ""); /* The following fields could be expected to change between otherwise identical compilations. Consider a distributed build @@ -19166,12 +19243,22 @@ module_state::read_config (module_state_ too. */ { unsigned ext = cfg.u (); - unsigned allowed = (flag_openmp ? SE_OPENMP : 0); + unsigned allowed = (flag_openmp ? SE_OPENMP | SE_OPENMP_SIMD : 0); + if (flag_openmp_simd) + allowed |= SE_OPENMP_SIMD; + if (flag_openacc) + allowed |= SE_OPENACC; if (unsigned bad = ext & ~allowed) { if (bad & SE_OPENMP) error_at (loc, "module contains OpenMP, use %<-fopenmp%> to enable"); + else if (bad & SE_OPENMP_SIMD) + error_at (loc, "module contains OpenMP, use %<-fopenmp%> or " + "%<-fopenmp-simd%> to enable"); + if (bad & SE_OPENACC) + error_at (loc, "module contains OpenACC, use %<-fopenacc%> to " + "enable"); cfg.set_overrun (); goto done; } --- gcc/testsuite/g++.dg/modules/pr119102_a.H.jj 2025-03-04 17:58:56.669389212 +0100 +++ gcc/testsuite/g++.dg/modules/pr119102_a.H 2025-03-04 17:58:48.221507257 +0100 @@ -0,0 +1,9 @@ +// PR c++/119102 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +int foo (int) +#if defined __x86_64__ || defined __aarch64__ +__attribute__((simd ("notinbranch"))) +#endif +; --- gcc/testsuite/g++.dg/modules/pr119102_b.C.jj 2025-03-04 17:59:31.234906196 +0100 +++ gcc/testsuite/g++.dg/modules/pr119102_b.C 2025-03-04 17:59:26.480972633 +0100 @@ -0,0 +1,9 @@ +// PR c++/119102 +// { dg-additional-options "-fmodules-ts" } + +import "pr119102_a.H"; + +int +main () +{ +} --- gcc/testsuite/g++.dg/modules/omp-3_a.C.jj 2025-03-04 18:28:22.694702204 +0100 +++ gcc/testsuite/g++.dg/modules/omp-3_a.C 2025-03-04 18:29:13.524991414 +0100 @@ -0,0 +1,14 @@ +// { dg-additional-options "-fmodules-ts -fopenmp-simd" } +// { dg-require-effective-target pthread } + +export module foo; +// { dg-module-cmi foo { target pthread } } + +export inline void frob (unsigned (&ary)[64]) +{ + int sum = 0; + +#pragma omp simd safelen(16) aligned (ary : 16) + for (unsigned ix = 0; ix < 64; ix++) + ary[ix] *= 2; +} --- gcc/testsuite/g++.dg/modules/omp-3_b.C.jj 2025-03-04 18:28:26.447649726 +0100 +++ gcc/testsuite/g++.dg/modules/omp-3_b.C 2025-03-04 18:29:36.630668318 +0100 @@ -0,0 +1,11 @@ +// { dg-additional-options "-fmodules-ts -fopenmp-simd" } +// { dg-require-effective-target pthread } + +import foo; + +unsigned ary[64]; + +int main () +{ + frob (ary); +} --- gcc/testsuite/g++.dg/modules/omp-3_c.C.jj 2025-03-04 18:28:30.428594057 +0100 +++ gcc/testsuite/g++.dg/modules/omp-3_c.C 2025-03-04 18:43:53.955666435 +0100 @@ -0,0 +1,11 @@ +// { dg-additional-options "-fmodules-ts -fopenmp" } +// { dg-require-effective-target pthread } + +import foo; + +unsigned ary[64]; + +int main () +{ + frob (ary); +} --- gcc/testsuite/g++.dg/modules/omp-3_d.C.jj 2025-03-04 18:43:59.424589869 +0100 +++ gcc/testsuite/g++.dg/modules/omp-3_d.C 2025-03-04 18:44:37.401058197 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-require-effective-target pthread } + +import foo; + +// { dg-regexp "In module imported at \[^\n]*omp-3_d.C:4:1:\nfoo: error: module contains OpenMP, use '-fopenmp' or '-fopenmp-simd' to enable\n" } +// { dg-prune-output "failed to read" } +// { dg-prune-output "fatal error:" } +// { dg-prune-output "compilation terminated" } --- gcc/testsuite/g++.dg/modules/oacc-1_a.C.jj 2025-03-04 18:45:22.097432445 +0100 +++ gcc/testsuite/g++.dg/modules/oacc-1_a.C 2025-03-04 18:50:18.536284123 +0100 @@ -0,0 +1,15 @@ +// { dg-additional-options "-fmodules-ts -fopenacc" } +// { dg-require-effective-target pthread } + +export module foo; +// { dg-module-cmi foo { target pthread } } + +export inline void frob (unsigned (&ary)[64]) +{ + int sum, i; +#pragma acc parallel +#pragma acc loop gang worker vector reduction (+:sum) + for (i = 0; i < 64; i++) + sum += ary[i]; + ary[0] += sum; +} --- gcc/testsuite/g++.dg/modules/oacc-1_b.C.jj 2025-03-04 18:48:24.387880885 +0100 +++ gcc/testsuite/g++.dg/modules/oacc-1_b.C 2025-03-04 18:48:38.816679049 +0100 @@ -0,0 +1,11 @@ +// { dg-additional-options "-fmodules-ts -fopenacc" } +// { dg-require-effective-target pthread } + +import foo; + +unsigned ary[64]; + +int main () +{ + frob (ary); +} --- gcc/testsuite/g++.dg/modules/oacc-1_c.C.jj 2025-03-04 18:48:44.342601750 +0100 +++ gcc/testsuite/g++.dg/modules/oacc-1_c.C 2025-03-04 18:49:01.724358608 +0100 @@ -0,0 +1,9 @@ +// { dg-additional-options "-fmodules-ts" } +// { dg-require-effective-target pthread } + +import foo; + +// { dg-regexp "In module imported at \[^\n]*oacc-1_c.C:4:1:\nfoo: error: module contains OpenACC, use '-fopenacc' to enable\n" } +// { dg-prune-output "failed to read" } +// { dg-prune-output "fatal error:" } +// { dg-prune-output "compilation terminated" } Jakub