mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-24 01:58:21 +00:00
[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:
parent
1b723a955d
commit
7a91794d5b
@ -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
|
||||
|
@ -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
|
||||
|
@ -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_
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
20
flang/test/Semantics/omp-private01.f90
Normal file
20
flang/test/Semantics/omp-private01.f90
Normal 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
|
46
flang/test/Semantics/omp-private02.f90
Normal file
46
flang/test/Semantics/omp-private02.f90
Normal 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
|
Loading…
x
Reference in New Issue
Block a user