Skip to content

[flang][OpenMP] Don't allow namelist variables with threadprivate #130957

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

tblah
Copy link
Contributor

@tblah tblah commented Mar 12, 2025

While the standard doesn't explicitly mention namelist variables in this case, it does prohibit privatization of namelist variables. Flang decided to also prohibit namelist variables from appearing in a reduction clause.

Variables that are part of a namelist are linked to I/O mechanisms, and their memory association and initialization are managed by the compiler in a way that conflicts with the requirements of threadprivate variables. I propose we should add this restriction.

While the standard doesn't explicitly mention namelist variables in this
case, it does prohibit privatization of namelist variables. Flang
decided to also prohibit namelist variables from appearing in a
reduction clause.

Variables that are part of a namelist are linked to I/O mechanisms, and
their memory association and initialization are managed by the compiler
in a way that conflicts with the requirements of threadprivate
variables. I propose we should add this restriction.
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:openmp flang:semantics labels Mar 12, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 12, 2025

@llvm/pr-subscribers-flang-openmp

Author: Tom Eccles (tblah)

Changes

While the standard doesn't explicitly mention namelist variables in this case, it does prohibit privatization of namelist variables. Flang decided to also prohibit namelist variables from appearing in a reduction clause.

Variables that are part of a namelist are linked to I/O mechanisms, and their memory association and initialization are managed by the compiler in a way that conflicts with the requirements of threadprivate variables. I propose we should add this restriction.

Fixes #112538


Full diff: https://github.com/llvm/llvm-project/pull/130957.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/check-omp-structure.cpp (+9)
  • (added) flang/test/Semantics/OpenMP/threadprivate09.f90 (+12)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 5fcebdca0bc5f..e98c9c3091cb4 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1516,6 +1516,10 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
                       "A variable in a %s directive cannot appear in an "
                       "EQUIVALENCE statement"_err_en_US,
                       ContextDirectiveAsFortran());
+                } else if (name->symbol->test(Symbol::Flag::InNamelist)) {
+                  context_.Say(name->source,
+                      "A variable in a %s directive cannot appear in a NAMELIST"_err_en_US,
+                      ContextDirectiveAsFortran());
                 } else if (name->symbol->test(Symbol::Flag::OmpThreadprivate) &&
                     GetContext().directive ==
                         llvm::omp::Directive::OMPD_declare_target) {
@@ -1571,6 +1575,11 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
                           ContextDirectiveAsFortran(), obj->name(),
                           name.symbol->name());
                     }
+                    if (obj->test(Symbol::Flag::InNamelist)) {
+                      context_.Say(name.source,
+                          "A variable in a %s directive cannot appear in a NAMELIST"_err_en_US,
+                          ContextDirectiveAsFortran());
+                    }
                   }
                 }
               }
diff --git a/flang/test/Semantics/OpenMP/threadprivate09.f90 b/flang/test/Semantics/OpenMP/threadprivate09.f90
new file mode 100644
index 0000000000000..02236d19d9d01
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/threadprivate09.f90
@@ -0,0 +1,12 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags
+
+! Check that namelist variables cannot be used with threadprivate
+
+module m
+  integer :: nam1
+  common /com1/nam1
+  namelist /nam/nam1
+
+  !ERROR: A variable in a THREADPRIVATE directive cannot appear in a NAMELIST
+  !$omp threadprivate(/com1/)
+end

@llvmbot
Copy link
Member

llvmbot commented Mar 12, 2025

@llvm/pr-subscribers-flang-semantics

Author: Tom Eccles (tblah)

Changes

While the standard doesn't explicitly mention namelist variables in this case, it does prohibit privatization of namelist variables. Flang decided to also prohibit namelist variables from appearing in a reduction clause.

Variables that are part of a namelist are linked to I/O mechanisms, and their memory association and initialization are managed by the compiler in a way that conflicts with the requirements of threadprivate variables. I propose we should add this restriction.

Fixes #112538


Full diff: https://github.com/llvm/llvm-project/pull/130957.diff

