9#ifndef FORTRAN_SEMANTICS_EXPRESSION_H_
10#define FORTRAN_SEMANTICS_EXPRESSION_H_
13#include "flang/Common/Fortran.h"
14#include "flang/Common/indirection.h"
15#include "flang/Common/restorer.h"
16#include "flang/Common/visit.h"
17#include "flang/Evaluate/characteristics.h"
18#include "flang/Evaluate/check-expression.h"
19#include "flang/Evaluate/expression.h"
20#include "flang/Evaluate/fold.h"
21#include "flang/Evaluate/tools.h"
22#include "flang/Evaluate/type.h"
23#include "flang/Parser/char-block.h"
24#include "flang/Parser/parse-tree-visitor.h"
25#include "flang/Parser/parse-tree.h"
26#include "flang/Parser/tools.h"
32using namespace Fortran::parser::literals;
36 template <
typename A>
bool Pre(
const A &x) {
38 source.ExtendToCover(x.source);
44 template <
typename A>
void Post(
const A &) {}
45 void Post(
const CharBlock &at) { source.ExtendToCover(at); }
50template <
typename A>
CharBlock FindSourceLocation(
const A &x) {
53 return visitor.source;
57using namespace Fortran::parser::literals;
70class IntrinsicProcTable;
76 evaluate::GenericExprWrapper::Deleter);
81 template <
typename T>
void Set(
const T &x) {
84 }
else if constexpr (ConstraintTrait<T>) {
86 }
else if constexpr (WrapperTrait<T>) {
94template <
typename T>
void ResetExpr(
const T &x) {
98template <
typename T>
void SetExpr(
const T &x,
Expr<SomeType> &&expr) {
99 SetExprHelper{GenericExprWrapper{std::move(expr)}}.Set(x);
104 using MaybeExpr = std::optional<Expr<SomeType>>;
108 : context_{sc}, foldingContext_{fc} {}
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);
251 MaybeExpr Analyze(
const parser::NullInit &);
259 MaybeExpr Designate(
DataRef &&);
262 int IntegerTypeSpecKind(
const parser::IntegerTypeSpec &);
268 return common::ScopedSet(isWholeAssumedSizeArrayOk_,
true);
273 return common::ScopedSet(isNullPointerOk_,
true);
284 MaybeExpr Analyze(
const parser::BOZLiteralConstant &);
285 MaybeExpr Analyze(
const parser::NamedConstant &);
292 MaybeExpr Analyze(
const parser::ArrayConstructor &);
294 std::optional<parser::StructureConstructor> * =
nullptr);
299 MaybeExpr Analyze(
const parser::Expr::PercentLoc &);
319 template <
typename A> MaybeExpr Analyze(
const A &x) {
322 template <
typename... As> MaybeExpr Analyze(
const std::variant<As...> &u) {
323 return common::visit([&](
const auto &x) {
return Analyze(x); }, u);
327 int AnalyzeKindParam(
328 const std::optional<parser::KindParam> &,
int defaultKind);
329 template <
typename PARSED>
331 template <
typename TYPES, TypeCategory CAT,
typename PARSED>
333 MaybeExpr AnalyzeString(std::string &&,
int kind);
334 std::optional<Expr<SubscriptInteger>> AsSubscript(MaybeExpr &&);
335 std::optional<Expr<SubscriptInteger>> TripletPart(
336 const std::optional<parser::Subscript> &);
337 std::optional<Subscript> AnalyzeSectionSubscript(
339 std::vector<Subscript> AnalyzeSectionSubscripts(
340 const std::list<parser::SectionSubscript> &);
341 std::optional<Component> CreateComponent(
DataRef &&,
const Symbol &,
343 MaybeExpr CompleteSubscripts(
ArrayRef &&);
344 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(
const parser::Name &, ActualArguments &&);
354 struct CalleeAndArguments {
358 std::variant<ProcedureDesignator, SymbolRef> u;
359 ActualArguments arguments;
362 std::optional<CalleeAndArguments> AnalyzeProcedureComponentRef(
364 std::optional<characteristics::Procedure> CheckCall(
366 using AdjustActuals =
367 std::optional<std::function<bool(
const Symbol &, ActualArguments &)>>;
369 std::pair<
const Symbol *,
bool > ResolveGeneric(
370 const Symbol &,
const ActualArguments &,
const AdjustActuals &,
371 bool isSubroutine,
bool mightBeStructureConstructor =
false);
372 void EmitGenericResolutionError(
373 const Symbol &,
bool dueToNullActuals,
bool isSubroutine);
374 const Symbol &AccessSpecific(
376 std::optional<CalleeAndArguments> GetCalleeAndArguments(
const parser::Name &,
377 ActualArguments &&,
bool isSubroutine =
false,
378 bool mightBeStructureConstructor =
false);
379 std::optional<CalleeAndArguments> GetCalleeAndArguments(
381 bool isSubroutine,
bool mightBeStructureConstructor =
false);
385 bool defaultKind =
false);
386 MaybeExpr MakeFunctionRef(
389 template <
typename T> T Fold(T &&expr) {
390 return evaluate::Fold(foldingContext_, std::move(expr));
393 MaybeExpr AnalyzeComplex(MaybeExpr &&re, MaybeExpr &&im,
const char *what);
396 MaybeExpr IterativelyAnalyzeSubexpressions(
const parser::Expr &);
400 std::map<parser::CharBlock, int> impliedDos_;
402 std::pair<parser::CharBlock, evaluate::characteristics::Procedure>>
404 bool isWholeAssumedSizeArrayOk_{
false};
405 bool isNullPointerOk_{
false};
406 bool useSavedTypedExprs_{
true};
407 bool inWhereBody_{
false};
408 bool inDataStmtObject_{
false};
409 bool inDataStmtConstant_{
false};
410 bool inStmtFunctionDefinition_{
false};
411 bool iterativelyAnalyzingSubexpressions_{
false};
415inline bool AreConformable(
int leftRank,
int rightRank) {
416 return leftRank == 0 || rightRank == 0 || leftRank == rightRank;
419template <
typename L,
typename R>
420bool AreConformable(
const L &left,
const R &right) {
421 return AreConformable(left.Rank(), right.Rank());
424template <
typename L,
typename R>
425void ConformabilityCheck(
427 if (!AreConformable(left, right)) {
428 context.Say(
"left operand has rank %d, right operand has rank %d"_err_en_US,
429 left.Rank(), right.Rank());
434namespace Fortran::semantics {
438std::optional<evaluate::Expr<evaluate::SomeType>> AnalyzeExpr(
439 SemanticsContext &context,
const A &expr) {
445 SemanticsContext &, common::TypeCategory,
446 const std::optional<parser::KindSelector> &);
454 template <
typename A>
bool Pre(
const A &) {
return true; }
455 template <
typename A>
void Post(
const A &) {}
456 bool Walk(
const parser::Program &);
459 exprAnalyzer_.Analyze(x);
463 exprAnalyzer_.Analyze(x);
467 exprAnalyzer_.Analyze(x);
471 exprAnalyzer_.Analyze(x);
475 exprAnalyzer_.Analyze(x);
479 exprAnalyzer_.Analyze(x);
487 exprAnalyzer_.Analyze(x);
491 exprAnalyzer_.Analyze(x);
495 exprAnalyzer_.Analyze(x);
502 exprAnalyzer_.set_inWhereBody(InWhereBody());
507 exprAnalyzer_.set_inWhereBody(InWhereBody());
511 exprAnalyzer_.set_inWhereBody(InWhereBody());
516 exprAnalyzer_.set_inWhereBody(InWhereBody());
520 inComponentDefStmt_ =
true;
529 return !inComponentDefStmt_ ||
530 std::holds_alternative<
531 std::list<common::Indirection<parser::DataStmtValue>>>(x.u);
535 exprAnalyzer_.Analyze(x);
539 exprAnalyzer_.Analyze(x);
543 exprAnalyzer_.Analyze(x);
547 exprAnalyzer_.Analyze(x);
551 exprAnalyzer_.Analyze(x);
556 bool InWhereBody()
const {
return whereDepth_ > 0; }
561 bool inComponentDefStmt_{
false};
Definition: indirection.h:31
Definition: restorer.h:24
Definition: expression.cpp:121
Definition: variable.h:208
Definition: expression.h:878
Definition: expression.h:102
Definition: char-block.h:28
Definition: message.h:363
Definition: message.h:188
Definition: expression.h:450
Definition: semantics.h:67
Definition: check-expression.h:19
Definition: variable.h:300
Definition: expression.h:896
Definition: expression.h:72
Definition: intrinsics.h:45
Definition: parse-tree.h:1923
Definition: parse-tree.h:1911
Definition: parse-tree.h:2016
Definition: parse-tree.h:3276
Definition: parse-tree.h:1840
Definition: parse-tree.h:868
Definition: parse-tree.h:1902
Definition: parse-tree.h:854
Definition: parse-tree.h:846
Definition: parse-tree.h:1116
Definition: parse-tree.h:300
Definition: parse-tree.h:1528
Definition: parse-tree.h:1818
Definition: parse-tree.h:1487
Definition: parse-tree.h:1536
Definition: parse-tree.h:1508
Definition: parse-tree.h:324
Definition: parse-tree.h:1857
Definition: parse-tree.h:1764
Definition: parse-tree.h:1737
Definition: parse-tree.h:1778
Definition: parse-tree.h:1743
Definition: parse-tree.h:1782
Definition: parse-tree.h:1719
Definition: parse-tree.h:1734
Definition: parse-tree.h:1770
Definition: parse-tree.h:1752
Definition: parse-tree.h:1758
Definition: parse-tree.h:1761
Definition: parse-tree.h:1749
Definition: parse-tree.h:1746
Definition: parse-tree.h:1731
Definition: parse-tree.h:1773
Definition: parse-tree.h:1755
Definition: parse-tree.h:1713
Definition: parse-tree.h:1710
Definition: parse-tree.h:1767
Definition: parse-tree.h:1704
Definition: parse-tree.h:1728
Definition: parse-tree.h:1740
Definition: parse-tree.h:1707
Definition: parse-tree.h:1700
Definition: parse-tree.h:3264
Definition: parse-tree.h:875
Definition: parse-tree.h:1026
Definition: parse-tree.h:802
Definition: parse-tree.h:308
Definition: parse-tree.h:882
Definition: parse-tree.h:316
Definition: parse-tree.h:580
Definition: parse-tree.h:2040
Definition: parse-tree.h:1999
Definition: parse-tree.h:1897
Definition: parse-tree.h:3231
Definition: parse-tree.h:821
Definition: parse-tree.h:292
Definition: parse-tree.h:1671
Definition: parse-tree.h:2151
Definition: parse-tree.h:860
Definition: parse-tree.h:795
Definition: parse-tree.h:835
Definition: expression.h:35
Definition: parse-tree.h:3342
Definition: parse-tree.h:1887
Definition: parse-tree.h:1226
Definition: parse-tree.h:1849
Definition: parse-tree.h:1835
Definition: parse-tree.h:808
Definition: parse-tree.h:1865
Definition: parse-tree.h:2066
Definition: parse-tree.h:2053