forked from OSchip/llvm-project
[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
This commit is contained in:
parent
48ca5d3398
commit
75ef78ffee
|
@ -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,
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 @@ private:
|
|||
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(
|
||||
|
|
|
@ -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<const parser::Name *> 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 <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
|
||||
|
|
|
@ -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 |
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in New Issue