[flang] Responses to review comments and team meeting

The most significant change is that I replaced the stack of
ExecutableConstruct's with a stack composed of ConstructNode's, each of which
is a variant of the constructs that made up the type ExecutableConstruct.  This
change allows the nodes of the stack to be extended to include the types needed
for OMP semantic checking.

I also extended the existing test to include some correct DO loops with CYCLE
and EXIT statements to test the code more completely.

Original-commit: flang-compiler/f18@d26f34e3a4
Reviewed-on: https://github.com/flang-compiler/f18/pull/686
Tree-same-pre-rewrite: false
This commit is contained in:
Pete Steinfeld 2019-08-29 16:02:37 -07:00
parent 73ef31b164
commit eedbe90e72
5 changed files with 186 additions and 33 deletions

View File

@ -647,21 +647,20 @@ void DoChecker::Leave(const parser::DoConstruct &x) {
doContext.Check(x);
}
void DoChecker::CheckLoneStmt(const char *stmtString) const {
for (auto &executable : context_.executables()) {
if (std::holds_alternative<common::Indirection<parser::DoConstruct>>(
executable->u)) {
return;
}
// C1134
void DoChecker::Enter(const parser::CycleStmt &) {
if (!context_.InsideDoConstruct()) {
context_.Say(
*context_.location(), "CYCLE must be within a DO construct"_err_en_US);
}
context_.Say(*context_.location(),
"%s must be within a DO construct"_err_en_US, stmtString);
}
// C1134
void DoChecker::Enter(const parser::CycleStmt &) { CheckLoneStmt("CYCLE"); }
// C1166
void DoChecker::Enter(const parser::ExitStmt &) { CheckLoneStmt("EXIT"); }
void DoChecker::Enter(const parser::ExitStmt &) {
if (!context_.InsideDoConstruct()) {
context_.Say(
*context_.location(), "EXIT must be within a DO construct"_err_en_US);
}
}
} // namespace Fortran::semantics

View File

@ -19,6 +19,8 @@
namespace Fortran::parser {
struct DoConstruct;
struct CycleStmt;
struct ExitStmt;
}
namespace Fortran::semantics {
@ -31,8 +33,6 @@ public:
void Enter(const parser::ExitStmt &);
private:
void CheckLoneStmt(const char *const) const;
SemanticsContext &context_;
};
}

View File