2 Files Affected:

  • (modified) flang/lib/Semantics/check-omp-structure.cpp (+9)
  • (added) flang/test/Semantics/OpenMP/threadprivate09.f90 (+12)
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 5fcebdca0bc5f..e98c9c3091cb4 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1516,6 +1516,10 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
                       "A variable in a %s directive cannot appear in an "
                       "EQUIVALENCE statement"_err_en_US,
                       ContextDirectiveAsFortran());
+                } else if (name->symbol->test(Symbol::Flag::InNamelist)) {
+                  context_.Say(name->source,
+                      "A variable in a %s directive cannot appear in a NAMELIST"_err_en_US,
+                      ContextDirectiveAsFortran());
                 } else if (name->symbol->test(Symbol::Flag::OmpThreadprivate) &&
                     GetContext().directive ==
                         llvm::omp::Directive::OMPD_declare_target) {
@@ -1571,6 +1575,11 @@ void OmpStructureChecker::CheckThreadprivateOrDeclareTargetVar(
                           ContextDirectiveAsFortran(), obj->name(),
                           name.symbol->name());
                     }
+                    if (obj->test(Symbol::Flag::InNamelist)) {
+                      context_.Say(name.source,
+                          "A variable in a %s directive cannot appear in a NAMELIST"_err_en_US,
+                          ContextDirectiveAsFortran());
+                    }
                   }
                 }
               }
diff --git a/flang/test/Semantics/OpenMP/threadprivate09.f90 b/flang/test/Semantics/OpenMP/threadprivate09.f90
new file mode 100644
index 0000000000000..02236d19d9d01
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/threadprivate09.f90
@@ -0,0 +1,12 @@
+! RUN: %python %S/../test_errors.py %s %flang_fc1 %openmp_flags
+
+! Check that namelist variables cannot be used with threadprivate
+
+module m
+  integer :: nam1
+  common /com1/nam1
+  namelist /nam/nam1
+
+  !ERROR: A variable in a THREADPRIVATE directive cannot appear in a NAMELIST
+  !$omp threadprivate(/com1/)
+end

@kiranchandramohan
Copy link
Contributor

If it is not in the standard, could you comment on what other compilers (gfortran, ifx, nvfortran/armflang) do? You can use godbolt for it.

The function you are making this change is called CheckThreadprivateOrDeclareTargetVar. So is this for DeclareTargetVar as well? If so, could you add a test?

Copy link
Contributor

@mjklemm mjklemm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@tblah
Copy link
Contributor Author

tblah commented Mar 18, 2025

If it is not in the standard, could you comment on what other compilers (gfortran, ifx, nvfortran/armflang) do? You can use godbolt for it.

Using the original fujitsu test (see #112538), nvfortran complains that nam1 and nam2 are not threadprivate (they are inside of a threadprivate common block so I don't think that is correct). GFortran does compile it (and produces a correct result). ifx and ifort also allow the code.

The function you are making this change is called CheckThreadprivateOrDeclareTargetVar. So is this for DeclareTargetVar as well? If so, could you add a test?
That wasn't intentional. I imagine namelists wouldn't work with anything on the target device but I don't know enough to be sure so I will restrict this to only threadprivate for now.

I'm still unsure why CI is failing and I can't reproduce the failure on my machine. Hopefully it will fix after I push a change. 🤞

@tblah
Copy link
Contributor Author

tblah commented Mar 18, 2025

With #131888 we can build the original test and it produces the correct results, however in my opinion it still doesn't make sense to mix namelists with threadprivate. It is up to you @kiranchandramohan

@jeanPerier
Copy link
Contributor

I was initially in favor of restricting this, but a few people I work with and are closer to OpenMP disagreed and think that if the OpenMP standard did restrict the private clause case but told nothing about threadprivate, it is because the threadprivate case should work.

So I would be OK supporting this by detecting that there is a threadprivate in the namelist and generating a local namelist descriptor near the IO statement in that case.

@tblah tblah closed this Mar 19, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:openmp flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants