103class ExpressionAnalyzer {
105 using MaybeExpr = std::optional<Expr<SomeType>>;
109 : context_{sc}, foldingContext_{fc} {}
110 ExpressionAnalyzer(
const ExpressionAnalyzer &) =
default;
113 bool inWhereBody()
const {
return inWhereBody_; }
114 void set_inWhereBody(
bool yes =
true) { inWhereBody_ = yes; }
115 bool inDataStmtObject()
const {
return inDataStmtObject_; }
116 void set_inDataStmtObject(
bool yes =
true) { inDataStmtObject_ = yes; }
118 FoldingContext &GetFoldingContext()
const {
return foldingContext_; }
121 return foldingContext_.messages();
125 return GetContextualMessages().Say(std::forward<A>(args)...);
127 template <
typename FeatureOrUsageWarning,
typename... A>
130 return context_.Warn(warning, at, std::forward<A>(args)...);
132 template <
typename FeatureOrUsageWarning,
typename... A>
135 warning, GetContextualMessages().at(), std::forward<A>(args)...);
138 template <
typename T,
typename... A>
140 return Say(parser::FindSourceLocation(parsed), std::forward<A>(args)...);
143 int GetDefaultKind(common::TypeCategory);
144 DynamicType GetDefaultKindOfType(common::TypeCategory);
147 bool CheckIntrinsicKind(TypeCategory, std::int64_t kind);
148 bool CheckIntrinsicSize(TypeCategory, std::int64_t size);
159 return common::ScopedSet(useSavedTypedExprs_,
false);
163 const std::optional<parser::KindSelector> &);
175 return Analyze(x.value());
177 template <
typename A> MaybeExpr Analyze(
const std::optional<A> &x) {
187 auto result{Analyze(x.thing)};
189 if (
int rank{result->Rank()}; rank != 0) {
190 SayAt(x,
"Must be a scalar value, but is a rank-%d array"_err_en_US,
200 GetFoldingContext().messages().SetLocation(FindSourceLocation(x))};
201 auto result{Analyze(x.thing)};
203 *result = Fold(std::move(*result));
204 if (!IsConstantExpr(*result)) {
205 SayAt(x,
"Must be a constant value"_err_en_US);
210 SetExpr(x, common::Clone(*result));
216 auto result{Analyze(x.thing)};
217 if (!EnforceTypeConstraint(
218 parser::FindSourceLocation(x), result, TypeCategory::Integer)) {
225 auto result{Analyze(x.thing)};
226 if (!EnforceTypeConstraint(
227 parser::FindSourceLocation(x), result, TypeCategory::Logical)) {
234 auto result{Analyze(x.thing)};
235 if (!EnforceTypeConstraint(parser::FindSourceLocation(x), result,
236 TypeCategory::Character,
true )) {
245 return Analyze<parser::DataRef>(dr);
252 MaybeExpr Analyze(
const parser::InitialDataTarget &);
253 MaybeExpr Analyze(
const parser::NullInit &);
261 MaybeExpr Designate(
DataRef &&);
267 return common::ScopedSet(isWholeAssumedSizeArrayOk_, yes);
271 int IntegerTypeSpecKind(
const parser::IntegerTypeSpec &);
276 return common::ScopedSet(isNullPointerOk_,
true);
287 MaybeExpr Analyze(
const parser::BOZLiteralConstant &);
288 MaybeExpr Analyze(
const parser::NamedConstant &);
295 MaybeExpr Analyze(
const parser::ArrayConstructor &);
297 std::optional<parser::StructureConstructor> * =
nullptr);
302 MaybeExpr Analyze(
const parser::Expr::PercentLoc &);
322 template <
typename A> MaybeExpr Analyze(
const A &x) {
325 template <
typename... As> MaybeExpr Analyze(
const std::variant<As...> &u) {
326 return common::visit([&](
const auto &x) {
return Analyze(x); }, u);
330 int AnalyzeKindParam(
331 const std::optional<parser::KindParam> &,
int defaultKind);
332 template <
typename PARSED>
334 template <
typename TYPES, TypeCategory CAT,
typename PARSED>
335 MaybeExpr IntLiteralConstant(
const PARSED &,
bool isNegated =
false);
336 MaybeExpr AnalyzeString(std::string &&,
int kind);
337 std::optional<Expr<SubscriptInteger>> AsSubscript(MaybeExpr &&);
338 std::optional<Expr<SubscriptInteger>> TripletPart(
339 const std::optional<parser::Subscript> &);
340 std::optional<Subscript> AnalyzeSectionSubscript(
342 std::vector<Subscript> AnalyzeSectionSubscripts(
343 const std::list<parser::SectionSubscript> &);
344 std::optional<Component> CreateComponent(
DataRef &&,
const Symbol &,
346 MaybeExpr CompleteSubscripts(
ArrayRef &&);
347 MaybeExpr ApplySubscripts(
DataRef &&, std::vector<Subscript> &&);
348 bool CheckRanks(
const DataRef &);
349 bool CheckPolymorphic(
const DataRef &);
350 bool CheckDataRef(
const DataRef &);
351 std::optional<Expr<SubscriptInteger>> GetSubstringBound(
352 const std::optional<parser::ScalarIntExpr> &);
353 MaybeExpr AnalyzeDefinedOp(
357 struct CalleeAndArguments {
361 std::variant<ProcedureDesignator, SymbolRef> u;
362 ActualArguments arguments;
365 std::optional<CalleeAndArguments> AnalyzeProcedureComponentRef(
367 std::optional<characteristics::Procedure> CheckCall(
369 using AdjustActuals =
370 std::optional<std::function<bool(
const Symbol &, ActualArguments &)>>;
372 struct GenericResolution {
373 const Symbol *specific{
nullptr};
374 bool failedDueToAmbiguity{
false};
375 SymbolVector tried{};
377 GenericResolution ResolveGeneric(
const Symbol &,
const ActualArguments &,
378 const AdjustActuals &,
bool isSubroutine, SymbolVector &&tried,
379 bool mightBeStructureConstructor =
false);
380 void EmitGenericResolutionError(
const Symbol &,
bool dueToNullActuals,
381 bool isSubroutine,
const ActualArguments &,
const SymbolVector &,
382 const AdjustActuals &);
383 const Symbol &AccessSpecific(
385 std::optional<CalleeAndArguments> GetCalleeAndArguments(
const parser::Name &,
386 ActualArguments &&,
bool isSubroutine =
false,
387 bool mightBeStructureConstructor =
false);
388 std::optional<CalleeAndArguments> GetCalleeAndArguments(
390 bool isSubroutine,
bool mightBeStructureConstructor =
false);
394 bool defaultKind =
false);
395 MaybeExpr MakeFunctionRef(
398 template <
typename T> T Fold(T &&expr) {
399 return evaluate::Fold(foldingContext_, std::move(expr));
402 MaybeExpr AnalyzeComplex(MaybeExpr &&re, MaybeExpr &&im,
const char *what);
407 struct ComponentSpec {
408 ComponentSpec() =
default;
409 ComponentSpec(ComponentSpec &&) =
default;
411 bool hasKeyword{
false};
412 const Symbol *keywordSymbol{
nullptr};
418 MaybeExpr IterativelyAnalyzeSubexpressions(
const parser::Expr &);
422 std::map<parser::CharBlock, int> impliedDos_;
424 std::pair<parser::CharBlock, evaluate::characteristics::Procedure>>
426 bool isWholeAssumedSizeArrayOk_{
false};
427 bool isNullPointerOk_{
false};
428 bool useSavedTypedExprs_{
true};
429 bool inWhereBody_{
false};
430 bool inDataStmtObject_{
false};
431 bool inDataStmtConstant_{
false};
432 bool inStmtFunctionDefinition_{
false};
433 bool iterativelyAnalyzingSubexpressions_{
false};
434 friend class ArgumentAnalyzer;