@ -81,15 +81,125 @@ public:
context_.set_location(std::nullopt);
}
bool Pre(const parser::ExecutableConstruct &executable) {
context_.PushExecutable(executable);
Enter(executable);
bool Pre(const parser::AssociateConstruct &associateConstruct) {
context_.PushConstruct(&associateConstruct);
Enter(associateConstruct);
return true;
}
void Post(const parser::ExecutableConstruct &executable) {
Leave(executable);
context_.PopExecutable();
bool Pre(const parser::BlockConstruct &blockConstruct) {
context_.PushConstruct(&blockConstruct);
Enter(blockConstruct);
return true;
}
bool Pre(const parser::CaseConstruct &caseConstruct) {
context_.PushConstruct(&caseConstruct);
Enter(caseConstruct);
return true;
}
bool Pre(const parser::DoConstruct &doConstruct) {
context_.PushConstruct(&doConstruct);
Enter(doConstruct);
return true;
}
bool Pre(const parser::CriticalConstruct &criticalConstruct) {
context_.PushConstruct(&criticalConstruct);
Enter(criticalConstruct);
return true;
}
bool Pre(const parser::ChangeTeamConstruct &changeTeamConstruct) {
context_.PushConstruct(&changeTeamConstruct);
Enter(changeTeamConstruct);
return true;
}
bool Pre(const parser::ForAllConstruct &forAllConstruct) {
context_.PushConstruct(&forAllConstruct);
Enter(forAllConstruct);
return true;
}
bool Pre(const parser::IfConstruct &ifConstruct) {
context_.PushConstruct(&ifConstruct);
Enter(ifConstruct);
return true;
}
bool Pre(const parser::SelectRankConstruct &selectRankConstruct) {
context_.PushConstruct(&selectRankConstruct);
Enter(selectRankConstruct);
return true;
}
bool Pre(const parser::SelectTypeConstruct &selectTypeConstruct) {
context_.PushConstruct(&selectTypeConstruct);
Enter(selectTypeConstruct);
return true;
}
bool Pre(const parser::WhereConstruct &whereConstruct) {
context_.PushConstruct(&whereConstruct);
Enter(whereConstruct);
return true;
}
void Post(const parser::AssociateConstruct &associateConstruct) {
Leave(associateConstruct);
context_.PopConstruct();
}
void Post(const parser::BlockConstruct &blockConstruct) {
Leave(blockConstruct);
context_.PopConstruct();
}
void Post(const parser::CaseConstruct &caseConstruct) {
Leave(caseConstruct);
context_.PopConstruct();
}
void Post(const parser::DoConstruct &doConstruct) {
Leave(doConstruct);
context_.PopConstruct();
}
void Post(const parser::CriticalConstruct &criticalConstruct) {
Leave(criticalConstruct);
context_.PopConstruct();
}
void Post(const parser::ChangeTeamConstruct &changeTeamConstruct) {
Leave(changeTeamConstruct);
context_.PopConstruct();
}
void Post(const parser::ForAllConstruct &forAllConstruct) {
Leave(forAllConstruct);
context_.PopConstruct();
}
void Post(const parser::IfConstruct &ifConstruct) {
Leave(ifConstruct);
context_.PopConstruct();
}
void Post(const parser::SelectRankConstruct &selectRankConstruct) {
Leave(selectRankConstruct);
context_.PopConstruct();
}
void Post(const parser::SelectTypeConstruct &selectTypeConstruct) {
Leave(selectTypeConstruct);
context_.PopConstruct();
}
void Post(const parser::WhereConstruct &whereConstruct) {
Leave(whereConstruct);
context_.PopConstruct();
}
bool Walk(const parser::Program &program) {
@ -188,14 +298,22 @@ Scope &SemanticsContext::FindScope(parser::CharBlock source) {
}
}
void SemanticsContext::PushExecutable(
const parser::ExecutableConstruct &executable) {
executables_.push_back(&executable);
void SemanticsContext::PushConstruct(const ConstructNode &construct) {
constructStack_.emplace_back(construct);
}
void SemanticsContext::PopExecutable() {
CHECK(executables_.size() > 0);
executables_.pop_back();
void SemanticsContext::PopConstruct() {
CHECK(!constructStack_.empty());
constructStack_.pop_back();
}
bool SemanticsContext::InsideDoConstruct() const {
for (const ConstructNode construct : constructStack_) {
if (std::holds_alternative<const parser::DoConstruct *>(construct)) {
return true;
}
}
return false;
}
bool Semantics::Perform() {

View File

@ -20,7 +20,6 @@
#include "../evaluate/intrinsics.h"
#include "../parser/features.h"
#include "../parser/message.h"
#include "../parser/parse-tree.h"
#include <iosfwd>
#include <string>
#include <vector>
@ -33,12 +32,31 @@ namespace Fortran::parser {
struct Name;
struct Program;
class CookedSource;
struct AssociateConstruct;
struct BlockConstruct;
struct CaseConstruct;
struct DoConstruct;
struct CriticalConstruct;
struct ChangeTeamConstruct;
struct ForAllConstruct;
struct IfConstruct;
struct SelectRankConstruct;
struct SelectTypeConstruct;
struct WhereConstruct;
}
namespace Fortran::semantics {
class Symbol;
using ConstructNode = std::variant<const parser::AssociateConstruct *,
const parser::BlockConstruct *, const parser::CaseConstruct *,
const parser::ChangeTeamConstruct *, const parser::CriticalConstruct *,
const parser::DoConstruct *, const parser::ForAllConstruct *,
const parser::IfConstruct *, const parser::SelectRankConstruct *,
const parser::SelectTypeConstruct *, const parser::WhereConstruct *>;
using ConstructStack = std::vector<ConstructNode>;
class SemanticsContext {
public:
SemanticsContext(const common::IntrinsicTypeDefaultKinds &,
@ -121,11 +139,10 @@ public:
const Scope &FindScope(parser::CharBlock) const;
Scope &FindScope(parser::CharBlock);
const std::vector<const parser::ExecutableConstruct *> executables() const {
return executables_;
}
void PushExecutable(const parser::ExecutableConstruct &executable);
void PopExecutable();
const ConstructStack &constructStack() const { return constructStack_; }
void PushConstruct(const ConstructNode &construct);
void PopConstruct();
bool InsideDoConstruct() const;
private:
const common::IntrinsicTypeDefaultKinds &defaultKinds_;
@ -143,7 +160,7 @@ private:
evaluate::FoldingContext foldingContext_{defaultKinds_};
bool CheckError(bool);
std::vector<const parser::ExecutableConstruct *> executables_;
ConstructStack constructStack_;
};
class Semantics {

View File

@ -17,6 +17,25 @@
! C1166 An EXIT statement must be within a DO construct
subroutine s1()
! this one's OK
do i = 1,10
cycle
end do
! this one's OK
do i = 1,10
exit
end do
! all of these are OK
outer: do i = 1,10
cycle
inner: do j = 1,10
cycle
end do inner
cycle
end do outer
!ERROR: CYCLE must be within a DO construct
cycle