ArgumentAnalyzer analyzer{*this};
analyzer.Analyze(std::get<parser::Variable>(x.t));
analyzer.Analyze(std::get<parser::Expr>(x.t));
- if (!analyzer.fatalErrors()) {
+ if (analyzer.fatalErrors()) {
+ x.typedAssignment.reset(new GenericAssignmentWrapper{});
+ } else {
std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()};
x.typedAssignment.reset(new GenericAssignmentWrapper{procRef
? Assignment{std::move(*procRef)}
Fold(analyzer.MoveExpr(0)), Fold(analyzer.MoveExpr(1))}}});
}
}
- return x.typedAssignment ? &x.typedAssignment->v : nullptr;
+ return common::GetPtrFromOptional(x.typedAssignment->v);
}
const Assignment *ExpressionAnalyzer::Analyze(
const parser::PointerAssignmentStmt &x) {
- MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))};
- MaybeExpr rhs{Analyze(std::get<parser::Expr>(x.t))};
- if (!lhs || !rhs) {
- return nullptr;
- }
- Assignment::PointerAssignment assignment{
- Fold(std::move(*lhs)), Fold(std::move(*rhs))};
- std::visit(
- common::visitors{
- [&](const std::list<parser::BoundsRemapping> &list) {
- if (!list.empty()) {
- Assignment::PointerAssignment::BoundsRemapping bounds;
- for (const auto &elem : list) {
- auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
- auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
- if (lower && upper) {
- bounds.emplace_back(
- Fold(std::move(*lower)), Fold(std::move(*upper)));
+ if (!x.typedAssignment) {
+ MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))};
+ MaybeExpr rhs{Analyze(std::get<parser::Expr>(x.t))};
+ decltype(Assignment::PointerAssignment::bounds) pointerBounds;
+ std::visit(
+ common::visitors{
+ [&](const std::list<parser::BoundsRemapping> &list) {
+ if (!list.empty()) {
+ Assignment::PointerAssignment::BoundsRemapping bounds;
+ for (const auto &elem : list) {
+ auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
+ auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
+ if (lower && upper) {
+ bounds.emplace_back(
+ Fold(std::move(*lower)), Fold(std::move(*upper)));
+ }
}
+ pointerBounds = bounds;
}
- assignment.bounds = bounds;
- }
- },
- [&](const std::list<parser::BoundsSpec> &list) {
- if (!list.empty()) {
- Assignment::PointerAssignment::BoundsSpec bounds;
- for (const auto &bound : list) {
- if (auto lower{AsSubscript(Analyze(bound.v))}) {
- bounds.emplace_back(Fold(std::move(*lower)));
+ },
+ [&](const std::list<parser::BoundsSpec> &list) {
+ if (!list.empty()) {
+ Assignment::PointerAssignment::BoundsSpec bounds;
+ for (const auto &bound : list) {
+ if (auto lower{AsSubscript(Analyze(bound.v))}) {
+ bounds.emplace_back(Fold(std::move(*lower)));
+ }
}
+ pointerBounds = bounds;
}
- assignment.bounds = bounds;
- }
- },
- },
- std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
- x.typedAssignment.reset(
- new GenericAssignmentWrapper{Assignment{std::move(assignment)}});
- return &x.typedAssignment->v;
+ },
+ },
+ std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
+ if (!lhs || !rhs) {
+ x.typedAssignment.reset(new GenericAssignmentWrapper{});
+ } else {
+ Assignment::PointerAssignment assignment{
+ Fold(std::move(*lhs)), Fold(std::move(*rhs))};
+ assignment.bounds = pointerBounds;
+ x.typedAssignment.reset(
+ new GenericAssignmentWrapper{Assignment{std::move(assignment)}});
+ }
+ }
+ return common::GetPtrFromOptional(x.typedAssignment->v);
}
static bool IsExternalCalledImplicitly(
#include "type.h"
#include "../common/Fortran.h"
#include "../common/indirection.h"
+#include "../parser/dump-parse-tree.h"
#include "../parser/message.h"
#include "../parser/parse-tree.h"
#include "../parser/tools.h"
#include <algorithm>
#include <set>
+#include <sstream>
#include <variant>
namespace Fortran::semantics {
dynamicType->kind() == context.GetDefaultKind(dynamicType->category());
}
+// If an analyzed expr or assignment is missing, dump the node and die.
+template<typename T> static void CheckMissingAnalysis(bool absent, const T &x) {
+ if (absent) {
+ std::ostringstream ss;
+ ss << "node has not been analyzed:\n";
+ parser::DumpTree(ss, x);
+ common::die(ss.str().c_str());
+ }
+}
+
+const SomeExpr *GetExprHelper::Get(const parser::Expr &x) {
+ CheckMissingAnalysis(!x.typedExpr, x);
+ return common::GetPtrFromOptional(x.typedExpr->v);
+}
+const SomeExpr *GetExprHelper::Get(const parser::Variable &x) {
+ CheckMissingAnalysis(!x.typedExpr, x);
+ return common::GetPtrFromOptional(x.typedExpr->v);
+}
+
const evaluate::Assignment *GetAssignment(const parser::AssignmentStmt &x) {
- const auto &typed{x.typedAssignment};
- return typed ? &typed->v : nullptr;
+ CheckMissingAnalysis(!x.typedAssignment, x);
+ return common::GetPtrFromOptional(x.typedAssignment->v);
}
const evaluate::Assignment *GetAssignment(
const parser::PointerAssignmentStmt &x) {
- const auto &typed{x.typedAssignment};
- return typed ? &typed->v : nullptr;
+ CheckMissingAnalysis(!x.typedAssignment, x);
+ return common::GetPtrFromOptional(x.typedAssignment->v);
}
const Symbol *FindInterface(const Symbol &symbol) {