[flang-commits] [flang] 75ef78f - [Flang][OpenMP] Add semantic checks for OpenMP clauses.
via flang-commits
flang-commits at lists.llvm.org
Mon Mar 1 06:25:18 PST 2021
Author: Praveen
Date: 2021-03-01T19:54:41+05:30
New Revision: 75ef78ffee7f7d6efa45af19f24fba7616290300
URL: https://github.com/llvm/llvm-project/commit/75ef78ffee7f7d6efa45af19f24fba7616290300
DIFF: https://github.com/llvm/llvm-project/commit/75ef78ffee7f7d6efa45af19f24fba7616290300.diff
LOG: [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
Added:
flang/test/Semantics/omp-copyprivate01.f90
flang/test/Semantics/omp-copyprivate02.f90
flang/test/Semantics/omp-copyprivate03.f90
flang/test/Semantics/omp-firstprivate01.f90
flang/test/Semantics/omp-lastprivate01.f90
flang/test/Semantics/omp-lastprivate02.f90
Modified:
flang/include/flang/Semantics/symbol.h
flang/lib/Semantics/check-directive-structure.h
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
flang/lib/Semantics/resolve-directives.cpp
flang/test/Semantics/omp-clause-validity01.f90
flang/test/Semantics/omp-single01.f90
flang/test/Semantics/omp-single02.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h
index f04b05afd6e4..6bc889fd2873 100644
--- a/flang/include/flang/Semantics/symbol.h
+++ b/flang/include/flang/Semantics/symbol.h
@@ -502,7 +502,7 @@ class Symbol {
// 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 43495b9cf730..468aa07bd174 100644
--- a/flang/lib/Semantics/check-directive-structure.h
+++ b/flang/lib/Semantics/check-directive-structure.h
@@ -209,6 +209,17 @@ class DirectiveStructureChecker : public virtual BaseChecker {
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 e31b2bfa1a73..cbb77c567fbc 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<const Symbol *> 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<const Symbol *> &symbols) {
+ const parser::OmpObjectList &objectList, SymbolSourceMap &symbols) {
for (const auto &ompObject : objectList.v) {
if (const auto *name{parser::Unwrap<parser::Name>(ompObject)}) {
if (const auto *symbol{name->symbol}) {
if (const auto *commonBlockDetails{
symbol->detailsIf<CommonBlockDetails>()}) {
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::<name> to the corresponding
+ // llvm::omp::Clause::OMPC_<name>
+ 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<parser::OmpObjectList>(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 c5d98d39d639..9415311a923b 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<const Symbol *, parser::CharBlock>;
+// Multimap to check the triple <current_dir, enclosing_dir, enclosing_clause>
+using DirectivesClauseTriple = std::multimap<llvm::omp::Directive,
+ std::pair<llvm::omp::Directive, const OmpClauseSet>>;
+
class OmpStructureChecker
: public DirectiveStructureChecker<llvm::omp::Directive, llvm::omp::Clause,
parser::OmpClause, llvm::omp::Clause_enumSize> {
@@ -158,8 +169,10 @@ class OmpStructureChecker
void CheckIsVarPartOfAnotherVar(const parser::OmpObjectList &objList);
void CheckIntentInPointer(
const parser::OmpObjectList &, const llvm::omp::Clause);
- void GetSymbolsInObjectList(
- const parser::OmpObjectList &, std::vector<const Symbol *> &);
+ 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 59cdf2060f57..726ffb1975d7 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -345,6 +345,10 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
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 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
Symbol::Flag::OmpThreadprivate};
static constexpr Symbol::Flags dataCopyingAttributeFlags{
- Symbol::Flag::OmpCopyIn};
+ Symbol::Flag::OmpCopyIn, Symbol::Flag::OmpCopyPrivate};
std::vector<const parser::Name *> allocateNames_; // on one directive
SymbolSet privateDataSharingAttributeObjects_; // on one directive
@@ -464,7 +468,6 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
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 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
sourceLabels_.clear();
targetLabels_.clear();
};
+ bool HasSymbolInEnclosingScope(const Symbol &, Scope &);
};
template <typename T>
@@ -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<HostAssocDetails>()})
- checkSymbol = &details->symbol();
+ if (const auto *details{symbol.detailsIf<HostAssocDetails>()})
+ 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 2a16fe375cc3..505dcba4ff02 100644
--- a/flang/test/Semantics/omp-clause-validity01.f90
+++ b/flang/test/Semantics/omp-clause-validity01.f90
@@ -322,6 +322,7 @@
!$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 @@
!$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 @@
! 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 000000000000..08bca731af3e
--- /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 000000000000..6a59fe943a6f
--- /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 000000000000..f016232804e0
--- /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 000000000000..8ff3237999f0
--- /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 000000000000..a44cdbd1be1b
--- /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 000000000000..a777739b4193
--- /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 def83462c1e7..ea09872a79e9 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 856c99338f7b..bdb0003d2dbb 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
More information about the flang-commits
mailing list