[flang] replace the stubs for translating terminal symbols to expressions; start...
authorEric Schweitz <eschweitz@nvidia.com>
Tue, 12 Mar 2019 14:36:36 +0000 (07:36 -0700)
committerEric Schweitz <eschweitz@nvidia.com>
Fri, 15 Mar 2019 17:03:06 +0000 (10:03 -0700)
Original-commit: flang-compiler/f18@c5561646ea4f72431174f28131a49426b8a03495
Reviewed-on: https://github.com/flang-compiler/f18/pull/334
Tree-same-pre-rewrite: false

17 files changed:
flang/lib/FIR/afforestation.cc
flang/lib/FIR/basicblock.cc
flang/lib/FIR/basicblock.h
flang/lib/FIR/builder.h
flang/lib/FIR/common.h
flang/lib/FIR/graph-writer.cc
flang/lib/FIR/mixin.h
flang/lib/FIR/procedure.cc
flang/lib/FIR/procedure.h
flang/lib/FIR/program.cc
flang/lib/FIR/program.h
flang/lib/FIR/region.cc
flang/lib/FIR/region.h
flang/lib/FIR/statements.cc
flang/lib/FIR/statements.h
flang/lib/FIR/value.h [new file with mode: 0644]
flang/lib/semantics/expression.h

