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