Skip to content

Commit

Permalink
[Flang][OpenMP] Add semantic check for OpenMP Private, Firstprivate a…
Browse files Browse the repository at this point in the history
…nd Lastprivate clauses.

OpenMP 4.5 - Variables that appear in expressions for statement function definitions
             may not appear in OpenMP Private, Firstprivate or Lastprivate clauses.

Test case : omp-private03.f90

Reviewed By: kiranchandramohan

Differential Revision: https://reviews.llvm.org/D93213
  • Loading branch information
praveen-g-ctt committed Dec 25, 2020
1 parent 893c84d commit a2ca6bb
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 9 deletions.
41 changes: 32 additions & 9 deletions flang/lib/Semantics/resolve-directives.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,18 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
return true;
}

bool Pre(const parser::StmtFunctionStmt &x) {
const auto &parsedExpr{std::get<parser::Scalar<parser::Expr>>(x.t)};
if (const auto *expr{GetExpr(parsedExpr)}) {
for (const Symbol &symbol : evaluate::CollectSymbols(*expr)) {
if (!IsStmtFunctionDummy(symbol)) {
stmtFunctionExprSymbols_.insert(symbol.GetUltimate());
}
}
}
return true;
}

bool Pre(const parser::OpenMPBlockConstruct &);
void Post(const parser::OpenMPBlockConstruct &);

Expand Down Expand Up @@ -342,6 +354,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {

std::vector<const parser::Name *> allocateNames_; // on one directive
SymbolSet privateDataSharingAttributeObjects_; // on one directive
SymbolSet stmtFunctionExprSymbols_;

void AddAllocateName(const parser::Name *&object) {
allocateNames_.push_back(object);
Expand Down Expand Up @@ -377,7 +390,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
const parser::Name &, const Symbol &, Symbol::Flag);

void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause);
void CheckObjectInNamelist(
void CheckPrivateDSAObject(
const parser::Name &, const Symbol &, Symbol::Flag);
};

Expand Down Expand Up @@ -1163,7 +1176,7 @@ void OmpAttributeVisitor::ResolveOmpObject(
CheckMultipleAppearances(*name, *symbol, ompFlag);
}
if (privateDataSharingAttributeFlags.test(ompFlag)) {
CheckObjectInNamelist(*name, *symbol, ompFlag);
CheckPrivateDSAObject(*name, *symbol, ompFlag);
}

if (ompFlag == Symbol::Flag::OmpAllocate) {
Expand Down Expand Up @@ -1317,18 +1330,28 @@ void OmpAttributeVisitor::CheckDataCopyingClause(
}
}

void OmpAttributeVisitor::CheckObjectInNamelist(
void OmpAttributeVisitor::CheckPrivateDSAObject(
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";
const auto &ultimateSymbol{symbol.GetUltimate()};
llvm::StringRef clauseName{"PRIVATE"};
if (ompFlag == Symbol::Flag::OmpFirstPrivate)
clauseName = "FIRSTPRIVATE";
else if (ompFlag == Symbol::Flag::OmpLastPrivate)
clauseName = "LASTPRIVATE";

if (ultimateSymbol.test(Symbol::Flag::InNamelist)) {
context_.Say(name.source,
"Variable '%s' in NAMELIST cannot be in a %s clause"_err_en_US,
name.ToString(), clauseName.str());
}

if (stmtFunctionExprSymbols_.find(ultimateSymbol) !=
stmtFunctionExprSymbols_.end()) {
context_.Say(name.source,
"Variable '%s' in STATEMENT FUNCTION expression cannot be in a "
"%s clause"_err_en_US,
name.ToString(), clauseName.str());
}
}

} // namespace Fortran::semantics
39 changes: 39 additions & 0 deletions flang/test/Semantics/omp-private03.f90
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
! RUN: %S/test_errors.sh %s %t %f18 -fopenmp
! OpenMP Version 4.5
! Variables that appear in expressions for statement function definitions
! may not appear in private, firstprivate or lastprivate clauses.

subroutine stmt_function(temp)

integer :: i, p, q, r
real :: c, f, s, v, t(10)
real, intent(in) :: temp

c(temp) = p * (temp - q) / r
f(temp) = q + (temp * r/p)
v(temp) = c(temp) + f(temp)/2 - s

p = 5
q = 32
r = 9

!ERROR: Variable 'p' in STATEMENT FUNCTION expression cannot be in a PRIVATE clause
!$omp parallel private(p)
s = c(temp)
!$omp end parallel

!ERROR: Variable 's' in STATEMENT FUNCTION expression cannot be in a FIRSTPRIVATE clause
!$omp parallel firstprivate(s)
s = s + f(temp)
!$omp end parallel

!ERROR: Variable 's' in STATEMENT FUNCTION expression cannot be in a LASTPRIVATE clause
!$omp parallel do lastprivate(s, t)
do i = 1, 10
t(i) = v(temp) + i - s
end do
!$omp end parallel do

print *, t

end subroutine stmt_function

0 comments on commit a2ca6bb

Please sign in to comment.