[Flang][OpenMP] Add semantic checks for OpenMP Private clause.

Add the semantic checks for the OpenMP 4.5 - 2.15.3.3 Private clause.

1. Pointers with the INTENT(IN) attribute may not appear in a private clause.
2. Variables that appear in namelist statements may not appear in a private clause.
   A flag 'InNamelist' is added to the Symbol::Flag to identify the symbols
   in Namelist statemnts.

Test cases : omp-private01.f90, omp-private02.f90

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D90210
This commit is contained in:
Praveen G 2020-11-30 11:35:35 -05:00
parent 1b723a955d
commit 7a91794d5b
7 changed files with 127 additions and 1 deletions

View File

@ -493,6 +493,7 @@ public:
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

View File

@ -417,6 +417,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
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::CheckDependArraySection(
}
}
void OmpStructureChecker::CheckIntentInPointer(
const parser::OmpObjectList &objectList, const llvm::omp::Clause clause) {
std::vector<const Symbol *> 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<const Symbol *> &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());
}
} else {
symbols.emplace_back(&symbol->GetUltimate());
}
}
}
}
}
} // namespace Fortran::semantics

View File

@ -185,8 +185,11 @@ private:
void CheckDependList(const parser::DataRef &);
void CheckDependArraySection(
const common::Indirection<parser::ArrayElement> &, 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<const Symbol *> &);
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_

View File

@ -375,6 +375,8 @@ private:
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 <typename T>
@ -1107,6 +1109,10 @@ void OmpAttributeVisitor::ResolveOmpObject(
if (dataSharingAttributeFlags.test(ompFlag)) {
CheckMultipleAppearances(*name, *symbol, ompFlag);
}
if (privateDataSharingAttributeFlags.test(ompFlag)) {
CheckObjectInNamelist(*name, *symbol, ompFlag);
}
if (ompFlag == Symbol::Flag::OmpAllocate) {
AddAllocateName(name);
}
@ -1258,4 +1264,18 @@ void OmpAttributeVisitor::CheckDataCopyingClause(
}
}
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

View File

@ -4289,6 +4289,7 @@ bool DeclarationVisitor::Pre(const parser::NamelistStmt::Group &x) {
} 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);
}

View File

@ -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

View File

@ -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