Index: flang/include/flang/Semantics/symbol.h =================================================================== --- flang/include/flang/Semantics/symbol.h +++ flang/include/flang/Semantics/symbol.h @@ -493,6 +493,7 @@ LocalityLocalInit, // named in LOCAL_INIT locality-spec LocalityShared, // named in SHARED locality-spec InDataStmt, // initialized in a DATA statement + InNamelist, // flag is set if the symbol is in Namelist statement // OpenACC data-sharing attribute AccPrivate, AccFirstPrivate, AccShared, // OpenACC data-mapping attribute Index: flang/lib/Semantics/check-omp-structure.h =================================================================== --- flang/lib/Semantics/check-omp-structure.h +++ flang/lib/Semantics/check-omp-structure.h @@ -185,8 +185,11 @@ void CheckDependList(const parser::DataRef &); void CheckDependArraySection( const common::Indirection &, const parser::Name &); - void CheckIsVarPartOfAnotherVar(const parser::OmpObjectList &objList); + void CheckIntentInPointer( + const parser::OmpObjectList &, const llvm::omp::Clause); + void GetSymbolsInObjectList( + const parser::OmpObjectList &, std::vector &); }; } // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_ Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -417,6 +417,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) { CheckAllowed(llvm::omp::Clause::OMPC_private); CheckIsVarPartOfAnotherVar(x.v); + CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_private); } void OmpStructureChecker::CheckIsVarPartOfAnotherVar( @@ -693,4 +694,38 @@ } } +void OmpStructureChecker::CheckIntentInPointer( + const parser::OmpObjectList &objectList, const llvm::omp::Clause clause) { + std::vector symbols; + GetSymbolsInObjectList(objectList, symbols); + for (const auto *symbol : symbols) { + if (IsPointer(*symbol) && IsIntentIn(*symbol)) { + context_.Say(GetContext().clauseSource, + "Pointer '%s' with the INTENT(IN) attribute may not appear " + "in a %s clause"_err_en_US, + symbol->name(), + parser::ToUpperCaseLetters(getClauseName(clause).str())); + } + } +} + +void OmpStructureChecker::GetSymbolsInObjectList( + const parser::OmpObjectList &objectList, + std::vector &symbols) { + for (const auto &ompObject : objectList.v) { + if (const auto *name{parser::Unwrap(ompObject)}) { + if (const auto *symbol{name->symbol}) { + if (const auto *commonBlockDetails{ + symbol->detailsIf()}) { + for (const auto &object : commonBlockDetails->objects()) { + symbols.emplace_back(&object->GetUltimate()); + } + } else { + symbols.emplace_back(&symbol->GetUltimate()); + } + } + } + } +} + } // namespace Fortran::semantics Index: flang/lib/Semantics/resolve-directives.cpp =================================================================== --- flang/lib/Semantics/resolve-directives.cpp +++ flang/lib/Semantics/resolve-directives.cpp @@ -371,6 +371,8 @@ const parser::Name &, const Symbol &, Symbol::Flag); void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause); + void CheckObjectInNamelist( + const parser::Name &, const Symbol &, Symbol::Flag); }; template @@ -1046,6 +1048,10 @@ if (dataSharingAttributeFlags.test(ompFlag)) { CheckMultipleAppearances(*name, *symbol, ompFlag); } + if (privateDataSharingAttributeFlags.test(ompFlag)) { + CheckObjectInNamelist(*name, *symbol, ompFlag); + } + if (ompFlag == Symbol::Flag::OmpAllocate) { AddAllocateName(name); } @@ -1197,4 +1203,18 @@ } } +void OmpAttributeVisitor::CheckObjectInNamelist( + const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) { + if (symbol.GetUltimate().test(Symbol::Flag::InNamelist)) { + llvm::StringRef clauseName{"PRIVATE"}; + if (ompFlag == Symbol::Flag::OmpFirstPrivate) + clauseName = "FIRSTPRIVATE"; + else if (ompFlag == Symbol::Flag::OmpLastPrivate) + clauseName = "LASTPRIVATE"; + context_.Say(name.source, + "Variable '%s' in NAMELIST cannot be in a %s clause"_err_en_US, + name.ToString(), clauseName.str()); + } +} + } // namespace Fortran::semantics Index: flang/lib/Semantics/resolve-names.cpp =================================================================== --- flang/lib/Semantics/resolve-names.cpp +++ flang/lib/Semantics/resolve-names.cpp @@ -4289,6 +4289,7 @@ } else if (!ConvertToObjectEntity(*symbol)) { SayWithDecl(name, *symbol, "'%s' is not a variable"_err_en_US); } + symbol->GetUltimate().set(Symbol::Flag::InNamelist); details.add_object(*symbol); } Index: flang/test/Semantics/omp-private01.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-private01.f90 @@ -0,0 +1,20 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.3.3 private Clause +! Pointers with the INTENT(IN) attribute may not appear in a private clause. + +subroutine omp_private(p) + integer :: a(10), b(10), c(10) + integer, pointer, intent(in) :: p + + a = 10 + b = 20 + + !ERROR: Pointer 'p' with the INTENT(IN) attribute may not appear in a PRIVATE clause + !$omp parallel private(p) + c = a + b + p + !$omp end parallel + + print *, c + +end subroutine omp_private Index: flang/test/Semantics/omp-private02.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-private02.f90 @@ -0,0 +1,46 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.3.3 private Clause +! Variables that appear in namelist statements may not appear in a private clause. + +module test + integer :: a, b, c + namelist /nlist1/ a, b +end module + +program omp_private + use test + + integer :: p(10) ,q(10) + namelist /nlist2/ c, d + + a = 5 + b = 10 + c = 100 + + !ERROR: Variable 'a' in NAMELIST cannot be in a PRIVATE clause + !ERROR: Variable 'c' in NAMELIST cannot be in a PRIVATE clause + !$omp parallel private(a, c) + d = a + b + !$omp end parallel + + call sb() + + contains + subroutine sb() + namelist /nlist3/ p, q + + !ERROR: Variable 'p' in NAMELIST cannot be in a PRIVATE clause + !ERROR: Variable 'd' in NAMELIST cannot be in a PRIVATE clause + !$omp parallel private(p, d) + p = c * b + q = p * d + !$omp end parallel + + write(*, nlist1) + write(*, nlist2) + write(*, nlist3) + + end subroutine + +end program omp_private