102class ExpressionAnalyzer {
104 using MaybeExpr = std::optional<Expr<SomeType>>;
108 : context_{sc}, foldingContext_{fc} {}
109 ExpressionAnalyzer(
const ExpressionAnalyzer &) =
default;
112 bool inWhereBody()
const {
return inWhereBody_; }
113 void set_inWhereBody(
bool yes =
true) { inWhereBody_ = yes; }
114 bool inDataStmtObject()
const {
return inDataStmtObject_; }
115 void set_inDataStmtObject(
bool yes =
true) { inDataStmtObject_ = yes; }
117 FoldingContext &GetFoldingContext()
const {
return foldingContext_; }
120 return foldingContext_.messages();
124 return GetContextualMessages().Say(std::forward<A>(args)...);
126 template <
typename FeatureOrUsageWarning,
typename... A>
129 return context_.Warn(warning, at, std::forward<A>(args)...);
131 template <
typename FeatureOrUsageWarning,
typename... A>
134 warning, GetContextualMessages().at(), std::forward<A>(args)...);
137 template <
typename T,
typename... A>
139 return Say(parser::FindSourceLocation(parsed), std::forward<A>(args)...);
142 int GetDefaultKind(common::TypeCategory);
143 DynamicType GetDefaultKindOfType(common::TypeCategory);
146 bool CheckIntrinsicKind(TypeCategory, std::int64_t kind);
147 bool CheckIntrinsicSize(TypeCategory, std::int64_t size);
158 return common::ScopedSet(useSavedTypedExprs_,
false);
162 const std::optional<parser::KindSelector> &);
173 return Analyze(x.value());
175 template <
typename A> MaybeExpr Analyze(
const std::optional<A> &x) {
185 auto result{Analyze(x.thing)};
187 if (
int rank{result->Rank()}; rank != 0) {
188 SayAt(x,
"Must be a scalar value, but is a rank-%d array"_err_en_US,
198 GetFoldingContext().messages().SetLocation(FindSourceLocation(x))};
199 auto result{Analyze(x.thing)};
201 *result = Fold(std::move(*result));
202 if (!IsConstantExpr(*result)) {
203 SayAt(x,
"Must be a constant value"_err_en_US);
208 SetExpr(x, common::Clone(*result));
214 auto result{Analyze(x.thing)};
215 if (!EnforceTypeConstraint(
216 parser::FindSourceLocation(x), result, TypeCategory::Integer)) {
223 auto result{Analyze(x.thing)};
224 if (!EnforceTypeConstraint(
225 parser::FindSourceLocation(x), result, TypeCategory::Logical)) {
232 auto result{Analyze(x.thing)};
233 if (!EnforceTypeConstraint(parser::FindSourceLocation(x), result,
234 TypeCategory::Character,
true )) {
243 return Analyze<parser::DataRef>(dr);
250 MaybeExpr Analyze(
const parser::InitialDataTarget &);
251 MaybeExpr Analyze(
const parser::NullInit &);
259 MaybeExpr Designate(
DataRef &&);
265 return common::ScopedSet(isWholeAssumedSizeArrayOk_, yes);
269 int IntegerTypeSpecKind(
const parser::IntegerTypeSpec &);
274 return common::ScopedSet(isNullPointerOk_,
true);
285 MaybeExpr Analyze(
const parser::BOZLiteralConstant &);
286 MaybeExpr Analyze(
const parser::NamedConstant &);
293 MaybeExpr Analyze(
const parser::ArrayConstructor &);
295 std::optional<parser::StructureConstructor> * =
nullptr);
300 MaybeExpr Analyze(
const parser::Expr::PercentLoc &);
320 template <
typename A> MaybeExpr Analyze(
const A &x) {
323 template <
typename... As> MaybeExpr Analyze(
const std::variant<As...> &u) {
324 return common::visit([&](
const auto &x) {
return Analyze(x); }, u);
328 int AnalyzeKindParam(
329 const std::optional<parser::KindParam> &,
int defaultKind);
330 template <
typename PARSED>
332 template <
typename TYPES, TypeCategory CAT,
typename PARSED>
333 MaybeExpr IntLiteralConstant(
const PARSED &,
bool isNegated =
false);
334 MaybeExpr AnalyzeString(std::string &&,
int kind);
335 std::optional<Expr<SubscriptInteger>> AsSubscript(MaybeExpr &&);
336 std::optional<Expr<SubscriptInteger>> TripletPart(
337 const std::optional<parser::Subscript> &);
338 std::optional<Subscript> AnalyzeSectionSubscript(
340 std::vector<Subscript> AnalyzeSectionSubscripts(
341 const std::list<parser::SectionSubscript> &);
342 std::optional<Component> CreateComponent(
DataRef &&,
const Symbol &,
344 MaybeExpr CompleteSubscripts(
ArrayRef &&);
345 MaybeExpr ApplySubscripts(
DataRef &&, std::vector<Subscript> &&);
346 bool CheckRanks(
const DataRef &);
347 bool CheckPolymorphic(
const DataRef &);
348 bool CheckDataRef(
const DataRef &);
349 std::optional<Expr<SubscriptInteger>> GetSubstringBound(
350 const std::optional<parser::ScalarIntExpr> &);
351 MaybeExpr AnalyzeDefinedOp(
355 struct CalleeAndArguments {
359 std::variant<ProcedureDesignator, SymbolRef> u;
360 ActualArguments arguments;
363 std::optional<CalleeAndArguments> AnalyzeProcedureComponentRef(
365 std::optional<characteristics::Procedure> CheckCall(
367 using AdjustActuals =
368 std::optional<std::function<bool(
const Symbol &, ActualArguments &)>>;
370 std::pair<
const Symbol *,
bool > ResolveGeneric(
371 const Symbol &,
const ActualArguments &,
const AdjustActuals &,
372 bool isSubroutine,
bool mightBeStructureConstructor =
false);
373 void EmitGenericResolutionError(
374 const Symbol &,
bool dueToNullActuals,
bool isSubroutine);
375 const Symbol &AccessSpecific(
377 std::optional<CalleeAndArguments> GetCalleeAndArguments(
const parser::Name &,
378 ActualArguments &&,
bool isSubroutine =
false,
379 bool mightBeStructureConstructor =
false);
380 std::optional<CalleeAndArguments> GetCalleeAndArguments(
382 bool isSubroutine,
bool mightBeStructureConstructor =
false);
386 bool defaultKind =
false);
387 MaybeExpr MakeFunctionRef(
390 template <
typename T> T Fold(T &&expr) {
391 return evaluate::Fold(foldingContext_, std::move(expr));
394 MaybeExpr AnalyzeComplex(MaybeExpr &&re, MaybeExpr &&im,
const char *what);
399 struct ComponentSpec {
400 ComponentSpec() =
default;
401 ComponentSpec(ComponentSpec &&) =
default;
403 bool hasKeyword{
false};
404 const Symbol *keywordSymbol{
nullptr};
410 MaybeExpr IterativelyAnalyzeSubexpressions(
const parser::Expr &);
414 std::map<parser::CharBlock, int> impliedDos_;
416 std::pair<parser::CharBlock, evaluate::characteristics::Procedure>>
418 bool isWholeAssumedSizeArrayOk_{
false};
419 bool isNullPointerOk_{
false};
420 bool useSavedTypedExprs_{
true};
421 bool inWhereBody_{
false};
422 bool inDataStmtObject_{
false};
423 bool inDataStmtConstant_{
false};
424 bool inStmtFunctionDefinition_{
false};
425 bool iterativelyAnalyzingSubexpressions_{
false};
426 friend class ArgumentAnalyzer;
468 template <
typename A>
bool Pre(
const A &) {
return true; }
469 template <
typename A>
void Post(
const A &) {}
470 bool Walk(
const parser::Program &);
473 exprAnalyzer_.Analyze(x);
477 exprAnalyzer_.Analyze(x);
481 exprAnalyzer_.Analyze(x);
485 exprAnalyzer_.Analyze(x);
489 exprAnalyzer_.Analyze(x);
493 exprAnalyzer_.Analyze(x);
501 exprAnalyzer_.Analyze(x);
505 exprAnalyzer_.Analyze(x);
509 exprAnalyzer_.Analyze(x);
516 exprAnalyzer_.set_inWhereBody(InWhereBody());
521 exprAnalyzer_.set_inWhereBody(InWhereBody());
525 exprAnalyzer_.set_inWhereBody(InWhereBody());
530 exprAnalyzer_.set_inWhereBody(InWhereBody());
534 inComponentDefStmt_ =
true;
543 return !inComponentDefStmt_ ||
544 std::holds_alternative<
545 std::list<common::Indirection<parser::DataStmtValue>>>(x.u);
549 exprAnalyzer_.Analyze(x);
553 exprAnalyzer_.Analyze(x);
557 exprAnalyzer_.Analyze(x);
561 exprAnalyzer_.Analyze(x);
565 exprAnalyzer_.Analyze(x);
570 bool InWhereBody()
const {
return whereDepth_ > 0; }
575 bool inComponentDefStmt_{
false};