Skip to content

Commit 35fd0cd

Browse files
authored
Merge pull request flang-compiler#989 from flang-compiler/tsk-forall
Add FORALL checking to DoChecker
2 parents fa6d475 + 8ecb6a2 commit 35fd0cd

24 files changed

+422
-425
lines changed

include/flang/evaluate/expression.h

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -811,28 +811,24 @@ template<> class Expr<SomeType> : public ExpressionBase<SomeType> {
811811
common::CombineVariants<TypelessExpression, CategoryExpression> u;
812812
};
813813

814-
// An assignment is either intrinsic (with lhs and rhs) or user-defined,
815-
// represented as a ProcedureRef. A pointer assignment optionally also has
816-
// a bounds-spec or bounds-remapping.
814+
// An assignment is either intrinsic, user-defined (with a ProcedureRef to
815+
// specify the procedure to call), or pointer assignment (with possibly empty
816+
// BoundsSpec or non-empty BoundsRemapping). In all cases there are Exprs
817+
// representing the LHS and RHS of the assignment.
817818
class Assignment {
818819
public:
819-
UNION_CONSTRUCTORS(Assignment)
820-
struct IntrinsicAssignment {
821-
Expr<SomeType> lhs;
822-
Expr<SomeType> rhs;
823-
};
824-
struct PointerAssignment {
825-
using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
826-
using BoundsRemapping =
827-
std::vector<std::pair<Expr<SubscriptInteger>, Expr<SubscriptInteger>>>;
828-
PointerAssignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs)
829-
: lhs{std::move(lhs)}, rhs{std::move(rhs)} {}
830-
Expr<SomeType> lhs;
831-
Expr<SomeType> rhs;
832-
std::variant<BoundsSpec, BoundsRemapping> bounds;
833-
};
820+
Assignment(Expr<SomeType> &&lhs, Expr<SomeType> &&rhs)
821+
: lhs(std::move(lhs)), rhs(std::move(rhs)) {}
822+
823+
struct Intrinsic {};
824+
using BoundsSpec = std::vector<Expr<SubscriptInteger>>;
825+
using BoundsRemapping =
826+
std::vector<std::pair<Expr<SubscriptInteger>, Expr<SubscriptInteger>>>;
834827
std::ostream &AsFortran(std::ostream &) const;
835-
std::variant<IntrinsicAssignment, ProcedureRef, PointerAssignment> u;
828+
829+
Expr<SomeType> lhs;
830+
Expr<SomeType> rhs;
831+
std::variant<Intrinsic, ProcedureRef, BoundsSpec, BoundsRemapping> u;
836832
};
837833

838834
// This wrapper class is used, by means of a forward reference with

include/flang/evaluate/tools.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -843,5 +843,8 @@ parser::Message *SayWithDeclaration(
843843
// of one to complain about, if any exist.
844844
std::optional<std::string> FindImpureCall(
845845
const IntrinsicProcTable &, const Expr<SomeType> &);
846+
std::optional<std::string> FindImpureCall(
847+
const IntrinsicProcTable &, const ProcedureRef &);
848+
846849
}
847850
#endif // FORTRAN_EVALUATE_TOOLS_H_

include/flang/semantics/semantics.h

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,18 @@ class SemanticsContext {
150150
}
151151
void PopConstruct();
152152

153-
// Check to see if a variable being redefined is a DO variable. If so, emit
154-
// a message
155-
void WarnDoVarRedefine(const parser::CharBlock &, const Symbol &);
156-
void CheckDoVarRedefine(const parser::CharBlock &, const Symbol &);
157-
void CheckDoVarRedefine(const parser::Variable &);
158-
void CheckDoVarRedefine(const parser::Name &);
159-
void ActivateDoVariable(const parser::Name &);
160-
void DeactivateDoVariable(const parser::Name &);
161-
bool IsActiveDoVariable(const Symbol &);
153+
ENUM_CLASS(IndexVarKind, DO, FORALL)
154+
// Check to see if a variable being redefined is a DO or FORALL index.
155+
// If so, emit a message.
156+
void WarnIndexVarRedefine(const parser::CharBlock &, const Symbol &);
157+
void CheckIndexVarRedefine(const parser::CharBlock &, const Symbol &);
158+
void CheckIndexVarRedefine(const parser::Variable &);
159+
void CheckIndexVarRedefine(const parser::Name &);
160+
void ActivateIndexVar(const parser::Name &, IndexVarKind);
161+
void DeactivateIndexVar(const parser::Name &);
162162

