From 351dc98948b972f6e21843dd414552f5b2cb9db3 Mon Sep 17 00:00:00 2001 From: Tim Keith Date: Thu, 9 May 2019 08:32:27 -0700 Subject: [PATCH] [flang] Change parse tree to allow DO loop over REAL It is a common extension to allow DO loops with REAL variable and bounds. The parse tree currently parses those with the variable as `scalar-int-variable-name` and the bounds as `scalar-int-expr`. That causes the INTEGER constraint to be enforced automatically. Change the grammar and parse tree to treat them as `scalar-variable-name` and `scalar-expr`. This allows the name and expression to be REAL, but we will have to verify that they aren't any other type (in a future change). To accomplish this, add a template parameter to `LoopBounds` for the type of the variable name (always `Scalar` or `Scalar>`). We sometimes need names for the instantiations of `LoopBounds` so add type aliases like `LoopControl::Bounds` for each one. Original-commit: flang-compiler/f18@d75aa039701186584d46f0126dcdc1186515a058 Reviewed-on: https://github.com/flang-compiler/f18/pull/455 Tree-same-pre-rewrite: false --- flang/lib/FIR/afforestation.cc | 19 ++++++++----------- flang/lib/parser/dump-parse-tree.h | 5 +++-- flang/lib/parser/grammar.h | 14 +++++++++++--- flang/lib/parser/parse-tree-visitor.h | 6 ++++-- flang/lib/parser/parse-tree.h | 25 +++++++++++++++---------- flang/lib/parser/unparse.cc | 6 +++--- flang/lib/semantics/expression.cc | 2 +- flang/lib/semantics/resolve-names.cc | 14 ++++++-------- 8 files changed, 51 insertions(+), 40 deletions(-) diff --git a/flang/lib/FIR/afforestation.cc b/flang/lib/FIR/afforestation.cc index a584cba414bf..62cc8030a4e2 100644 --- a/flang/lib/FIR/afforestation.cc +++ b/flang/lib/FIR/afforestation.cc @@ -974,17 +974,15 @@ public: if (ctrl.has_value()) { std::visit( common::visitors{ - [&](const parser::LoopBounds &bounds) { - auto name{builder_->CreateAddr( - ToExpression(bounds.name.thing.thing))}; + [&](const parser::LoopControl::Bounds &bounds) { + auto name{ + builder_->CreateAddr(ToExpression(bounds.name.thing))}; // evaluate e1, e2 [, e3] ... - auto *e1{ - builder_->CreateExpr(ExprRef(bounds.lower.thing.thing))}; - auto *e2{ - builder_->CreateExpr(ExprRef(bounds.upper.thing.thing))}; + auto *e1{builder_->CreateExpr(ExprRef(bounds.lower.thing))}; + auto *e2{builder_->CreateExpr(ExprRef(bounds.upper.thing))}; Statement *e3; if (bounds.step.has_value()) { - e3 = builder_->CreateExpr(ExprRef(bounds.step->thing.thing)); + e3 = builder_->CreateExpr(ExprRef(bounds.step->thing)); } else { e3 = builder_->CreateExpr(CreateConstant(1)); } @@ -1025,8 +1023,7 @@ public: void FinishConstruct(const parser::NonLabelDoStmt *stmt) { auto &ctrl{std::get>(stmt->t)}; if (ctrl.has_value()) { - using A = parser::LoopBounds; - if (std::holds_alternative(ctrl->u)) { + if (std::holds_alternative(ctrl->u)) { PopDoContext(stmt); } } @@ -1037,7 +1034,7 @@ public: if (loopCtrl.has_value()) { return std::visit( common::visitors{ - [&](const parser::LoopBounds &) { + [&](const parser::LoopControl::Bounds &) { return doMap_.find(stmt)->second.condition; }, [&](const parser::ScalarLogicalExpr &sle) { diff --git a/flang/lib/parser/dump-parse-tree.h b/flang/lib/parser/dump-parse-tree.h index 453098bee668..10867fd45bb9 100644 --- a/flang/lib/parser/dump-parse-tree.h +++ b/flang/lib/parser/dump-parse-tree.h @@ -380,8 +380,9 @@ public: NODE(parser, LockStmt) NODE(parser::LockStmt, LockStat) NODE(parser, LogicalLiteralConstant) - NODE_NAME(parser::LoopBounds, "LoopBounds") - NODE_NAME(parser::LoopBounds, "LoopBounds") + NODE_NAME(parser::LoopControl::Bounds, "LoopBounds") + NODE_NAME(parser::AcImpliedDoControl::Bounds, "LoopBounds") + NODE_NAME(parser::DataImpliedDo::Bounds, "LoopBounds") NODE(parser, LoopControl) NODE(parser::LoopControl, Concurrent) NODE(parser, MainProgram) diff --git a/flang/lib/parser/grammar.h b/flang/lib/parser/grammar.h index 4651ad46f3c7..3a23c2f18a34 100644 --- a/flang/lib/parser/grammar.h +++ b/flang/lib/parser/grammar.h @@ -259,6 +259,7 @@ constexpr auto scalarIntExpr{scalar(intExpr)}; // R1029 constant-expr -> expr constexpr auto constantExpr{constant(indirect(expr))}; +constexpr auto scalarExpr{scalar(indirect(expr))}; // R1030 default-char-constant-expr -> default-char-expr constexpr auto scalarDefaultCharConstantExpr{scalar(defaultChar(constantExpr))}; @@ -959,9 +960,16 @@ TYPE_PARSER(construct(BOZLiteral{})) // R1124 do-variable -> scalar-int-variable-name constexpr auto doVariable{scalar(integer(name))}; +// NOTE: In loop-control we allow REAL name and bounds too. +// This means parse them without the integer constraint and check later. template inline constexpr auto loopBounds(const PA &p) { - return construct>( - doVariable / "=", p / ",", p, maybe("," >> p)); + if constexpr (std::is_same_v) { + return construct>( + scalar(name) / "=", p / ",", p, maybe("," >> p)); + } else { + return construct>( + doVariable / "=", p / ",", p, maybe("," >> p)); + } } // R769 array-constructor -> (/ ac-spec /) | lbracket ac-spec rbracket @@ -2162,7 +2170,7 @@ TYPE_PARSER(construct(construct( // R1129 concurrent-locality -> [locality-spec]... TYPE_CONTEXT_PARSER("loop control"_en_US, maybe(","_tok) >> - (construct(loopBounds(scalarIntExpr)) || + (construct(loopBounds(scalarExpr)) || construct( "WHILE" >> parenthesized(scalarLogicalExpr)) || construct(construct( diff --git a/flang/lib/parser/parse-tree-visitor.h b/flang/lib/parser/parse-tree-visitor.h index 5d6efdefec0a..96d8a3c395e2 100644 --- a/flang/lib/parser/parse-tree-visitor.h +++ b/flang/lib/parser/parse-tree-visitor.h @@ -450,7 +450,8 @@ template void Walk(IntrinsicTypeSpec::Real &x, M &mutator) { mutator.Post(x); } } -template void Walk(const LoopBounds &x, V &visitor) { +template +void Walk(const LoopBounds &x, V &visitor) { if (visitor.Pre(x)) { Walk(x.name, visitor); Walk(x.lower, visitor); @@ -459,7 +460,8 @@ template void Walk(const LoopBounds &x, V &visitor) { visitor.Post(x); } } -template void Walk(LoopBounds &x, M &mutator) { +template +void Walk(LoopBounds &x, M &mutator) { if (mutator.Pre(x)) { Walk(x.name, mutator); Walk(x.lower, mutator); diff --git a/flang/lib/parser/parse-tree.h b/flang/lib/parser/parse-tree.h index 469309134f3d..5ea32a83d8f1 100644 --- a/flang/lib/parser/parse-tree.h +++ b/flang/lib/parser/parse-tree.h @@ -1208,24 +1208,28 @@ WRAPPER_CLASS(ArrayConstructor, AcSpec); // R1124 do-variable -> scalar-int-variable-name using DoVariable = Scalar>; -template struct LoopBounds { +template struct LoopBounds { LoopBounds(LoopBounds &&that) = default; - LoopBounds(DoVariable &&n, A &&a, A &&z, std::optional &&s) + LoopBounds(A &&n, B &&a, B &&z, std::optional &&s) : name{std::move(n)}, lower{std::move(a)}, upper{std::move(z)}, step{std::move(s)} {} LoopBounds &operator=(LoopBounds &&) = default; - DoVariable name; - A lower, upper; - std::optional step; + A name; + B lower, upper; + std::optional step; }; +using ScalarName = Scalar; +using ScalarExpr = Scalar>; + // R775 ac-implied-do-control -> // [integer-type-spec ::] ac-do-variable = scalar-int-expr , // scalar-int-expr [, scalar-int-expr] // R776 ac-do-variable -> do-variable struct AcImpliedDoControl { TUPLE_CLASS_BOILERPLATE(AcImpliedDoControl); - std::tuple, LoopBounds> t; + using Bounds = LoopBounds; + std::tuple, Bounds> t; }; // R774 ac-implied-do -> ( ac-value-list , ac-implied-do-control ) @@ -1432,8 +1436,8 @@ struct DataIDoObject { // R842 data-i-do-variable -> do-variable struct DataImpliedDo { TUPLE_CLASS_BOILERPLATE(DataImpliedDo); - std::tuple, std::optional, - LoopBounds> + using Bounds = LoopBounds; + std::tuple, std::optional, Bounds> t; }; @@ -2186,7 +2190,8 @@ struct LoopControl { TUPLE_CLASS_BOILERPLATE(Concurrent); std::tuple> t; }; - std::variant, ScalarLogicalExpr, Concurrent> u; + using Bounds = LoopBounds; + std::variant u; }; // R1121 label-do-stmt -> [do-construct-name :] DO label [loop-control] @@ -2657,7 +2662,7 @@ struct PrintStmt { // R1220 io-implied-do-control -> // do-variable = scalar-int-expr , scalar-int-expr [, scalar-int-expr] -using IoImpliedDoControl = LoopBounds; +using IoImpliedDoControl = LoopBounds; // R1218 io-implied-do -> ( io-implied-do-object-list , io-implied-do-control ) // R1219 io-implied-do-object -> input-item | output-item diff --git a/flang/lib/parser/unparse.cc b/flang/lib/parser/unparse.cc index fdc8145e80bd..89bd665ac9bd 100644 --- a/flang/lib/parser/unparse.cc +++ b/flang/lib/parser/unparse.cc @@ -386,7 +386,7 @@ public: void Unparse(const AcSpec &x) { // R770 Walk(x.type, "::"), Walk(x.values, ", "); } - template void Unparse(const LoopBounds &x) { + template void Unparse(const LoopBounds &x) { Walk(x.name), Put('='), Walk(x.lower), Put(','), Walk(x.upper); Walk(",", x.step); } @@ -396,7 +396,7 @@ public: } void Unparse(const AcImpliedDoControl &x) { // R775 Walk(std::get>(x.t), "::"); - Walk(std::get>(x.t)); + Walk(std::get(x.t)); } void Unparse(const TypeDeclarationStmt &x) { // R801 @@ -598,7 +598,7 @@ public: void Unparse(const DataImpliedDo &x) { // R840, R842 Put('('), Walk(std::get>(x.t), ", "), Put(','); Walk(std::get>(x.t), "::"); - Walk(std::get>(x.t)), Put(')'); + Walk(std::get(x.t)), Put(')'); } void Unparse(const DataStmtValue &x) { // R843 Walk(std::get>(x.t), "*"); diff --git a/flang/lib/semantics/expression.cc b/flang/lib/semantics/expression.cc index c8d0f5ecc332..b658efb002d7 100644 --- a/flang/lib/semantics/expression.cc +++ b/flang/lib/semantics/expression.cc @@ -1101,7 +1101,7 @@ void ArrayConstructorContext::Add(const parser::AcValue &x) { const auto &control{ std::get(impliedDo.value().t)}; const auto &bounds{ - std::get>(control.t)}; + std::get(control.t)}; Analyze(bounds.name); parser::CharBlock name{bounds.name.thing.thing.source}; int kind{IntType::kind}; diff --git a/flang/lib/semantics/resolve-names.cc b/flang/lib/semantics/resolve-names.cc index 5d45f165bda0..6452fb2d1287 100644 --- a/flang/lib/semantics/resolve-names.cc +++ b/flang/lib/semantics/resolve-names.cc @@ -978,7 +978,10 @@ public: void Post(const parser::AllocateObject &); bool Pre(const parser::PointerAssignmentStmt &); void Post(const parser::Designator &); - template void Post(const parser::LoopBounds &); + template + void Post(const parser::LoopBounds &x) { + ResolveName(*parser::Unwrap(x.name)); + } void Post(const parser::ProcComponentRef &); bool Pre(const parser::FunctionReference &); bool Pre(const parser::CallStmt &); @@ -3812,7 +3815,7 @@ bool ConstructVisitor::Pre(const parser::AcImpliedDo &x) { auto &values{std::get>(x.t)}; auto &control{std::get(x.t)}; auto &type{std::get>(control.t)}; - auto &bounds{std::get>(control.t)}; + auto &bounds{std::get(control.t)}; DeclareStatementEntity(bounds.name.thing.thing, type); Walk(bounds); Walk(values); @@ -3822,8 +3825,7 @@ bool ConstructVisitor::Pre(const parser::AcImpliedDo &x) { bool ConstructVisitor::Pre(const parser::DataImpliedDo &x) { auto &objects{std::get>(x.t)}; auto &type{std::get>(x.t)}; - auto &bounds{ - std::get>(x.t)}; + auto &bounds{std::get(x.t)}; DeclareStatementEntity(bounds.name.thing.thing, type); Walk(bounds); Walk(objects); @@ -4558,10 +4560,6 @@ void ResolveNamesVisitor::Post(const parser::Designator &x) { ResolveDesignator(x); } -template -void ResolveNamesVisitor::Post(const parser::LoopBounds &x) { - ResolveName(x.name.thing.thing); -} void ResolveNamesVisitor::Post(const parser::ProcComponentRef &x) { ResolveStructureComponent(x.v.thing); } -- 2.34.1