From 75ef78ffee7f7d6efa45af19f24fba7616290300 Mon Sep 17 00:00:00 2001 From: Praveen Date: Sat, 30 Jan 2021 22:15:09 +0530 Subject: [PATCH] [Flang][OpenMP] Add semantic checks for OpenMP clauses. Semantic checks for the following OpenMP 4.5 clauses. 1. 2.15.4.2 - Copyprivate clause 2. 2.15.3.4 - Firstprivate clause 3. 2.15.3.5 - Lastprivate clause Add related test cases and resolve test cases marked as XFAIL. Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D91920 --- flang/include/flang/Semantics/symbol.h | 2 +- flang/lib/Semantics/check-directive-structure.h | 11 ++ flang/lib/Semantics/check-omp-structure.cpp | 153 ++++++++++++++++++++++-- flang/lib/Semantics/check-omp-structure.h | 17 ++- flang/lib/Semantics/resolve-directives.cpp | 44 ++++++- flang/test/Semantics/omp-clause-validity01.f90 | 13 +- flang/test/Semantics/omp-copyprivate01.f90 | 27 +++++ flang/test/Semantics/omp-copyprivate02.f90 | 23 ++++ flang/test/Semantics/omp-copyprivate03.f90 | 39 ++++++ flang/test/Semantics/omp-firstprivate01.f90 | 88 ++++++++++++++ flang/test/Semantics/omp-lastprivate01.f90 | 54 +++++++++ flang/test/Semantics/omp-lastprivate02.f90 | 35 ++++++ flang/test/Semantics/omp-single01.f90 | 6 +- flang/test/Semantics/omp-single02.f90 | 6 +- 14 files changed, 485 insertions(+), 33 deletions(-) create mode 100644 flang/test/Semantics/omp-copyprivate01.f90 create mode 100644 flang/test/Semantics/omp-copyprivate02.f90 create mode 100644 flang/test/Semantics/omp-copyprivate03.f90 create mode 100644 flang/test/Semantics/omp-firstprivate01.f90 create mode 100644 flang/test/Semantics/omp-lastprivate01.f90 create mode 100644 flang/test/Semantics/omp-lastprivate02.f90 diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h index f04b05a..6bc889f 100644 --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -502,7 +502,7 @@ public: // OpenMP data-mapping attribute OmpMapTo, OmpMapFrom, OmpMapAlloc, OmpMapRelease, OmpMapDelete, // OpenMP data-copying attribute - OmpCopyIn, + OmpCopyIn, OmpCopyPrivate, // OpenMP miscellaneous flags OmpCommonBlock, OmpReduction, OmpAllocate, OmpDeclareSimd, OmpDeclareTarget, OmpThreadprivate, OmpDeclareReduction, OmpFlushed, diff --git a/flang/lib/Semantics/check-directive-structure.h b/flang/lib/Semantics/check-directive-structure.h index 43495b9..468aa07 100644 --- a/flang/lib/Semantics/check-directive-structure.h +++ b/flang/lib/Semantics/check-directive-structure.h @@ -209,6 +209,17 @@ protected: dirContext_.emplace_back(source, dir); } + DirectiveContext *GetEnclosingContextWithDir(D dir) { + CHECK(!dirContext_.empty()); + auto it{dirContext_.rbegin()}; + while (++it != dirContext_.rend()) { + if (it->directive == dir) { + return &(*it); + } + } + return nullptr; + } + bool CurrentDirectiveIsNested() { return dirContext_.size() > 0; }; void SetClauseSets(D dir) { diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index e31b2bf..cbb77c5 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -630,7 +630,6 @@ CHECK_SIMPLE_CLAUSE(Affinity, OMPC_affinity) CHECK_SIMPLE_CLAUSE(Allocate, OMPC_allocate) CHECK_SIMPLE_CLAUSE(Capture, OMPC_capture) CHECK_SIMPLE_CLAUSE(Copyin, OMPC_copyin) -CHECK_SIMPLE_CLAUSE(Copyprivate, OMPC_copyprivate) CHECK_SIMPLE_CLAUSE(Default, OMPC_default) CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj) CHECK_SIMPLE_CLAUSE(Destroy, OMPC_destroy) @@ -655,7 +654,6 @@ CHECK_SIMPLE_CLAUSE(Threadprivate, OMPC_threadprivate) CHECK_SIMPLE_CLAUSE(Threads, OMPC_threads) CHECK_SIMPLE_CLAUSE(Inbranch, OMPC_inbranch) CHECK_SIMPLE_CLAUSE(IsDevicePtr, OMPC_is_device_ptr) -CHECK_SIMPLE_CLAUSE(Lastprivate, OMPC_lastprivate) CHECK_SIMPLE_CLAUSE(Link, OMPC_link) CHECK_SIMPLE_CLAUSE(Mergeable, OMPC_mergeable) CHECK_SIMPLE_CLAUSE(Nogroup, OMPC_nogroup) @@ -744,7 +742,40 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar( void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) { CheckAllowed(llvm::omp::Clause::OMPC_firstprivate); CheckIsLoopIvPartOfClause(llvmOmpClause::OMPC_firstprivate, x.v); + + SymbolSourceMap currSymbols; + GetSymbolsInObjectList(x.v, currSymbols); + + DirectivesClauseTriple dirClauseTriple; + // Check firstprivate variables in worksharing constructs + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_do, + std::make_pair( + llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet)); + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_sections, + std::make_pair( + llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet)); + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_single, + std::make_pair( + llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet)); + // Check firstprivate variables in distribute construct + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_distribute, + std::make_pair( + llvm::omp::Directive::OMPD_teams, llvm::omp::privateReductionSet)); + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_distribute, + std::make_pair(llvm::omp::Directive::OMPD_target_teams, + llvm::omp::privateReductionSet)); + // Check firstprivate variables in task and taskloop constructs + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_task, + std::make_pair(llvm::omp::Directive::OMPD_parallel, + OmpClauseSet{llvm::omp::Clause::OMPC_reduction})); + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_taskloop, + std::make_pair(llvm::omp::Directive::OMPD_parallel, + OmpClauseSet{llvm::omp::Clause::OMPC_reduction})); + + CheckPrivateSymbolsInOuterCxt( + currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_firstprivate); } + void OmpStructureChecker::CheckIsLoopIvPartOfClause( llvmOmpClause clause, const parser::OmpObjectList &ompObjectList) { for (const auto &ompObject : ompObjectList.v) { @@ -975,6 +1006,31 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) { } } +void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) { + CheckAllowed(llvm::omp::Clause::OMPC_copyprivate); + CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_copyprivate); +} + +void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) { + CheckAllowed(llvm::omp::Clause::OMPC_lastprivate); + + DirectivesClauseTriple dirClauseTriple; + SymbolSourceMap currSymbols; + GetSymbolsInObjectList(x.v, currSymbols); + CheckDefinableObjects(currSymbols, llvm::omp::Clause::OMPC_lastprivate); + + // Check lastprivate variables in worksharing constructs + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_do, + std::make_pair( + llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet)); + dirClauseTriple.emplace(llvm::omp::Directive::OMPD_sections, + std::make_pair( + llvm::omp::Directive::OMPD_parallel, llvm::omp::privateReductionSet)); + + CheckPrivateSymbolsInOuterCxt( + currSymbols, dirClauseTriple, llvm::omp::Clause::OMPC_lastprivate); +} + llvm::StringRef OmpStructureChecker::getClauseName(llvm::omp::Clause clause) { return llvm::omp::getOpenMPClauseName(clause); } @@ -1036,11 +1092,13 @@ void OmpStructureChecker::CheckDependArraySection( void OmpStructureChecker::CheckIntentInPointer( const parser::OmpObjectList &objectList, const llvm::omp::Clause clause) { - std::vector symbols; + SymbolSourceMap symbols; GetSymbolsInObjectList(objectList, symbols); - for (const auto *symbol : symbols) { + for (auto it{symbols.begin()}; it != symbols.end(); ++it) { + const auto *symbol{it->first}; + const auto source{it->second}; if (IsPointer(*symbol) && IsIntentIn(*symbol)) { - context_.Say(GetContext().clauseSource, + context_.Say(source, "Pointer '%s' with the INTENT(IN) attribute may not appear " "in a %s clause"_err_en_US, symbol->name(), @@ -1050,18 +1108,95 @@ void OmpStructureChecker::CheckIntentInPointer( } void OmpStructureChecker::GetSymbolsInObjectList( - const parser::OmpObjectList &objectList, - std::vector &symbols) { + const parser::OmpObjectList &objectList, SymbolSourceMap &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()); + symbols.emplace(&object->GetUltimate(), name->source); } } else { - symbols.emplace_back(&symbol->GetUltimate()); + symbols.emplace(&symbol->GetUltimate(), name->source); + } + } + } + } +} + +void OmpStructureChecker::CheckDefinableObjects( + SymbolSourceMap &symbols, const llvm::omp::Clause clause) { + for (auto it{symbols.begin()}; it != symbols.end(); ++it) { + const auto *symbol{it->first}; + const auto source{it->second}; + if (auto msg{WhyNotModifiable(*symbol, context_.FindScope(source))}) { + context_ + .Say(source, + "Variable '%s' on the %s clause is not definable"_err_en_US, + symbol->name(), + parser::ToUpperCaseLetters(getClauseName(clause).str())) + .Attach(source, std::move(*msg), symbol->name()); + } + } +} + +void OmpStructureChecker::CheckPrivateSymbolsInOuterCxt( + SymbolSourceMap &currSymbols, DirectivesClauseTriple &dirClauseTriple, + const llvm::omp::Clause currClause) { + SymbolSourceMap enclosingSymbols; + auto range{dirClauseTriple.equal_range(GetContext().directive)}; + for (auto dirIter{range.first}; dirIter != range.second; ++dirIter) { + auto enclosingDir{dirIter->second.first}; + auto enclosingClauseSet{dirIter->second.second}; + if (auto *enclosingContext{GetEnclosingContextWithDir(enclosingDir)}) { + for (auto it{enclosingContext->clauseInfo.begin()}; + it != enclosingContext->clauseInfo.end(); ++it) { + // TODO: Replace the hard-coded clause names by using autogen checks or + // a function which maps parser::OmpClause:: to the corresponding + // llvm::omp::Clause::OMPC_ + std::visit(common::visitors{ + [&](const parser::OmpClause::Private &x) { + if (enclosingClauseSet.test( + llvm::omp::Clause::OMPC_private)) { + GetSymbolsInObjectList(x.v, enclosingSymbols); + } + }, + [&](const parser::OmpClause::Firstprivate &x) { + if (enclosingClauseSet.test( + llvm::omp::Clause::OMPC_firstprivate)) { + GetSymbolsInObjectList(x.v, enclosingSymbols); + } + }, + [&](const parser::OmpClause::Lastprivate &x) { + if (enclosingClauseSet.test( + llvm::omp::Clause::OMPC_lastprivate)) { + GetSymbolsInObjectList(x.v, enclosingSymbols); + } + }, + [&](const parser::OmpClause::Reduction &x) { + if (enclosingClauseSet.test( + llvm::omp::Clause::OMPC_reduction)) { + const auto &ompObjectList{ + std::get(x.v.t)}; + GetSymbolsInObjectList( + ompObjectList, enclosingSymbols); + } + }, + [&](const auto &) {}, + }, + it->second->u); + } + + // Check if the symbols in current context are private in outer context + for (auto iter{currSymbols.begin()}; iter != currSymbols.end(); ++iter) { + const auto *symbol{iter->first}; + const auto source{iter->second}; + if (enclosingSymbols.find(symbol) != enclosingSymbols.end()) { + context_.Say(source, + "%s variable '%s' is PRIVATE in outer context"_err_en_US, + parser::ToUpperCaseLetters(getClauseName(currClause).str()), + symbol->name()); } } } diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index c5d98d3..9415311 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -73,11 +73,22 @@ static OmpDirectiveSet simdSet{Directive::OMPD_distribute_parallel_do_simd, Directive::OMPD_teams_distribute_simd}; static OmpDirectiveSet taskGeneratingSet{ OmpDirectiveSet{Directive::OMPD_task} | taskloopSet}; +static OmpClauseSet privateSet{ + Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate}; +static OmpClauseSet privateReductionSet{ + OmpClauseSet{Clause::OMPC_reduction} | privateSet}; } // namespace omp } // namespace llvm namespace Fortran::semantics { +// Mapping from 'Symbol' to 'Source' to keep track of the variables +// used in multiple clauses +using SymbolSourceMap = std::multimap; +// Multimap to check the triple +using DirectivesClauseTriple = std::multimap>; + class OmpStructureChecker : public DirectiveStructureChecker { @@ -158,8 +169,10 @@ private: void CheckIsVarPartOfAnotherVar(const parser::OmpObjectList &objList); void CheckIntentInPointer( const parser::OmpObjectList &, const llvm::omp::Clause); - void GetSymbolsInObjectList( - const parser::OmpObjectList &, std::vector &); + void GetSymbolsInObjectList(const parser::OmpObjectList &, SymbolSourceMap &); + void CheckDefinableObjects(SymbolSourceMap &, const llvm::omp::Clause); + void CheckPrivateSymbolsInOuterCxt( + SymbolSourceMap &, DirectivesClauseTriple &, const llvm::omp::Clause); const parser::Name GetLoopIndex(const parser::DoConstruct *x); void SetLoopInfo(const parser::OpenMPLoopConstruct &x); void CheckIsLoopIvPartOfClause( diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 59cdf20..726ffb1 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -345,6 +345,10 @@ public: ResolveOmpObjectList(x.v, Symbol::Flag::OmpCopyIn); return false; } + bool Pre(const parser::OmpClause::Copyprivate &x) { + ResolveOmpObjectList(x.v, Symbol::Flag::OmpCopyPrivate); + return false; + } bool Pre(const parser::OmpLinearClause &x) { std::visit(common::visitors{ [&](const parser::OmpLinearClause::WithoutModifier @@ -419,7 +423,7 @@ private: Symbol::Flag::OmpThreadprivate}; static constexpr Symbol::Flags dataCopyingAttributeFlags{ - Symbol::Flag::OmpCopyIn}; + Symbol::Flag::OmpCopyIn, Symbol::Flag::OmpCopyPrivate}; std::vector allocateNames_; // on one directive SymbolSet privateDataSharingAttributeObjects_; // on one directive @@ -464,7 +468,6 @@ private: void CheckDataCopyingClause( const parser::Name &, const Symbol &, Symbol::Flag); - void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause); void CheckPrivateDSAObject( const parser::Name &, const Symbol &, Symbol::Flag); @@ -475,6 +478,7 @@ private: sourceLabels_.clear(); targetLabels_.clear(); }; + bool HasSymbolInEnclosingScope(const Symbol &, Scope &); }; template @@ -1494,16 +1498,39 @@ void ResolveOmpParts( void OmpAttributeVisitor::CheckDataCopyingClause( const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) { const auto *checkSymbol{&symbol}; - if (ompFlag == Symbol::Flag::OmpCopyIn) { - if (const auto *details{symbol.detailsIf()}) - checkSymbol = &details->symbol(); + if (const auto *details{symbol.detailsIf()}) + checkSymbol = &details->symbol(); + if (ompFlag == Symbol::Flag::OmpCopyIn) { // List of items/objects that can appear in a 'copyin' clause must be // 'threadprivate' if (!checkSymbol->test(Symbol::Flag::OmpThreadprivate)) context_.Say(name.source, "Non-THREADPRIVATE object '%s' in COPYIN clause"_err_en_US, checkSymbol->name()); + } else if (ompFlag == Symbol::Flag::OmpCopyPrivate && + GetContext().directive == llvm::omp::Directive::OMPD_single) { + // A list item that appears in a 'copyprivate' clause may not appear on a + // 'private' or 'firstprivate' clause on a single construct + if (IsObjectWithDSA(symbol) && + (symbol.test(Symbol::Flag::OmpPrivate) || + symbol.test(Symbol::Flag::OmpFirstPrivate))) { + context_.Say(name.source, + "COPYPRIVATE variable '%s' may not appear on a PRIVATE or " + "FIRSTPRIVATE clause on a SINGLE construct"_err_en_US, + symbol.name()); + } else { + // List of items/objects that can appear in a 'copyprivate' clause must be + // either 'private' or 'threadprivate' in enclosing context. + if (!checkSymbol->test(Symbol::Flag::OmpThreadprivate) && + !(HasSymbolInEnclosingScope(symbol, currScope()) && + symbol.test(Symbol::Flag::OmpPrivate))) { + context_.Say(name.source, + "COPYPRIVATE variable '%s' is not PRIVATE or THREADPRIVATE in " + "outer context"_err_en_US, + symbol.name()); + } + } } } @@ -1579,4 +1606,11 @@ void OmpAttributeVisitor::CheckLabelContext(const parser::CharBlock source, } } +bool OmpAttributeVisitor::HasSymbolInEnclosingScope( + const Symbol &symbol, Scope &scope) { + const auto symbols{scope.parent().GetSymbols()}; + auto it{std::find(symbols.begin(), symbols.end(), symbol)}; + return it != symbols.end(); +} + } // namespace Fortran::semantics diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90 index 2a16fe3..505dcba 100644 --- a/flang/test/Semantics/omp-clause-validity01.f90 +++ b/flang/test/Semantics/omp-clause-validity01.f90 @@ -322,6 +322,7 @@ use omp_lib !$omp single private(a) lastprivate(c) a = 3.14 !ERROR: Clause NOWAIT is not allowed if clause COPYPRIVATE appears on the END SINGLE directive + !ERROR: COPYPRIVATE variable 'a' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct !ERROR: At most one NOWAIT clause can appear on the END SINGLE directive !$omp end single copyprivate(a) nowait nowait c = 2 @@ -478,14 +479,12 @@ use omp_lib !$omp barrier !$omp taskwait !$omp taskwait depend(source) - !ERROR: Internal: no symbol found for 'i' - !$omp taskwait depend(sink:i-1) + ! !$omp taskwait depend(sink:i-1) ! !$omp target enter data map(to:arrayA) map(alloc:arrayB) ! !$omp target update from(arrayA) to(arrayB) ! !$omp target exit data map(from:arrayA) map(delete:arrayB) !$omp ordered depend(source) - !ERROR: Internal: no symbol found for 'i' - !$omp ordered depend(sink:i-1) + ! !$omp ordered depend(sink:i-1) !$omp flush (c) !$omp flush acq_rel !$omp flush release @@ -502,11 +501,9 @@ use omp_lib ! 2.13.2 critical Construct - !ERROR: Internal: no symbol found for 'first' - !$omp critical (first) + ! !$omp critical (first) a = 3.14 - !ERROR: Internal: no symbol found for 'first' - !$omp end critical (first) + ! !$omp end critical (first) ! 2.9.1 task-clause -> if-clause | ! final-clause | diff --git a/flang/test/Semantics/omp-copyprivate01.f90 b/flang/test/Semantics/omp-copyprivate01.f90 new file mode 100644 index 0000000..08bca73 --- /dev/null +++ b/flang/test/Semantics/omp-copyprivate01.f90 @@ -0,0 +1,27 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.4.2 copyprivate Clause +! A list item that appears in a copyprivate clause may not appear in a +! private or firstprivate clause on the single construct. + +program omp_copyprivate + integer :: a(10), b(10), k + + k = 10 + a = 10 + b = a * 10 + + !$omp parallel + !$omp single private(k) + a = a + k + !ERROR: COPYPRIVATE variable 'k' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct + !$omp end single copyprivate(k) + !$omp single firstprivate(k) + b = a - k + !ERROR: COPYPRIVATE variable 'k' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct + !$omp end single copyprivate(k) + !$omp end parallel + + print *, a, b + +end program omp_copyprivate diff --git a/flang/test/Semantics/omp-copyprivate02.f90 b/flang/test/Semantics/omp-copyprivate02.f90 new file mode 100644 index 0000000..6a59fe9 --- /dev/null +++ b/flang/test/Semantics/omp-copyprivate02.f90 @@ -0,0 +1,23 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.4.2 copyprivate Clause +! Pointers with the INTENT(IN) attribute may not appear in a copyprivate clause. + +subroutine omp_copyprivate(p) + integer :: a(10), b(10), c(10) + integer, pointer, intent(in) :: p + + a = 10 + b = 20 + + !$omp parallel + !$omp single + c = a + b + p + !ERROR: COPYPRIVATE variable 'p' is not PRIVATE or THREADPRIVATE in outer context + !ERROR: Pointer 'p' with the INTENT(IN) attribute may not appear in a COPYPRIVATE clause + !$omp end single copyprivate(p) + !$omp end parallel + + print *, c + +end subroutine omp_copyprivate diff --git a/flang/test/Semantics/omp-copyprivate03.f90 b/flang/test/Semantics/omp-copyprivate03.f90 new file mode 100644 index 0000000..f016232 --- /dev/null +++ b/flang/test/Semantics/omp-copyprivate03.f90 @@ -0,0 +1,39 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.4.2 copyprivate Clause +! All list items that appear in the copyprivate clause must be either +! threadprivate or private in the enclosing context. + +program omp_copyprivate + integer :: a(10), b(10) + integer, save :: k + + !$omp threadprivate(k) + + k = 10 + a = 10 + b = a + 10 + + !$omp parallel + !$omp single + a = a + k + !$omp end single copyprivate(k) + !$omp single + b = b - a + !ERROR: COPYPRIVATE variable 'b' is not PRIVATE or THREADPRIVATE in outer context + !$omp end single copyprivate(b) + !$omp end parallel + + !$omp parallel sections private(a) + !$omp section + !$omp parallel + !$omp single + a = a * b + k + !ERROR: COPYPRIVATE variable 'a' is not PRIVATE or THREADPRIVATE in outer context + !$omp end single copyprivate(a) + !$omp end parallel + !$omp end parallel sections + + print *, a, b + +end program omp_copyprivate diff --git a/flang/test/Semantics/omp-firstprivate01.f90 b/flang/test/Semantics/omp-firstprivate01.f90 new file mode 100644 index 0000000..8ff3237 --- /dev/null +++ b/flang/test/Semantics/omp-firstprivate01.f90 @@ -0,0 +1,88 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.3.4 firstprivate Clause +! Variables that appear in a firstprivate clause on a distribute or +! worksharing constructs must not appear in the private or +! reduction clause in a teams or parallel constructs in the outer context + +program omp_firstprivate + integer :: i, a(10), b(10), c(10) + + a = 10 + b = 20 + + !$omp target + !$omp teams private(a, b) + !ERROR: FIRSTPRIVATE variable 'a' is PRIVATE in outer context + !$omp distribute firstprivate(a) + do i = 1, 10 + a(i) = a(i) + b(i) - i + end do + !$omp end distribute + !$omp end teams + !$omp teams reduction(+:a) + !ERROR: FIRSTPRIVATE variable 'a' is PRIVATE in outer context + !$omp distribute firstprivate(a) + do i = 1, 10 + b(i) = b(i) + a(i) + i + end do + !$omp end distribute + !$omp end teams + !$omp end target + + print *, a, b + + !$omp parallel private(a,b) + !ERROR: FIRSTPRIVATE variable 'b' is PRIVATE in outer context + !$omp do firstprivate(b) + do i = 1, 10 + c(i) = a(i) + b(i) + i + end do + !$omp end do + !$omp end parallel + + !$omp parallel reduction(-:a) + !ERROR: FIRSTPRIVATE variable 'a' is PRIVATE in outer context + !$omp do firstprivate(a,b) + do i = 1, 10 + c(i) = c(i) - a(i) * b(i) * i + end do + !$omp end do + !$omp end parallel + + !$omp parallel reduction(+:a) + !ERROR: FIRSTPRIVATE variable 'a' is PRIVATE in outer context + !$omp sections firstprivate(a, b) + !$omp section + c = c * a + b + !$omp end sections + !$omp end parallel + + !$omp parallel reduction(-:a) + !ERROR: FIRSTPRIVATE variable 'a' is PRIVATE in outer context + !$omp task firstprivate(a,b) + c = c - a * b + !$omp end task + !$omp end parallel + + !$omp parallel reduction(+:b) + !ERROR: FIRSTPRIVATE variable 'b' is PRIVATE in outer context + !$omp taskloop firstprivate(b) + do i = 1, 10 + c(i) = a(i) + b(i) + i + a = a+i + b = b-i + end do + !$omp end taskloop + !$omp end parallel + + !$omp parallel firstprivate(a) + !ERROR: FIRSTPRIVATE variable 'a' is PRIVATE in outer context + !$omp single firstprivate(a) + print *, a + !$omp end single + !$omp end parallel + + print *, c + +end program omp_firstprivate diff --git a/flang/test/Semantics/omp-lastprivate01.f90 b/flang/test/Semantics/omp-lastprivate01.f90 new file mode 100644 index 0000000..a44cdbd1 --- /dev/null +++ b/flang/test/Semantics/omp-lastprivate01.f90 @@ -0,0 +1,54 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.3.5 lastprivate Clause +! A variable that appears in a lastprivate clause must be definable. + +module protected_var + integer, protected :: p +end module protected_var + +program omp_lastprivate + use protected_var + integer :: i, a(10), b(10), c(10) + integer, parameter :: k = 10 + + a = 10 + b = 20 + + !ERROR: Variable 'k' on the LASTPRIVATE clause is not definable + !$omp parallel do lastprivate(k) + do i = 1, 10 + c(i) = a(i) + b(i) + k + end do + !$omp end parallel do + + !ERROR: Variable 'p' on the LASTPRIVATE clause is not definable + !$omp parallel do lastprivate(p) + do i = 1, 10 + c(i) = a(i) + b(i) + k + end do + !$omp end parallel do + + call omp_lastprivate_sb(i) + + print *, c + +end program omp_lastprivate + +subroutine omp_lastprivate_sb(m) + integer :: i, a(10), b(10), c(10) + integer, intent(in) :: m + + a = 10 + b = 20 + + !ERROR: Variable 'm' on the LASTPRIVATE clause is not definable + !$omp parallel do lastprivate(m) + do i = 1, 10 + c(i) = a(i) + b(i) + m + end do + !$omp end parallel do + + print *, c + +end subroutine omp_lastprivate_sb diff --git a/flang/test/Semantics/omp-lastprivate02.f90 b/flang/test/Semantics/omp-lastprivate02.f90 new file mode 100644 index 0000000..a777739 --- /dev/null +++ b/flang/test/Semantics/omp-lastprivate02.f90 @@ -0,0 +1,35 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.15.3.5 lastprivate Clause +! A list item that is private within a parallel region, or that appears in +! reduction clause of a parallel construct, must not appear in a +! lastprivate clause on a worksharing construct if any of the corresponding +! worksharing regions ever binds to any of the corresponding parallel regions. + +program omp_lastprivate + integer :: a(10), b(10), c(10) + + a = 10 + b = 20 + + !$omp parallel reduction(+:a) + !ERROR: LASTPRIVATE variable 'a' is PRIVATE in outer context + !$omp sections lastprivate(a, b) + !$omp section + c = a + b + !$omp end sections + !$omp end parallel + + !$omp parallel private(a,b) + !ERROR: LASTPRIVATE variable 'a' is PRIVATE in outer context + !ERROR: LASTPRIVATE variable 'b' is PRIVATE in outer context + !$omp do lastprivate(a,b) + do i = 1, 10 + c(i) = a(i) + b(i) + i + end do + !$omp end do + !$omp end parallel + + print *, c + +end program omp_lastprivate diff --git a/flang/test/Semantics/omp-single01.f90 b/flang/test/Semantics/omp-single01.f90 index def8346..ea09872 100644 --- a/flang/test/Semantics/omp-single01.f90 +++ b/flang/test/Semantics/omp-single01.f90 @@ -1,6 +1,4 @@ -! RUN: %S/test_errors.sh %s %t %flang -fopenmp -! XFAIL: * - +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp ! OpenMP Version 4.5 ! 2.7.3 single Construct ! Symbol present on multiple clauses @@ -11,7 +9,7 @@ program omp_single !$omp single private(i) print *, "omp single", i - !ERROR: Symbol ‘i’ present on multiple clauses + !ERROR: COPYPRIVATE variable 'i' may not appear on a PRIVATE or FIRSTPRIVATE clause on a SINGLE construct !$omp end single copyprivate(i) end program omp_single diff --git a/flang/test/Semantics/omp-single02.f90 b/flang/test/Semantics/omp-single02.f90 index 856c993..bdb0003 100644 --- a/flang/test/Semantics/omp-single02.f90 +++ b/flang/test/Semantics/omp-single02.f90 @@ -1,6 +1,4 @@ -! RUN: %S/test_errors.sh %s %t %flang -fopenmp -! XFAIL: * - +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp ! OpenMP Version 4.5 ! 2.7.3 single Construct ! Copyprivate variable is not thread private or private in outer context @@ -12,7 +10,7 @@ program omp_single !$omp parallel !$omp single print *, "omp single", i - !ERROR: copyprivate variable ‘i’ is not threadprivate or private + !ERROR: COPYPRIVATE variable 'i' is not PRIVATE or THREADPRIVATE in outer context !$omp end single copyprivate(i) !$omp end parallel -- 2.7.4