index cb8cf04..ff7fdf5 100644 (file)
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 
-namespace Fortran::howdowedothis {
-
-// need to be able to convert variable-like things to Expressions, or forego
-// using Expressions entirely. The .typedExpr data member is only on
-// parser::Expr nodes, which is not sufficient.
-
-semantics::MaybeExpr AnalyzeVariable(
-    semantics::SemanticsContext &context, const parser::Variable &var) {
-  return {};
-}
-semantics::MaybeExpr AnalyzeName(
-    semantics::SemanticsContext &context, const parser::Name &name) {
-  return {};
-}
-semantics::MaybeExpr AnalyzeDataRef(
-    semantics::SemanticsContext &context, const parser::DataRef &dataRef) {
-  return {};
-}
-}
-
 namespace Fortran::FIR {
 namespace {
 Expression *ExprRef(const parser::Expr &a) { return &a.typedExpr.value(); }
@@ -66,7 +46,9 @@ struct LinearLabelBuilder {
   LinearLabelRef getNext() {
     LinearLabelRef next{counter++};
     auto cap{referenced.capacity()};
-    if (cap < counter) referenced.reserve(2 * cap);
+    if (cap < counter) {
+      referenced.reserve(2 * cap);
+    }
     referenced[next] = false;
     return next;
   }
@@ -108,8 +90,8 @@ struct LinearGoto {
 };
 
 struct LinearReturn
-  : public SumTypeCopyMixin<std::variant<const parser::FailImageStmt *,
-        const parser::ReturnStmt *, const parser::StopStmt *>> {
+  : public SumTypeCopyMixin<const parser::FailImageStmt *,
+        const parser::ReturnStmt *, const parser::StopStmt *> {
   SUM_TYPE_COPY_MIXIN(LinearReturn)
   template<typename T> LinearReturn(const T &stmt) : SumTypeCopyMixin{&stmt} {}
 };
@@ -172,24 +154,24 @@ struct LinearAction {
   const parser::Statement<parser::ActionStmt> *v;
 };
 
-using ConstructVariant = std::variant<const parser::AssociateConstruct *,
-    const parser::BlockConstruct *, const parser::CaseConstruct *,
-    const parser::ChangeTeamConstruct *, const parser::CriticalConstruct *,
-    const parser::DoConstruct *, const parser::IfConstruct *,
-    const parser::SelectRankConstruct *, const parser::SelectTypeConstruct *,
-    const parser::WhereConstruct *, const parser::ForallConstruct *,
-    const parser::CompilerDirective *, const parser::OpenMPConstruct *,
-    const parser::OpenMPEndLoopDirective *>;
+#define WRAP(T) const parser::T *
+#define CONSTRUCT_TYPES \
+  WRAP(AssociateConstruct), WRAP(BlockConstruct), WRAP(CaseConstruct), \
+      WRAP(ChangeTeamConstruct), WRAP(CriticalConstruct), WRAP(DoConstruct), \
+      WRAP(IfConstruct), WRAP(SelectRankConstruct), WRAP(SelectTypeConstruct), \
+      WRAP(WhereConstruct), WRAP(ForallConstruct), WRAP(CompilerDirective), \
+      WRAP(OpenMPConstruct), WRAP(OpenMPEndLoopDirective)
 
-struct LinearBeginConstruct : public SumTypeCopyMixin<ConstructVariant> {
+struct LinearBeginConstruct : public SumTypeCopyMixin<CONSTRUCT_TYPES> {
   SUM_TYPE_COPY_MIXIN(LinearBeginConstruct)
   template<typename T>
   LinearBeginConstruct(const T &c) : SumTypeCopyMixin{&c} {}
 };
-struct LinearEndConstruct : public SumTypeCopyMixin<ConstructVariant> {
+struct LinearEndConstruct : public SumTypeCopyMixin<CONSTRUCT_TYPES> {
   SUM_TYPE_COPY_MIXIN(LinearEndConstruct)
   template<typename T> LinearEndConstruct(const T &c) : SumTypeCopyMixin{&c} {}
 };
+
 struct LinearDoIncrement {
   LinearDoIncrement(const parser::DoConstruct &stmt) : v{&stmt} {}
   const parser::DoConstruct *v;
@@ -413,11 +395,10 @@ LinearLabelRef NearestEnclosingDoConstruct(AnalysisData &ad) {
   return unspecifiedLabel;
 }
 
-struct LinearOp
-  : public SumTypeMixin<std::variant<LinearLabel, LinearGoto, LinearReturn,
-        LinearConditionalGoto, LinearSwitchingIO, LinearSwitch, LinearAction,
-        LinearBeginConstruct, LinearEndConstruct, LinearIndirectGoto,
-        LinearDoIncrement, LinearDoCompare>> {
+struct LinearOp : public SumTypeMixin<LinearLabel, LinearGoto, LinearReturn,
+                      LinearConditionalGoto, LinearSwitchingIO, LinearSwitch,
+                      LinearAction, LinearBeginConstruct, LinearEndConstruct,
+                      LinearIndirectGoto, LinearDoIncrement, LinearDoCompare> {
   template<typename T> LinearOp(const T &thing) : SumTypeMixin{thing} {}
   void dump() const;
 
@@ -533,44 +514,17 @@ struct LinearOp
 };
 
 template<typename STMTTYPE, typename CT>
-Evaluation GetSwitchSelector(const CT *selectConstruct) {
-  const auto &selector{std::get<parser::Selector>(
-      std::get<parser::Statement<STMTTYPE>>(selectConstruct->t).statement.t)};
-  return std::visit(
-      common::visitors{
-          [](const parser::Expr &e) { return Evaluation{ExprRef(e)}; },
-          [](const parser::Variable &variable) {
-            return Evaluation{&variable};
-          },
-      },
-      selector.u);
-}
-Evaluation GetSwitchRankSelector(
-    const parser::SelectRankConstruct *selectRankConstruct) {
-  return GetSwitchSelector<parser::SelectRankStmt>(selectRankConstruct);
-}
-Evaluation GetSwitchTypeSelector(
-    const parser::SelectTypeConstruct *selectTypeConstruct) {
-  return GetSwitchSelector<parser::SelectTypeStmt>(selectTypeConstruct);
-}
-Evaluation GetSwitchCaseSelector(const parser::CaseConstruct *construct) {
-  auto &s{std::get<parser::Statement<parser::SelectCaseStmt>>(construct->t)};
-  return Evaluation{
-      ExprRef(std::get<parser::Scalar<parser::Expr>>(s.statement.t).thing)};
-}
-
-template<typename STMTTYPE, typename CT>
 const std::optional<parser::Name> &GetSwitchAssociateName(
     const CT *selectConstruct) {
   return std::get<1>(
       std::get<parser::Statement<STMTTYPE>>(selectConstruct->t).statement.t);
 }
 
-template<typename CONSTRUCT, typename GSF>
+template<typename CONSTRUCT>
 void DumpSwitchWithSelector(
-    const CONSTRUCT *construct, char const *const name, GSF getSelector) {
-  auto selector{getSelector(construct)};
-  DebugChannel() << name << "(" << selector.dump();
+    const CONSTRUCT *construct, char const *const name) {
+  /// auto selector{getSelector(construct)};
+  DebugChannel() << name << "(";  // << selector.dump()
 }
 
 void LinearOp::dump() const {
@@ -599,16 +553,13 @@ void LinearOp::dump() const {
             std::visit(
                 common::visitors{
                     [](const parser::CaseConstruct *caseConstruct) {
-                      DumpSwitchWithSelector(
-                          caseConstruct, "case", GetSwitchCaseSelector);
+                      DumpSwitchWithSelector(caseConstruct, "case");
                     },
                     [](const parser::SelectRankConstruct *selectRankConstruct) {
-                      DumpSwitchWithSelector(
-                          selectRankConstruct, "rank", GetSwitchRankSelector);
+                      DumpSwitchWithSelector(selectRankConstruct, "rank");
                     },
                     [](const parser::SelectTypeConstruct *selectTypeConstruct) {
-                      DumpSwitchWithSelector(
-                          selectTypeConstruct, "type", GetSwitchTypeSelector);
+                      DumpSwitchWithSelector(selectTypeConstruct, "type");
                     },
                     [](const parser::ComputedGotoStmt *computedGotoStmt) {
                       DebugChannel() << "igoto(?";
@@ -865,30 +816,16 @@ struct ControlFlowAnalyzer {
   AnalysisData &ad;
 };
 
-struct SwitchArguments {
-  Evaluation exp;
-  LinearLabelRef defLab;
-  std::vector<SwitchStmt::ValueType> values;
-  std::vector<LinearLabelRef> labels;
-};
-struct SwitchCaseArguments {
-  Evaluation exp;
-  LinearLabelRef defLab;
-  std::vector<SwitchCaseStmt::ValueType> ranges;
-  std::vector<LinearLabelRef> labels;
-};
-struct SwitchRankArguments {
-  Evaluation exp;
-  LinearLabelRef defLab;
-  std::vector<SwitchRankStmt::ValueType> ranks;
-  std::vector<LinearLabelRef> labels;
-};
-struct SwitchTypeArguments {
-  Evaluation exp;
+template<typename T> struct SwitchArgs {
+  Value exp;
   LinearLabelRef defLab;
-  std::vector<SwitchTypeStmt::ValueType> types;
+  std::vector<T> values;
   std::vector<LinearLabelRef> labels;
 };
+struct SwitchArguments : public SwitchArgs<SwitchStmt::ValueType> {};
+struct SwitchCaseArguments : public SwitchArgs<SwitchCaseStmt::ValueType> {};
+struct SwitchRankArguments : public SwitchArgs<SwitchRankStmt::ValueType> {};
+struct SwitchTypeArguments : public SwitchArgs<SwitchTypeStmt::ValueType> {};
 
 template<typename T> bool IsDefault(const typename T::ValueType &valueType) {
   return std::holds_alternative<typename T::Default>(valueType);
@@ -914,7 +851,7 @@ void cleanupSwitchPairs(LinearLabelRef &defLab,
 }
 
 static std::vector<SwitchCaseStmt::ValueType> populateSwitchValues(
-    const std::list<parser::CaseConstruct::Case> &list) {
+    FIRBuilder *builder, const std::list<parser::CaseConstruct::Case> &list) {
   std::vector<SwitchCaseStmt::ValueType> result;
   for (auto &v : list) {
     auto &caseSelector{std::get<parser::CaseSelector>(
@@ -929,21 +866,28 @@ static std::vector<SwitchCaseStmt::ValueType> populateSwitchValues(
             common::visitors{
                 [&](const parser::CaseValue &caseValue) {
                   const auto &e{caseValue.thing.thing.value()};
-                  valueList.emplace_back(SwitchCaseStmt::Exactly{ExprRef(e)});
+                  auto *app{builder->MakeAsExpr(ExprRef(e))};
+                  valueList.emplace_back(SwitchCaseStmt::Exactly{app});
                 },
                 [&](const parser::CaseValueRange::Range &range) {
                   if (range.lower.has_value()) {
                     if (range.upper.has_value()) {
-                      valueList.emplace_back(SwitchCaseStmt::InclusiveRange{
-                          ExprRef(range.lower->thing.thing),
-                          ExprRef(range.upper->thing.thing)});
+                      auto *appl{builder->MakeAsExpr(
+                          ExprRef(range.lower->thing.thing))};
+                      auto *apph{builder->MakeAsExpr(
+                          ExprRef(range.upper->thing.thing))};
+                      valueList.emplace_back(
+                          SwitchCaseStmt::InclusiveRange{appl, apph});
                     } else {
-                      valueList.emplace_back(SwitchCaseStmt::InclusiveAbove{
-                          ExprRef(range.lower->thing.thing)});
+                      auto *app{builder->MakeAsExpr(
+                          ExprRef(range.lower->thing.thing))};
+                      valueList.emplace_back(
+                          SwitchCaseStmt::InclusiveAbove{app});
                     }
                   } else {
-                    valueList.emplace_back(SwitchCaseStmt::InclusiveBelow{
-                        ExprRef(range.upper->thing.thing)});
+                    auto *app{
+                        builder->MakeAsExpr(ExprRef(range.upper->thing.thing))};
+                    valueList.emplace_back(SwitchCaseStmt::InclusiveBelow{app});
                   }
                 },
             },
@@ -1005,76 +949,10 @@ static std::vector<SwitchTypeStmt::ValueType> populateSwitchValues(
   return result;
 }
 
-static SwitchCaseArguments ComposeSwitchCaseArguments(
-    const parser::CaseConstruct *caseConstruct,
-    const std::vector<LinearLabelRef> &refs) {
-  auto &cases{
-      std::get<std::list<parser::CaseConstruct::Case>>(caseConstruct->t)};
-  SwitchCaseArguments result{GetSwitchCaseSelector(caseConstruct),
-      unspecifiedLabel, populateSwitchValues(cases), std::move(refs)};
-  cleanupSwitchPairs<SwitchCaseStmt>(
-      result.defLab, result.ranges, result.labels);
-  return result;
-}
-
-static SwitchRankArguments ComposeSwitchRankArguments(
-    const parser::SelectRankConstruct *selectRankConstruct,
-    const std::vector<LinearLabelRef> &refs) {
-  auto &ranks{std::get<std::list<parser::SelectRankConstruct::RankCase>>(
-      selectRankConstruct->t)};
-  SwitchRankArguments result{GetSwitchRankSelector(selectRankConstruct),
-      unspecifiedLabel, populateSwitchValues(ranks), std::move(refs)};
-  if (auto &name{GetSwitchAssociateName<parser::SelectRankStmt>(
-          selectRankConstruct)}) {
-    (void)name;  // get rid of warning
-    // TODO: handle associate-name -> Add an assignment stmt?
-  }
-  cleanupSwitchPairs<SwitchRankStmt>(
-      result.defLab, result.ranks, result.labels);
-  return result;
-}
-static SwitchTypeArguments ComposeSwitchTypeArguments(
-    const parser::SelectTypeConstruct *selectTypeConstruct,
-    const std::vector<LinearLabelRef> &refs) {
-  auto &types{std::get<std::list<parser::SelectTypeConstruct::TypeCase>>(
-      selectTypeConstruct->t)};
-  SwitchTypeArguments result{GetSwitchTypeSelector(selectTypeConstruct),
-      unspecifiedLabel, populateSwitchValues(types), std::move(refs)};
-  if (auto &name{GetSwitchAssociateName<parser::SelectTypeStmt>(
-          selectTypeConstruct)}) {
-    (void)name;  // get rid of warning
-    // TODO: handle associate-name -> Add an assignment stmt?
-  }
-  cleanupSwitchPairs<SwitchTypeStmt>(
-      result.defLab, result.types, result.labels);
-  return result;
-}
-
 static void buildMultiwayDefaultNext(SwitchArguments &result) {
   result.defLab = result.labels.back();
   result.labels.pop_back();
 }
-static SwitchArguments ComposeSwitchArgs(const LinearSwitch &op) {
-  SwitchArguments result{nullptr, unspecifiedLabel, {}, op.refs};
-  std::visit(
-      common::visitors{
-          [&](const parser::ComputedGotoStmt *c) {
-            const auto &e{std::get<parser::ScalarIntExpr>(c->t)};
-            result.exp = ExprRef(e.thing.thing);
-            buildMultiwayDefaultNext(result);
-          },
-          [&](const parser::ArithmeticIfStmt *c) {
-            result.exp = ExprRef(std::get<parser::Expr>(c->t));
-          },
-          [&](const parser::CallStmt *c) {
-            result.exp = nullptr;  // fixme - result of call
-            buildMultiwayDefaultNext(result);
-          },
-          [](const auto *) { WRONG_PATH(); },
-      },
-      op.u);
-  return result;
-}
 
 template<typename T>
 const T *FindReadWriteSpecifier(
@@ -1120,22 +998,22 @@ static Expression CreateConstant(int64_t value) {
   return {evaluate::AsGenericExpr(evaluate::Constant<T>{value})};
 }
 
-static void CreateSwitchHelper(FIRBuilder *builder, const Evaluation &condition,
+static void CreateSwitchHelper(FIRBuilder *builder, Value condition,
     BasicBlock *defaultCase, const SwitchStmt::ValueSuccPairListType &rest) {
   builder->CreateSwitch(condition, defaultCase, rest);
 }
-static void CreateSwitchCaseHelper(FIRBuilder *builder,
-    const Evaluation &condition, BasicBlock *defaultCase,
+static void CreateSwitchCaseHelper(FIRBuilder *builder, Value condition,
+    BasicBlock *defaultCase,
     const SwitchCaseStmt::ValueSuccPairListType &rest) {
   builder->CreateSwitchCase(condition, defaultCase, rest);
 }
-static void CreateSwitchRankHelper(FIRBuilder *builder,
-    const Evaluation &condition, BasicBlock *defaultCase,
+static void CreateSwitchRankHelper(FIRBuilder *builder, Value condition,
+    BasicBlock *defaultCase,
     const SwitchRankStmt::ValueSuccPairListType &rest) {
   builder->CreateSwitchRank(condition, defaultCase, rest);
 }
-static void CreateSwitchTypeHelper(FIRBuilder *builder,
-    const Evaluation &condition, BasicBlock *defaultCase,
+static void CreateSwitchTypeHelper(FIRBuilder *builder, Value condition,
+    BasicBlock *defaultCase,
     const SwitchTypeStmt::ValueSuccPairListType &rest) {
   builder->CreateSwitchType(condition, defaultCase, rest);
 }
@@ -1353,26 +1231,127 @@ public:
   }
 
   // CALL translations ...
-  const Value *CreateCalleeValue(
-      const parser::ProcedureDesignator &designator) {
-    return nullptr;
+  const Value CreateCalleeValue(const parser::ProcedureDesignator &designator) {
+    return NOTHING;
   }
   CallArguments CreateCallArguments(
       const std::list<parser::ActualArgSpec> &arguments) {
     return CallArguments{};
   }
 
+  template<typename STMTTYPE, typename CT>
+  Statement *GetSwitchSelector(const CT *selectConstruct) {
+    return std::visit(
+        common::visitors{
+            [&](const parser::Expr &e) {
+              return builder_->CreateExpr(ExprRef(e));
+            },
+            [&](const parser::Variable &v) {
+              return builder_->CreateExpr(VariableToExpression(v));
+            },
+        },
+        std::get<parser::Selector>(
+            std::get<parser::Statement<STMTTYPE>>(selectConstruct->t)
+                .statement.t)
+            .u);
+  }
+  Statement *GetSwitchRankSelector(
+      const parser::SelectRankConstruct *selectRankConstruct) {
+    return GetSwitchSelector<parser::SelectRankStmt>(selectRankConstruct);
+  }
+  Statement *GetSwitchTypeSelector(
+      const parser::SelectTypeConstruct *selectTypeConstruct) {
+    return GetSwitchSelector<parser::SelectTypeStmt>(selectTypeConstruct);
+  }
+  Statement *GetSwitchCaseSelector(const parser::CaseConstruct *construct) {
+    const auto &x{std::get<parser::Scalar<parser::Expr>>(
+        std::get<parser::Statement<parser::SelectCaseStmt>>(construct->t)
+            .statement.t)};
+    return builder_->CreateExpr(ExprRef(x.thing));
+  }
+  SwitchArguments ComposeSwitchArgs(const LinearSwitch &op) {
+    SwitchArguments result{NOTHING, unspecifiedLabel, {}, op.refs};
+    std::visit(
+        common::visitors{
+            [&](const parser::ComputedGotoStmt *c) {
+              const auto &e{std::get<parser::ScalarIntExpr>(c->t)};
+              result.exp = builder_->CreateExpr(ExprRef(e.thing.thing));
+              buildMultiwayDefaultNext(result);
+            },
+            [&](const parser::ArithmeticIfStmt *c) {
+              result.exp =
+                  builder_->CreateExpr(ExprRef(std::get<parser::Expr>(c->t)));
+            },
+            [&](const parser::CallStmt *c) {
+              result.exp = NOTHING;  // fixme - result of call
+              buildMultiwayDefaultNext(result);
+            },
+            [](const auto *) { WRONG_PATH(); },
+        },
+        op.u);
+    return result;
+  }
+  SwitchCaseArguments ComposeSwitchCaseArguments(
+      const parser::CaseConstruct *caseConstruct,
+      const std::vector<LinearLabelRef> &refs) {
+    auto &cases{
+        std::get<std::list<parser::CaseConstruct::Case>>(caseConstruct->t)};
+    SwitchCaseArguments result{GetSwitchCaseSelector(caseConstruct),
+        unspecifiedLabel, populateSwitchValues(builder_, cases),
+        std::move(refs)};
+    cleanupSwitchPairs<SwitchCaseStmt>(
+        result.defLab, result.values, result.labels);
+    return result;
+  }
+  SwitchRankArguments ComposeSwitchRankArguments(
+      const parser::SelectRankConstruct *selectRankConstruct,
+      const std::vector<LinearLabelRef> &refs) {
+    auto &ranks{std::get<std::list<parser::SelectRankConstruct::RankCase>>(
+        selectRankConstruct->t)};
+    SwitchRankArguments result{GetSwitchRankSelector(selectRankConstruct),
+        unspecifiedLabel, populateSwitchValues(ranks), std::move(refs)};
+    if (auto &name{GetSwitchAssociateName<parser::SelectRankStmt>(
+            selectRankConstruct)}) {
+      (void)name;  // get rid of warning
+      // TODO: handle associate-name -> Add an assignment stmt?
+    }
+    cleanupSwitchPairs<SwitchRankStmt>(
+        result.defLab, result.values, result.labels);
+    return result;
+  }
+  SwitchTypeArguments ComposeSwitchTypeArguments(
+      const parser::SelectTypeConstruct *selectTypeConstruct,
+      const std::vector<LinearLabelRef> &refs) {
+    auto &types{std::get<std::list<parser::SelectTypeConstruct::TypeCase>>(
+        selectTypeConstruct->t)};
+    SwitchTypeArguments result{GetSwitchTypeSelector(selectTypeConstruct),
+        unspecifiedLabel, populateSwitchValues(types), std::move(refs)};
+    if (auto &name{GetSwitchAssociateName<parser::SelectTypeStmt>(
+            selectTypeConstruct)}) {
+      (void)name;  // get rid of warning
+      // TODO: handle associate-name -> Add an assignment stmt?
+    }
+    cleanupSwitchPairs<SwitchTypeStmt>(
+        result.defLab, result.values, result.labels);
+    return result;
+  }
+
   Expression VariableToExpression(const parser::Variable &var) {
-    auto maybe{howdowedothis::AnalyzeVariable(semanticsContext_, var)};
-    return {std::move(maybe.value())};
+    evaluate::ExpressionAnalyzer analyzer{semanticsContext_};
+    return {std::move(analyzer.Analyze(var).value())};
   }
   Expression DataRefToExpression(const parser::DataRef &dr) {
-    auto maybe{howdowedothis::AnalyzeDataRef(semanticsContext_, dr)};
-    return {std::move(maybe.value())};
+    evaluate::ExpressionAnalyzer analyzer{semanticsContext_};
+    return {std::move(analyzer.Analyze(dr).value())};
   }
   Expression NameToExpression(const parser::Name &name) {
-    auto maybe{howdowedothis::AnalyzeName(semanticsContext_, name)};
-    return {std::move(maybe.value())};
+    evaluate::ExpressionAnalyzer analyzer{semanticsContext_};
+    return {std::move(analyzer.Analyze(name).value())};
+  }
+  Expression StructureComponentToExpression(
+      const parser::StructureComponent &sc) {
+    evaluate::ExpressionAnalyzer analyzer{semanticsContext_};
+    return {std::move(analyzer.Analyze(sc).value())};
   }
 
   void handleIntrinsicAssignmentStmt(const parser::AssignmentStmt &stmt) {
@@ -1395,8 +1374,8 @@ public:
   }
 
   struct AllocOpts {
-    std::optional<Expression *> mold;
-    std::optional<Expression *> source;
+    std::optional<Expression> mold;
+    std::optional<Expression> source;
     std::optional<Expression> stat;
     std::optional<Expression> errmsg;
   };
@@ -1407,10 +1386,10 @@ public:
       std::visit(
           common::visitors{
               [&](const parser::AllocOpt::Mold &m) {
-                opts.mold = ExprRef(m.v);
+                opts.mold = *ExprRef(m.v);
               },
               [&](const parser::AllocOpt::Source &s) {
-                opts.source = ExprRef(s.v);
+                opts.source = *ExprRef(s.v);
               },
               [&](const parser::StatOrErrmsg &var) {
                 std::visit(
@@ -1517,7 +1496,21 @@ public:
                   RuntimeCallLock, CreateLockArguments(s.value()));
             },
             [&](const common::Indirection<parser::NullifyStmt> &s) {
-              builder_->CreateNullify(&s.value());
+              for (auto &obj : s.value().v) {
+                std::visit(
+                    common::visitors{
+                        [&](const parser::Name &n) {
+                          auto *s{builder_->CreateAddr(NameToExpression(n))};
+                          builder_->CreateNullify(s);
+                        },
+                        [&](const parser::StructureComponent &sc) {
+                          auto *s{builder_->CreateAddr(
+                              StructureComponentToExpression(sc))};
+                          builder_->CreateNullify(s);
+                        },
+                    },
+                    obj.u);
+              }
             },
             [&](const common::Indirection<parser::OpenStmt> &s) {
               builder_->CreateIOCall(
@@ -1795,10 +1788,14 @@ public:
                           builder_->CreateUnreachable();
                         },
                         [&](const parser::ReturnStmt *s) {
+                          // alt-return
                           if (s->v) {
-                            builder_->CreateReturn(ExprRef(s->v->thing.thing));
+                            auto *app{builder_->CreateExpr(
+                                ExprRef(s->v->thing.thing))};
+                            builder_->CreateReturn(app);
                           } else {
-                            builder_->CreateRetVoid();
+                            auto *zero{builder_->CreateExpr(CreateConstant(0))};
+                            builder_->CreateReturn(zero);
                           }
                         },
                         [&](const parser::StopStmt *s) {
@@ -1857,7 +1854,7 @@ public:
               [&](const LinearSwitchingIO &linearIO) {
                 CheckInsertionPoint();
                 AddOrQueueSwitch<SwitchStmt>(
-                    nullptr, linearIO.next, {}, {}, CreateSwitchHelper);
+                    NOTHING, linearIO.next, {}, {}, CreateSwitchHelper);
                 builder_->ClearInsertionPoint();
               },
               [&](const LinearSwitch &linearSwitch) {
@@ -1873,7 +1870,7 @@ public:
                           auto args{ComposeSwitchCaseArguments(
                               caseConstruct, linearSwitch.refs)};
                           AddOrQueueSwitch<SwitchCaseStmt>(args.exp,
-                              args.defLab, args.ranges, args.labels,
+                              args.defLab, args.values, args.labels,
                               CreateSwitchCaseHelper);
                         },
                         [&](const parser::SelectRankConstruct
@@ -1881,7 +1878,7 @@ public:
                           auto args{ComposeSwitchRankArguments(
                               selectRankConstruct, linearSwitch.refs)};
                           AddOrQueueSwitch<SwitchRankStmt>(args.exp,
-                              args.defLab, args.ranks, args.labels,
+                              args.defLab, args.values, args.labels,
                               CreateSwitchRankHelper);
                         },
                         [&](const parser::SelectTypeConstruct
@@ -1889,7 +1886,7 @@ public:
                           auto args{ComposeSwitchTypeArguments(
                               selectTypeConstruct, linearSwitch.refs)};
                           AddOrQueueSwitch<SwitchTypeStmt>(args.exp,
-                              args.defLab, args.types, args.labels,
+                              args.defLab, args.values, args.labels,
                               CreateSwitchTypeHelper);
                         },
                     },
@@ -2082,8 +2079,7 @@ public:
   }
 
   template<typename SWITCHTYPE, typename F>
-  void AddOrQueueSwitch(const Evaluation &condition,
-      LinearLabelRef defaultLabel,
+  void AddOrQueueSwitch(Value condition, LinearLabelRef defaultLabel,
       const std::vector<typename SWITCHTYPE::ValueType> &values,
       const std::vector<LinearLabelRef> &labels, F function) {
     auto defer{false};
@@ -2107,7 +2103,7 @@ public:
     if (defer) {
       using namespace std::placeholders;
       controlFlowEdgesToAdd_.emplace_back(std::bind(
-          [](FIRBuilder *builder, BasicBlock *block, const Evaluation &expr,
+          [](FIRBuilder *builder, BasicBlock *block, Value expr,
               LinearLabelRef defaultDest,
               const std::vector<typename SWITCHTYPE::ValueType> &values,
               const std::vector<LinearLabelRef> &labels, F function,
index 1529796..0271409 100644 (file)
@@ -12,7 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "program.h"
+#include "basicblock.h"
 #include "statements.h"
 
 namespace Fortran::FIR {
index 2ad0f74..aed8127 100644 (file)
@@ -15,7 +15,6 @@
 #ifndef FORTRAN_FIR_BASICBLOCK_H_
 #define FORTRAN_FIR_BASICBLOCK_H_
 
-#include "mixin.h"
 #include "region.h"
 #include <iostream>
 
@@ -25,7 +24,8 @@ class Region;
 class Statement;
 
 class BasicBlock final : public llvm::ilist_node<BasicBlock>,
-                         public ChildMixin<BasicBlock, Region> {
+                         public ChildMixin<BasicBlock, Region>,
+                         public Value_impl {
 public:
   using StatementListType = llvm::iplist<Statement>;
   using iterator = StatementListType::iterator;
index 70dc72a..8530db2 100644 (file)
@@ -50,14 +50,13 @@ struct FIRBuilder {
   Statement *CreateBranch(BasicBlock *block) {
     return InsertTerminator(BranchStmt::Create(block));
   }
-  Statement *CreateCall(const FunctionType *type, const Value *callee,
-      CallArguments &&arguments) {
-    return Insert(CallStmt::Create(type, callee, std::move(arguments)));
+  Statement *CreateCall(
+      const FunctionType *type, const Value callee, CallArguments &&args) {
+    return Insert(CallStmt::Create(type, callee, std::move(args)));
   }
   Statement *CreateConditionalBranch(
-      Statement *condition, BasicBlock *trueBlock, BasicBlock *falseBlock) {
-    return InsertTerminator(
-        BranchStmt::Create(condition, trueBlock, falseBlock));
+      Statement *cond, BasicBlock *trueBlock, BasicBlock *falseBlock) {
+    return InsertTerminator(BranchStmt::Create(cond, trueBlock, falseBlock));
   }
   Statement *CreateDealloc(AllocateInsn *alloc) {
     return Insert(DeallocateInsn::Create(alloc));
@@ -68,6 +67,9 @@ struct FIRBuilder {
   Statement *CreateExpr(Expression &&e) {
     return Insert(ApplyExprStmt::Create(std::move(e)));
   }
+  ApplyExprStmt *MakeAsExpr(const Expression *e) {
+    return GetApplyExpr(CreateExpr(e));
+  }
   Statement *CreateAddr(const Expression *e) {
     return Insert(LocateExprStmt::Create(e));
   }
@@ -95,35 +97,32 @@ struct FIRBuilder {
   Statement *CreateIndirectBr(Variable *v, const std::vector<BasicBlock *> &p) {
     return InsertTerminator(IndirectBranchStmt::Create(v, p));
   }
-  Statement *CreateNullify(const parser::NullifyStmt *s) {
+  Statement *CreateNullify(Statement *s) {
     return Insert(DisassociateInsn::Create(s));
   }
-  Statement *CreateRetVoid() { return InsertTerminator(ReturnStmt::Create()); }
-  template<typename A> Statement *CreateReturn(A *expr) {
+  Statement *CreateReturn(Statement *expr) {
     return InsertTerminator(ReturnStmt::Create(expr));
   }
   Statement *CreateRuntimeCall(
       RuntimeCallType call, RuntimeCallArguments &&arguments) {
     return Insert(RuntimeStmt::Create(call, std::move(arguments)));
   }
-  Statement *CreateSwitch(const Evaluation &condition, BasicBlock *defaultCase,
+  Statement *CreateSwitch(Value condition, BasicBlock *defaultCase,
       const SwitchStmt::ValueSuccPairListType &rest) {
     return InsertTerminator(SwitchStmt::Create(condition, defaultCase, rest));
   }
-  Statement *CreateSwitchCase(const Evaluation &condition,
-      BasicBlock *defaultCase,
+  Statement *CreateSwitchCase(Value condition, BasicBlock *defaultCase,
       const SwitchCaseStmt::ValueSuccPairListType &rest) {
     return InsertTerminator(
         SwitchCaseStmt::Create(condition, defaultCase, rest));
   }
-  Statement *CreateSwitchType(const Evaluation &condition,
-      BasicBlock *defaultCase,
+  Statement *CreateSwitchType(Value condition, BasicBlock *defaultCase,
       const SwitchTypeStmt::ValueSuccPairListType &rest) {
     return InsertTerminator(
         SwitchTypeStmt::Create(condition, defaultCase, rest));
   }
-  Statement *CreateSwitchRank(const Evaluation &c, BasicBlock *d,
-      const SwitchRankStmt::ValueSuccPairListType &r) {
+  Statement *CreateSwitchRank(
+      Value c, BasicBlock *d, const SwitchRankStmt::ValueSuccPairListType &r) {
     return InsertTerminator(SwitchRankStmt::Create(c, d, r));
   }
   Statement *CreateUnreachable() {
index b5660a9..cb964a3 100644 (file)
 #define WRONG_PATH() DIE("control should not reach here" AT_HERE)
 
 namespace Fortran::FIR {
+
+CLASS_TRAIT(ValueTrait)
+
+class Value_impl {
+public:
+  using ValueTrait = std::true_type;
+
+  std::string dump() const { return {}; }
+};
+
+struct Nothing {};
+constexpr Nothing NOTHING{};
+
+class Value;
 class Statement;
 class BasicBlock;
+class Region;
+class Procedure;
 class Program;
 class GraphWriter;
+class DataObject;
 
 struct Attribute {
-  enum { IntentIn, IntentOut, IntentInOut } attribute;
+  enum { IntentIn, IntentOut, IntentInOut, Value } attribute;
   unsigned short position;
 };
 using FunctionType = evaluate::SomeType;  // TODO: what should this be?
@@ -53,9 +70,8 @@ using Expression = evaluate::GenericExprWrapper;
 using Variable = const semantics::Symbol *;
 using PathVariable = const parser::Variable;
 using Scope = const semantics::Scope;
-using Value = Expression;
-using PHIPair = std::pair<Value *, BasicBlock *>;
-using CallArguments = std::vector<const Expression *>;
+using PHIPair = std::pair<Value, BasicBlock *>;
+using CallArguments = std::vector<Expression>;
 using Type = const semantics::DeclTypeSpec *;  // FIXME
 
 enum InputOutputCallType {
index d96f11b..f642b33 100644 (file)
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "graph-writer.h"
+#include "statements.h"
 
 namespace Fortran::FIR {
 
index d7d4ea4..2af0ff1 100644 (file)
 
 namespace Fortran::FIR {
 
-inline constexpr bool has_size(std::size_t size) { return size > 0; }
-
 // implementation of a (moveable) sum type (variant)
-template<typename T, typename E = void> struct SumTypeMixin {};
-template<typename T>  // T must be std::variant<...>
-struct SumTypeMixin<T, std::enable_if_t<has_size(std::variant_size_v<T>)>> {
+template<typename... Ts> struct SumTypeMixin {
   template<typename A> SumTypeMixin(A &&x) : u{std::move(x)} {}
   using SumTypeTrait = std::true_type;
   SumTypeMixin(SumTypeMixin &&) = default;
@@ -41,13 +37,11 @@ struct SumTypeMixin<T, std::enable_if_t<has_size(std::variant_size_v<T>)>> {
   SumTypeMixin(const SumTypeMixin &) = delete;
   SumTypeMixin &operator=(const SumTypeMixin &) = delete;
   SumTypeMixin() = delete;
-  T u;
+  std::variant<Ts...> u;
 };
 
 // implementation of a copyable sum type
-template<typename T, typename E = void> struct SumTypeCopyMixin {};
-template<typename T>  // T must be std::variant<...>
-struct SumTypeCopyMixin<T, std::enable_if_t<has_size(std::variant_size_v<T>)>> {
+template<typename... Ts> struct SumTypeCopyMixin {
   template<typename A> SumTypeCopyMixin(A &&x) : u{std::move(x)} {}
   template<typename A> SumTypeCopyMixin(const A &x) : u{x} {}
   using CopyableSumTypeTrait = std::true_type;
@@ -56,7 +50,7 @@ struct SumTypeCopyMixin<T, std::enable_if_t<has_size(std::variant_size_v<T>)>> {
   SumTypeCopyMixin(const SumTypeCopyMixin &) = default;
   SumTypeCopyMixin &operator=(const SumTypeCopyMixin &) = default;
   SumTypeCopyMixin() = delete;
-  T u;
+  std::variant<Ts...> u;
 };
 #define SUM_TYPE_COPY_MIXIN(DT) \
   DT(const DT &derived) : SumTypeCopyMixin(derived.u) {} \
@@ -66,9 +60,7 @@ struct SumTypeCopyMixin<T, std::enable_if_t<has_size(std::variant_size_v<T>)>> {
   }
 
 // implementation of a (moveable) product type (tuple)
-template<typename T, typename E = void> struct ProductTypeMixin {};
-template<typename T>  // T must be std::tuple<...>
-struct ProductTypeMixin<T, std::enable_if_t<has_size(std::tuple_size_v<T>)>> {
+template<typename... Ts> struct ProductTypeMixin {
   template<typename A> ProductTypeMixin(A &&x) : t{std::move(x)} {}
   using ProductTypeTrait = std::true_type;
   ProductTypeMixin(ProductTypeMixin &&) = default;
@@ -76,23 +68,20 @@ struct ProductTypeMixin<T, std::enable_if_t<has_size(std::tuple_size_v<T>)>> {
   ProductTypeMixin(const ProductTypeMixin &) = delete;
   ProductTypeMixin &operator=(const ProductTypeMixin &) = delete;
   ProductTypeMixin() = delete;
-  T t;
+  std::tuple<Ts...> t;
 };
 
 // implementation of a (moveable) maybe type
-template<typename T, typename E = void> struct MaybeMixin {};
 template<typename T>  // T must be std::optional<...>
-struct MaybeMixin<T,
-    std::enable_if_t<
-        std::is_same_v<std::optional<typename T::value_type>, T>>> {
-  template<typename A> MaybeMixin(A &&x) : o{std::move(x)} {}
+struct MaybeMixin {
+  MaybeMixin(T &&x) : o{std::move(x)} {}
   using MaybeTrait = std::true_type;
   MaybeMixin(MaybeMixin &&) = default;
   MaybeMixin &operator=(MaybeMixin &&) = default;
   MaybeMixin(const MaybeMixin &) = delete;
   MaybeMixin &operator=(const MaybeMixin &) = delete;
   MaybeMixin() = delete;
-  T o;
+  std::optional<T> o;
 };
 
 // implementation of a child type (composable hierarchy)
@@ -125,6 +114,12 @@ template<typename A, typename B> B &Unzip(B &out, A first, A last) {
       [](auto &&a) -> decltype(a.second) { return a.second; });
   return out;
 }
+
+template<typename A, typename B> B &UnzipSnd(B &out, A first, A last) {
+  std::transform(first, last, std::back_inserter(out.second),
+      [](auto &&a) -> decltype(a.second) { return a.second; });
+  return out;
+}
 }
 
 #endif  // FORTRAN_FIR_COMMON_H_
index 2a6560a..ad48312 100644 (file)
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "procedure.h"
+#include "statements.h"
 
 namespace Fortran::FIR {
 
@@ -81,4 +82,8 @@ void Procedure::FlattenRegions() {
     }
   }
 }
+
+Value Procedure::CreateIntrinsicProcedure(int value) {
+  return {NOTHING};  // FIXME
+}
 }
index 043c937..83da0a0 100644 (file)
 #ifndef FORTRAN_FIR_PROCEDURE_H_
 #define FORTRAN_FIR_PROCEDURE_H_
 
-#include "mixin.h"
 #include "program.h"
-#include "region.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/ADT/Twine.h"
 
 namespace Fortran::FIR {
 
-class Program;
-class Region;
-class GraphWriter;
-
 class Procedure final : public llvm::ilist_node<Procedure>,
-                        public ChildMixin<Procedure, Program> {
+                        public ChildMixin<Procedure, Program>,
+                        public Value_impl {
 public:
   friend GraphWriter;
   friend Program;
@@ -63,6 +58,8 @@ public:
   llvm::StringRef getName() const { return name_; }
   void FlattenRegions();
 
+  static Value CreateIntrinsicProcedure(int value);
+
 private:
   RegionListType regionList_;
   BasicBlockListType basicBlockList_;
index abe7237..d26786c 100644 (file)
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 #include "program.h"
+#include "basicblock.h"
 
 namespace Fortran::FIR {
 
index 33a791f..99672dc 100644 (file)
@@ -15,8 +15,7 @@
 #ifndef FORTRAN_FIR_PROGRAM_H_
 #define FORTRAN_FIR_PROGRAM_H_
 
-#include "common.h"
-#include "procedure.h"
+#include "value.h"
 #include "../evaluate/type.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/ADT/StringRef.h"
index 0a3e497..dba4e2c 100644 (file)
@@ -12,7 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "program.h"
+#include "region.h"
+#include "basicblock.h"
 
 namespace Fortran::FIR {
 
index 756d77d..25c9a05 100644 (file)
@@ -16,7 +16,6 @@
 #define FORTRAN_FIR_REGION_H_
 
 #include "procedure.h"
-#include "statements.h"
 #include "../semantics/semantics.h"
 
 namespace Fortran::FIR {
index ed57593..8cab875 100644 (file)
@@ -16,7 +16,7 @@
 
 namespace Fortran::FIR {
 
-static Addressable_impl *GetAddressable(Statement *stmt) {
+Addressable_impl *GetAddressable(Statement *stmt) {
   return std::visit(
       [](auto &s) -> Addressable_impl * {
         if constexpr (std::is_base_of_v<Addressable_impl,
@@ -28,99 +28,14 @@ static Addressable_impl *GetAddressable(Statement *stmt) {
       stmt->u);
 }
 
-static ApplyExprStmt *GetApplyExpr(Statement *stmt) {
-  return std::visit(
-      common::visitors{
-          [](ApplyExprStmt &s) { return &s; },
-          [](auto &) -> ApplyExprStmt * { return nullptr; },
-      },
-      stmt->u);
-}
-
 static std::string dump(const Expression &e) {
   std::stringstream stringStream;
   e.v.AsFortran(stringStream);
   return stringStream.str();
 }
 
-static std::string dump(const Expression *e) {
-  if (e) {
-    return dump(*e);
-  }
-  return "<null-expr>"s;
-}
-
-static std::string dump(const Variable *var) {
-#if 0
-  if (auto *var{std::get_if<const semantics::Symbol *>(&var->u)}) {
-    return (*var)->name().ToString();
-  }
-  return "<var>"s;
-#endif
-  return (*var)->name().ToString();
-}
-
-static std::string dump(PathVariable *pathVariable) {
-  if (pathVariable) {
-    return std::visit(
-        common::visitors{
-            [](const common::Indirection<parser::Designator> &designator) {
-              return std::visit(
-                  common::visitors{
-                      [](const parser::ObjectName &objectName) {
-                        return objectName.symbol->name().ToString();
-                      },
-                      [](const parser::DataRef &dataRef) {
-                        return std::visit(
-                            common::visitors{
-                                [](const parser::Name &name) {
-                                  return name.symbol->name().ToString();
-                                },
-                                [](const common::Indirection<
-                                    parser::StructureComponent> &) {
-                                  return "<structure-component>"s;
-                                },
-                                [](const common::Indirection<
-                                    parser::ArrayElement> &) {
-                                  return "<array-element>"s;
-                                },
-                                [](const common::Indirection<
-                                    parser::CoindexedNamedObject> &) {
-                                  return "<coindexed-named-object>"s;
-                                },
-                            },
-                            dataRef.u);
-                      },
-                      [](const parser::Substring &substring) {
-                        return "<substring>"s;
-                      },
-                  },
-                  designator.value().u);
-            },
-            [](const common::Indirection<parser::FunctionReference> &) {
-              return "<function-reference>"s;
-            },
-        },
-        pathVariable->u);
-  }
-  return "<emty>"s;
-}
-
-std::string Evaluation::dump() const {
-  return std::visit(
-      common::visitors{
-          [](Expression *expression) { return FIR::dump(expression); },
-          [](Variable *variable) { return FIR::dump(variable); },
-          [](PathVariable *pathVariable) { return FIR::dump(pathVariable); },
-          [](const semantics::Symbol *symbol) {
-            return symbol->name().ToString();
-          },
-      },
-      u);
-}
-
-BranchStmt::BranchStmt(
-    Statement *cond, BasicBlock *trueBlock, BasicBlock *falseBlock)
+BranchStmt::BranchStmt(const std::optional<Value> &cond, BasicBlock *trueBlock,
+    BasicBlock *falseBlock)
   : condition_{cond}, succs_{trueBlock, falseBlock} {
   CHECK(succs_[TrueIndex]);
   if (cond) {
@@ -130,56 +45,68 @@ BranchStmt::BranchStmt(
 }
 
 template<typename L>
-static std::list<BasicBlock *> SuccBlocks(const L &valueSuccPairList) {
-  std::list<BasicBlock *> result;
-  for (auto &p : valueSuccPairList) {
-    result.push_back(p.second);
-  }
-  return result;
+static std::list<BasicBlock *> SuccBlocks(
+    const typename L::ValueSuccPairListType &valueSuccPairList) {
+  std::pair<std::list<typename L::ValueType>, std::list<BasicBlock *>> result;
+  UnzipSnd(result, valueSuccPairList.begin(), valueSuccPairList.end());
+  return result.second;
+}
+
+ReturnStmt::ReturnStmt(Statement *exp) : returnValue_{GetApplyExpr(exp)} {
+  CHECK(returnValue_);
 }
 
-SwitchStmt::SwitchStmt(const Evaluation &condition, BasicBlock *defaultBlock,
+SwitchStmt::SwitchStmt(const Value &cond, BasicBlock *defaultBlock,
     const ValueSuccPairListType &args)
-  : condition_{condition} {
-  valueSuccPairs_.push_back({nullptr, defaultBlock});
+  : condition_{cond} {
+  valueSuccPairs_.push_back({NOTHING, defaultBlock});
   valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end());
 }
 std::list<BasicBlock *> SwitchStmt::succ_blocks() const {
-  return SuccBlocks(valueSuccPairs_);
+  return SuccBlocks<SwitchStmt>(valueSuccPairs_);
 }
 
-SwitchCaseStmt::SwitchCaseStmt(const Evaluation &condition,
-    BasicBlock *defaultBlock, const ValueSuccPairListType &args)
-  : condition_{condition} {
+SwitchCaseStmt::SwitchCaseStmt(
+    Value cond, BasicBlock *defaultBlock, const ValueSuccPairListType &args)
+  : condition_{cond} {
   valueSuccPairs_.push_back({SwitchCaseStmt::Default{}, defaultBlock});
   valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end());
 }
 std::list<BasicBlock *> SwitchCaseStmt::succ_blocks() const {
-  return SuccBlocks(valueSuccPairs_);
+  return SuccBlocks<SwitchCaseStmt>(valueSuccPairs_);
 }
 
-SwitchTypeStmt::SwitchTypeStmt(const Evaluation &condition,
-    BasicBlock *defaultBlock, const ValueSuccPairListType &args)
-  : condition_{condition} {
+SwitchTypeStmt::SwitchTypeStmt(
+    Value cond, BasicBlock *defaultBlock, const ValueSuccPairListType &args)
+  : condition_{cond} {
   valueSuccPairs_.push_back({SwitchTypeStmt::Default{}, defaultBlock});
   valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end());
 }
 std::list<BasicBlock *> SwitchTypeStmt::succ_blocks() const {
-  return SuccBlocks(valueSuccPairs_);
+  return SuccBlocks<SwitchTypeStmt>(valueSuccPairs_);
 }
 
-SwitchRankStmt ::SwitchRankStmt(const Evaluation &condition,
-    BasicBlock *defaultBlock, const ValueSuccPairListType &args)
-  : condition_{condition} {
+SwitchRankStmt ::SwitchRankStmt(
+    Value cond, BasicBlock *defaultBlock, const ValueSuccPairListType &args)
+  : condition_{cond} {
   valueSuccPairs_.push_back({SwitchRankStmt::Default{}, defaultBlock});
   valueSuccPairs_.insert(valueSuccPairs_.end(), args.begin(), args.end());
 }
 std::list<BasicBlock *> SwitchRankStmt::succ_blocks() const {
-  return SuccBlocks(valueSuccPairs_);
+  return SuccBlocks<SwitchRankStmt>(valueSuccPairs_);
+}
+
+template<typename T> bool PointerNotNull(const T &variant) {
+  return std::visit(
+      common::visitors{
+          [](const Addressable_impl *p) { return p != nullptr; },
+          [](const Value &value) { return !IsNothing(value); },
+      },
+      variant);
 }
 
 LoadInsn::LoadInsn(Statement *addr) : address_{GetAddressable(addr)} {
-  CHECK(address_);
+  CHECK(PointerNotNull(address_));
 }
 
 StoreInsn::StoreInsn(Statement *addr, Statement *val)
@@ -200,9 +127,9 @@ StoreInsn::StoreInsn(Statement *addr, BasicBlock *val)
   CHECK(val);
 }
 
-IncrementStmt::IncrementStmt(Statement *v1, Statement *v2) : value_{v1, v2} {}
+IncrementStmt::IncrementStmt(Value v1, Value v2) : value_{v1, v2} {}
 
-DoConditionStmt::DoConditionStmt(Statement *dir, Statement *v1, Statement *v2)
+DoConditionStmt::DoConditionStmt(Value dir, Value v1, Value v2)
   : value_{dir, v1, v2} {}
 
 std::string Statement::dump() const {
@@ -212,9 +139,11 @@ std::string Statement::dump() const {
           [](const BranchStmt &branch) {
             if (branch.hasCondition()) {
               std::string cond{"???"};
+#if 0
               if (auto expr{GetApplyExpr(branch.getCond())}) {
                 cond = FIR::dump(expr->expression());
               }
+#endif
               return "branch (" + cond + ") " +
                   std::to_string(
                       reinterpret_cast<std::intptr_t>(branch.getTrueSucc())) +
@@ -227,16 +156,20 @@ std::string Statement::dump() const {
                     reinterpret_cast<std::intptr_t>(branch.getTrueSucc()));
           },
           [](const SwitchStmt &stmt) {
-            return "switch(" + stmt.getCond().dump() + ")";
+            // return "switch(" + stmt.getCond().dump() + ")";
+            return "switch(?)"s;
           },
           [](const SwitchCaseStmt &switchCaseStmt) {
-            return "switch-case(" + switchCaseStmt.getCond().dump() + ")";
+            // return "switch-case(" + switchCaseStmt.getCond().dump() + ")";
+            return "switch-case(?)"s;
           },
           [](const SwitchTypeStmt &switchTypeStmt) {
-            return "switch-type(" + switchTypeStmt.getCond().dump() + ")";
+            // return "switch-type(" + switchTypeStmt.getCond().dump() + ")";
+            return "switch-type(?)"s;
           },
           [](const SwitchRankStmt &switchRankStmt) {
-            return "switch-rank(" + switchRankStmt.getCond().dump() + ")";
+            // return "switch-rank(" + switchRankStmt.getCond().dump() + ")";
+            return "switch-rank(?)"s;
           },
           [](const IndirectBranchStmt &) { return "ibranch"s; },
           [](const UnreachableStmt &) { return "unreachable"s; },
index a2684e7..eaf5862 100644 (file)
 #define FORTRAN_FIR_STATEMENTS_H_
 
 #include "basicblock.h"
-#include "common.h"
-#include "mixin.h"
 #include <initializer_list>
-#include <ostream>
 
 namespace Fortran::FIR {
 
@@ -54,23 +51,6 @@ CLASS_TRAIT(StatementTrait)
 CLASS_TRAIT(TerminatorTrait)
 CLASS_TRAIT(ActionTrait)
 
-class Evaluation : public SumTypeCopyMixin<std::variant<Expression *,
-                       Variable *, PathVariable *, const semantics::Symbol *>> {
-public:
-  SUM_TYPE_COPY_MIXIN(Evaluation)
-  Evaluation(PathVariable *pv) : SumTypeCopyMixin(pv) {
-    if (const auto *designator{
-            std::get_if<common::Indirection<parser::Designator>>(&pv->u)}) {
-      if (const auto *obj{
-              std::get_if<parser::ObjectName>(&designator->value().u)}) {
-        u = obj->symbol;
-      }
-    }
-  }
-  template<typename A> Evaluation(A *a) : SumTypeCopyMixin{a} {}
-  std::string dump() const;
-};
-
 class Stmt_impl {
 public:
   using StatementTrait = std::true_type;
@@ -79,39 +59,35 @@ public:
 // Every basic block must end in a terminator
 class TerminatorStmt_impl : public Stmt_impl {
 public:
-  virtual std::list<BasicBlock *> succ_blocks() const { return {}; }
-  virtual ~TerminatorStmt_impl() {}
+  virtual std::list<BasicBlock *> succ_blocks() const = 0;
+  virtual ~TerminatorStmt_impl() = default;
   using TerminatorTrait = std::true_type;
 };
 
 // Transfer control out of the current procedure
 class ReturnStmt : public TerminatorStmt_impl {
 public:
-  static ReturnStmt Create() { return ReturnStmt{}; }
-  static ReturnStmt Create(Expression *e) { return ReturnStmt{*e}; }
-  static ReturnStmt Create(Expression &&e) { return ReturnStmt{std::move(e)}; }
-
-  bool IsVoid() const { return !returnValue_.has_value(); }
+  static ReturnStmt Create(Statement *stmt) { return ReturnStmt{stmt}; }
+  std::list<BasicBlock *> succ_blocks() const override { return {}; }
+  Statement *returnValue() const;
 
 private:
-  std::optional<Expression> returnValue_;
-  explicit ReturnStmt() : returnValue_{std::nullopt} {}
-  explicit ReturnStmt(const Expression &e) : returnValue_{e} {}
-  explicit ReturnStmt(Expression &&e) : returnValue_{e} {}
+  ApplyExprStmt *returnValue_;
+  explicit ReturnStmt(Statement *exp);
 };
 
 // Encodes two-way conditional branch and one-way absolute branch
 class BranchStmt : public TerminatorStmt_impl {
 public:
   static BranchStmt Create(
-      Statement *condition, BasicBlock *trueBlock, BasicBlock *falseBlock) {
+      Value condition, BasicBlock *trueBlock, BasicBlock *falseBlock) {
     return BranchStmt{condition, trueBlock, falseBlock};
   }
   static BranchStmt Create(BasicBlock *succ) {
-    return BranchStmt{nullptr, succ, nullptr};
+    return BranchStmt{std::nullopt, succ, nullptr};
   }
-  bool hasCondition() const { return condition_ != nullptr; }
-  Statement *getCond() const { return condition_; }
+  bool hasCondition() const { return condition_.has_value(); }
+  Value getCond() const { return condition_.value(); }
   std::list<BasicBlock *> succ_blocks() const override {
     if (hasCondition()) {
       return {succs_[TrueIndex], succs_[FalseIndex]};
@@ -122,32 +98,33 @@ public:
   BasicBlock *getFalseSucc() const { return succs_[FalseIndex]; }
 
 private:
-  explicit BranchStmt(
-      Statement *condition, BasicBlock *trueBlock, BasicBlock *falseBlock);
+  explicit BranchStmt(const std::optional<Value> &condition,
+      BasicBlock *trueBlock, BasicBlock *falseBlock);
   static constexpr int TrueIndex{0};
   static constexpr int FalseIndex{1};
-  Statement *condition_;
+  std::optional<Value> condition_;
   BasicBlock *succs_[2];
 };
 
 // Switch on an expression into a set of constant values
 class SwitchStmt : public TerminatorStmt_impl {
 public:
-  using ValueType = Expression *;
+  using ValueType = Value;
   using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
   using ValueSuccPairListType = std::vector<ValueSuccPairType>;
-  static SwitchStmt Create(const Evaluation &switchEval,
-      BasicBlock *defaultBlock, const ValueSuccPairListType &args) {
+  static SwitchStmt Create(const Value &switchEval, BasicBlock *defaultBlock,
+      const ValueSuccPairListType &args) {
     return SwitchStmt{switchEval, defaultBlock, args};
   }
   BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; }
   std::list<BasicBlock *> succ_blocks() const override;
-  const Evaluation &getCond() const { return condition_; }
+  Value getCond() const { return condition_; }
 
 private:
-  explicit SwitchStmt(const Evaluation &condition, BasicBlock *defaultBlock,
+  explicit SwitchStmt(const Value &condition, BasicBlock *defaultBlock,
       const ValueSuccPairListType &args);
-  Evaluation condition_;
+
+  Value condition_;
   ValueSuccPairListType valueSuccPairs_;
 };
 
@@ -156,17 +133,17 @@ class SwitchCaseStmt : public TerminatorStmt_impl {
 public:
   struct Default {};
   struct Exactly {  // selector == v
-    Expression *v;
+    ApplyExprStmt *v;
   };
   struct InclusiveAbove {  // v <= selector
-    Expression *v;
+    ApplyExprStmt *v;
   };
   struct InclusiveBelow {  // selector <= v
-    Expression *v;
+    ApplyExprStmt *v;
   };
   struct InclusiveRange {  // lower <= selector <= upper
-    Expression *lower;
-    Expression *upper;
+    ApplyExprStmt *lower;
+    ApplyExprStmt *upper;
   };
   using RangeAlternative =
       std::variant<Exactly, InclusiveAbove, InclusiveBelow, InclusiveRange>;
@@ -174,18 +151,19 @@ public:
   using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
   using ValueSuccPairListType = std::vector<ValueSuccPairType>;
 
-  static SwitchCaseStmt Create(const Evaluation &switchEval,
-      BasicBlock *defaultBlock, const ValueSuccPairListType &args) {
+  static SwitchCaseStmt Create(Value switchEval, BasicBlock *defaultBlock,
+      const ValueSuccPairListType &args) {
     return SwitchCaseStmt{switchEval, defaultBlock, args};
   }
   BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; }
   std::list<BasicBlock *> succ_blocks() const override;
-  const Evaluation &getCond() const { return condition_; }
+  Value getCond() const { return condition_; }
 
 private:
-  explicit SwitchCaseStmt(const Evaluation &condition, BasicBlock *defaultBlock,
+  explicit SwitchCaseStmt(Value condition, BasicBlock *defaultBlock,
       const ValueSuccPairListType &args);
-  Evaluation condition_;
+
+  Value condition_;
   ValueSuccPairListType valueSuccPairs_;
 };
 
@@ -202,18 +180,18 @@ public:
   using ValueType = std::variant<Default, TypeSpec, DerivedTypeSpec>;
   using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
   using ValueSuccPairListType = std::vector<ValueSuccPairType>;
-  static SwitchTypeStmt Create(const Evaluation &switchEval,
-      BasicBlock *defaultBlock, const ValueSuccPairListType &args) {
+  static SwitchTypeStmt Create(Value switchEval, BasicBlock *defaultBlock,
+      const ValueSuccPairListType &args) {
     return SwitchTypeStmt{switchEval, defaultBlock, args};
   }
   BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; }
   std::list<BasicBlock *> succ_blocks() const override;
-  const Evaluation &getCond() const { return condition_; }
+  Value getCond() const { return condition_; }
 
 private:
-  explicit SwitchTypeStmt(const Evaluation &condition, BasicBlock *defaultBlock,
+  explicit SwitchTypeStmt(Value condition, BasicBlock *defaultBlock,
       const ValueSuccPairListType &args);
-  Evaluation condition_;
+  Value condition_;
   ValueSuccPairListType valueSuccPairs_;
 };
 
@@ -228,18 +206,19 @@ public:
   using ValueType = std::variant<Exactly, AssumedSize, Default>;
   using ValueSuccPairType = std::pair<ValueType, BasicBlock *>;
   using ValueSuccPairListType = std::vector<ValueSuccPairType>;
-  static SwitchRankStmt Create(const Evaluation &switchEval,
-      BasicBlock *defaultBlock, const ValueSuccPairListType &args) {
+  static SwitchRankStmt Create(Value switchEval, BasicBlock *defaultBlock,
+      const ValueSuccPairListType &args) {
     return SwitchRankStmt{switchEval, defaultBlock, args};
   }
   BasicBlock *defaultSucc() const { return valueSuccPairs_[0].second; }
   std::list<BasicBlock *> succ_blocks() const override;
-  const Evaluation &getCond() const { return condition_; }
+  Value getCond() const { return condition_; }
 
 private:
-  explicit SwitchRankStmt(const Evaluation &condition, BasicBlock *defaultBlock,
+  explicit SwitchRankStmt(Value condition, BasicBlock *defaultBlock,
       const ValueSuccPairListType &args);
-  Evaluation condition_;
+
+  Value condition_;
   ValueSuccPairListType valueSuccPairs_;
 };
 
@@ -252,6 +231,9 @@ public:
   }
 
   Variable *variable() const { return variable_; }
+  std::list<BasicBlock *> succ_blocks() const override {
+    return {potentialTargets_.begin(), potentialTargets_.end()};
+  }
 
 private:
   explicit IndirectBranchStmt(
@@ -265,6 +247,7 @@ private:
 class UnreachableStmt : public TerminatorStmt_impl {
 public:
   static UnreachableStmt Create() { return UnreachableStmt{}; }
+  std::list<BasicBlock *> succ_blocks() const override { return {}; }
 
 private:
   explicit UnreachableStmt() = default;
@@ -283,30 +266,29 @@ protected:
 
 class IncrementStmt : public ActionStmt_impl {
 public:
-  static IncrementStmt Create(Statement *v1, Statement *v2) {
+  static IncrementStmt Create(Value v1, Value v2) {
     return IncrementStmt(v1, v2);
   }
-  Statement *leftValue() const { return value_[0]; }
-  Statement *rightValue() const { return value_[1]; }
+  Value leftValue() const { return value_[0]; }
+  Value rightValue() const { return value_[1]; }
 
 private:
-  explicit IncrementStmt(Statement *v1, Statement *v2);
-  Statement *value_[2];
+  explicit IncrementStmt(Value v1, Value v2);
+  Value value_[2];
 };
 
 class DoConditionStmt : public ActionStmt_impl {
 public:
-  static DoConditionStmt Create(
-      Statement *dir, Statement *left, Statement *right) {
+  static DoConditionStmt Create(Value dir, Value left, Value right) {
     return DoConditionStmt(dir, left, right);
   }
-  Statement *direction() const { return value_[0]; }
-  Statement *leftValue() const { return value_[1]; }
-  Statement *rightValue() const { return value_[2]; }
+  Value direction() const { return value_[0]; }
+  Value leftValue() const { return value_[1]; }
+  Value rightValue() const { return value_[2]; }
 
 private:
-  explicit DoConditionStmt(Statement *dir, Statement *left, Statement *right);
-  Statement *value_[3];
+  explicit DoConditionStmt(Value dir, Value left, Value right);
+  Value value_[3];
 };
 
 // Compute the value of an expression
@@ -411,59 +393,60 @@ private:
 // Load value(s) from a location
 class LoadInsn : public MemoryStmt_impl {
 public:
+  static LoadInsn Create(Value addr) { return LoadInsn{addr}; }
   static LoadInsn Create(Statement *addr) { return LoadInsn{addr}; }
 
 private:
+  explicit LoadInsn(Value addr) : address_{addr} {}
   explicit LoadInsn(Statement *addr);
-  Addressable_impl *address_;
+  std::variant<Addressable_impl *, Value> address_;
 };
 
 // Store value(s) from an applied expression to a location
 class StoreInsn : public MemoryStmt_impl {
 public:
-  static StoreInsn Create(Statement *addr, Statement *value) {
+  template<typename T> static StoreInsn Create(T *addr, T *value) {
     return StoreInsn{addr, value};
   }
-  static StoreInsn Create(Statement *addr, BasicBlock *value) {
+  template<typename T> static StoreInsn Create(T *addr, BasicBlock *value) {
     return StoreInsn{addr, value};
   }
 
 private:
+  explicit StoreInsn(Value addr, Value val);
+  explicit StoreInsn(Value addr, BasicBlock *val);
   explicit StoreInsn(Statement *addr, Statement *val);
   explicit StoreInsn(Statement *addr, BasicBlock *val);
 
   Addressable_impl *address_;
-  std::variant<ApplyExprStmt *, Addressable_impl *, BasicBlock *> value_;
+  std::variant<Value, ApplyExprStmt *, Addressable_impl *, BasicBlock *> value_;
 };
 
 // NULLIFY - make pointer object disassociated
 class DisassociateInsn : public ActionStmt_impl {
 public:
-  static DisassociateInsn Create(const parser::NullifyStmt *n) {
-    return DisassociateInsn{n};
-  }
+  static DisassociateInsn Create(Statement *s) { return DisassociateInsn{s}; }
 
-  // FIXME - remove parse tree reference
-  const parser::NullifyStmt *disassociate() { return disassociate_; }
+  Statement *disassociate() { return disassociate_; }
 
 private:
-  DisassociateInsn(const parser::NullifyStmt *n) : disassociate_{n} {}
-  const parser::NullifyStmt *disassociate_;
+  DisassociateInsn(Statement *s) : disassociate_{s} {}
+  Statement *disassociate_;
 };
 
 // base class for all call-like IR statements
 class CallStmt_impl : public ActionStmt_impl {
 public:
-  const Value *Callee() const { return callee_; }
+  Value Callee() const { return callee_; }
   unsigned NumArgs() const { return arguments_.size(); }
 
 protected:
-  CallStmt_impl(const FunctionType *functionType, const Value *callee,
-      CallArguments &&arguments)
+  CallStmt_impl(
+      const FunctionType *functionType, Value callee, CallArguments &&arguments)
     : functionType_{functionType}, callee_{callee}, arguments_{arguments} {}
 
   const FunctionType *functionType_;
-  const Value *callee_;
+  Value callee_;
   CallArguments arguments_;
 };
 
@@ -472,14 +455,14 @@ protected:
 // explicitly by passing addresses of objects or temporaries.
 class CallStmt : public CallStmt_impl {
 public:
-  static CallStmt Create(const FunctionType *type, const Value *callee,
-      CallArguments &&arguments) {
+  static CallStmt Create(
+      const FunctionType *type, Value callee, CallArguments &&arguments) {
     return CallStmt{type, callee, std::move(arguments)};
   }
 
 private:
-  explicit CallStmt(const FunctionType *functionType, const Value *callee,
-      CallArguments &&arguments)
+  explicit CallStmt(
+      const FunctionType *functionType, Value callee, CallArguments &&arguments)
     : CallStmt_impl{functionType, callee, std::move(arguments)} {}
 };
 
@@ -495,7 +478,9 @@ public:
 
 private:
   explicit RuntimeStmt(RuntimeCallType call, RuntimeCallArguments &&arguments)
-    : CallStmt_impl{nullptr, nullptr, std::move(arguments)}, call_{call} {}
+    : CallStmt_impl{nullptr, Procedure::CreateIntrinsicProcedure(call),
+          std::move(arguments)},
+      call_{call} {}
 
   RuntimeCallType call_;
 };
@@ -513,7 +498,9 @@ public:
 
 private:
   explicit IORuntimeStmt(InputOutputCallType call, IOCallArguments &&arguments)
-    : CallStmt_impl{nullptr, nullptr, std::move(arguments)}, call_{call} {}
+    : CallStmt_impl{nullptr, Procedure::CreateIntrinsicProcedure(call),
+          std::move(arguments)},
+      call_{call} {}
 
   InputOutputCallType call_;
 };
@@ -559,7 +546,7 @@ private:
 };
 
 // Sum type over all statement classes
-class Statement : public SumTypeMixin<std::variant<ReturnStmt,  //
+class Statement : public SumTypeMixin<ReturnStmt,  //
                       BranchStmt,  //
                       SwitchStmt,  //
                       SwitchCaseStmt,  //
@@ -583,7 +570,8 @@ class Statement : public SumTypeMixin<std::variant<ReturnStmt,  //
                       ScopeEnterStmt,  //
                       ScopeExitStmt,  //
                       PHIStmt  //
-                      >>,
+                      >,
+                  public Value_impl,
                   public ChildMixin<Statement, BasicBlock>,
                   public llvm::ilist_node<Statement> {
 public:
@@ -592,6 +580,15 @@ public:
     parent->insertBefore(this);
   }
   std::string dump() const;
+
+  static constexpr std::size_t offsetof_impl() {
+    Statement *s{nullptr};
+    return reinterpret_cast<char *>(&s->u) - reinterpret_cast<char *>(s);
+  }
+  static Statement *From(Stmt_impl *stmt) {
+    return reinterpret_cast<Statement *>(
+        reinterpret_cast<char *>(stmt) - Statement::offsetof_impl());
+  }
 };
 
 inline std::list<BasicBlock *> succ_list(BasicBlock &block) {
@@ -602,6 +599,21 @@ inline std::list<BasicBlock *> succ_list(BasicBlock &block) {
   // CHECK(false && "block does not have terminator");
   return {};
 }
+
+inline Statement *ReturnStmt::returnValue() const {
+  return Statement::From(returnValue_);
+}
+
+inline ApplyExprStmt *GetApplyExpr(Statement *stmt) {
+  return std::visit(
+      common::visitors{
+          [](ApplyExprStmt &s) { return &s; },
+          [](auto &) -> ApplyExprStmt * { return nullptr; },
+      },
+      stmt->u);
+}
+
+Addressable_impl *GetAddressable(Statement *stmt);
 }
 
 #endif  // FORTRAN_FIR_STATEMENTS_H_
diff --git a/flang/lib/FIR/value.h b/flang/lib/FIR/value.h
new file mode 100644 (file)
index 0000000..a9382d1
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright (c) 2019, NVIDIA CORPORATION.  All rights reserved.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef FORTRAN_FIR_VALUE_H_
+#define FORTRAN_FIR_VALUE_H_
+
+#include "common.h"
+#include "mixin.h"
+#include "../common/idioms.h"
+#include <string>
+
+namespace Fortran::FIR {
+
+class Statement;
+class BasicBlock;
+class Procedure;
+class DataObject;
+
+class Value : public SumTypeCopyMixin<Nothing, DataObject *, Statement *,
+                  BasicBlock *, Procedure *> {
+public:
+  SUM_TYPE_COPY_MIXIN(Value)
+  template<typename A> Value(A *a) : SumTypeCopyMixin{a} {}
+  Value(const Nothing &n) : SumTypeCopyMixin{n} {}
+  Value(Nothing &&n) : SumTypeCopyMixin{std::move(n)} {}
+  Value() : SumTypeCopyMixin{NOTHING} {}
+};
+
+inline bool IsNothing(Value value) {
+  return std::visit(
+      common::visitors{
+          [](Nothing &) { return true; },
+          [](auto *) { return false; },
+      },
+      value.u);
+}
+}
+
+#endif  // FORTRAN_FIR_VALUE_H_
index 96cdd74..4aa68b6 100644 (file)
@@ -170,6 +170,11 @@ public:
     }
     return result;
   }
+  MaybeExpr Analyze(const parser::Name &);
+  MaybeExpr Analyze(const parser::DataRef &dr) {
+    return Analyze<parser::DataRef>(dr);
+  }
+  MaybeExpr Analyze(const parser::StructureComponent &);
 
 protected:
   int IntegerTypeSpecKind(const parser::IntegerTypeSpec &);
@@ -186,11 +191,9 @@ private:
   MaybeExpr Analyze(const parser::CharLiteralConstant &);
   MaybeExpr Analyze(const parser::HollerithLiteralConstant &);
   MaybeExpr Analyze(const parser::BOZLiteralConstant &);
-  MaybeExpr Analyze(const parser::Name &);
   MaybeExpr Analyze(const parser::NamedConstant &);
   MaybeExpr Analyze(const parser::Substring &);
   MaybeExpr Analyze(const parser::ArrayElement &);
-  MaybeExpr Analyze(const parser::StructureComponent &);
   MaybeExpr Analyze(const parser::CoindexedNamedObject &);
   MaybeExpr Analyze(const parser::CharLiteralConstantSubstring &);
   MaybeExpr Analyze(const parser::ArrayConstructor &);