163163
private:
164-
parser::CharBlock GetDoVariableLocation(const Symbol &);
165-
void CheckDoVarRedefine(
164+
void CheckIndexVarRedefine(
166165
const parser::CharBlock &, const Symbol &, parser::MessageFixedText &&);
167166
const common::IntrinsicTypeDefaultKinds &defaultKinds_;
168167
const common::LanguageFeatureControl languageFeatures_;
@@ -180,7 +179,11 @@ class SemanticsContext {
180179

181180
bool CheckError(bool);
182181
ConstructStack constructStack_;
183-
std::map<SymbolRef, const parser::CharBlock> activeDoVariables_;
182+
struct IndexVarInfo {
183+
parser::CharBlock location;
184+
IndexVarKind kind;
185+
};
186+
std::map<SymbolRef, const IndexVarInfo> activeIndexVars_;
184187
};
185188

186189
class Semantics {

lib/evaluate/expression.cpp

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -168,40 +168,33 @@ GenericExprWrapper::~GenericExprWrapper() {}
168168
std::ostream &Assignment::AsFortran(std::ostream &o) const {
169169
std::visit(
170170
common::visitors{
171-
[&](const evaluate::Assignment::IntrinsicAssignment &x) {
172-
x.rhs.AsFortran(x.lhs.AsFortran(o) << '=');
171+
[&](const Assignment::Intrinsic &) {
172+
rhs.AsFortran(lhs.AsFortran(o) << '=');
173173
},
174-
[&](const evaluate::ProcedureRef &x) { x.AsFortran(o << "CALL "); },
175-
[&](const evaluate::Assignment::PointerAssignment &x) {
176-
x.lhs.AsFortran(o);
177-
std::visit(
178-
common::visitors{
179-
[&](const evaluate::Assignment::PointerAssignment::
180-
BoundsSpec &bounds) {
181-
if (!bounds.empty()) {
182-
char sep{'('};
183-
for (const auto &bound : bounds) {
184-
bound.AsFortran(o << sep) << ':';
185-
sep = ',';
186-
}
187-
o << ')';
188-
}
189-
},
190-
[&](const evaluate::Assignment::PointerAssignment::
191-
BoundsRemapping &bounds) {
192-
if (!bounds.empty()) {
193-
char sep{'('};
194-
for (const auto &bound : bounds) {
195-
bound.first.AsFortran(o << sep) << ':';
196-
bound.second.AsFortran(o);
197-
sep = ',';
198-
}
199-
o << ')';
200-
}
201-
},
202-
},
203-
x.bounds);
204-
x.rhs.AsFortran(o << " => ");
174+
[&](const ProcedureRef &proc) { proc.AsFortran(o << "CALL "); },
175+
[&](const BoundsSpec &bounds) {
176+
lhs.AsFortran(o);
177+
if (!bounds.empty()) {
178+
char sep{'('};
179+
for (const auto &bound : bounds) {
180+
bound.AsFortran(o << sep) << ':';
181+
sep = ',';
182+
}
183+
o << ')';
184+
}
185+
},
186+
[&](const BoundsRemapping &bounds) {
187+
lhs.AsFortran(o);
188+
if (!bounds.empty()) {
189+
char sep{'('};
190+
for (const auto &bound : bounds) {
191+
bound.first.AsFortran(o << sep) << ':';
192+
bound.second.AsFortran(o);
193+
sep = ',';
194+
}
195+
o << ')';
196+
}
197+
rhs.AsFortran(o << " => ");
205198
},
206199
},
207200
u);

lib/evaluate/tools.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -842,5 +842,9 @@ std::optional<std::string> FindImpureCall(
842842
const IntrinsicProcTable &intrinsics, const Expr<SomeType> &expr) {
843843
return FindImpureCallHelper{intrinsics}(expr);
844844
}
845+
std::optional<std::string> FindImpureCall(
846+
const IntrinsicProcTable &intrinsics, const ProcedureRef &proc) {
847+
return FindImpureCallHelper{intrinsics}(proc);
848+
}
845849

846850
}

lib/semantics/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ add_library(FortranSemantics
1717
check-coarray.cpp
1818
check-deallocate.cpp
1919
check-declarations.cpp
20-
check-do.cpp
20+
check-do-forall.cpp
2121
check-if-stmt.cpp
2222
check-io.cpp
2323
check-nullify.cpp

0 commit comments

Comments
 (0)