Index: flang/include/flang/Common/indirection.h =================================================================== --- flang/include/flang/Common/indirection.h +++ flang/include/flang/Common/indirection.h @@ -28,7 +28,8 @@ namespace Fortran::common { // The default case does not support (deep) copy construction or assignment. -template class Indirection { +template +class Indirection : public std::in_place_t { public: using element_type = A; Indirection() = delete; @@ -69,7 +70,7 @@ }; // Variant with copy construction and assignment -template class Indirection { +template class Indirection : public std::in_place_t { public: using element_type = A; @@ -122,20 +123,28 @@ template using CopyableIndirection = Indirection; -// A variation of std::unique_ptr<> with a reified deletion routine. +// A variation of std::unique_ptr<> with reified deletion and +// copying routines. // Used to avoid dependence cycles between shared libraries. template class ForwardOwningPointer { public: ForwardOwningPointer() {} - ForwardOwningPointer(A *p, void (*del)(A *)) : p_{p}, deleter_{del} {} + ForwardOwningPointer(A *p, void (*del)(A *), A *(*copy)(const A *)) + : p_{p}, deleter_{del}, copier_{copy} {} ForwardOwningPointer(ForwardOwningPointer &&that) - : p_{that.p_}, deleter_{that.deleter_} { + : p_{that.p_}, deleter_{that.deleter_}, copier_{that.copier_} { that.p_ = nullptr; } ForwardOwningPointer &operator=(ForwardOwningPointer &&that) { - p_ = that.p_; + Reset(that.p_, that.deleter_, that.copier_); that.p_ = nullptr; - deleter_ = that.deleter_; + return *this; + } + ForwardOwningPointer(const ForwardOwningPointer &that) + : p_{that.copier_(that.p_)}, deleter_{that.deleter_}, copier_{ + that.copier_} {} + ForwardOwningPointer &operator=(const ForwardOwningPointer &that) { + Reset(that.copier_(that.p_), that.deleter_, that.copier_); return *this; } ~ForwardOwningPointer() { @@ -161,14 +170,16 @@ } p_ = p; } - void Reset(A *p, void (*del)(A *)) { + void Reset(A *p, void (*del)(A *), A *(*copy)(A *)) { Reset(p); deleter_ = del; + copier_ = copy; } private: A *p_{nullptr}; void (*deleter_)(A *){nullptr}; + A *(*copier_)(A *){nullptr}; }; } // namespace Fortran::common #endif // FORTRAN_COMMON_INDIRECTION_H_ Index: flang/include/flang/Evaluate/call.h =================================================================== --- flang/include/flang/Evaluate/call.h +++ flang/include/flang/Evaluate/call.h @@ -220,6 +220,7 @@ hasAlternateReturns_{hasAlternateReturns} {} ~ProcedureRef(); static void Deleter(ProcedureRef *); + static ProcedureRef *Copier(ProcedureRef *); ProcedureDesignator &proc() { return proc_; } const ProcedureDesignator &proc() const { return proc_; } Index: flang/include/flang/Evaluate/expression.h =================================================================== --- flang/include/flang/Evaluate/expression.h +++ flang/include/flang/Evaluate/expression.h @@ -859,6 +859,7 @@ : v{std::move(x)} {} ~GenericExprWrapper(); static void Deleter(GenericExprWrapper *); + static GenericExprWrapper *Copier(GenericExprWrapper *); std::optional> v; // vacant if error }; @@ -870,6 +871,7 @@ : v{std::move(x)} {} ~GenericAssignmentWrapper(); static void Deleter(GenericAssignmentWrapper *); + static GenericAssignmentWrapper *Copier(GenericAssignmentWrapper *); std::optional v; // vacant if error }; Index: flang/include/flang/Lower/Support/Utils.h =================================================================== --- flang/include/flang/Lower/Support/Utils.h +++ flang/include/flang/Lower/Support/Utils.h @@ -41,7 +41,11 @@ return a; } template -const A &removeIndirection(const Fortran::common::Indirection &a) { +const A &removeIndirection(const Fortran::common::Indirection &a) { + return a.value(); +} +template +const A &removeIndirection(const Fortran::common::Indirection &a) { return a.value(); } Index: flang/include/flang/Parser/dump-parse-tree.h =================================================================== --- flang/include/flang/Parser/dump-parse-tree.h +++ flang/include/flang/Parser/dump-parse-tree.h @@ -792,10 +792,8 @@ template bool Pre(const UnlabeledStatement &) { return true; } template void Post(const UnlabeledStatement &) {} - template bool Pre(const common::Indirection &) { - return true; - } - template void Post(const common::Indirection &) {} + template bool Pre(const Indirection &) { return true; } + template void Post(const Indirection &) {} template bool Pre(const Scalar &) { Prefix("Scalar"); Index: flang/include/flang/Parser/format-specification.h =================================================================== --- flang/include/flang/Parser/format-specification.h +++ flang/include/flang/Parser/format-specification.h @@ -39,6 +39,11 @@ IntrinsicTypeDataEditDesc() = delete; IntrinsicTypeDataEditDesc(IntrinsicTypeDataEditDesc &&) = default; IntrinsicTypeDataEditDesc &operator=(IntrinsicTypeDataEditDesc &&) = default; +#ifdef ENABLE_PARSE_TREE_COPYING + IntrinsicTypeDataEditDesc(const IntrinsicTypeDataEditDesc &) = default; + IntrinsicTypeDataEditDesc &operator=( + const IntrinsicTypeDataEditDesc &) = default; +#endif IntrinsicTypeDataEditDesc(Kind &&k, std::optional &&w, std::optional &&d, std::optional &&e) : kind{k}, width{std::move(w)}, digits{std::move(d)}, exponentWidth{ @@ -56,6 +61,10 @@ DerivedTypeDataEditDesc() = delete; DerivedTypeDataEditDesc(DerivedTypeDataEditDesc &&) = default; DerivedTypeDataEditDesc &operator=(DerivedTypeDataEditDesc &&) = default; +#ifdef ENABLE_PARSE_TREE_COPYING + DerivedTypeDataEditDesc(const DerivedTypeDataEditDesc &) = default; + DerivedTypeDataEditDesc &operator=(const DerivedTypeDataEditDesc &) = default; +#endif DerivedTypeDataEditDesc(std::string &&t, std::list &&p) : type{std::move(t)}, parameters{std::move(p)} {} std::string type; @@ -100,6 +109,10 @@ ControlEditDesc() = delete; ControlEditDesc(ControlEditDesc &&) = default; ControlEditDesc &operator=(ControlEditDesc &&) = default; +#ifdef ENABLE_PARSE_TREE_COPYING + ControlEditDesc(const ControlEditDesc &) = default; + ControlEditDesc &operator=(const ControlEditDesc &) = default; +#endif explicit ControlEditDesc(Kind k) : kind{k} {} ControlEditDesc(Kind k, std::int64_t ct) : kind{k}, count{ct} {} ControlEditDesc(std::int64_t ct, Kind k) : kind{k}, count{ct} {} @@ -116,6 +129,10 @@ FormatItem() = delete; FormatItem(FormatItem &&) = default; FormatItem &operator=(FormatItem &&) = default; +#ifdef ENABLE_PARSE_TREE_COPYING + FormatItem(const FormatItem &) = default; + FormatItem &operator=(const FormatItem &) = default; +#endif template > FormatItem(std::optional &&r, A &&x) : repeatCount{std::move(r)}, u{std::move(x)} {} @@ -135,6 +152,10 @@ FormatSpecification() = delete; FormatSpecification(FormatSpecification &&) = default; FormatSpecification &operator=(FormatSpecification &&) = default; +#ifdef ENABLE_PARSE_TREE_COPYING + FormatSpecification(const FormatSpecification &) = default; + FormatSpecification &operator=(const FormatSpecification &) = default; +#endif explicit FormatSpecification(std::list &&is) : items(std::move(is)) {} FormatSpecification(std::list &&is, std::list &&us) Index: flang/include/flang/Parser/parse-tree-visitor.h =================================================================== --- flang/include/flang/Parser/parse-tree-visitor.h +++ flang/include/flang/Parser/parse-tree-visitor.h @@ -237,11 +237,10 @@ } template -void Walk(const common::Indirection &x, V &visitor) { +void Walk(const Indirection &x, V &visitor) { Walk(x.value(), visitor); } -template -void Walk(common::Indirection &x, M &mutator) { +template void Walk(Indirection &x, M &mutator) { Walk(x.value(), mutator); } Index: flang/include/flang/Parser/parse-tree.h =================================================================== --- flang/include/flang/Parser/parse-tree.h +++ flang/include/flang/Parser/parse-tree.h @@ -17,6 +17,17 @@ // run-time I/O support library have been isolated into a distinct header file // (viz., format-specification.h). +// Parse tree node class types do not, by default, have copy constructors +// or copy assignment operators. They are explicitly declared "= delete; +// to make this clear, although a C++ compiler shouldn't default them anyway +// due to the presence of explicitly defaulted move constructors and move +// assignments. This default behavior ensures that the parser is always +// correctly using fast move semantics and can't be mysteriously slowed +// down by an unintentional deep copy. + +// Include this header with ENABLE_PARSE_TREE_COPYING defined in order +// to enable copy constructors and copy assignment operators. + #include "char-block.h" #include "characters.h" #include "format-specification.h" @@ -42,11 +53,6 @@ // prevents the introduction of what would be a viral requirement to include // std::monostate among most std::variant<> discriminated union members. -// Parse tree node class types do not have copy constructors or copy assignment -// operators. They are explicitly declared "= delete;" to make this clear, -// although a C++ compiler wouldn't default them anyway due to the presence -// of explicitly defaulted move constructors and move assignments. - CLASS_TRAIT(EmptyTrait) CLASS_TRAIT(WrapperTrait) CLASS_TRAIT(UnionTrait) @@ -70,14 +76,26 @@ class ProcedureRef; // forward definition, represents a CALL or function ref } // namespace Fortran::evaluate +namespace Fortran::parser { + // Most non-template classes in this file use these default definitions // for their move constructor and move assignment operator=, and disable // their copy constructor and copy assignment operator=. +#ifdef ENABLE_PARSE_TREE_COPYING +static constexpr bool isCopyingEnabled{true}; #define COPY_AND_ASSIGN_BOILERPLATE(classname) \ classname(classname &&) = default; \ + classname(const classname &) = default; \ classname &operator=(classname &&) = default; \ + classname &operator=(const classname &) = default +#else +static constexpr bool isCopyingEnabled{false}; +#define COPY_AND_ASSIGN_BOILERPLATE(classname) \ + classname(classname &&) = default; \ classname(const classname &) = delete; \ + classname &operator=(classname &&) = default; \ classname &operator=(const classname &) = delete +#endif // Almost all classes in this file have no default constructor. #define BOILERPLATE(classname) \ @@ -125,8 +143,6 @@ WRAPPER_CLASS_BOILERPLATE(classname, type); \ } -namespace Fortran::parser { - // These are the unavoidable recursively-defined productions of Fortran. // Some references to the representations of their parses require // indirection. The Indirect<> pointer wrapper class is used to @@ -270,6 +286,9 @@ // Cooked character stream locations using Location = const char *; +template +using Indirection = common::Indirection; + // A parse tree node with provenance only struct Verbatim { // Allow a no-arg constructor for Verbatim so parsers can return `RESULT{}`. @@ -286,48 +305,43 @@ // scalar-xyz, constant-xzy, int-xzy, default-char-xyz, & logical-xyz. template struct Scalar { using ConstraintTrait = std::true_type; - Scalar(Scalar &&that) = default; Scalar(A &&that) : thing(std::move(that)) {} - Scalar &operator=(Scalar &&) = default; + BOILERPLATE(Scalar); A thing; }; template struct Constant { using ConstraintTrait = std::true_type; - Constant(Constant &&that) = default; Constant(A &&that) : thing(std::move(that)) {} - Constant &operator=(Constant &&) = default; + BOILERPLATE(Constant); A thing; }; template struct Integer { using ConstraintTrait = std::true_type; - Integer(Integer &&that) = default; Integer(A &&that) : thing(std::move(that)) {} - Integer &operator=(Integer &&) = default; + BOILERPLATE(Integer); A thing; }; template struct Logical { using ConstraintTrait = std::true_type; - Logical(Logical &&that) = default; Logical(A &&that) : thing(std::move(that)) {} - Logical &operator=(Logical &&) = default; + BOILERPLATE(Logical); A thing; }; template struct DefaultChar { using ConstraintTrait = std::true_type; - DefaultChar(DefaultChar &&that) = default; DefaultChar(A &&that) : thing(std::move(that)) {} - DefaultChar &operator=(DefaultChar &&) = default; + BOILERPLATE(DefaultChar); A thing; }; -using LogicalExpr = Logical>; // R1024 -using DefaultCharExpr = DefaultChar>; // R1025 -using IntExpr = Integer>; // R1026 -using ConstantExpr = Constant>; // R1029 +using LogicalExpr = Logical>; // R1024 +using DefaultCharExpr = DefaultChar>; // R1025 +using IntExpr = Integer>; // R1026 +using ConstantExpr = Constant>; // R1029 using IntConstantExpr = Integer; // R1031 using ScalarLogicalExpr = Scalar; using ScalarIntExpr = Scalar; @@ -343,13 +357,15 @@ // A wrapper for xzy-stmt productions that are statements, so that // source provenances and labels have a uniform representation. template struct UnlabeledStatement { - explicit UnlabeledStatement(A &&s) : statement(std::move(s)) {} + UnlabeledStatement(A &&s) : statement(std::move(s)) {} + COPY_AND_ASSIGN_BOILERPLATE(UnlabeledStatement); CharBlock source; A statement; }; template struct Statement : public UnlabeledStatement { Statement(std::optional &&lab, A &&s) : UnlabeledStatement{std::move(s)}, label(std::move(lab)) {} + COPY_AND_ASSIGN_BOILERPLATE(Statement); std::optional(x.value()); } @@ -148,10 +148,6 @@ return std::nullopt; } } - template - static Result GetSource(const common::Indirection &x) { - return GetSource(x.value()); - } template static Result GetSource(const common::Indirection &x) { Index: flang/include/flang/Parser/user-state.h =================================================================== --- flang/include/flang/Parser/user-state.h +++ flang/include/flang/Parser/user-state.h @@ -112,12 +112,12 @@ }; struct CapturedLabelDoStmt { - using resultType = Statement>; + using resultType = Statement>; static std::optional Parse(ParseState &); }; struct EndDoStmtForCapturedLabelDoStmt { - using resultType = Statement>; + using resultType = Statement>; static std::optional Parse(ParseState &); }; Index: flang/include/flang/Semantics/expression.h =================================================================== --- flang/include/flang/Semantics/expression.h +++ flang/include/flang/Semantics/expression.h @@ -73,9 +73,11 @@ explicit SetExprHelper(GenericExprWrapper &&expr) : expr_{std::move(expr)} {} void Set(parser::TypedExpr &x) { x.Reset(new GenericExprWrapper{std::move(expr_)}, - evaluate::GenericExprWrapper::Deleter); + evaluate::GenericExprWrapper::Deleter, + evaluate::GenericExprWrapper::Copier); } - template void Set(const common::Indirection &x) { + template + void Set(const common::Indirection &x) { Set(x.value()); } template void Set(const T &x) { @@ -159,7 +161,7 @@ MaybeExpr Analyze(const parser::AllocateObject &); MaybeExpr Analyze(const parser::PointerObject &); - template MaybeExpr Analyze(const common::Indirection &x) { + template MaybeExpr Analyze(const parser::Indirection &x) { return Analyze(x.value()); } template MaybeExpr Analyze(const std::optional &x) { Index: flang/include/flang/Semantics/tools.h =================================================================== --- flang/include/flang/Semantics/tools.h +++ flang/include/flang/Semantics/tools.h @@ -293,7 +293,8 @@ const SomeExpr *Get(const parser::AllocateObject &); const SomeExpr *Get(const parser::PointerObject &); - template const SomeExpr *Get(const common::Indirection &x) { + template + const SomeExpr *Get(const common::Indirection &x) { return Get(x.value()); } template const SomeExpr *Get(const std::optional &x) { Index: flang/lib/Evaluate/call.cpp =================================================================== --- flang/lib/Evaluate/call.cpp +++ flang/lib/Evaluate/call.cpp @@ -247,5 +247,8 @@ ProcedureRef::~ProcedureRef() {} void ProcedureRef::Deleter(ProcedureRef *p) { delete p; } +ProcedureRef *ProcedureRef::Copier(ProcedureRef *p) { + return p ? new ProcedureRef{*p} : nullptr; +} } // namespace Fortran::evaluate Index: flang/lib/Evaluate/expression.cpp =================================================================== --- flang/lib/Evaluate/expression.cpp +++ flang/lib/Evaluate/expression.cpp @@ -314,12 +314,19 @@ GenericExprWrapper::~GenericExprWrapper() {} void GenericExprWrapper::Deleter(GenericExprWrapper *p) { delete p; } +GenericExprWrapper *GenericExprWrapper::Copier(GenericExprWrapper *p) { + return p ? new GenericExprWrapper(*p) : nullptr; +} GenericAssignmentWrapper::~GenericAssignmentWrapper() {} void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *p) { delete p; } +GenericAssignmentWrapper *GenericAssignmentWrapper::Copier( + GenericAssignmentWrapper *p) { + return p ? new GenericAssignmentWrapper{*p} : nullptr; +} template int Expr>::GetKind() const { return common::visit( Index: flang/lib/Lower/Bridge.cpp =================================================================== --- flang/lib/Lower/Bridge.cpp +++ flang/lib/Lower/Bridge.cpp @@ -2072,7 +2072,7 @@ void genFIR(const Fortran::parser::ForallStmt &stmt) { const auto &concurrentHeader = std::get< - Fortran::common::Indirection>( + Fortran::parser::Indirection>( stmt.t) .value(); if (lowerToHighLevelFIR()) { @@ -2110,7 +2110,7 @@ std::visit( Fortran::common::visitors{ [&](const Fortran::parser::WhereConstruct &b) { genFIR(b); }, - [&](const Fortran::common::Indirection< + [&](const Fortran::parser::Indirection< Fortran::parser::ForallConstruct> &b) { genFIR(b.value()); }, [&](const auto &b) { genNestedStatement(b); }}, s.u); @@ -2128,7 +2128,7 @@ void genFIR(const Fortran::parser::ForallConstructStmt &stmt) { const auto &concurrentHeader = std::get< - Fortran::common::Indirection>( + Fortran::parser::Indirection>( stmt.t) .value(); if (lowerToHighLevelFIR()) @@ -3693,7 +3693,7 @@ }, [&](const Fortran::parser::Statement &stmt) { genNestedStatement(stmt); }, - [&](const Fortran::common::Indirection< + [&](const Fortran::parser::Indirection< Fortran::parser::WhereConstruct> &c) { genFIR(c.value()); }, }, body.u); @@ -4505,7 +4505,7 @@ } void analyzeExplicitSpace(const Fortran::parser::WhereBodyConstruct &body) { std::visit(Fortran::common::visitors{ - [&](const Fortran::common::Indirection< + [&](const Fortran::parser::Indirection< Fortran::parser::WhereConstruct> &wc) { analyzeExplicitSpace(wc.value()); }, @@ -4537,7 +4537,7 @@ void analyzeExplicitSpace(const Fortran::parser::ForallStmt &forall) { analyzeExplicitSpace( std::get< - Fortran::common::Indirection>( + Fortran::parser::Indirection>( forall.t) .value()); analyzeExplicitSpace(std::get>( + Fortran::parser::Indirection>( forall.t) .value()); } @@ -4562,7 +4562,7 @@ for (const Fortran::parser::ForallBodyConstruct &s : std::get>(forall.t)) { std::visit(Fortran::common::visitors{ - [&](const Fortran::common::Indirection< + [&](const Fortran::parser::Indirection< Fortran::parser::ForallConstruct> &b) { analyzeExplicitSpace(b.value()); }, Index: flang/lib/Lower/OpenMP.cpp =================================================================== --- flang/lib/Lower/OpenMP.cpp +++ flang/lib/Lower/OpenMP.cpp @@ -2172,8 +2172,8 @@ // Check if the assignment statement has a single variable on the RHS const Fortran::parser::Expr &expr{ std::get(assignmentStmt.t)}; - const Fortran::common::Indirection *designator = - std::get_if>( + const Fortran::parser::Indirection *designator = + std::get_if>( &expr.u); const Fortran::parser::Name *name = designator @@ -2321,7 +2321,7 @@ mlir::Value val = fir::getBase(atomicUpdateOp.getRegion().front().getArgument(0)); auto varDesignator = - std::get_if>( + std::get_if>( &assignmentStmtVariable.u); assert(varDesignator && "Variable designator for atomic update assignment " "statement does not exist"); Index: flang/lib/Lower/PFTBuilder.cpp =================================================================== --- flang/lib/Lower/PFTBuilder.cpp +++ flang/lib/Lower/PFTBuilder.cpp @@ -34,7 +34,11 @@ using Type = A; }; template -struct RemoveIndirectionHelper> { +struct RemoveIndirectionHelper> { + using Type = A; +}; +template +struct RemoveIndirectionHelper> { using Type = A; }; @@ -105,14 +109,14 @@ } else if constexpr (std::is_same_v) { return std::visit( common::visitors{ - [&](const common::Indirection &x) { + [&](const parser::Indirection &x) { addEvaluation(lower::pft::Evaluation{ removeIndirection(x), pftParentStack.back(), stmt.position, stmt.label}); checkForRoundingModeCall(x.value()); return true; }, - [&](const common::Indirection &x) { + [&](const parser::Indirection &x) { convertIfStmt(x.value(), stmt.position, stmt.label); return false; }, Index: flang/lib/Parser/basic-parsers.h =================================================================== --- flang/lib/Parser/basic-parsers.h +++ flang/lib/Parser/basic-parsers.h @@ -770,7 +770,7 @@ // For a parser p, indirect(p) returns a parser that builds an indirect // reference to p's return type. template inline constexpr auto indirect(PA p) { - return construct>(p); + return construct>(p); } // If a and b are parsers, then nonemptySeparated(a, b) returns a parser Index: flang/lib/Parser/parse-tree.cpp =================================================================== --- flang/lib/Parser/parse-tree.cpp +++ flang/lib/Parser/parse-tree.cpp @@ -8,7 +8,6 @@ #include "flang/Parser/parse-tree.h" #include "flang/Common/idioms.h" -#include "flang/Common/indirection.h" #include "flang/Parser/tools.h" #include "flang/Parser/user-state.h" #include "llvm/Support/raw_ostream.h" @@ -36,8 +35,7 @@ common::visitors{ [](const DataRef &dr) { return std::holds_alternative(dr.u) || - std::holds_alternative>( - dr.u); + std::holds_alternative>(dr.u); }, [](const Substring &) { return false; }, }, @@ -49,25 +47,24 @@ for (bool first{true}; !prl.empty(); first = false, prl.pop_front()) { PartRef &pr{prl.front()}; if (!first) { - u = common::Indirection::Make( + u = Indirection::Make( std::move(*this), std::move(pr.name)); } if (!pr.subscripts.empty()) { - u = common::Indirection::Make( + u = Indirection::Make( std::move(*this), std::move(pr.subscripts)); } if (pr.imageSelector) { - u = common::Indirection::Make( + u = Indirection::Make( std::move(*this), std::move(*pr.imageSelector)); } } } // R1001 - R1022 expression -Expr::Expr(Designator &&x) - : u{common::Indirection::Make(std::move(x))} {} +Expr::Expr(Designator &&x) : u{Indirection::Make(std::move(x))} {} Expr::Expr(FunctionReference &&x) - : u{common::Indirection::Make(std::move(x))} {} + : u{Indirection::Make(std::move(x))} {} const std::optional &DoConstruct::GetLoopControl() const { const NonLabelDoStmt &doStmt{ @@ -97,20 +94,23 @@ ArrayElement arrayElement{DataRef{Name{name}}, std::list{}}; for (Expr &expr : subscripts) { arrayElement.subscripts.push_back( - SectionSubscript{Integer{common::Indirection{std::move(expr)}}}); + SectionSubscript{Integer{Indirection{std::move(expr)}}}); } - return Designator{DataRef{common::Indirection{std::move(arrayElement)}}}; + return Designator{ + DataRef{Indirection{std::move(arrayElement)}}}; } static Designator MakeArrayElementRef( StructureComponent &&sc, std::list &&subscripts) { - ArrayElement arrayElement{DataRef{common::Indirection{std::move(sc)}}, + ArrayElement arrayElement{ + DataRef{Indirection{std::move(sc)}}, std::list{}}; for (Expr &expr : subscripts) { arrayElement.subscripts.push_back( - SectionSubscript{Integer{common::Indirection{std::move(expr)}}}); + SectionSubscript{Integer{Indirection{std::move(expr)}}}); } - return Designator{DataRef{common::Indirection{std::move(arrayElement)}}}; + return Designator{ + DataRef{Indirection{std::move(arrayElement)}}}; } // Set source in any type of node that has it. @@ -122,15 +122,15 @@ static Expr ActualArgToExpr(ActualArgSpec &arg) { return common::visit( common::visitors{ - [&](common::Indirection &y) { return std::move(y.value()); }, - [&](common::Indirection &y) { + [&](Indirection &y) { return std::move(y.value()); }, + [&](Indirection &y) { return common::visit( common::visitors{ - [&](common::Indirection &z) { + [&](Indirection &z) { return WithSource( z.value().source, Expr{std::move(z.value())}); }, - [&](common::Indirection &z) { + [&](Indirection &z) { return WithSource( z.value().source, Expr{std::move(z.value())}); }, @@ -163,7 +163,7 @@ StructureConstructor FunctionReference::ConvertToStructureConstructor( const semantics::DerivedTypeSpec &derived) { - Name name{std::get(std::get(v.t).u)}; + Name name{std::get(std::get(v.t).u)}; std::list components; for (auto &arg : std::get>(v.t)) { std::optional keyword; @@ -180,7 +180,7 @@ StructureConstructor ArrayElement::ConvertToStructureConstructor( const semantics::DerivedTypeSpec &derived) { - Name name{std::get(base.u)}; + Name name{std::get(base.u)}; std::list components; for (auto &subscript : subscripts) { components.emplace_back(std::optional{}, @@ -230,22 +230,21 @@ Call{ProcedureDesignator{Name{funcName.source, funcName.symbol}}, std::move(actuals)}}; funcRef.source = source; - auto variable{Variable{common::Indirection{std::move(funcRef)}}}; + auto variable{Variable{Indirection{std::move(funcRef)}}}; return Statement{std::nullopt, - ActionStmt{common::Indirection{ + ActionStmt{Indirection{ AssignmentStmt{std::move(variable), std::move(funcExpr)}}}}; } CharBlock Variable::GetSource() const { - return common::visit( - common::visitors{ - [&](const common::Indirection &des) { - return des.value().source; - }, - [&](const common::Indirection &call) { - return call.value().source; - }, - }, + return common::visit(common::visitors{ + [&](const Indirection &des) { + return des.value().source; + }, + [&](const Indirection &call) { + return call.value().source; + }, + }, u); } Index: flang/lib/Parser/tools.cpp =================================================================== --- flang/lib/Parser/tools.cpp +++ flang/lib/Parser/tools.cpp @@ -20,13 +20,15 @@ return common::visit( common::visitors{ [](const Name &name) -> const Name & { return name; }, - [](const common::Indirection &sc) - -> const Name & { return GetLastName(sc.value()); }, - [](const common::Indirection &sc) -> const Name & { + [](const Indirection &sc) -> const Name & { + return GetLastName(sc.value()); + }, + [](const Indirection &sc) -> const Name & { return GetLastName(sc.value().base); }, - [](const common::Indirection &ci) - -> const Name & { return GetLastName(ci.value().base); }, + [](const Indirection &ci) -> const Name & { + return GetLastName(ci.value().base); + }, }, x.u); } @@ -78,13 +80,15 @@ return common::visit( common::visitors{ [](const Name &name) -> const Name & { return name; }, - [](const common::Indirection &sc) - -> const Name & { return GetFirstName(sc.value()); }, - [](const common::Indirection &sc) -> const Name & { + [](const Indirection &sc) -> const Name & { + return GetFirstName(sc.value()); + }, + [](const Indirection &sc) -> const Name & { return GetFirstName(sc.value().base); }, - [](const common::Indirection &ci) - -> const Name & { return GetFirstName(ci.value().base); }, + [](const Indirection &ci) -> const Name & { + return GetFirstName(ci.value().base); + }, }, x.u); } @@ -127,7 +131,7 @@ return common::visit( common::visitors{ [](const Name &) -> const CoindexedNamedObject * { return nullptr; }, - [](const common::Indirection &x) + [](const Indirection &x) -> const CoindexedNamedObject * { return &x.value(); }, [](const auto &x) -> const CoindexedNamedObject * { return GetCoindexedNamedObject(x.value().base); @@ -151,7 +155,7 @@ const CoindexedNamedObject *GetCoindexedNamedObject(const Variable &variable) { return common::visit( common::visitors{ - [](const common::Indirection &designator) + [](const Indirection &designator) -> const CoindexedNamedObject * { return GetCoindexedNamedObject(designator.value()); }, Index: flang/lib/Parser/unparse.cpp =================================================================== --- flang/lib/Parser/unparse.cpp +++ flang/lib/Parser/unparse.cpp @@ -286,8 +286,8 @@ const auto &init{ std::get>(d.t)}; return init && - std::holds_alternative>>( + std::holds_alternative< + std::list>>( init->u); }, [](const FillDecl &) { return false; }, @@ -350,15 +350,14 @@ } void Unparse(const Pass &x) { Word("PASS"), Walk("(", x.v, ")"); } void Unparse(const Initialization &x) { // R743 & R805 - common::visit( - common::visitors{ - [&](const ConstantExpr &y) { Put(" = "), Walk(y); }, - [&](const NullInit &y) { Put(" => "), Walk(y); }, - [&](const InitialDataTarget &y) { Put(" => "), Walk(y); }, - [&](const std::list> &y) { - Walk("/", y, ", ", "/"); - }, - }, + common::visit(common::visitors{ + [&](const ConstantExpr &y) { Put(" = "), Walk(y); }, + [&](const NullInit &y) { Put(" => "), Walk(y); }, + [&](const InitialDataTarget &y) { Put(" => "), Walk(y); }, + [&](const std::list> &y) { + Walk("/", y, ", ", "/"); + }, + }, x.u); } void Unparse(const PrivateStmt &) { // R745 @@ -379,7 +378,7 @@ } void Unparse(const TypeBoundGenericStmt &x) { // R751 Word("GENERIC"), Walk(", ", std::get>(x.t)); - Put(" :: "), Walk(std::get>(x.t)); + Put(" :: "), Walk(std::get>(x.t)); Put(" => "), Walk(std::get>(x.t), ", "); } void Post(const BindAttr::Deferred &) { Word("DEFERRED"); } // R752 @@ -449,8 +448,7 @@ Walk(dts), Walk(", ", attrs, ", "); static const auto isInitializerOldStyle{[](const Initialization &i) { - return std::holds_alternative< - std::list>>(i.u); + return std::holds_alternative>>(i.u); }}; static const auto hasAssignmentInitializer{[](const EntityDecl &d) { // Does a declaration have a new-style =x initializer? @@ -945,7 +943,7 @@ } void Unparse(const ForallConstructStmt &x) { // R1051 Walk(std::get>(x.t), ": "); - Word("FORALL"), Walk(std::get>(x.t)); + Word("FORALL"), Walk(std::get>(x.t)); Indent(); } void Unparse(const EndForallStmt &x) { // R1054 Index: flang/lib/Semantics/canonicalize-do.cpp =================================================================== --- flang/lib/Semantics/canonicalize-do.cpp +++ flang/lib/Semantics/canonicalize-do.cpp @@ -29,59 +29,59 @@ [](auto &) {}, // Labels on end-stmt of constructs are accepted by f18 as an // extension. - [&](common::Indirection &associate) { + [&](Indirection &associate) { CanonicalizeIfMatch(block, stack, i, std::get>( associate.value().t)); }, - [&](common::Indirection &blockConstruct) { + [&](Indirection &blockConstruct) { CanonicalizeIfMatch(block, stack, i, std::get>( blockConstruct.value().t)); }, - [&](common::Indirection &changeTeam) { + [&](Indirection &changeTeam) { CanonicalizeIfMatch(block, stack, i, std::get>( changeTeam.value().t)); }, - [&](common::Indirection &critical) { + [&](Indirection &critical) { CanonicalizeIfMatch(block, stack, i, std::get>(critical.value().t)); }, - [&](common::Indirection &doConstruct) { + [&](Indirection &doConstruct) { CanonicalizeIfMatch(block, stack, i, std::get>(doConstruct.value().t)); }, - [&](common::Indirection &ifConstruct) { + [&](Indirection &ifConstruct) { CanonicalizeIfMatch(block, stack, i, std::get>(ifConstruct.value().t)); }, - [&](common::Indirection &caseConstruct) { + [&](Indirection &caseConstruct) { CanonicalizeIfMatch(block, stack, i, std::get>( caseConstruct.value().t)); }, - [&](common::Indirection &selectRank) { + [&](Indirection &selectRank) { CanonicalizeIfMatch(block, stack, i, std::get>(selectRank.value().t)); }, - [&](common::Indirection &selectType) { + [&](Indirection &selectType) { CanonicalizeIfMatch(block, stack, i, std::get>(selectType.value().t)); }, - [&](common::Indirection &forall) { + [&](Indirection &forall) { CanonicalizeIfMatch(block, stack, i, std::get>(forall.value().t)); }, - [&](common::Indirection &where) { + [&](Indirection &where) { CanonicalizeIfMatch(block, stack, i, std::get>(where.value().t)); }, - [&](Statement> &labelDoStmt) { + [&](Statement> &labelDoStmt) { auto &label{std::get &x) { + template + static MaybeMsg WhyNotOk(const common::Indirection &x) { return WhyNotOk(x.value()); } template @@ -232,17 +232,17 @@ common::visit( common::visitors{ [&](const parser::ExecutableConstruct &x) { Check(x); }, - [&](const parser::Statement> + [&](const parser::Statement> &x) { context_.Say(x.source, "Device code may not contain an ENTRY statement"_err_en_US); }, - [](const parser::Statement> + [](const parser::Statement> &) {}, - [](const parser::Statement> + [](const parser::Statement> &) {}, [](const parser::Statement< - common::Indirection> &) {}, + parser::Indirection> &) {}, [](const parser::ErrorRecovery &) {}, }, epc.u); @@ -253,17 +253,17 @@ [&](const parser::Statement &stmt) { Check(stmt.statement, stmt.source); }, - [&](const common::Indirection &x) { + [&](const parser::Indirection &x) { if (const std::optional &control{ x.value().GetLoopControl()}) { common::visit([&](const auto &y) { Check(y); }, control->u); } Check(std::get(x.value().t)); }, - [&](const common::Indirection &x) { + [&](const parser::Indirection &x) { Check(std::get(x.value().t)); }, - [&](const common::Indirection &x) { + [&](const parser::Indirection &x) { Check(x.value()); }, [&](const auto &x) { @@ -376,7 +376,7 @@ if (const auto *execConstruct{ std::get_if(&innerBlock->front().u)}) { if (const auto *next{ - std::get_if>( + std::get_if>( &execConstruct->u)}) { return 1 + DoConstructTightNesting(&next->value(), innerBlock); } Index: flang/lib/Semantics/check-data.cpp =================================================================== --- flang/lib/Semantics/check-data.cpp +++ flang/lib/Semantics/check-data.cpp @@ -187,7 +187,7 @@ void DataChecker::Leave(const parser::DataIDoObject &object) { if (const auto *designator{ - std::get_if>>( + std::get_if>>( &object.u)}) { if (MaybeExpr expr{exprAnalyzer_.Analyze(*designator)}) { auto source{designator->thing.value().source}; @@ -243,7 +243,7 @@ std::get>(decl.t)}) { const Symbol *name{std::get(decl.t).symbol}; const auto *list{ - std::get_if>>( + std::get_if>>( &init->u)}; if (name && list) { AccumulateDataInitializations(inits_, exprAnalyzer_, *name, *list); Index: flang/lib/Semantics/check-do-forall.cpp =================================================================== --- flang/lib/Semantics/check-do-forall.cpp +++ flang/lib/Semantics/check-do-forall.cpp @@ -47,13 +47,13 @@ const parser::ForallConstruct &construct) { const auto &stmt{ std::get>(construct.t)}; - return std::get>( + return std::get>( stmt.statement.t) .value(); } static const parser::ConcurrentHeader &GetConcurrentHeader( const parser::ForallStmt &stmt) { - return std::get>(stmt.t) + return std::get>(stmt.t) .value(); } template @@ -987,7 +987,7 @@ if (checkedOptionalArg) { const evaluate::ActualArgument &checkedArg{*checkedOptionalArg}; if (const auto *parsedExpr{ - std::get_if>(&parsedArg.u)}) { + std::get_if>(&parsedArg.u)}) { CheckIfArgIsDoVar(checkedArg, parsedExpr->value().source, context_); } } Index: flang/lib/Semantics/check-if-stmt.cpp =================================================================== --- flang/lib/Semantics/check-if-stmt.cpp +++ flang/lib/Semantics/check-if-stmt.cpp @@ -17,7 +17,7 @@ // C1143 Check that the action stmt is not an if stmt const auto &body{ std::get>(ifStmt.t)}; - if (std::holds_alternative>( + if (std::holds_alternative>( body.statement.u)) { context_.Say( body.source, "IF statement is not allowed in IF statement"_err_en_US); Index: flang/lib/Semantics/check-io.h =================================================================== --- flang/lib/Semantics/check-io.h +++ flang/lib/Semantics/check-io.h @@ -36,7 +36,7 @@ void Enter(const parser::WriteStmt &) { Init(IoStmtKind::Write); } void Enter( - const parser::Statement> &); + const parser::Statement> &); void Enter(const parser::ConnectSpec &); void Enter(const parser::ConnectSpec::CharExpr &); Index: flang/lib/Semantics/check-io.cpp =================================================================== --- flang/lib/Semantics/check-io.cpp +++ flang/lib/Semantics/check-io.cpp @@ -58,7 +58,7 @@ } void IoChecker::Enter( - const parser::Statement> &stmt) { + const parser::Statement> &stmt) { if (!stmt.label) { context_.Say("Format statement must be labeled"_err_en_US); // C1301 } Index: flang/lib/Semantics/check-omp-structure.h =================================================================== --- flang/lib/Semantics/check-omp-structure.h +++ flang/lib/Semantics/check-omp-structure.h @@ -210,7 +210,7 @@ void CheckDependList(const parser::DataRef &); void CheckDependArraySection( - const common::Indirection &, const parser::Name &); + const parser::Indirection &, const parser::Name &); bool IsDataRefTypeParamInquiry(const parser::DataRef *dataRef); void CheckIsVarPartOfAnotherVar( const parser::CharBlock &source, const parser::OmpObjectList &objList); Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -1617,7 +1617,7 @@ const auto &var{std::get(assignment.t)}; common::visit( common::visitors{ - [&](const common::Indirection &x) { + [&](const parser::Indirection &x) { const auto &procedureDesignator{ std::get(x.value().v.t)}; const parser::Name *name{ @@ -1632,7 +1632,7 @@ } else if (name) { bool foundMatch{false}; if (auto varDesignatorIndirection = - std::get_if>(&var.u)) { const auto &varDesignator = varDesignatorIndirection->value(); if (const auto *dataRef = std::get_if( @@ -2491,7 +2491,7 @@ if (const auto *dataRef{std::get_if(&ele.u)}) { CheckDependList(*dataRef); if (const auto *arr{ - std::get_if>( + std::get_if>( &dataRef->u)}) { CheckArraySection(arr->value(), GetLastName(*dataRef), llvm::omp::Clause::OMPC_depend); @@ -2568,18 +2568,18 @@ void OmpStructureChecker::CheckDependList(const parser::DataRef &d) { common::visit( common::visitors{ - [&](const common::Indirection &elem) { + [&](const parser::Indirection &elem) { // Check if the base element is valid on Depend Clause CheckDependList(elem.value().base); }, - [&](const common::Indirection &) { + [&](const parser::Indirection &) { context_.Say(GetContext().clauseSource, "A variable that is part of another variable " "(such as an element of a structure) but is not an array " "element or an array section cannot appear in a DEPEND " "clause"_err_en_US); }, - [&](const common::Indirection &) { + [&](const parser::Indirection &) { context_.Say(GetContext().clauseSource, "Coarrays are not supported in DEPEND clause"_err_en_US); }, Index: flang/lib/Semantics/data-to-inits.h =================================================================== --- flang/lib/Semantics/data-to-inits.h +++ flang/lib/Semantics/data-to-inits.h @@ -12,13 +12,10 @@ #include "flang/Common/default-kinds.h" #include "flang/Common/interval.h" #include "flang/Evaluate/initial-image.h" +#include "flang/Parser/parse-tree.h" #include #include -namespace Fortran::parser { -struct DataStmtSet; -struct DataStmtValue; -} // namespace Fortran::parser namespace Fortran::evaluate { class ExpressionAnalyzer; } @@ -44,7 +41,7 @@ // For legacy DATA-style initialization extension: integer n(2)/1,2/ void AccumulateDataInitializations(DataInitializations &, evaluate::ExpressionAnalyzer &, const Symbol &, - const std::list> &); + const std::list> &); void ConvertToInitializers( DataInitializations &, evaluate::ExpressionAnalyzer &); Index: flang/lib/Semantics/data-to-inits.cpp =================================================================== --- flang/lib/Semantics/data-to-inits.cpp +++ flang/lib/Semantics/data-to-inits.cpp @@ -136,7 +136,7 @@ const parser::DataStmtObject &object) { return common::visit( common::visitors{ - [&](const common::Indirection &var) { + [&](const parser::Indirection &var) { return Scan(var.value()); }, [&](const parser::DataImpliedDo &ido) { return Scan(ido); }, @@ -241,9 +241,9 @@ const parser::DataIDoObject &object) { return common::visit( common::visitors{ - [&](const parser::Scalar> + [&](const parser::Scalar> &var) { return Scan(var.thing.value()); }, - [&](const common::Indirection &ido) { + [&](const parser::Indirection &ido) { return Scan(ido.value()); }, }, @@ -488,8 +488,8 @@ void AccumulateDataInitializations(DataInitializations &inits, evaluate::ExpressionAnalyzer &exprAnalyzer, const Symbol &symbol, - const std::list> &list) { - DataInitializationCompiler> + const std::list> &list) { + DataInitializationCompiler> scanner{inits, exprAnalyzer, list}; if (scanner.Scan(symbol) && scanner.HasSurplusValues()) { exprAnalyzer.context().Say( Index: flang/lib/Semantics/expression.cpp =================================================================== --- flang/lib/Semantics/expression.cpp +++ flang/lib/Semantics/expression.cpp @@ -131,7 +131,7 @@ Expr &&MoveExpr(std::size_t i) { return std::move(DEREF(actuals_.at(i).value().UnwrapExpr())); } - void Analyze(const common::Indirection &x) { + void Analyze(const parser::Indirection &x) { Analyze(x.value()); } void Analyze(const parser::Expr &x) { @@ -496,7 +496,7 @@ static std::optional FixMisparsedSubstringDataRef( parser::DataRef &dataRef) { if (auto *ae{ - std::get_if>(&dataRef.u)}) { + std::get_if>(&dataRef.u)}) { // ...%a(j:k) and "a" is a character scalar parser::ArrayElement &arrElement{ae->value()}; if (arrElement.subscripts.size() == 1) { @@ -532,7 +532,7 @@ const parser::Designator &d) { auto &mutate{const_cast(d)}; if (auto *dataRef{std::get_if(&mutate.u)}) { - if (auto *sc{std::get_if>( + if (auto *sc{std::get_if>( &dataRef->u)}) { parser::StructureComponent &structComponent{sc->value()}; parser::CharBlock which{structComponent.component.source}; @@ -1659,10 +1659,10 @@ common::visit( common::visitors{ [&](const parser::AcValue::Triplet &triplet) { Add(triplet); }, - [&](const common::Indirection &expr) { + [&](const parser::Indirection &expr) { Add(expr.value()); }, - [&](const common::Indirection &impliedDo) { + [&](const parser::Indirection &impliedDo) { Add(impliedDo.value()); }, }, @@ -2667,7 +2667,7 @@ template static const Symbol *AssumedTypeDummy(const A &x) { if (const auto *designator{ - std::get_if>(&x.u)}) { + std::get_if>(&x.u)}) { if (const auto *dataRef{ std::get_if(&designator->value().u)}) { if (const auto *name{std::get_if(&dataRef->u)}) { @@ -2872,7 +2872,7 @@ callStmt.typedCall.Reset( new ProcedureRef{std::move(*proc), std::move(callee->arguments), HasAlternateReturns(callee->arguments)}, - ProcedureRef::Deleter); + ProcedureRef::Deleter, ProcedureRef::Copier); DEREF(callStmt.typedCall.get()).set_chevrons(std::move(*chevrons)); return; } @@ -2919,7 +2919,7 @@ } } x.typedAssignment.Reset(new GenericAssignmentWrapper{std::move(assignment)}, - GenericAssignmentWrapper::Deleter); + GenericAssignmentWrapper::Deleter, GenericAssignmentWrapper::Copier); } return common::GetPtrFromOptional(x.typedAssignment->v); } @@ -2934,8 +2934,8 @@ rhs = Analyze(std::get(x.t)); } if (!lhs || !rhs) { - x.typedAssignment.Reset( - new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter); + x.typedAssignment.Reset(new GenericAssignmentWrapper{}, + GenericAssignmentWrapper::Deleter, GenericAssignmentWrapper::Copier); } else { Assignment assignment{std::move(*lhs), std::move(*rhs)}; common::visit( @@ -2965,7 +2965,7 @@ std::get(x.t).u); x.typedAssignment.Reset( new GenericAssignmentWrapper{std::move(assignment)}, - GenericAssignmentWrapper::Deleter); + GenericAssignmentWrapper::Deleter, GenericAssignmentWrapper::Copier); } } return common::GetPtrFromOptional(x.typedAssignment->v); @@ -3395,7 +3395,7 @@ using uType = std::decay_t; auto &u{const_cast(constU)}; if (auto *func{ - std::get_if>(&u)}) { + std::get_if>(&u)}) { parser::FunctionReference &funcRef{func->value()}; // Ensure that there are no argument keywords for (const auto &arg : @@ -3418,10 +3418,11 @@ symbol.has()) { // Note that expression in AssocEntityDetails cannot be a procedure // pointer as per C1105 so this cannot be a function reference. - if constexpr (common::HasMember, + if constexpr (common::HasMember, uType>) { if (CheckFuncRefToArrayElement(context, funcRef)) { - u = common::Indirection{funcRef.ConvertToArrayElementRef()}; + u = parser::Indirection{ + funcRef.ConvertToArrayElementRef()}; } } else { DIE("can't fix misparsed function as array reference"); @@ -3449,10 +3450,10 @@ MaybeExpr result; if constexpr (common::HasMember> && - common::HasMember, + common::HasMember, std::decay_t>) { if (const auto *funcRef{ - std::get_if>( + std::get_if>( &x.u)}) { // Function references in Exprs might turn out to be misparsed structure // constructors; we have to try generic procedure resolution @@ -3579,7 +3580,7 @@ auto restorer{GetContextualMessages().SetLocation(source)}; FixMisparsedFunctionReference(context_, var->u); if (const auto *funcRef{ - std::get_if>( + std::get_if>( &var->u)}) { // A Selector that parsed as a Variable might turn out during analysis // to actually be a structure constructor. In that case, repair the @@ -3854,7 +3855,7 @@ // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed. std::optional actual; common::visit(common::visitors{ - [&](const common::Indirection &x) { + [&](const parser::Indirection &x) { actual = AnalyzeExpr(x.value()); SetArgSourceLocation(actual, x.value().source); }, Index: flang/lib/Semantics/mod-file.cpp =================================================================== --- flang/lib/Semantics/mod-file.cpp +++ flang/lib/Semantics/mod-file.cpp @@ -1150,7 +1150,7 @@ const parser::Program &program) { CHECK(program.v.size() == 1); auto &unit{program.v.front()}; - auto &submod{std::get>(unit.u)}; + auto &submod{std::get>(unit.u)}; auto &stmt{ std::get>(submod.value().t)}; auto &parentId{std::get(stmt.statement.t)}; Index: flang/lib/Semantics/program-tree.cpp =================================================================== --- flang/lib/Semantics/program-tree.cpp +++ flang/lib/Semantics/program-tree.cpp @@ -18,7 +18,7 @@ const auto &implicitPart{std::get(spec.t)}; for (const parser::ImplicitPartStmt &stmt : implicitPart.v) { if (const auto *entryStmt{std::get_if< - parser::Statement>>( + parser::Statement>>( &stmt.u)}) { node.AddEntry(entryStmt->statement.value()); } @@ -26,7 +26,7 @@ for (const auto &decl : std::get>(spec.t)) { if (const auto *entryStmt{std::get_if< - parser::Statement>>( + parser::Statement>>( &decl.u)}) { node.AddEntry(entryStmt->statement.value()); } @@ -37,7 +37,7 @@ ProgramTree &node, const parser::ExecutionPart &exec) { for (const auto &epConstruct : exec.v) { if (const auto *entryStmt{std::get_if< - parser::Statement>>( + parser::Statement>>( &epConstruct.u)}) { node.AddEntry(entryStmt->statement.value()); } @@ -53,13 +53,13 @@ if (const auto *spec{ std::get_if(&decl.u)}) { if (const auto *generic{std::get_if< - parser::Statement>>( + parser::Statement>>( &spec->u)}) { const parser::GenericStmt &genericStmt{generic->statement.value()}; const auto &genericSpec{std::get(genericStmt.t)}; node.AddGeneric(genericSpec); } else if (const auto *interface{ - std::get_if>( + std::get_if>( &spec->u)}) { const parser::InterfaceBlock &interfaceBlock{interface->value()}; const parser::InterfaceStmt &interfaceStmt{ Index: flang/lib/Semantics/resolve-labels.cpp =================================================================== --- flang/lib/Semantics/resolve-labels.cpp +++ flang/lib/Semantics/resolve-labels.cpp @@ -58,7 +58,7 @@ // F18:R1131 template constexpr Legality IsLegalDoTerm(const parser::Statement &) { - if (std::is_same_v> || + if (std::is_same_v> || std::is_same_v) { return Legality::always; } else if (std::is_same_v || @@ -78,18 +78,18 @@ // See F08:C816 return Legality::always; } else if (!(std::holds_alternative< - common::Indirection>( + parser::Indirection>( actionStmt.statement.u) || - std::holds_alternative>( + std::holds_alternative>( actionStmt.statement.u) || - std::holds_alternative>( + std::holds_alternative>( actionStmt.statement.u) || - std::holds_alternative>( + std::holds_alternative>( actionStmt.statement.u) || - std::holds_alternative>( + std::holds_alternative>( actionStmt.statement.u) || std::holds_alternative< - common::Indirection>( + parser::Indirection>( actionStmt.statement.u))) { return Legality::formerly; } else { @@ -98,7 +98,7 @@ } template constexpr bool IsFormat(const parser::Statement &) { - return std::is_same_v>; + return std::is_same_v>; } template @@ -112,10 +112,10 @@ std::is_same_v || std::is_same_v || std::is_same_v || - std::is_same_v> || + std::is_same_v> || std::is_same_v || std::is_same_v || - std::is_same_v> || + std::is_same_v> || std::is_same_v || std::is_same_v || std::is_same_v || Index: flang/lib/Semantics/resolve-names-utils.cpp =================================================================== --- flang/lib/Semantics/resolve-names-utils.cpp +++ flang/lib/Semantics/resolve-names-utils.cpp @@ -533,13 +533,13 @@ return common::visit( common::visitors{ [&](const parser::Name &name) { return CheckObject(name); }, - [&](const common::Indirection &) { + [&](const parser::Indirection &) { context_.Say(source, // C8107 "Derived type component '%s' is not allowed in an equivalence set"_err_en_US, source); return false; }, - [&](const common::Indirection &elem) { + [&](const parser::Indirection &elem) { bool ok{CheckDataRef(source, elem.value().base)}; for (const auto &subscript : elem.value().subscripts) { ok &= common::visit( @@ -558,7 +558,7 @@ } return ok; }, - [&](const common::Indirection &) { + [&](const parser::Indirection &) { context_.Say(source, // C924 (R872) "Coindexed object '%s' is not allowed in an equivalence set"_err_en_US, source); Index: flang/lib/Semantics/resolve-names.cpp =================================================================== --- flang/lib/Semantics/resolve-names.cpp +++ flang/lib/Semantics/resolve-names.cpp @@ -16,7 +16,6 @@ #include "rewrite-parse-tree.h" #include "flang/Common/Fortran.h" #include "flang/Common/default-kinds.h" -#include "flang/Common/indirection.h" #include "flang/Common/restorer.h" #include "flang/Common/visit.h" #include "flang/Evaluate/characteristics.h" @@ -47,7 +46,7 @@ using namespace parser::literals; -template using Indirection = common::Indirection; +template using Indirection = parser::Indirection; using Message = parser::Message; using Messages = parser::Messages; using MessageFixedText = parser::MessageFixedText; @@ -7879,7 +7878,7 @@ currScope().InstantiateDerivedTypes(); for (const auto &decl : decls) { if (const auto *statement{std::get_if< - parser::Statement>>( + parser::Statement>>( &decl.u)}) { AnalyzeStmtFunctionStmt(statement->statement.value()); } @@ -8158,7 +8157,7 @@ } bool ResolveNamesVisitor::Pre(const parser::ProgramUnit &x) { - if (std::holds_alternative>( + if (std::holds_alternative>( x.u)) { // TODO: global directives return true; @@ -8178,7 +8177,7 @@ if constexpr (!std::is_same_v) { const auto &spec{std::get(x.t)}; const auto &unitUses{std::get< - std::list>>>( + std::list>>>( spec.t)}; for (const auto &u : unitUses) { uses.insert(u.statement.value().moduleName.source); @@ -8193,7 +8192,7 @@ bool disordered{false}; for (const auto &progUnit : x.v) { if (const auto *indMod{ - std::get_if>(&progUnit.u)}) { + std::get_if>(&progUnit.u)}) { const parser::Module &mod{indMod->value()}; const auto &moduleStmt{ std::get>(mod.t)}; @@ -8229,7 +8228,7 @@ const SourceName &name{pair.first}; const parser::ProgramUnit &progUnit{*pair.second}; const parser::Module &m{ - std::get>(progUnit.u).value()}; + std::get>(progUnit.u).value()}; ok = true; for (const SourceName &use : GetUses(m)) { if (modules.find(use) != modules.end()) { @@ -8262,7 +8261,7 @@ Walk(*progUnit); } for (const auto &progUnit : x.v) { - if (!std::get_if>(&progUnit.u)) { + if (!std::get_if>(&progUnit.u)) { Walk(progUnit); } } Index: flang/lib/Semantics/rewrite-parse-tree.cpp =================================================================== --- flang/lib/Semantics/rewrite-parse-tree.cpp +++ flang/lib/Semantics/rewrite-parse-tree.cpp @@ -64,7 +64,7 @@ private: using stmtFuncType = - parser::Statement>; + parser::Statement>; bool errorOnUnresolvedName_{true}; parser::Messages &messages_; std::list stmtFuncsToConvert_; Index: flang/lib/Semantics/semantics.cpp =================================================================== --- flang/lib/Semantics/semantics.cpp +++ flang/lib/Semantics/semantics.cpp @@ -508,7 +508,7 @@ // (e.g., __builtin_team_type) are available to semantics, esp. for // intrinsic checking. if (!program_.v.empty()) { - const auto *frontModule{std::get_if>( + const auto *frontModule{std::get_if>( &program_.v.front().u)}; if (frontModule && (std::get>(frontModule->value().t) Index: flang/lib/Semantics/tools.cpp =================================================================== --- flang/lib/Semantics/tools.cpp +++ flang/lib/Semantics/tools.cpp @@ -904,7 +904,8 @@ template bool operator()(const T &) { return common::HasMember; } - template bool operator()(const common::Indirection &x) { + template + bool operator()(const common::Indirection &x) { return (*this)(x.value()); } template bool operator()(const parser::Statement &x) { @@ -943,7 +944,7 @@ const parser::ActualArg &actualArg{ std::get(args.front().t)}; if (const auto *argExpr{ - std::get_if>( + std::get_if>( &actualArg.u)}) { return HasCoarray(argExpr->value()); } @@ -983,17 +984,17 @@ std::get_if>(&construct.u)}) { return common::visit( common::visitors{ - [](const common::Indirection &) + [](const parser::Indirection &) -> std::optional { return "ALLOCATE of a coarray is an image control" " statement"_en_US; }, - [](const common::Indirection &) + [](const parser::Indirection &) -> std::optional { return "DEALLOCATE of a coarray is an image control" " statement"_en_US; }, - [](const common::Indirection &) + [](const parser::Indirection &) -> std::optional { return "MOVE_ALLOC of a coarray is an image control" " statement "_en_US; @@ -1011,13 +1012,13 @@ const parser::ExecutableConstruct &executableConstruct) { return common::visit( common::visitors{ - [](const common::Indirection + [](const parser::Indirection &construct) { return std::get>( construct.value().t) .source; }, - [](const common::Indirection &construct) { + [](const parser::Indirection &construct) { return std::get>( construct.value().t) .source; Index: flang/tools/f18-parse-demo/stub-evaluate.cpp =================================================================== --- flang/tools/f18-parse-demo/stub-evaluate.cpp +++ flang/tools/f18-parse-demo/stub-evaluate.cpp @@ -9,19 +9,30 @@ // The parse tree has slots in which pointers to the results of semantic // analysis may be placed. When using the parser without the semantics // libraries, as here, we need to stub out the dependences on the external -// deleters, which will never actually be called. +// deleters and copiers, which will never actually be called. namespace Fortran::evaluate { struct GenericExprWrapper { static void Deleter(GenericExprWrapper *); + static GenericExprWrapper *Copier(GenericExprWrapper *); }; void GenericExprWrapper::Deleter(GenericExprWrapper *) {} +GenericExprWrapper *GenericExprWrapper::Copier(GenericExprWrapper *) { + return nullptr; +} struct GenericAssignmentWrapper { static void Deleter(GenericAssignmentWrapper *); + static GenericAssignmentWrapper *Copier(GenericAssignmentWrapper *); }; void GenericAssignmentWrapper::Deleter(GenericAssignmentWrapper *) {} +GenericAssignmentWrapper *GenericAssignmentWrapper::Copier( + GenericAssignmentWrapper *) { + return nullptr; +} struct ProcedureRef { static void Deleter(ProcedureRef *); + static ProcedureRef *Copier(ProcedureRef *); }; void ProcedureRef::Deleter(ProcedureRef *) {} +ProcedureRef *ProcedureRef::Copier(ProcedureRef *) { return nullptr; } } // namespace Fortran::evaluate