xref: /llvm-project/flang/lib/Parser/parse-tree.cpp (revision bde79c0e27fd0fb1e31c9b8b34ae71716c51a8e8)
164ab3302SCarolineConcatto //===-- lib/Parser/parse-tree.cpp -----------------------------------------===//
264ab3302SCarolineConcatto //
364ab3302SCarolineConcatto // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
464ab3302SCarolineConcatto // See https://llvm.org/LICENSE.txt for license information.
564ab3302SCarolineConcatto // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
664ab3302SCarolineConcatto //
764ab3302SCarolineConcatto //===----------------------------------------------------------------------===//
864ab3302SCarolineConcatto 
964ab3302SCarolineConcatto #include "flang/Parser/parse-tree.h"
1064ab3302SCarolineConcatto #include "flang/Common/idioms.h"
1164ab3302SCarolineConcatto #include "flang/Common/indirection.h"
12914a91c1STim Keith #include "flang/Parser/tools.h"
1364ab3302SCarolineConcatto #include "flang/Parser/user-state.h"
148670e499SCaroline Concatto #include "llvm/Support/raw_ostream.h"
1564ab3302SCarolineConcatto #include <algorithm>
1664ab3302SCarolineConcatto 
1764ab3302SCarolineConcatto namespace Fortran::parser {
1864ab3302SCarolineConcatto 
1964ab3302SCarolineConcatto // R867
2064ab3302SCarolineConcatto ImportStmt::ImportStmt(common::ImportKind &&k, std::list<Name> &&n)
2164ab3302SCarolineConcatto     : kind{k}, names(std::move(n)) {
2264ab3302SCarolineConcatto   CHECK(kind == common::ImportKind::Default ||
2364ab3302SCarolineConcatto       kind == common::ImportKind::Only || names.empty());
2464ab3302SCarolineConcatto }
2564ab3302SCarolineConcatto 
2664ab3302SCarolineConcatto // R873
2764ab3302SCarolineConcatto CommonStmt::CommonStmt(std::optional<Name> &&name,
2864ab3302SCarolineConcatto     std::list<CommonBlockObject> &&objects, std::list<Block> &&others) {
2964ab3302SCarolineConcatto   blocks.emplace_front(std::move(name), std::move(objects));
3064ab3302SCarolineConcatto   blocks.splice(blocks.end(), std::move(others));
3164ab3302SCarolineConcatto }
3264ab3302SCarolineConcatto 
3364ab3302SCarolineConcatto // R901 designator
3464ab3302SCarolineConcatto bool Designator::EndsInBareName() const {
35cd03e96fSPeter Klausler   return common::visit(
3664ab3302SCarolineConcatto       common::visitors{
3764ab3302SCarolineConcatto           [](const DataRef &dr) {
3864ab3302SCarolineConcatto             return std::holds_alternative<Name>(dr.u) ||
3964ab3302SCarolineConcatto                 std::holds_alternative<common::Indirection<StructureComponent>>(
4064ab3302SCarolineConcatto                     dr.u);
4164ab3302SCarolineConcatto           },
4264ab3302SCarolineConcatto           [](const Substring &) { return false; },
4364ab3302SCarolineConcatto       },
4464ab3302SCarolineConcatto       u);
4564ab3302SCarolineConcatto }
4664ab3302SCarolineConcatto 
4764ab3302SCarolineConcatto // R911 data-ref -> part-ref [% part-ref]...
4864ab3302SCarolineConcatto DataRef::DataRef(std::list<PartRef> &&prl) : u{std::move(prl.front().name)} {
4964ab3302SCarolineConcatto   for (bool first{true}; !prl.empty(); first = false, prl.pop_front()) {
5064ab3302SCarolineConcatto     PartRef &pr{prl.front()};
5164ab3302SCarolineConcatto     if (!first) {
5264ab3302SCarolineConcatto       u = common::Indirection<StructureComponent>::Make(
5364ab3302SCarolineConcatto           std::move(*this), std::move(pr.name));
5464ab3302SCarolineConcatto     }
5564ab3302SCarolineConcatto     if (!pr.subscripts.empty()) {
5664ab3302SCarolineConcatto       u = common::Indirection<ArrayElement>::Make(
5764ab3302SCarolineConcatto           std::move(*this), std::move(pr.subscripts));
5864ab3302SCarolineConcatto     }
5964ab3302SCarolineConcatto     if (pr.imageSelector) {
6064ab3302SCarolineConcatto       u = common::Indirection<CoindexedNamedObject>::Make(
6164ab3302SCarolineConcatto           std::move(*this), std::move(*pr.imageSelector));
6264ab3302SCarolineConcatto     }
6364ab3302SCarolineConcatto   }
6464ab3302SCarolineConcatto }
6564ab3302SCarolineConcatto 
6664ab3302SCarolineConcatto // R1001 - R1022 expression
6764ab3302SCarolineConcatto Expr::Expr(Designator &&x)
6864ab3302SCarolineConcatto     : u{common::Indirection<Designator>::Make(std::move(x))} {}
6964ab3302SCarolineConcatto Expr::Expr(FunctionReference &&x)
7064ab3302SCarolineConcatto     : u{common::Indirection<FunctionReference>::Make(std::move(x))} {}
7164ab3302SCarolineConcatto 
7264ab3302SCarolineConcatto const std::optional<LoopControl> &DoConstruct::GetLoopControl() const {
7364ab3302SCarolineConcatto   const NonLabelDoStmt &doStmt{
7464ab3302SCarolineConcatto       std::get<Statement<NonLabelDoStmt>>(t).statement};
7564ab3302SCarolineConcatto   const std::optional<LoopControl> &control{
7664ab3302SCarolineConcatto       std::get<std::optional<LoopControl>>(doStmt.t)};
7764ab3302SCarolineConcatto   return control;
7864ab3302SCarolineConcatto }
7964ab3302SCarolineConcatto 
8064ab3302SCarolineConcatto bool DoConstruct::IsDoNormal() const {
8164ab3302SCarolineConcatto   const std::optional<LoopControl> &control{GetLoopControl()};
8264ab3302SCarolineConcatto   return control && std::holds_alternative<LoopControl::Bounds>(control->u);
8364ab3302SCarolineConcatto }
8464ab3302SCarolineConcatto 
8564ab3302SCarolineConcatto bool DoConstruct::IsDoWhile() const {
8664ab3302SCarolineConcatto   const std::optional<LoopControl> &control{GetLoopControl()};
8764ab3302SCarolineConcatto   return control && std::holds_alternative<ScalarLogicalExpr>(control->u);
8864ab3302SCarolineConcatto }
8964ab3302SCarolineConcatto 
9064ab3302SCarolineConcatto bool DoConstruct::IsDoConcurrent() const {
9164ab3302SCarolineConcatto   const std::optional<LoopControl> &control{GetLoopControl()};
9264ab3302SCarolineConcatto   return control && std::holds_alternative<LoopControl::Concurrent>(control->u);
9364ab3302SCarolineConcatto }
9464ab3302SCarolineConcatto 
9564ab3302SCarolineConcatto static Designator MakeArrayElementRef(
9664ab3302SCarolineConcatto     const Name &name, std::list<Expr> &&subscripts) {
9764ab3302SCarolineConcatto   ArrayElement arrayElement{DataRef{Name{name}}, std::list<SectionSubscript>{}};
9864ab3302SCarolineConcatto   for (Expr &expr : subscripts) {
9964ab3302SCarolineConcatto     arrayElement.subscripts.push_back(
10064ab3302SCarolineConcatto         SectionSubscript{Integer{common::Indirection{std::move(expr)}}});
10164ab3302SCarolineConcatto   }
10264ab3302SCarolineConcatto   return Designator{DataRef{common::Indirection{std::move(arrayElement)}}};
10364ab3302SCarolineConcatto }
10464ab3302SCarolineConcatto 
10564ab3302SCarolineConcatto static Designator MakeArrayElementRef(
10664ab3302SCarolineConcatto     StructureComponent &&sc, std::list<Expr> &&subscripts) {
10764ab3302SCarolineConcatto   ArrayElement arrayElement{DataRef{common::Indirection{std::move(sc)}},
10864ab3302SCarolineConcatto       std::list<SectionSubscript>{}};
10964ab3302SCarolineConcatto   for (Expr &expr : subscripts) {
11064ab3302SCarolineConcatto     arrayElement.subscripts.push_back(
11164ab3302SCarolineConcatto         SectionSubscript{Integer{common::Indirection{std::move(expr)}}});
11264ab3302SCarolineConcatto   }
11364ab3302SCarolineConcatto   return Designator{DataRef{common::Indirection{std::move(arrayElement)}}};
11464ab3302SCarolineConcatto }
11564ab3302SCarolineConcatto 
11664ab3302SCarolineConcatto // Set source in any type of node that has it.
11764ab3302SCarolineConcatto template <typename T> T WithSource(CharBlock source, T &&x) {
11864ab3302SCarolineConcatto   x.source = source;
11964ab3302SCarolineConcatto   return std::move(x);
12064ab3302SCarolineConcatto }
12164ab3302SCarolineConcatto 
12264ab3302SCarolineConcatto static Expr ActualArgToExpr(ActualArgSpec &arg) {
123cd03e96fSPeter Klausler   return common::visit(
12464ab3302SCarolineConcatto       common::visitors{
12564ab3302SCarolineConcatto           [&](common::Indirection<Expr> &y) { return std::move(y.value()); },
12664ab3302SCarolineConcatto           [&](common::Indirection<Variable> &y) {
127cd03e96fSPeter Klausler             return common::visit(
12864ab3302SCarolineConcatto                 common::visitors{
12964ab3302SCarolineConcatto                     [&](common::Indirection<Designator> &z) {
13064ab3302SCarolineConcatto                       return WithSource(
13164ab3302SCarolineConcatto                           z.value().source, Expr{std::move(z.value())});
13264ab3302SCarolineConcatto                     },
13364ab3302SCarolineConcatto                     [&](common::Indirection<FunctionReference> &z) {
13464ab3302SCarolineConcatto                       return WithSource(
1354ad72793SPeter Klausler                           z.value().source, Expr{std::move(z.value())});
13664ab3302SCarolineConcatto                     },
13764ab3302SCarolineConcatto                 },
13864ab3302SCarolineConcatto                 y.value().u);
13964ab3302SCarolineConcatto           },
14064ab3302SCarolineConcatto           [&](auto &) -> Expr { common::die("unexpected type"); },
14164ab3302SCarolineConcatto       },
14264ab3302SCarolineConcatto       std::get<ActualArg>(arg.t).u);
14364ab3302SCarolineConcatto }
14464ab3302SCarolineConcatto 
14564ab3302SCarolineConcatto Designator FunctionReference::ConvertToArrayElementRef() {
14664ab3302SCarolineConcatto   std::list<Expr> args;
14764ab3302SCarolineConcatto   for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
14864ab3302SCarolineConcatto     args.emplace_back(ActualArgToExpr(arg));
14964ab3302SCarolineConcatto   }
150cd03e96fSPeter Klausler   return common::visit(
15164ab3302SCarolineConcatto       common::visitors{
15264ab3302SCarolineConcatto           [&](const Name &name) {
15364ab3302SCarolineConcatto             return WithSource(
1544ad72793SPeter Klausler                 source, MakeArrayElementRef(name, std::move(args)));
15564ab3302SCarolineConcatto           },
15664ab3302SCarolineConcatto           [&](ProcComponentRef &pcr) {
1574ad72793SPeter Klausler             return WithSource(source,
15864ab3302SCarolineConcatto                 MakeArrayElementRef(std::move(pcr.v.thing), std::move(args)));
15964ab3302SCarolineConcatto           },
16064ab3302SCarolineConcatto       },
16164ab3302SCarolineConcatto       std::get<ProcedureDesignator>(v.t).u);
16264ab3302SCarolineConcatto }
16364ab3302SCarolineConcatto 
16464ab3302SCarolineConcatto StructureConstructor FunctionReference::ConvertToStructureConstructor(
16564ab3302SCarolineConcatto     const semantics::DerivedTypeSpec &derived) {
16664ab3302SCarolineConcatto   Name name{std::get<parser::Name>(std::get<ProcedureDesignator>(v.t).u)};
16764ab3302SCarolineConcatto   std::list<ComponentSpec> components;
16864ab3302SCarolineConcatto   for (auto &arg : std::get<std::list<ActualArgSpec>>(v.t)) {
16964ab3302SCarolineConcatto     std::optional<Keyword> keyword;
17064ab3302SCarolineConcatto     if (auto &kw{std::get<std::optional<Keyword>>(arg.t)}) {
17164ab3302SCarolineConcatto       keyword.emplace(Keyword{Name{kw->v}});
17264ab3302SCarolineConcatto     }
17364ab3302SCarolineConcatto     components.emplace_back(
17464ab3302SCarolineConcatto         std::move(keyword), ComponentDataSource{ActualArgToExpr(arg)});
17564ab3302SCarolineConcatto   }
17664ab3302SCarolineConcatto   DerivedTypeSpec spec{std::move(name), std::list<TypeParamSpec>{}};
17764ab3302SCarolineConcatto   spec.derivedTypeSpec = &derived;
17864ab3302SCarolineConcatto   return StructureConstructor{std::move(spec), std::move(components)};
17964ab3302SCarolineConcatto }
18064ab3302SCarolineConcatto 
181914a91c1STim Keith StructureConstructor ArrayElement::ConvertToStructureConstructor(
182914a91c1STim Keith     const semantics::DerivedTypeSpec &derived) {
183914a91c1STim Keith   Name name{std::get<parser::Name>(base.u)};
184914a91c1STim Keith   std::list<ComponentSpec> components;
185914a91c1STim Keith   for (auto &subscript : subscripts) {
186914a91c1STim Keith     components.emplace_back(std::optional<Keyword>{},
187914a91c1STim Keith         ComponentDataSource{std::move(*Unwrap<Expr>(subscript))});
188914a91c1STim Keith   }
189914a91c1STim Keith   DerivedTypeSpec spec{std::move(name), std::list<TypeParamSpec>{}};
190914a91c1STim Keith   spec.derivedTypeSpec = &derived;
191914a91c1STim Keith   return StructureConstructor{std::move(spec), std::move(components)};
192914a91c1STim Keith }
193914a91c1STim Keith 
19464ab3302SCarolineConcatto Substring ArrayElement::ConvertToSubstring() {
19564ab3302SCarolineConcatto   auto iter{subscripts.begin()};
19664ab3302SCarolineConcatto   CHECK(iter != subscripts.end());
19764ab3302SCarolineConcatto   auto &triplet{std::get<SubscriptTriplet>(iter->u)};
19864ab3302SCarolineConcatto   CHECK(!std::get<2>(triplet.t));
19964ab3302SCarolineConcatto   CHECK(++iter == subscripts.end());
20064ab3302SCarolineConcatto   return Substring{std::move(base),
20164ab3302SCarolineConcatto       SubstringRange{std::get<0>(std::move(triplet.t)),
20264ab3302SCarolineConcatto           std::get<1>(std::move(triplet.t))}};
20364ab3302SCarolineConcatto }
20464ab3302SCarolineConcatto 
20564ab3302SCarolineConcatto // R1544 stmt-function-stmt
206149d3e43SPeter Klausler // Convert this stmt-function-stmt to an assignment to the result of a
207149d3e43SPeter Klausler // pointer-valued function call -- which itself will be converted to a
208149d3e43SPeter Klausler // much more likely array element assignment statement if it needs
209149d3e43SPeter Klausler // to be.
21064ab3302SCarolineConcatto Statement<ActionStmt> StmtFunctionStmt::ConvertToAssignment() {
21164ab3302SCarolineConcatto   auto &funcName{std::get<Name>(t)};
21264ab3302SCarolineConcatto   auto &funcArgs{std::get<std::list<Name>>(t)};
21364ab3302SCarolineConcatto   auto &funcExpr{std::get<Scalar<Expr>>(t).thing};
21464ab3302SCarolineConcatto   CharBlock source{funcName.source};
215149d3e43SPeter Klausler   // Extend source to include closing parenthesis
21664ab3302SCarolineConcatto   if (funcArgs.empty()) {
21764ab3302SCarolineConcatto     CHECK(*source.end() == '(');
21864ab3302SCarolineConcatto     source = CharBlock{source.begin(), source.end() + 1};
21964ab3302SCarolineConcatto   }
220149d3e43SPeter Klausler   std::list<ActualArgSpec> actuals;
221149d3e43SPeter Klausler   for (const Name &arg : funcArgs) {
222149d3e43SPeter Klausler     actuals.emplace_back(std::optional<Keyword>{},
223149d3e43SPeter Klausler         ActualArg{Expr{WithSource(
224149d3e43SPeter Klausler             arg.source, Designator{DataRef{Name{arg.source, arg.symbol}}})}});
225149d3e43SPeter Klausler     source.ExtendToCover(arg.source);
226149d3e43SPeter Klausler   }
22764ab3302SCarolineConcatto   CHECK(*source.end() == ')');
22864ab3302SCarolineConcatto   source = CharBlock{source.begin(), source.end() + 1};
2294ad72793SPeter Klausler   FunctionReference funcRef{
230149d3e43SPeter Klausler       Call{ProcedureDesignator{Name{funcName.source, funcName.symbol}},
2314ad72793SPeter Klausler           std::move(actuals)}};
2324ad72793SPeter Klausler   funcRef.source = source;
233149d3e43SPeter Klausler   auto variable{Variable{common::Indirection{std::move(funcRef)}}};
23464ab3302SCarolineConcatto   return Statement{std::nullopt,
23564ab3302SCarolineConcatto       ActionStmt{common::Indirection{
23664ab3302SCarolineConcatto           AssignmentStmt{std::move(variable), std::move(funcExpr)}}}};
23764ab3302SCarolineConcatto }
23864ab3302SCarolineConcatto 
23964ab3302SCarolineConcatto CharBlock Variable::GetSource() const {
240cd03e96fSPeter Klausler   return common::visit(
24164ab3302SCarolineConcatto       common::visitors{
24264ab3302SCarolineConcatto           [&](const common::Indirection<Designator> &des) {
24364ab3302SCarolineConcatto             return des.value().source;
24464ab3302SCarolineConcatto           },
24564ab3302SCarolineConcatto           [&](const common::Indirection<parser::FunctionReference> &call) {
2464ad72793SPeter Klausler             return call.value().source;
24764ab3302SCarolineConcatto           },
24864ab3302SCarolineConcatto       },
24964ab3302SCarolineConcatto       u);
25064ab3302SCarolineConcatto }
25164ab3302SCarolineConcatto 
2528670e499SCaroline Concatto llvm::raw_ostream &operator<<(llvm::raw_ostream &os, const Name &x) {
25364ab3302SCarolineConcatto   return os << x.ToString();
25464ab3302SCarolineConcatto }
255c478aab6SKrzysztof Parzyszek 
256cfd67c21SKrzysztof Parzyszek OmpDependenceType::Value OmpDoacross::GetDepType() const {
257f87737f3SKrzysztof Parzyszek   return common::visit( //
258c478aab6SKrzysztof Parzyszek       common::visitors{
259f87737f3SKrzysztof Parzyszek           [](const OmpDoacross::Sink &) {
260cfd67c21SKrzysztof Parzyszek             return OmpDependenceType::Value::Sink;
261c478aab6SKrzysztof Parzyszek           },
262f87737f3SKrzysztof Parzyszek           [](const OmpDoacross::Source &) {
263cfd67c21SKrzysztof Parzyszek             return OmpDependenceType::Value::Source;
264c478aab6SKrzysztof Parzyszek           },
265c478aab6SKrzysztof Parzyszek       },
266c478aab6SKrzysztof Parzyszek       u);
267c478aab6SKrzysztof Parzyszek }
268c478aab6SKrzysztof Parzyszek 
269cfd67c21SKrzysztof Parzyszek OmpTaskDependenceType::Value OmpDependClause::TaskDep::GetTaskDepType() const {
270*bde79c0eSKrzysztof Parzyszek   using Modifier = OmpDependClause::TaskDep::Modifier;
271*bde79c0eSKrzysztof Parzyszek   auto &modifiers{std::get<std::optional<std::list<Modifier>>>(t)};
272*bde79c0eSKrzysztof Parzyszek   if (modifiers) {
273*bde79c0eSKrzysztof Parzyszek     for (auto &m : *modifiers) {
274*bde79c0eSKrzysztof Parzyszek       if (auto *dep{std::get_if<OmpTaskDependenceType>(&m.u)}) {
275*bde79c0eSKrzysztof Parzyszek         return dep->v;
276*bde79c0eSKrzysztof Parzyszek       }
277*bde79c0eSKrzysztof Parzyszek     }
278*bde79c0eSKrzysztof Parzyszek     llvm_unreachable("expecting OmpTaskDependenceType in TaskDep");
279*bde79c0eSKrzysztof Parzyszek   } else {
280*bde79c0eSKrzysztof Parzyszek     llvm_unreachable("expecting modifiers on OmpDependClause::TaskDep");
281*bde79c0eSKrzysztof Parzyszek   }
282f87737f3SKrzysztof Parzyszek }
283f87737f3SKrzysztof Parzyszek 
2841f879005STim Keith } // namespace Fortran::parser
285852e4779SKrzysztof Parzyszek 
286852e4779SKrzysztof Parzyszek template <typename C> static llvm::omp::Clause getClauseIdForClass(C &&) {
287852e4779SKrzysztof Parzyszek   using namespace Fortran;
288852e4779SKrzysztof Parzyszek   using A = llvm::remove_cvref_t<C>; // A is referenced in OMP.inc
289852e4779SKrzysztof Parzyszek   // The code included below contains a sequence of checks like the following
290852e4779SKrzysztof Parzyszek   // for each OpenMP clause
291852e4779SKrzysztof Parzyszek   //   if constexpr (std::is_same_v<A, parser::OmpClause::AcqRel>)
292852e4779SKrzysztof Parzyszek   //     return llvm::omp::Clause::OMPC_acq_rel;
293852e4779SKrzysztof Parzyszek   //   [...]
294852e4779SKrzysztof Parzyszek #define GEN_FLANG_CLAUSE_PARSER_KIND_MAP
295852e4779SKrzysztof Parzyszek #include "llvm/Frontend/OpenMP/OMP.inc"
296852e4779SKrzysztof Parzyszek }
297852e4779SKrzysztof Parzyszek 
298852e4779SKrzysztof Parzyszek namespace Fortran::parser {
299852e4779SKrzysztof Parzyszek llvm::omp::Clause OmpClause::Id() const {
300852e4779SKrzysztof Parzyszek   return std::visit([](auto &&s) { return getClauseIdForClass(s); }, u);
301852e4779SKrzysztof Parzyszek }
302852e4779SKrzysztof Parzyszek } // namespace Fortran::parser
303