#include "flang/Evaluate/call.h"
#include "flang/Evaluate/expression.h"
#include "flang/Evaluate/tools.h"
+#include "flang/Evaluate/traverse.h"
#include "flang/Parser/message.h"
#include "flang/Parser/parse-tree-visitor.h"
#include "flang/Parser/tools.h"
: context_{context}, doConcurrentSourcePosition_{
doConcurrentSourcePosition} {}
std::set<parser::Label> labels() { return labels_; }
- template <typename T> bool Pre(const T &) { return true; }
- template <typename T> void Post(const T &) {}
-
+ template <typename T> bool Pre(const T &x) {
+ if (const auto *expr{GetExpr(context_, x)}) {
+ if (auto bad{FindImpureCall(context_.foldingContext(), *expr)}) {
+ context_.Say(currentStatementSourcePosition_,
+ "Impure procedure '%s' may not be referenced in DO CONCURRENT"_err_en_US,
+ *bad);
+ }
+ }
+ return true;
+ }
template <typename T> bool Pre(const parser::Statement<T> &statement) {
currentStatementSourcePosition_ = statement.source;
if (statement.label.has_value()) {
}
return true;
}
-
template <typename T> bool Pre(const parser::UnlabeledStatement<T> &stmt) {
currentStatementSourcePosition_ = stmt.source;
return true;
}
+ bool Pre(const parser::CallStmt &x) {
+ if (x.typedCall.get()) {
+ if (auto bad{FindImpureCall(context_.foldingContext(), *x.typedCall)}) {
+ context_.Say(currentStatementSourcePosition_,
+ "Impure procedure '%s' may not be referenced in DO CONCURRENT"_err_en_US,
+ *bad);
+ }
+ }
+ return true;
+ }
+ template <typename T> void Post(const T &) {}
// C1140 -- Can't deallocate a polymorphic entity in a DO CONCURRENT.
// Deallocation can be caused by exiting a block that declares an allocatable
// not pure, and impure procedures are caught by checks for constraint C1139
void Post(const parser::ProcedureDesignator &procedureDesignator) {
if (auto *name{std::get_if<parser::Name>(&procedureDesignator.u)}) {
- if (name->symbol && !IsPureProcedure(*name->symbol)) {
- SayWithDo(context_, currentStatementSourcePosition_,
- "Call to an impure procedure is not allowed in DO"
- " CONCURRENT"_err_en_US,
- doConcurrentSourcePosition_);
- }
if (name->symbol &&
fromScope(*name->symbol, "__fortran_ieee_exceptions"s)) {
if (name->source == "ieee_set_halting_mode") {
doConcurrentSourcePosition_);
}
}
- } else {
- // C1139: this a procedure component
- auto &component{std::get<parser::ProcComponentRef>(procedureDesignator.u)
- .v.thing.component};
- if (component.symbol && !IsPureProcedure(*component.symbol)) {
- SayWithDo(context_, currentStatementSourcePosition_,
- "Call to an impure procedure component is not allowed"
- " in DO CONCURRENT"_err_en_US,
- doConcurrentSourcePosition_);
- }
}
}
void Check(const parser::DoConstruct &doConstruct) {
if (doConstruct.IsDoConcurrent()) {
CheckDoConcurrent(doConstruct);
- return;
- }
- if (doConstruct.IsDoNormal()) {
+ } else if (doConstruct.IsDoNormal()) {
CheckDoNormal(doConstruct);
- return;
+ } else {
+ // TODO: handle the other cases
}
- // TODO: handle the other cases
}
void Check(const parser::ForallStmt &stmt) {
change team (j)
!ERROR: An image control statement is not allowed in DO CONCURRENT
critical
-!ERROR: Call to an impure procedure is not allowed in DO CONCURRENT
- call ieee_get_status(status)
+ call ieee_get_status(status) ! ok
!ERROR: IEEE_SET_HALTING_MODE is not allowed in DO CONCURRENT
call ieee_set_halting_mode(flag, halting)
end critical
pure integer function pf()
end function pf
end interface
+ interface generic
+ impure integer function ipf()
+ end function ipf
+ end interface
type :: procTypeNotPure
procedure(notPureFunc), pointer, nopass :: notPureProcComponent
! This should generate an error
do concurrent (i = 1:10)
-!ERROR: Call to an impure procedure component is not allowed in DO CONCURRENT
+!ERROR: Impure procedure 'notpureproccomponent' may not be referenced in DO CONCURRENT
ivar = procVarNotPure%notPureProcComponent()
end do
+ ! This should generate an error
+ do concurrent (i = 1:10)
+!ERROR: Impure procedure 'ipf' may not be referenced in DO CONCURRENT
+ ivar = generic()
+ end do
+
contains
integer function notPureFunc()
notPureFunc = 2