1 //===-- lib/Semantics/expression.cpp --------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "flang/Semantics/expression.h"
10 #include "check-call.h"
11 #include "pointer-assignment.h"
12 #include "resolve-names.h"
13 #include "flang/Common/idioms.h"
14 #include "flang/Evaluate/common.h"
15 #include "flang/Evaluate/fold.h"
16 #include "flang/Evaluate/tools.h"
17 #include "flang/Parser/characters.h"
18 #include "flang/Parser/dump-parse-tree.h"
19 #include "flang/Parser/parse-tree-visitor.h"
20 #include "flang/Parser/parse-tree.h"
21 #include "flang/Semantics/scope.h"
22 #include "flang/Semantics/semantics.h"
23 #include "flang/Semantics/symbol.h"
24 #include "flang/Semantics/tools.h"
25 #include "llvm/Support/raw_ostream.h"
26 #include <algorithm>
27 #include <functional>
28 #include <optional>
29 #include <set>
30 
31 // Typedef for optional generic expressions (ubiquitous in this file)
32 using MaybeExpr =
33     std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>;
34 
35 // Much of the code that implements semantic analysis of expressions is
36 // tightly coupled with their typed representations in lib/Evaluate,
37 // and appears here in namespace Fortran::evaluate for convenience.
38 namespace Fortran::evaluate {
39 
40 using common::LanguageFeature;
41 using common::NumericOperator;
42 using common::TypeCategory;
43 
44 static inline std::string ToUpperCase(const std::string &str) {
45   return parser::ToUpperCaseLetters(str);
46 }
47 
48 struct DynamicTypeWithLength : public DynamicType {
49   explicit DynamicTypeWithLength(const DynamicType &t) : DynamicType{t} {}
50   std::optional<Expr<SubscriptInteger>> LEN() const;
51   std::optional<Expr<SubscriptInteger>> length;
52 };
53 
54 std::optional<Expr<SubscriptInteger>> DynamicTypeWithLength::LEN() const {
55   if (length) {
56     return length;
57   }
58   if (auto *lengthParam{charLength()}) {
59     if (const auto &len{lengthParam->GetExplicit()}) {
60       return ConvertToType<SubscriptInteger>(common::Clone(*len));
61     }
62   }
63   return std::nullopt; // assumed or deferred length
64 }
65 
66 static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
67     const std::optional<parser::TypeSpec> &spec) {
68   if (spec) {
69     if (const semantics::DeclTypeSpec * typeSpec{spec->declTypeSpec}) {
70       // Name resolution sets TypeSpec::declTypeSpec only when it's valid
71       // (viz., an intrinsic type with valid known kind or a non-polymorphic
72       // & non-ABSTRACT derived type).
73       if (const semantics::IntrinsicTypeSpec *
74           intrinsic{typeSpec->AsIntrinsic()}) {
75         TypeCategory category{intrinsic->category()};
76         if (auto optKind{ToInt64(intrinsic->kind())}) {
77           int kind{static_cast<int>(*optKind)};
78           if (category == TypeCategory::Character) {
79             const semantics::CharacterTypeSpec &cts{
80                 typeSpec->characterTypeSpec()};
81             const semantics::ParamValue &len{cts.length()};
82             // N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() &
83             // type guards, but not in array constructors.
84             return DynamicTypeWithLength{DynamicType{kind, len}};
85           } else {
86             return DynamicTypeWithLength{DynamicType{category, kind}};
87           }
88         }
89       } else if (const semantics::DerivedTypeSpec *
90           derived{typeSpec->AsDerived()}) {
91         return DynamicTypeWithLength{DynamicType{*derived}};
92       }
93     }
94   }
95   return std::nullopt;
96 }
97 
98 class ArgumentAnalyzer {
99 public:
100   explicit ArgumentAnalyzer(ExpressionAnalyzer &context)
101       : context_{context}, allowAssumedType_{false} {}
102   ArgumentAnalyzer(ExpressionAnalyzer &context, parser::CharBlock source,
103       bool allowAssumedType = false)
104       : context_{context}, source_{source}, allowAssumedType_{
105                                                 allowAssumedType} {}
106   bool fatalErrors() const { return fatalErrors_; }
107   ActualArguments &&GetActuals() {
108     CHECK(!fatalErrors_);
109     return std::move(actuals_);
110   }
111   const Expr<SomeType> &GetExpr(std::size_t i) const {
112     return DEREF(actuals_.at(i).value().UnwrapExpr());
113   }
114   Expr<SomeType> &&MoveExpr(std::size_t i) {
115     return std::move(DEREF(actuals_.at(i).value().UnwrapExpr()));
116   }
117   void Analyze(const common::Indirection<parser::Expr> &x) {
118     Analyze(x.value());
119   }
120   void Analyze(const parser::Expr &x) {
121     actuals_.emplace_back(AnalyzeExpr(x));
122     fatalErrors_ |= !actuals_.back();
123   }
124   void Analyze(const parser::Variable &);
125   void Analyze(const parser::ActualArgSpec &, bool isSubroutine);
126 
127   bool IsIntrinsicRelational(RelationalOperator) const;
128   bool IsIntrinsicLogical() const;
129   bool IsIntrinsicNumeric(NumericOperator) const;
130   bool IsIntrinsicConcat() const;
131 
132   // Find and return a user-defined operator or report an error.
133   // The provided message is used if there is no such operator.
134   MaybeExpr TryDefinedOp(
135       const char *, parser::MessageFixedText &&, bool isUserOp = false);
136   template <typename E>
137   MaybeExpr TryDefinedOp(E opr, parser::MessageFixedText &&msg) {
138     return TryDefinedOp(
139         context_.context().languageFeatures().GetNames(opr), std::move(msg));
140   }
141   // Find and return a user-defined assignment
142   std::optional<ProcedureRef> TryDefinedAssignment();
143   std::optional<ProcedureRef> GetDefinedAssignmentProc();
144   void Dump(llvm::raw_ostream &);
145 
146 private:
147   MaybeExpr TryDefinedOp(
148       std::vector<const char *>, parser::MessageFixedText &&);
149   MaybeExpr TryBoundOp(const Symbol &, int passIndex);
150   std::optional<ActualArgument> AnalyzeExpr(const parser::Expr &);
151   bool AreConformable() const;
152   const Symbol *FindBoundOp(parser::CharBlock, int passIndex);
153   void AddAssignmentConversion(
154       const DynamicType &lhsType, const DynamicType &rhsType);
155   bool OkLogicalIntegerAssignment(TypeCategory lhs, TypeCategory rhs);
156   std::optional<DynamicType> GetType(std::size_t) const;
157   int GetRank(std::size_t) const;
158   bool IsBOZLiteral(std::size_t i) const {
159     return std::holds_alternative<BOZLiteralConstant>(GetExpr(i).u);
160   }
161   void SayNoMatch(const std::string &, bool isAssignment = false);
162   std::string TypeAsFortran(std::size_t);
163   bool AnyUntypedOperand();
164 
165   ExpressionAnalyzer &context_;
166   ActualArguments actuals_;
167   parser::CharBlock source_;
168   bool fatalErrors_{false};
169   const bool allowAssumedType_;
170   const Symbol *sawDefinedOp_{nullptr};
171 };
172 
173 // Wraps a data reference in a typed Designator<>, and a procedure
174 // or procedure pointer reference in a ProcedureDesignator.
175 MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
176   const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
177   if (semantics::IsProcedure(symbol)) {
178     if (auto *component{std::get_if<Component>(&ref.u)}) {
179       return Expr<SomeType>{ProcedureDesignator{std::move(*component)}};
180     } else if (!std::holds_alternative<SymbolRef>(ref.u)) {
181       DIE("unexpected alternative in DataRef");
182     } else if (!symbol.attrs().test(semantics::Attr::INTRINSIC)) {
183       return Expr<SomeType>{ProcedureDesignator{symbol}};
184     } else if (auto interface{context_.intrinsics().IsSpecificIntrinsicFunction(
185                    symbol.name().ToString())}) {
186       SpecificIntrinsic intrinsic{
187           symbol.name().ToString(), std::move(*interface)};
188       intrinsic.isRestrictedSpecific = interface->isRestrictedSpecific;
189       return Expr<SomeType>{ProcedureDesignator{std::move(intrinsic)}};
190     } else {
191       Say("'%s' is not a specific intrinsic procedure"_err_en_US,
192           symbol.name());
193       return std::nullopt;
194     }
195   } else if (auto dyType{DynamicType::From(symbol)}) {
196     return TypedWrapper<Designator, DataRef>(*dyType, std::move(ref));
197   }
198   return std::nullopt;
199 }
200 
201 // Some subscript semantic checks must be deferred until all of the
202 // subscripts are in hand.
203 MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
204   const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
205   const auto *object{symbol.detailsIf<semantics::ObjectEntityDetails>()};
206   int symbolRank{symbol.Rank()};
207   int subscripts{static_cast<int>(ref.size())};
208   if (subscripts == 0) {
209     // nothing to check
210   } else if (subscripts != symbolRank) {
211     if (symbolRank != 0) {
212       Say("Reference to rank-%d object '%s' has %d subscripts"_err_en_US,
213           symbolRank, symbol.name(), subscripts);
214     }
215     return std::nullopt;
216   } else if (Component * component{ref.base().UnwrapComponent()}) {
217     int baseRank{component->base().Rank()};
218     if (baseRank > 0) {
219       int subscriptRank{0};
220       for (const auto &expr : ref.subscript()) {
221         subscriptRank += expr.Rank();
222       }
223       if (subscriptRank > 0) {
224         Say("Subscripts of component '%s' of rank-%d derived type "
225             "array have rank %d but must all be scalar"_err_en_US,
226             symbol.name(), baseRank, subscriptRank);
227         return std::nullopt;
228       }
229     }
230   } else if (object) {
231     // C928 & C1002
232     if (Triplet * last{std::get_if<Triplet>(&ref.subscript().back().u)}) {
233       if (!last->upper() && object->IsAssumedSize()) {
234         Say("Assumed-size array '%s' must have explicit final "
235             "subscript upper bound value"_err_en_US,
236             symbol.name());
237         return std::nullopt;
238       }
239     }
240   }
241   return Designate(DataRef{std::move(ref)});
242 }
243 
244 // Applies subscripts to a data reference.
245 MaybeExpr ExpressionAnalyzer::ApplySubscripts(
246     DataRef &&dataRef, std::vector<Subscript> &&subscripts) {
247   return std::visit(
248       common::visitors{
249           [&](SymbolRef &&symbol) {
250             return CompleteSubscripts(ArrayRef{symbol, std::move(subscripts)});
251           },
252           [&](Component &&c) {
253             return CompleteSubscripts(
254                 ArrayRef{std::move(c), std::move(subscripts)});
255           },
256           [&](auto &&) -> MaybeExpr {
257             DIE("bad base for ArrayRef");
258             return std::nullopt;
259           },
260       },
261       std::move(dataRef.u));
262 }
263 
264 // Top-level checks for data references.
265 MaybeExpr ExpressionAnalyzer::TopLevelChecks(DataRef &&dataRef) {
266   if (Component * component{std::get_if<Component>(&dataRef.u)}) {
267     const Symbol &symbol{component->GetLastSymbol()};
268     int componentRank{symbol.Rank()};
269     if (componentRank > 0) {
270       int baseRank{component->base().Rank()};
271       if (baseRank > 0) {
272         Say("Reference to whole rank-%d component '%%%s' of "
273             "rank-%d array of derived type is not allowed"_err_en_US,
274             componentRank, symbol.name(), baseRank);
275       }
276     }
277   }
278   return Designate(std::move(dataRef));
279 }
280 
281 // Parse tree correction after a substring S(j:k) was misparsed as an
282 // array section.  N.B. Fortran substrings have to have a range, not a
283 // single index.
284 static void FixMisparsedSubstring(const parser::Designator &d) {
285   auto &mutate{const_cast<parser::Designator &>(d)};
286   if (auto *dataRef{std::get_if<parser::DataRef>(&mutate.u)}) {
287     if (auto *ae{std::get_if<common::Indirection<parser::ArrayElement>>(
288             &dataRef->u)}) {
289       parser::ArrayElement &arrElement{ae->value()};
290       if (!arrElement.subscripts.empty()) {
291         auto iter{arrElement.subscripts.begin()};
292         if (auto *triplet{std::get_if<parser::SubscriptTriplet>(&iter->u)}) {
293           if (!std::get<2>(triplet->t) /* no stride */ &&
294               ++iter == arrElement.subscripts.end() /* one subscript */) {
295             if (Symbol *
296                 symbol{std::visit(
297                     common::visitors{
298                         [](parser::Name &n) { return n.symbol; },
299                         [](common::Indirection<parser::StructureComponent>
300                                 &sc) { return sc.value().component.symbol; },
301                         [](auto &) -> Symbol * { return nullptr; },
302                     },
303                     arrElement.base.u)}) {
304               const Symbol &ultimate{symbol->GetUltimate()};
305               if (const semantics::DeclTypeSpec * type{ultimate.GetType()}) {
306                 if (!ultimate.IsObjectArray() &&
307                     type->category() == semantics::DeclTypeSpec::Character) {
308                   // The ambiguous S(j:k) was parsed as an array section
309                   // reference, but it's now clear that it's a substring.
310                   // Fix the parse tree in situ.
311                   mutate.u = arrElement.ConvertToSubstring();
312                 }
313               }
314             }
315           }
316         }
317       }
318     }
319   }
320 }
321 
322 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
323   auto restorer{GetContextualMessages().SetLocation(d.source)};
324   FixMisparsedSubstring(d);
325   // These checks have to be deferred to these "top level" data-refs where
326   // we can be sure that there are no following subscripts (yet).
327   // Substrings have already been run through TopLevelChecks() and
328   // won't be returned by ExtractDataRef().
329   if (MaybeExpr result{Analyze(d.u)}) {
330     if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(result))}) {
331       return TopLevelChecks(std::move(*dataRef));
332     }
333     return result;
334   }
335   return std::nullopt;
336 }
337 
338 // A utility subroutine to repackage optional expressions of various levels
339 // of type specificity as fully general MaybeExpr values.
340 template <typename A> common::IfNoLvalue<MaybeExpr, A> AsMaybeExpr(A &&x) {
341   return AsGenericExpr(std::move(x));
342 }
343 template <typename A> MaybeExpr AsMaybeExpr(std::optional<A> &&x) {
344   if (x) {
345     return AsMaybeExpr(std::move(*x));
346   }
347   return std::nullopt;
348 }
349 
350 // Type kind parameter values for literal constants.
351 int ExpressionAnalyzer::AnalyzeKindParam(
352     const std::optional<parser::KindParam> &kindParam, int defaultKind) {
353   if (!kindParam) {
354     return defaultKind;
355   }
356   return std::visit(
357       common::visitors{
358           [](std::uint64_t k) { return static_cast<int>(k); },
359           [&](const parser::Scalar<
360               parser::Integer<parser::Constant<parser::Name>>> &n) {
361             if (MaybeExpr ie{Analyze(n)}) {
362               if (std::optional<std::int64_t> i64{ToInt64(*ie)}) {
363                 int iv = *i64;
364                 if (iv == *i64) {
365                   return iv;
366                 }
367               }
368             }
369             return defaultKind;
370           },
371       },
372       kindParam->u);
373 }
374 
375 // Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant
376 struct IntTypeVisitor {
377   using Result = MaybeExpr;
378   using Types = IntegerTypes;
379   template <typename T> Result Test() {
380     if (T::kind >= kind) {
381       const char *p{digits.begin()};
382       auto value{T::Scalar::Read(p, 10, true /*signed*/)};
383       if (!value.overflow) {
384         if (T::kind > kind) {
385           if (!isDefaultKind ||
386               !analyzer.context().IsEnabled(LanguageFeature::BigIntLiterals)) {
387             return std::nullopt;
388           } else if (analyzer.context().ShouldWarn(
389                          LanguageFeature::BigIntLiterals)) {
390             analyzer.Say(digits,
391                 "Integer literal is too large for default INTEGER(KIND=%d); "
392                 "assuming INTEGER(KIND=%d)"_en_US,
393                 kind, T::kind);
394           }
395         }
396         return Expr<SomeType>{
397             Expr<SomeInteger>{Expr<T>{Constant<T>{std::move(value.value)}}}};
398       }
399     }
400     return std::nullopt;
401   }
402   ExpressionAnalyzer &analyzer;
403   parser::CharBlock digits;
404   int kind;
405   bool isDefaultKind;
406 };
407 
408 template <typename PARSED>
409 MaybeExpr ExpressionAnalyzer::IntLiteralConstant(const PARSED &x) {
410   const auto &kindParam{std::get<std::optional<parser::KindParam>>(x.t)};
411   bool isDefaultKind{!kindParam};
412   int kind{AnalyzeKindParam(kindParam, GetDefaultKind(TypeCategory::Integer))};
413   if (CheckIntrinsicKind(TypeCategory::Integer, kind)) {
414     auto digits{std::get<parser::CharBlock>(x.t)};
415     if (MaybeExpr result{common::SearchTypes(
416             IntTypeVisitor{*this, digits, kind, isDefaultKind})}) {
417       return result;
418     } else if (isDefaultKind) {
419       Say(digits,
420           "Integer literal is too large for any allowable "
421           "kind of INTEGER"_err_en_US);
422     } else {
423       Say(digits, "Integer literal is too large for INTEGER(KIND=%d)"_err_en_US,
424           kind);
425     }
426   }
427   return std::nullopt;
428 }
429 
430 MaybeExpr ExpressionAnalyzer::Analyze(const parser::IntLiteralConstant &x) {
431   auto restorer{
432       GetContextualMessages().SetLocation(std::get<parser::CharBlock>(x.t))};
433   return IntLiteralConstant(x);
434 }
435 
436 MaybeExpr ExpressionAnalyzer::Analyze(
437     const parser::SignedIntLiteralConstant &x) {
438   auto restorer{GetContextualMessages().SetLocation(x.source)};
439   return IntLiteralConstant(x);
440 }
441 
442 template <typename TYPE>
443 Constant<TYPE> ReadRealLiteral(
444     parser::CharBlock source, FoldingContext &context) {
445   const char *p{source.begin()};
446   auto valWithFlags{Scalar<TYPE>::Read(p, context.rounding())};
447   CHECK(p == source.end());
448   RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
449   auto value{valWithFlags.value};
450   if (context.flushSubnormalsToZero()) {
451     value = value.FlushSubnormalToZero();
452   }
453   return {value};
454 }
455 
456 struct RealTypeVisitor {
457   using Result = std::optional<Expr<SomeReal>>;
458   using Types = RealTypes;
459 
460   RealTypeVisitor(int k, parser::CharBlock lit, FoldingContext &ctx)
461       : kind{k}, literal{lit}, context{ctx} {}
462 
463   template <typename T> Result Test() {
464     if (kind == T::kind) {
465       return {AsCategoryExpr(ReadRealLiteral<T>(literal, context))};
466     }
467     return std::nullopt;
468   }
469 
470   int kind;
471   parser::CharBlock literal;
472   FoldingContext &context;
473 };
474 
475 // Reads a real literal constant and encodes it with the right kind.
476 MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
477   // Use a local message context around the real literal for better
478   // provenance on any messages.
479   auto restorer{GetContextualMessages().SetLocation(x.real.source)};
480   // If a kind parameter appears, it defines the kind of the literal and the
481   // letter used in an exponent part must be 'E' (e.g., the 'E' in
482   // "6.02214E+23").  In the absence of an explicit kind parameter, any
483   // exponent letter determines the kind.  Otherwise, defaults apply.
484   auto &defaults{context_.defaultKinds()};
485   int defaultKind{defaults.GetDefaultKind(TypeCategory::Real)};
486   const char *end{x.real.source.end()};
487   char expoLetter{' '};
488   std::optional<int> letterKind;
489   for (const char *p{x.real.source.begin()}; p < end; ++p) {
490     if (parser::IsLetter(*p)) {
491       expoLetter = *p;
492       switch (expoLetter) {
493       case 'e':
494         letterKind = defaults.GetDefaultKind(TypeCategory::Real);
495         break;
496       case 'd':
497         letterKind = defaults.doublePrecisionKind();
498         break;
499       case 'q':
500         letterKind = defaults.quadPrecisionKind();
501         break;
502       default:
503         Say("Unknown exponent letter '%c'"_err_en_US, expoLetter);
504       }
505       break;
506     }
507   }
508   if (letterKind) {
509     defaultKind = *letterKind;
510   }
511   // C716 requires 'E' as an exponent, but this is more useful
512   auto kind{AnalyzeKindParam(x.kind, defaultKind)};
513   if (letterKind && kind != *letterKind && expoLetter != 'e') {
514     Say("Explicit kind parameter on real constant disagrees with "
515         "exponent letter '%c'"_en_US,
516         expoLetter);
517   }
518   auto result{common::SearchTypes(
519       RealTypeVisitor{kind, x.real.source, GetFoldingContext()})};
520   if (!result) { // C717
521     Say("Unsupported REAL(KIND=%d)"_err_en_US, kind);
522   }
523   return AsMaybeExpr(std::move(result));
524 }
525 
526 MaybeExpr ExpressionAnalyzer::Analyze(
527     const parser::SignedRealLiteralConstant &x) {
528   if (auto result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) {
529     auto &realExpr{std::get<Expr<SomeReal>>(result->u)};
530     if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
531       if (sign == parser::Sign::Negative) {
532         return AsGenericExpr(-std::move(realExpr));
533       }
534     }
535     return result;
536   }
537   return std::nullopt;
538 }
539 
540 MaybeExpr ExpressionAnalyzer::Analyze(
541     const parser::SignedComplexLiteralConstant &x) {
542   auto result{Analyze(std::get<parser::ComplexLiteralConstant>(x.t))};
543   if (!result) {
544     return std::nullopt;
545   } else if (std::get<parser::Sign>(x.t) == parser::Sign::Negative) {
546     return AsGenericExpr(-std::move(std::get<Expr<SomeComplex>>(result->u)));
547   } else {
548     return result;
549   }
550 }
551 
552 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexPart &x) {
553   return Analyze(x.u);
554 }
555 
556 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexLiteralConstant &z) {
557   return AsMaybeExpr(
558       ConstructComplex(GetContextualMessages(), Analyze(std::get<0>(z.t)),
559           Analyze(std::get<1>(z.t)), GetDefaultKind(TypeCategory::Real)));
560 }
561 
562 // CHARACTER literal processing.
563 MaybeExpr ExpressionAnalyzer::AnalyzeString(std::string &&string, int kind) {
564   if (!CheckIntrinsicKind(TypeCategory::Character, kind)) {
565     return std::nullopt;
566   }
567   switch (kind) {
568   case 1:
569     return AsGenericExpr(Constant<Type<TypeCategory::Character, 1>>{
570         parser::DecodeString<std::string, parser::Encoding::LATIN_1>(
571             string, true)});
572   case 2:
573     return AsGenericExpr(Constant<Type<TypeCategory::Character, 2>>{
574         parser::DecodeString<std::u16string, parser::Encoding::UTF_8>(
575             string, true)});
576   case 4:
577     return AsGenericExpr(Constant<Type<TypeCategory::Character, 4>>{
578         parser::DecodeString<std::u32string, parser::Encoding::UTF_8>(
579             string, true)});
580   default:
581     CRASH_NO_CASE;
582   }
583 }
584 
585 MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) {
586   int kind{
587       AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t), 1)};
588   auto value{std::get<std::string>(x.t)};
589   return AnalyzeString(std::move(value), kind);
590 }
591 
592 MaybeExpr ExpressionAnalyzer::Analyze(
593     const parser::HollerithLiteralConstant &x) {
594   int kind{GetDefaultKind(TypeCategory::Character)};
595   auto value{x.v};
596   return AnalyzeString(std::move(value), kind);
597 }
598 
599 // .TRUE. and .FALSE. of various kinds
600 MaybeExpr ExpressionAnalyzer::Analyze(const parser::LogicalLiteralConstant &x) {
601   auto kind{AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t),
602       GetDefaultKind(TypeCategory::Logical))};
603   bool value{std::get<bool>(x.t)};
604   auto result{common::SearchTypes(
605       TypeKindVisitor<TypeCategory::Logical, Constant, bool>{
606           kind, std::move(value)})};
607   if (!result) {
608     Say("unsupported LOGICAL(KIND=%d)"_err_en_US, kind); // C728
609   }
610   return result;
611 }
612 
613 // BOZ typeless literals
614 MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
615   const char *p{x.v.c_str()};
616   std::uint64_t base{16};
617   switch (*p++) {
618   case 'b':
619     base = 2;
620     break;
621   case 'o':
622     base = 8;
623     break;
624   case 'z':
625     break;
626   case 'x':
627     break;
628   default:
629     CRASH_NO_CASE;
630   }
631   CHECK(*p == '"');
632   ++p;
633   auto value{BOZLiteralConstant::Read(p, base, false /*unsigned*/)};
634   if (*p != '"') {
635     Say("Invalid digit ('%c') in BOZ literal '%s'"_err_en_US, *p, x.v);
636     return std::nullopt;
637   }
638   if (value.overflow) {
639     Say("BOZ literal '%s' too large"_err_en_US, x.v);
640     return std::nullopt;
641   }
642   return AsGenericExpr(std::move(value.value));
643 }
644 
645 // For use with SearchTypes to create a TypeParamInquiry with the
646 // right integer kind.
647 struct TypeParamInquiryVisitor {
648   using Result = std::optional<Expr<SomeInteger>>;
649   using Types = IntegerTypes;
650   TypeParamInquiryVisitor(int k, NamedEntity &&b, const Symbol &param)
651       : kind{k}, base{std::move(b)}, parameter{param} {}
652   TypeParamInquiryVisitor(int k, const Symbol &param)
653       : kind{k}, parameter{param} {}
654   template <typename T> Result Test() {
655     if (kind == T::kind) {
656       return Expr<SomeInteger>{
657           Expr<T>{TypeParamInquiry<T::kind>{std::move(base), parameter}}};
658     }
659     return std::nullopt;
660   }
661   int kind;
662   std::optional<NamedEntity> base;
663   const Symbol &parameter;
664 };
665 
666 static std::optional<Expr<SomeInteger>> MakeBareTypeParamInquiry(
667     const Symbol *symbol) {
668   if (std::optional<DynamicType> dyType{DynamicType::From(symbol)}) {
669     if (dyType->category() == TypeCategory::Integer) {
670       return common::SearchTypes(
671           TypeParamInquiryVisitor{dyType->kind(), *symbol});
672     }
673   }
674   return std::nullopt;
675 }
676 
677 // Names and named constants
678 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
679   if (std::optional<int> kind{IsImpliedDo(n.source)}) {
680     return AsMaybeExpr(ConvertToKind<TypeCategory::Integer>(
681         *kind, AsExpr(ImpliedDoIndex{n.source})));
682   } else if (context_.HasError(n) || !n.symbol) {
683     return std::nullopt;
684   } else {
685     const Symbol &ultimate{n.symbol->GetUltimate()};
686     if (ultimate.has<semantics::TypeParamDetails>()) {
687       // A bare reference to a derived type parameter (within a parameterized
688       // derived type definition)
689       return AsMaybeExpr(MakeBareTypeParamInquiry(&ultimate));
690     } else {
691       if (n.symbol->attrs().test(semantics::Attr::VOLATILE)) {
692         if (const semantics::Scope *
693             pure{semantics::FindPureProcedureContaining(
694                 context_.FindScope(n.source))}) {
695           SayAt(n,
696               "VOLATILE variable '%s' may not be referenced in pure subprogram '%s'"_err_en_US,
697               n.source, DEREF(pure->symbol()).name());
698           n.symbol->attrs().reset(semantics::Attr::VOLATILE);
699         }
700       }
701       return Designate(DataRef{*n.symbol});
702     }
703   }
704 }
705 
706 MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) {
707   if (MaybeExpr value{Analyze(n.v)}) {
708     Expr<SomeType> folded{Fold(std::move(*value))};
709     if (IsConstantExpr(folded)) {
710       return folded;
711     }
712     Say(n.v.source, "must be a constant"_err_en_US); // C718
713   }
714   return std::nullopt;
715 }
716 
717 MaybeExpr ExpressionAnalyzer::Analyze(const parser::NullInit &x) {
718   return Expr<SomeType>{NullPointer{}};
719 }
720 
721 MaybeExpr ExpressionAnalyzer::Analyze(const parser::InitialDataTarget &x) {
722   return Analyze(x.value());
723 }
724 
725 MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtValue &x) {
726   if (const auto &repeat{
727           std::get<std::optional<parser::DataStmtRepeat>>(x.t)}) {
728     x.repetitions = -1;
729     if (MaybeExpr expr{Analyze(repeat->u)}) {
730       Expr<SomeType> folded{Fold(std::move(*expr))};
731       if (auto value{ToInt64(folded)}) {
732         if (*value >= 0) { // C882
733           x.repetitions = *value;
734         } else {
735           Say(FindSourceLocation(repeat),
736               "Repeat count (%jd) for data value must not be negative"_err_en_US,
737               *value);
738         }
739       }
740     }
741   }
742   return Analyze(std::get<parser::DataStmtConstant>(x.t));
743 }
744 
745 // Substring references
746 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::GetSubstringBound(
747     const std::optional<parser::ScalarIntExpr> &bound) {
748   if (bound) {
749     if (MaybeExpr expr{Analyze(*bound)}) {
750       if (expr->Rank() > 1) {
751         Say("substring bound expression has rank %d"_err_en_US, expr->Rank());
752       }
753       if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
754         if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
755           return {std::move(*ssIntExpr)};
756         }
757         return {Expr<SubscriptInteger>{
758             Convert<SubscriptInteger, TypeCategory::Integer>{
759                 std::move(*intExpr)}}};
760       } else {
761         Say("substring bound expression is not INTEGER"_err_en_US);
762       }
763     }
764   }
765   return std::nullopt;
766 }
767 
768 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
769   if (MaybeExpr baseExpr{Analyze(std::get<parser::DataRef>(ss.t))}) {
770     if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) {
771       if (MaybeExpr newBaseExpr{TopLevelChecks(std::move(*dataRef))}) {
772         if (std::optional<DataRef> checked{
773                 ExtractDataRef(std::move(*newBaseExpr))}) {
774           const parser::SubstringRange &range{
775               std::get<parser::SubstringRange>(ss.t)};
776           std::optional<Expr<SubscriptInteger>> first{
777               GetSubstringBound(std::get<0>(range.t))};
778           std::optional<Expr<SubscriptInteger>> last{
779               GetSubstringBound(std::get<1>(range.t))};
780           const Symbol &symbol{checked->GetLastSymbol()};
781           if (std::optional<DynamicType> dynamicType{
782                   DynamicType::From(symbol)}) {
783             if (dynamicType->category() == TypeCategory::Character) {
784               return WrapperHelper<TypeCategory::Character, Designator,
785                   Substring>(dynamicType->kind(),
786                   Substring{std::move(checked.value()), std::move(first),
787                       std::move(last)});
788             }
789           }
790           Say("substring may apply only to CHARACTER"_err_en_US);
791         }
792       }
793     }
794   }
795   return std::nullopt;
796 }
797 
798 // CHARACTER literal substrings
799 MaybeExpr ExpressionAnalyzer::Analyze(
800     const parser::CharLiteralConstantSubstring &x) {
801   const parser::SubstringRange &range{std::get<parser::SubstringRange>(x.t)};
802   std::optional<Expr<SubscriptInteger>> lower{
803       GetSubstringBound(std::get<0>(range.t))};
804   std::optional<Expr<SubscriptInteger>> upper{
805       GetSubstringBound(std::get<1>(range.t))};
806   if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) {
807     if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) {
808       Expr<SubscriptInteger> length{
809           std::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
810               charExpr->u)};
811       if (!lower) {
812         lower = Expr<SubscriptInteger>{1};
813       }
814       if (!upper) {
815         upper = Expr<SubscriptInteger>{
816             static_cast<std::int64_t>(ToInt64(length).value())};
817       }
818       return std::visit(
819           [&](auto &&ckExpr) -> MaybeExpr {
820             using Result = ResultType<decltype(ckExpr)>;
821             auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)};
822             CHECK(DEREF(cp).size() == 1);
823             StaticDataObject::Pointer staticData{StaticDataObject::Create()};
824             staticData->set_alignment(Result::kind)
825                 .set_itemBytes(Result::kind)
826                 .Push(cp->GetScalarValue().value());
827             Substring substring{std::move(staticData), std::move(lower.value()),
828                 std::move(upper.value())};
829             return AsGenericExpr(
830                 Expr<Result>{Designator<Result>{std::move(substring)}});
831           },
832           std::move(charExpr->u));
833     }
834   }
835   return std::nullopt;
836 }
837 
838 // Subscripted array references
839 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::AsSubscript(
840     MaybeExpr &&expr) {
841   if (expr) {
842     if (expr->Rank() > 1) {
843       Say("Subscript expression has rank %d greater than 1"_err_en_US,
844           expr->Rank());
845     }
846     if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
847       if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
848         return std::move(*ssIntExpr);
849       } else {
850         return Expr<SubscriptInteger>{
851             Convert<SubscriptInteger, TypeCategory::Integer>{
852                 std::move(*intExpr)}};
853       }
854     } else {
855       Say("Subscript expression is not INTEGER"_err_en_US);
856     }
857   }
858   return std::nullopt;
859 }
860 
861 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
862     const std::optional<parser::Subscript> &s) {
863   if (s) {
864     return AsSubscript(Analyze(*s));
865   } else {
866     return std::nullopt;
867   }
868 }
869 
870 std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
871     const parser::SectionSubscript &ss) {
872   return std::visit(common::visitors{
873                         [&](const parser::SubscriptTriplet &t) {
874                           return std::make_optional<Subscript>(
875                               Triplet{TripletPart(std::get<0>(t.t)),
876                                   TripletPart(std::get<1>(t.t)),
877                                   TripletPart(std::get<2>(t.t))});
878                         },
879                         [&](const auto &s) -> std::optional<Subscript> {
880                           if (auto subscriptExpr{AsSubscript(Analyze(s))}) {
881                             return Subscript{std::move(*subscriptExpr)};
882                           } else {
883                             return std::nullopt;
884                           }
885                         },
886                     },
887       ss.u);
888 }
889 
890 // Empty result means an error occurred
891 std::vector<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscripts(
892     const std::list<parser::SectionSubscript> &sss) {
893   bool error{false};
894   std::vector<Subscript> subscripts;
895   for (const auto &s : sss) {
896     if (auto subscript{AnalyzeSectionSubscript(s)}) {
897       subscripts.emplace_back(std::move(*subscript));
898     } else {
899       error = true;
900     }
901   }
902   return !error ? subscripts : std::vector<Subscript>{};
903 }
904 
905 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {
906   if (MaybeExpr baseExpr{Analyze(ae.base)}) {
907     if (ae.subscripts.empty()) {
908       // will be converted to function call later or error reported
909       return std::nullopt;
910     } else if (baseExpr->Rank() == 0) {
911       if (const Symbol * symbol{GetLastSymbol(*baseExpr)}) {
912         Say("'%s' is not an array"_err_en_US, symbol->name());
913       }
914     } else if (std::optional<DataRef> dataRef{
915                    ExtractDataRef(std::move(*baseExpr))}) {
916       return ApplySubscripts(
917           std::move(*dataRef), AnalyzeSectionSubscripts(ae.subscripts));
918     } else {
919       Say("Subscripts may be applied only to an object, component, or array constant"_err_en_US);
920     }
921   }
922   // error was reported: analyze subscripts without reporting more errors
923   auto restorer{GetContextualMessages().DiscardMessages()};
924   AnalyzeSectionSubscripts(ae.subscripts);
925   return std::nullopt;
926 }
927 
928 // Type parameter inquiries apply to data references, but don't depend
929 // on any trailing (co)subscripts.
930 static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) {
931   return std::visit(
932       common::visitors{
933           [](SymbolRef &&symbol) { return NamedEntity{symbol}; },
934           [](Component &&component) {
935             return NamedEntity{std::move(component)};
936           },
937           [](ArrayRef &&arrayRef) { return std::move(arrayRef.base()); },
938           [](CoarrayRef &&coarrayRef) {
939             return NamedEntity{coarrayRef.GetLastSymbol()};
940           },
941       },
942       std::move(designator.u));
943 }
944 
945 // Components of parent derived types are explicitly represented as such.
946 static std::optional<Component> CreateComponent(
947     DataRef &&base, const Symbol &component, const semantics::Scope &scope) {
948   if (&component.owner() == &scope) {
949     return Component{std::move(base), component};
950   }
951   if (const semantics::Scope * parentScope{scope.GetDerivedTypeParent()}) {
952     if (const Symbol * parentComponent{parentScope->GetSymbol()}) {
953       return CreateComponent(
954           DataRef{Component{std::move(base), *parentComponent}}, component,
955           *parentScope);
956     }
957   }
958   return std::nullopt;
959 }
960 
961 // Derived type component references and type parameter inquiries
962 MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
963   MaybeExpr base{Analyze(sc.base)};
964   if (!base) {
965     return std::nullopt;
966   }
967   Symbol *sym{sc.component.symbol};
968   if (context_.HasError(sym)) {
969     return std::nullopt;
970   }
971   const auto &name{sc.component.source};
972   if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
973     const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())};
974     if (sym->detailsIf<semantics::TypeParamDetails>()) {
975       if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
976         if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
977           if (dyType->category() == TypeCategory::Integer) {
978             return AsMaybeExpr(
979                 common::SearchTypes(TypeParamInquiryVisitor{dyType->kind(),
980                     IgnoreAnySubscripts(std::move(*designator)), *sym}));
981           }
982         }
983         Say(name, "Type parameter is not INTEGER"_err_en_US);
984       } else {
985         Say(name,
986             "A type parameter inquiry must be applied to "
987             "a designator"_err_en_US);
988       }
989     } else if (!dtSpec || !dtSpec->scope()) {
990       CHECK(context_.AnyFatalError() || !foldingContext_.messages().empty());
991       return std::nullopt;
992     } else if (std::optional<DataRef> dataRef{
993                    ExtractDataRef(std::move(*dtExpr))}) {
994       if (auto component{
995               CreateComponent(std::move(*dataRef), *sym, *dtSpec->scope())}) {
996         return Designate(DataRef{std::move(*component)});
997       } else {
998         Say(name, "Component is not in scope of derived TYPE(%s)"_err_en_US,
999             dtSpec->typeSymbol().name());
1000       }
1001     } else {
1002       Say(name,
1003           "Base of component reference must be a data reference"_err_en_US);
1004     }
1005   } else if (auto *details{sym->detailsIf<semantics::MiscDetails>()}) {
1006     // special part-ref: %re, %im, %kind, %len
1007     // Type errors are detected and reported in semantics.
1008     using MiscKind = semantics::MiscDetails::Kind;
1009     MiscKind kind{details->kind()};
1010     if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) {
1011       if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) {
1012         if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*zExpr))}) {
1013           Expr<SomeReal> realExpr{std::visit(
1014               [&](const auto &z) {
1015                 using PartType = typename ResultType<decltype(z)>::Part;
1016                 auto part{kind == MiscKind::ComplexPartRe
1017                         ? ComplexPart::Part::RE
1018                         : ComplexPart::Part::IM};
1019                 return AsCategoryExpr(Designator<PartType>{
1020                     ComplexPart{std::move(*dataRef), part}});
1021               },
1022               zExpr->u)};
1023           return AsGenericExpr(std::move(realExpr));
1024         }
1025       }
1026     } else if (kind == MiscKind::KindParamInquiry ||
1027         kind == MiscKind::LenParamInquiry) {
1028       // Convert x%KIND -> intrinsic KIND(x), x%LEN -> intrinsic LEN(x)
1029       return MakeFunctionRef(
1030           name, ActualArguments{ActualArgument{std::move(*base)}});
1031     } else {
1032       DIE("unexpected MiscDetails::Kind");
1033     }
1034   } else {
1035     Say(name, "derived type required before component reference"_err_en_US);
1036   }
1037   return std::nullopt;
1038 }
1039 
1040 MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
1041   if (auto maybeDataRef{ExtractDataRef(Analyze(x.base))}) {
1042     DataRef *dataRef{&*maybeDataRef};
1043     std::vector<Subscript> subscripts;
1044     SymbolVector reversed;
1045     if (auto *aRef{std::get_if<ArrayRef>(&dataRef->u)}) {
1046       subscripts = std::move(aRef->subscript());
1047       reversed.push_back(aRef->GetLastSymbol());
1048       if (Component * component{aRef->base().UnwrapComponent()}) {
1049         dataRef = &component->base();
1050       } else {
1051         dataRef = nullptr;
1052       }
1053     }
1054     if (dataRef) {
1055       while (auto *component{std::get_if<Component>(&dataRef->u)}) {
1056         reversed.push_back(component->GetLastSymbol());
1057         dataRef = &component->base();
1058       }
1059       if (auto *baseSym{std::get_if<SymbolRef>(&dataRef->u)}) {
1060         reversed.push_back(*baseSym);
1061       } else {
1062         Say("Base of coindexed named object has subscripts or cosubscripts"_err_en_US);
1063       }
1064     }
1065     std::vector<Expr<SubscriptInteger>> cosubscripts;
1066     bool cosubsOk{true};
1067     for (const auto &cosub :
1068         std::get<std::list<parser::Cosubscript>>(x.imageSelector.t)) {
1069       MaybeExpr coex{Analyze(cosub)};
1070       if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(coex)}) {
1071         cosubscripts.push_back(
1072             ConvertToType<SubscriptInteger>(std::move(*intExpr)));
1073       } else {
1074         cosubsOk = false;
1075       }
1076     }
1077     if (cosubsOk && !reversed.empty()) {
1078       int numCosubscripts{static_cast<int>(cosubscripts.size())};
1079       const Symbol &symbol{reversed.front()};
1080       if (numCosubscripts != symbol.Corank()) {
1081         Say("'%s' has corank %d, but coindexed reference has %d cosubscripts"_err_en_US,
1082             symbol.name(), symbol.Corank(), numCosubscripts);
1083       }
1084     }
1085     // TODO: stat=/team=/team_number=
1086     // Reverse the chain of symbols so that the base is first and coarray
1087     // ultimate component is last.
1088     return Designate(
1089         DataRef{CoarrayRef{SymbolVector{reversed.crbegin(), reversed.crend()},
1090             std::move(subscripts), std::move(cosubscripts)}});
1091   }
1092   return std::nullopt;
1093 }
1094 
1095 int ExpressionAnalyzer::IntegerTypeSpecKind(
1096     const parser::IntegerTypeSpec &spec) {
1097   Expr<SubscriptInteger> value{
1098       AnalyzeKindSelector(TypeCategory::Integer, spec.v)};
1099   if (auto kind{ToInt64(value)}) {
1100     return static_cast<int>(*kind);
1101   }
1102   SayAt(spec, "Constant INTEGER kind value required here"_err_en_US);
1103   return GetDefaultKind(TypeCategory::Integer);
1104 }
1105 
1106 // Array constructors
1107 
1108 // Inverts a collection of generic ArrayConstructorValues<SomeType> that
1109 // all happen to have the same actual type T into one ArrayConstructor<T>.
1110 template <typename T>
1111 ArrayConstructorValues<T> MakeSpecific(
1112     ArrayConstructorValues<SomeType> &&from) {
1113   ArrayConstructorValues<T> to;
1114   for (ArrayConstructorValue<SomeType> &x : from) {
1115     std::visit(
1116         common::visitors{
1117             [&](common::CopyableIndirection<Expr<SomeType>> &&expr) {
1118               auto *typed{UnwrapExpr<Expr<T>>(expr.value())};
1119               to.Push(std::move(DEREF(typed)));
1120             },
1121             [&](ImpliedDo<SomeType> &&impliedDo) {
1122               to.Push(ImpliedDo<T>{impliedDo.name(),
1123                   std::move(impliedDo.lower()), std::move(impliedDo.upper()),
1124                   std::move(impliedDo.stride()),
1125                   MakeSpecific<T>(std::move(impliedDo.values()))});
1126             },
1127         },
1128         std::move(x.u));
1129   }
1130   return to;
1131 }
1132 
1133 class ArrayConstructorContext {
1134 public:
1135   ArrayConstructorContext(
1136       ExpressionAnalyzer &c, std::optional<DynamicTypeWithLength> &&t)
1137       : exprAnalyzer_{c}, type_{std::move(t)} {}
1138 
1139   void Add(const parser::AcValue &);
1140   MaybeExpr ToExpr();
1141 
1142   // These interfaces allow *this to be used as a type visitor argument to
1143   // common::SearchTypes() to convert the array constructor to a typed
1144   // expression in ToExpr().
1145   using Result = MaybeExpr;
1146   using Types = AllTypes;
1147   template <typename T> Result Test() {
1148     if (type_ && type_->category() == T::category) {
1149       if constexpr (T::category == TypeCategory::Derived) {
1150         return AsMaybeExpr(ArrayConstructor<T>{
1151             type_->GetDerivedTypeSpec(), MakeSpecific<T>(std::move(values_))});
1152       } else if (type_->kind() == T::kind) {
1153         if constexpr (T::category == TypeCategory::Character) {
1154           if (auto len{type_->LEN()}) {
1155             return AsMaybeExpr(ArrayConstructor<T>{
1156                 *std::move(len), MakeSpecific<T>(std::move(values_))});
1157           }
1158         } else {
1159           return AsMaybeExpr(
1160               ArrayConstructor<T>{MakeSpecific<T>(std::move(values_))});
1161         }
1162       }
1163     }
1164     return std::nullopt;
1165   }
1166 
1167 private:
1168   void Push(MaybeExpr &&);
1169 
1170   template <int KIND, typename A>
1171   std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr(
1172       const A &x) {
1173     if (MaybeExpr y{exprAnalyzer_.Analyze(x)}) {
1174       Expr<SomeInteger> *intExpr{UnwrapExpr<Expr<SomeInteger>>(*y)};
1175       return ConvertToType<Type<TypeCategory::Integer, KIND>>(
1176           std::move(DEREF(intExpr)));
1177     }
1178     return std::nullopt;
1179   }
1180 
1181   // Nested array constructors all reference the same ExpressionAnalyzer,
1182   // which represents the nest of active implied DO loop indices.
1183   ExpressionAnalyzer &exprAnalyzer_;
1184   std::optional<DynamicTypeWithLength> type_;
1185   bool explicitType_{type_.has_value()};
1186   std::optional<std::int64_t> constantLength_;
1187   ArrayConstructorValues<SomeType> values_;
1188 };
1189 
1190 void ArrayConstructorContext::Push(MaybeExpr &&x) {
1191   if (!x) {
1192     return;
1193   }
1194   if (auto dyType{x->GetType()}) {
1195     DynamicTypeWithLength xType{*dyType};
1196     if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) {
1197       CHECK(xType.category() == TypeCategory::Character);
1198       xType.length =
1199           std::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
1200     }
1201     if (!type_) {
1202       // If there is no explicit type-spec in an array constructor, the type
1203       // of the array is the declared type of all of the elements, which must
1204       // be well-defined and all match.
1205       // TODO: Possible language extension: use the most general type of
1206       // the values as the type of a numeric constructed array, convert all
1207       // of the other values to that type.  Alternative: let the first value
1208       // determine the type, and convert the others to that type.
1209       CHECK(!explicitType_);
1210       type_ = std::move(xType);
1211       constantLength_ = ToInt64(type_->length);
1212       values_.Push(std::move(*x));
1213     } else if (!explicitType_) {
1214       if (static_cast<const DynamicType &>(*type_) ==
1215           static_cast<const DynamicType &>(xType)) {
1216         values_.Push(std::move(*x));
1217         if (auto thisLen{ToInt64(xType.LEN())}) {
1218           if (constantLength_) {
1219             if (exprAnalyzer_.context().warnOnNonstandardUsage() &&
1220                 *thisLen != *constantLength_) {
1221               exprAnalyzer_.Say(
1222                   "Character literal in array constructor without explicit "
1223                   "type has different length than earlier element"_en_US);
1224             }
1225             if (*thisLen > *constantLength_) {
1226               // Language extension: use the longest literal to determine the
1227               // length of the array constructor's character elements, not the
1228               // first, when there is no explicit type.
1229               *constantLength_ = *thisLen;
1230               type_->length = xType.LEN();
1231             }
1232           } else {
1233             constantLength_ = *thisLen;
1234             type_->length = xType.LEN();
1235           }
1236         }
1237       } else {
1238         exprAnalyzer_.Say(
1239             "Values in array constructor must have the same declared type "
1240             "when no explicit type appears"_err_en_US);
1241       }
1242     } else {
1243       if (auto cast{ConvertToType(*type_, std::move(*x))}) {
1244         values_.Push(std::move(*cast));
1245       } else {
1246         exprAnalyzer_.Say(
1247             "Value in array constructor could not be converted to the type "
1248             "of the array"_err_en_US);
1249       }
1250     }
1251   }
1252 }
1253 
1254 void ArrayConstructorContext::Add(const parser::AcValue &x) {
1255   using IntType = ResultType<ImpliedDoIndex>;
1256   std::visit(
1257       common::visitors{
1258           [&](const parser::AcValue::Triplet &triplet) {
1259             // Transform l:u(:s) into (_,_=l,u(,s)) with an anonymous index '_'
1260             std::optional<Expr<IntType>> lower{
1261                 GetSpecificIntExpr<IntType::kind>(std::get<0>(triplet.t))};
1262             std::optional<Expr<IntType>> upper{
1263                 GetSpecificIntExpr<IntType::kind>(std::get<1>(triplet.t))};
1264             std::optional<Expr<IntType>> stride{
1265                 GetSpecificIntExpr<IntType::kind>(std::get<2>(triplet.t))};
1266             if (lower && upper) {
1267               if (!stride) {
1268                 stride = Expr<IntType>{1};
1269               }
1270               if (!type_) {
1271                 type_ = DynamicTypeWithLength{IntType::GetType()};
1272               }
1273               auto v{std::move(values_)};
1274               parser::CharBlock anonymous;
1275               Push(Expr<SomeType>{
1276                   Expr<SomeInteger>{Expr<IntType>{ImpliedDoIndex{anonymous}}}});
1277               std::swap(v, values_);
1278               values_.Push(ImpliedDo<SomeType>{anonymous, std::move(*lower),
1279                   std::move(*upper), std::move(*stride), std::move(v)});
1280             }
1281           },
1282           [&](const common::Indirection<parser::Expr> &expr) {
1283             auto restorer{exprAnalyzer_.GetContextualMessages().SetLocation(
1284                 expr.value().source)};
1285             if (MaybeExpr v{exprAnalyzer_.Analyze(expr.value())}) {
1286               Push(std::move(*v));
1287             }
1288           },
1289           [&](const common::Indirection<parser::AcImpliedDo> &impliedDo) {
1290             const auto &control{
1291                 std::get<parser::AcImpliedDoControl>(impliedDo.value().t)};
1292             const auto &bounds{
1293                 std::get<parser::AcImpliedDoControl::Bounds>(control.t)};
1294             exprAnalyzer_.Analyze(bounds.name);
1295             parser::CharBlock name{bounds.name.thing.thing.source};
1296             const Symbol *symbol{bounds.name.thing.thing.symbol};
1297             int kind{IntType::kind};
1298             if (const auto dynamicType{DynamicType::From(symbol)}) {
1299               kind = dynamicType->kind();
1300             }
1301             if (exprAnalyzer_.AddImpliedDo(name, kind)) {
1302               std::optional<Expr<IntType>> lower{
1303                   GetSpecificIntExpr<IntType::kind>(bounds.lower)};
1304               std::optional<Expr<IntType>> upper{
1305                   GetSpecificIntExpr<IntType::kind>(bounds.upper)};
1306               if (lower && upper) {
1307                 std::optional<Expr<IntType>> stride{
1308                     GetSpecificIntExpr<IntType::kind>(bounds.step)};
1309                 auto v{std::move(values_)};
1310                 for (const auto &value :
1311                     std::get<std::list<parser::AcValue>>(impliedDo.value().t)) {
1312                   Add(value);
1313                 }
1314                 if (!stride) {
1315                   stride = Expr<IntType>{1};
1316                 }
1317                 std::swap(v, values_);
1318                 values_.Push(ImpliedDo<SomeType>{name, std::move(*lower),
1319                     std::move(*upper), std::move(*stride), std::move(v)});
1320               }
1321               exprAnalyzer_.RemoveImpliedDo(name);
1322             } else {
1323               exprAnalyzer_.SayAt(name,
1324                   "Implied DO index is active in surrounding implied DO loop "
1325                   "and may not have the same name"_err_en_US);
1326             }
1327           },
1328       },
1329       x.u);
1330 }
1331 
1332 MaybeExpr ArrayConstructorContext::ToExpr() {
1333   return common::SearchTypes(std::move(*this));
1334 }
1335 
1336 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
1337   const parser::AcSpec &acSpec{array.v};
1338   ArrayConstructorContext acContext{*this, AnalyzeTypeSpec(acSpec.type)};
1339   for (const parser::AcValue &value : acSpec.values) {
1340     acContext.Add(value);
1341   }
1342   return acContext.ToExpr();
1343 }
1344 
1345 MaybeExpr ExpressionAnalyzer::Analyze(
1346     const parser::StructureConstructor &structure) {
1347   auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)};
1348   parser::CharBlock typeName{std::get<parser::Name>(parsedType.t).source};
1349   if (!parsedType.derivedTypeSpec) {
1350     return std::nullopt;
1351   }
1352   const auto &spec{*parsedType.derivedTypeSpec};
1353   const Symbol &typeSymbol{spec.typeSymbol()};
1354   if (!spec.scope() || !typeSymbol.has<semantics::DerivedTypeDetails>()) {
1355     return std::nullopt; // error recovery
1356   }
1357   const auto &typeDetails{typeSymbol.get<semantics::DerivedTypeDetails>()};
1358   const Symbol *parentComponent{typeDetails.GetParentComponent(*spec.scope())};
1359 
1360   if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796
1361     AttachDeclaration(Say(typeName,
1362                           "ABSTRACT derived type '%s' may not be used in a "
1363                           "structure constructor"_err_en_US,
1364                           typeName),
1365         typeSymbol);
1366   }
1367 
1368   // This iterator traverses all of the components in the derived type and its
1369   // parents.  The symbols for whole parent components appear after their
1370   // own components and before the components of the types that extend them.
1371   // E.g., TYPE :: A; REAL X; END TYPE
1372   //       TYPE, EXTENDS(A) :: B; REAL Y; END TYPE
1373   // produces the component list X, A, Y.
1374   // The order is important below because a structure constructor can
1375   // initialize X or A by name, but not both.
1376   auto components{semantics::OrderedComponentIterator{spec}};
1377   auto nextAnonymous{components.begin()};
1378 
1379   std::set<parser::CharBlock> unavailable;
1380   bool anyKeyword{false};
1381   StructureConstructor result{spec};
1382   bool checkConflicts{true}; // until we hit one
1383   auto &messages{GetContextualMessages()};
1384 
1385   for (const auto &component :
1386       std::get<std::list<parser::ComponentSpec>>(structure.t)) {
1387     const parser::Expr &expr{
1388         std::get<parser::ComponentDataSource>(component.t).v.value()};
1389     parser::CharBlock source{expr.source};
1390     auto restorer{messages.SetLocation(source)};
1391     const Symbol *symbol{nullptr};
1392     MaybeExpr value{Analyze(expr)};
1393     std::optional<DynamicType> valueType{DynamicType::From(value)};
1394     if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
1395       anyKeyword = true;
1396       source = kw->v.source;
1397       symbol = kw->v.symbol;
1398       if (!symbol) {
1399         auto componentIter{std::find_if(components.begin(), components.end(),
1400             [=](const Symbol &symbol) { return symbol.name() == source; })};
1401         if (componentIter != components.end()) {
1402           symbol = &*componentIter;
1403         }
1404       }
1405       if (!symbol) { // C7101
1406         Say(source,
1407             "Keyword '%s=' does not name a component of derived type '%s'"_err_en_US,
1408             source, typeName);
1409       }
1410     } else {
1411       if (anyKeyword) { // C7100
1412         Say(source,
1413             "Value in structure constructor lacks a component name"_err_en_US);
1414         checkConflicts = false; // stem cascade
1415       }
1416       // Here's a regrettably common extension of the standard: anonymous
1417       // initialization of parent components, e.g., T(PT(1)) rather than
1418       // T(1) or T(PT=PT(1)).
1419       if (nextAnonymous == components.begin() && parentComponent &&
1420           valueType == DynamicType::From(*parentComponent) &&
1421           context().IsEnabled(LanguageFeature::AnonymousParents)) {
1422         auto iter{
1423             std::find(components.begin(), components.end(), *parentComponent)};
1424         if (iter != components.end()) {
1425           symbol = parentComponent;
1426           nextAnonymous = ++iter;
1427           if (context().ShouldWarn(LanguageFeature::AnonymousParents)) {
1428             Say(source,
1429                 "Whole parent component '%s' in structure "
1430                 "constructor should not be anonymous"_en_US,
1431                 symbol->name());
1432           }
1433         }
1434       }
1435       while (!symbol && nextAnonymous != components.end()) {
1436         const Symbol &next{*nextAnonymous};
1437         ++nextAnonymous;
1438         if (!next.test(Symbol::Flag::ParentComp)) {
1439           symbol = &next;
1440         }
1441       }
1442       if (!symbol) {
1443         Say(source, "Unexpected value in structure constructor"_err_en_US);
1444       }
1445     }
1446     if (symbol) {
1447       if (const auto *currScope{context_.globalScope().FindScope(source)}) {
1448         if (auto msg{CheckAccessibleComponent(*currScope, *symbol)}) {
1449           Say(source, *msg);
1450         }
1451       }
1452       if (checkConflicts) {
1453         auto componentIter{
1454             std::find(components.begin(), components.end(), *symbol)};
1455         if (unavailable.find(symbol->name()) != unavailable.cend()) {
1456           // C797, C798
1457           Say(source,
1458               "Component '%s' conflicts with another component earlier in "
1459               "this structure constructor"_err_en_US,
1460               symbol->name());
1461         } else if (symbol->test(Symbol::Flag::ParentComp)) {
1462           // Make earlier components unavailable once a whole parent appears.
1463           for (auto it{components.begin()}; it != componentIter; ++it) {
1464             unavailable.insert(it->name());
1465           }
1466         } else {
1467           // Make whole parent components unavailable after any of their
1468           // constituents appear.
1469           for (auto it{componentIter}; it != components.end(); ++it) {
1470             if (it->test(Symbol::Flag::ParentComp)) {
1471               unavailable.insert(it->name());
1472             }
1473           }
1474         }
1475       }
1476       unavailable.insert(symbol->name());
1477       if (value) {
1478         if (symbol->has<semantics::ProcEntityDetails>()) {
1479           CHECK(IsPointer(*symbol));
1480         } else if (symbol->has<semantics::ObjectEntityDetails>()) {
1481           // C1594(4)
1482           const auto &innermost{context_.FindScope(expr.source)};
1483           if (const auto *pureProc{FindPureProcedureContaining(innermost)}) {
1484             if (const Symbol * pointer{FindPointerComponent(*symbol)}) {
1485               if (const Symbol *
1486                   object{FindExternallyVisibleObject(*value, *pureProc)}) {
1487                 if (auto *msg{Say(expr.source,
1488                         "Externally visible object '%s' may not be "
1489                         "associated with pointer component '%s' in a "
1490                         "pure procedure"_err_en_US,
1491                         object->name(), pointer->name())}) {
1492                   msg->Attach(object->name(), "Object declaration"_en_US)
1493                       .Attach(pointer->name(), "Pointer declaration"_en_US);
1494                 }
1495               }
1496             }
1497           }
1498         } else if (symbol->has<semantics::TypeParamDetails>()) {
1499           Say(expr.source,
1500               "Type parameter '%s' may not appear as a component "
1501               "of a structure constructor"_err_en_US,
1502               symbol->name());
1503           continue;
1504         } else {
1505           Say(expr.source,
1506               "Component '%s' is neither a procedure pointer "
1507               "nor a data object"_err_en_US,
1508               symbol->name());
1509           continue;
1510         }
1511         if (IsPointer(*symbol)) {
1512           semantics::CheckPointerAssignment(
1513               GetFoldingContext(), *symbol, *value); // C7104, C7105
1514           result.Add(*symbol, Fold(std::move(*value)));
1515         } else if (MaybeExpr converted{
1516                        ConvertToType(*symbol, std::move(*value))}) {
1517           if (auto componentShape{GetShape(GetFoldingContext(), *symbol)}) {
1518             if (auto valueShape{GetShape(GetFoldingContext(), *converted)}) {
1519               if (GetRank(*componentShape) == 0 && GetRank(*valueShape) > 0) {
1520                 AttachDeclaration(
1521                     Say(expr.source,
1522                         "Rank-%d array value is not compatible with scalar component '%s'"_err_en_US,
1523                         symbol->name()),
1524                     *symbol);
1525               } else if (CheckConformance(messages, *componentShape,
1526                              *valueShape, "component", "value")) {
1527                 if (GetRank(*componentShape) > 0 && GetRank(*valueShape) == 0 &&
1528                     !IsExpandableScalar(*converted)) {
1529                   AttachDeclaration(
1530                       Say(expr.source,
1531                           "Scalar value cannot be expanded to shape of array component '%s'"_err_en_US,
1532                           symbol->name()),
1533                       *symbol);
1534                 } else {
1535                   result.Add(*symbol, std::move(*converted));
1536                 }
1537               }
1538             } else {
1539               Say(expr.source, "Shape of value cannot be determined"_err_en_US);
1540             }
1541           } else {
1542             AttachDeclaration(
1543                 Say(expr.source,
1544                     "Shape of component '%s' cannot be determined"_err_en_US,
1545                     symbol->name()),
1546                 *symbol);
1547           }
1548         } else if (IsAllocatable(*symbol) &&
1549             std::holds_alternative<NullPointer>(value->u)) {
1550           // NULL() with no arguments allowed by 7.5.10 para 6 for ALLOCATABLE
1551         } else if (auto symType{DynamicType::From(symbol)}) {
1552           if (valueType) {
1553             AttachDeclaration(
1554                 Say(expr.source,
1555                     "Value in structure constructor of type %s is "
1556                     "incompatible with component '%s' of type %s"_err_en_US,
1557                     valueType->AsFortran(), symbol->name(),
1558                     symType->AsFortran()),
1559                 *symbol);
1560           } else {
1561             AttachDeclaration(
1562                 Say(expr.source,
1563                     "Value in structure constructor is incompatible with "
1564                     " component '%s' of type %s"_err_en_US,
1565                     symbol->name(), symType->AsFortran()),
1566                 *symbol);
1567           }
1568         }
1569       }
1570     }
1571   }
1572 
1573   // Ensure that unmentioned component objects have default initializers.
1574   for (const Symbol &symbol : components) {
1575     if (!symbol.test(Symbol::Flag::ParentComp) &&
1576         unavailable.find(symbol.name()) == unavailable.cend() &&
1577         !IsAllocatable(symbol)) {
1578       if (const auto *details{
1579               symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
1580         if (details->init()) {
1581           result.Add(symbol, common::Clone(*details->init()));
1582         } else { // C799
1583           AttachDeclaration(Say(typeName,
1584                                 "Structure constructor lacks a value for "
1585                                 "component '%s'"_err_en_US,
1586                                 symbol.name()),
1587               symbol);
1588         }
1589       }
1590     }
1591   }
1592 
1593   return AsMaybeExpr(Expr<SomeDerived>{std::move(result)});
1594 }
1595 
1596 static std::optional<parser::CharBlock> GetPassName(
1597     const semantics::Symbol &proc) {
1598   return std::visit(
1599       [](const auto &details) {
1600         if constexpr (std::is_base_of_v<semantics::WithPassArg,
1601                           std::decay_t<decltype(details)>>) {
1602           return details.passName();
1603         } else {
1604           return std::optional<parser::CharBlock>{};
1605         }
1606       },
1607       proc.details());
1608 }
1609 
1610 static int GetPassIndex(const Symbol &proc) {
1611   CHECK(!proc.attrs().test(semantics::Attr::NOPASS));
1612   std::optional<parser::CharBlock> passName{GetPassName(proc)};
1613   const auto *interface{semantics::FindInterface(proc)};
1614   if (!passName || !interface) {
1615     return 0; // first argument is passed-object
1616   }
1617   const auto &subp{interface->get<semantics::SubprogramDetails>()};
1618   int index{0};
1619   for (const auto *arg : subp.dummyArgs()) {
1620     if (arg && arg->name() == passName) {
1621       return index;
1622     }
1623     ++index;
1624   }
1625   DIE("PASS argument name not in dummy argument list");
1626 }
1627 
1628 // Injects an expression into an actual argument list as the "passed object"
1629 // for a type-bound procedure reference that is not NOPASS.  Adds an
1630 // argument keyword if possible, but not when the passed object goes
1631 // before a positional argument.
1632 // e.g., obj%tbp(x) -> tbp(obj,x).
1633 static void AddPassArg(ActualArguments &actuals, const Expr<SomeDerived> &expr,
1634     const Symbol &component, bool isPassedObject = true) {
1635   if (component.attrs().test(semantics::Attr::NOPASS)) {
1636     return;
1637   }
1638   int passIndex{GetPassIndex(component)};
1639   auto iter{actuals.begin()};
1640   int at{0};
1641   while (iter < actuals.end() && at < passIndex) {
1642     if (*iter && (*iter)->keyword()) {
1643       iter = actuals.end();
1644       break;
1645     }
1646     ++iter;
1647     ++at;
1648   }
1649   ActualArgument passed{AsGenericExpr(common::Clone(expr))};
1650   passed.set_isPassedObject(isPassedObject);
1651   if (iter == actuals.end()) {
1652     if (auto passName{GetPassName(component)}) {
1653       passed.set_keyword(*passName);
1654     }
1655   }
1656   actuals.emplace(iter, std::move(passed));
1657 }
1658 
1659 // Return the compile-time resolution of a procedure binding, if possible.
1660 static const Symbol *GetBindingResolution(
1661     const std::optional<DynamicType> &baseType, const Symbol &component) {
1662   const auto *binding{component.detailsIf<semantics::ProcBindingDetails>()};
1663   if (!binding) {
1664     return nullptr;
1665   }
1666   if (!component.attrs().test(semantics::Attr::NON_OVERRIDABLE) &&
1667       (!baseType || baseType->IsPolymorphic())) {
1668     return nullptr;
1669   }
1670   return &binding->symbol();
1671 }
1672 
1673 auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
1674     const parser::ProcComponentRef &pcr, ActualArguments &&arguments)
1675     -> std::optional<CalleeAndArguments> {
1676   const parser::StructureComponent &sc{pcr.v.thing};
1677   const auto &name{sc.component.source};
1678   if (MaybeExpr base{Analyze(sc.base)}) {
1679     if (const Symbol * sym{sc.component.symbol}) {
1680       if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
1681         if (sym->has<semantics::GenericDetails>()) {
1682           AdjustActuals adjustment{
1683               [&](const Symbol &proc, ActualArguments &actuals) {
1684                 if (!proc.attrs().test(semantics::Attr::NOPASS)) {
1685                   AddPassArg(actuals, std::move(*dtExpr), proc);
1686                 }
1687                 return true;
1688               }};
1689           sym = ResolveGeneric(*sym, arguments, adjustment);
1690           if (!sym) {
1691             EmitGenericResolutionError(*sc.component.symbol);
1692             return std::nullopt;
1693           }
1694         }
1695         if (const Symbol *
1696             resolution{GetBindingResolution(dtExpr->GetType(), *sym)}) {
1697           AddPassArg(arguments, std::move(*dtExpr), *sym, false);
1698           return CalleeAndArguments{
1699               ProcedureDesignator{*resolution}, std::move(arguments)};
1700         } else if (std::optional<DataRef> dataRef{
1701                        ExtractDataRef(std::move(*dtExpr))}) {
1702           if (sym->attrs().test(semantics::Attr::NOPASS)) {
1703             return CalleeAndArguments{
1704                 ProcedureDesignator{Component{std::move(*dataRef), *sym}},
1705                 std::move(arguments)};
1706           } else {
1707             AddPassArg(arguments,
1708                 Expr<SomeDerived>{Designator<SomeDerived>{std::move(*dataRef)}},
1709                 *sym);
1710             return CalleeAndArguments{
1711                 ProcedureDesignator{*sym}, std::move(arguments)};
1712           }
1713         }
1714       }
1715       Say(name,
1716           "Base of procedure component reference is not a derived-type object"_err_en_US);
1717     }
1718   }
1719   CHECK(!GetContextualMessages().empty());
1720   return std::nullopt;
1721 }
1722 
1723 // Can actual be argument associated with dummy?
1724 static bool CheckCompatibleArgument(bool isElemental,
1725     const ActualArgument &actual, const characteristics::DummyArgument &dummy) {
1726   return std::visit(
1727       common::visitors{
1728           [&](const characteristics::DummyDataObject &x) {
1729             characteristics::TypeAndShape dummyTypeAndShape{x.type};
1730             if (!isElemental && actual.Rank() != dummyTypeAndShape.Rank()) {
1731               return false;
1732             } else if (auto actualType{actual.GetType()}) {
1733               return dummyTypeAndShape.type().IsTkCompatibleWith(*actualType);
1734             } else {
1735               return false;
1736             }
1737           },
1738           [&](const characteristics::DummyProcedure &) {
1739             const auto *expr{actual.UnwrapExpr()};
1740             return expr && IsProcedurePointer(*expr);
1741           },
1742           [&](const characteristics::AlternateReturn &) {
1743             return actual.isAlternateReturn();
1744           },
1745       },
1746       dummy.u);
1747 }
1748 
1749 // Are the actual arguments compatible with the dummy arguments of procedure?
1750 static bool CheckCompatibleArguments(
1751     const characteristics::Procedure &procedure,
1752     const ActualArguments &actuals) {
1753   bool isElemental{procedure.IsElemental()};
1754   const auto &dummies{procedure.dummyArguments};
1755   CHECK(dummies.size() == actuals.size());
1756   for (std::size_t i{0}; i < dummies.size(); ++i) {
1757     const characteristics::DummyArgument &dummy{dummies[i]};
1758     const std::optional<ActualArgument> &actual{actuals[i]};
1759     if (actual && !CheckCompatibleArgument(isElemental, *actual, dummy)) {
1760       return false;
1761     }
1762   }
1763   return true;
1764 }
1765 
1766 // Handles a forward reference to a module function from what must
1767 // be a specification expression.  Return false if the symbol is
1768 // an invalid forward reference.
1769 bool ExpressionAnalyzer::ResolveForward(const Symbol &symbol) {
1770   if (context_.HasError(symbol)) {
1771     return false;
1772   }
1773   if (const auto *details{
1774           symbol.detailsIf<semantics::SubprogramNameDetails>()}) {
1775     if (details->kind() == semantics::SubprogramKind::Module) {
1776       // If this symbol is still a SubprogramNameDetails, we must be
1777       // checking a specification expression in a sibling module
1778       // procedure.  Resolve its names now so that its interface
1779       // is known.
1780       semantics::ResolveSpecificationParts(context_, symbol);
1781       if (symbol.has<semantics::SubprogramNameDetails>()) {
1782         // When the symbol hasn't had its details updated, we must have
1783         // already been in the process of resolving the function's
1784         // specification part; but recursive function calls are not
1785         // allowed in specification parts (10.1.11 para 5).
1786         Say("The module function '%s' may not be referenced recursively in a specification expression"_err_en_US,
1787             symbol.name());
1788         context_.SetError(const_cast<Symbol &>(symbol));
1789         return false;
1790       }
1791     } else { // 10.1.11 para 4
1792       Say("The internal function '%s' may not be referenced in a specification expression"_err_en_US,
1793           symbol.name());
1794       context_.SetError(const_cast<Symbol &>(symbol));
1795       return false;
1796     }
1797   }
1798   return true;
1799 }
1800 
1801 // Resolve a call to a generic procedure with given actual arguments.
1802 // adjustActuals is called on procedure bindings to handle pass arg.
1803 const Symbol *ExpressionAnalyzer::ResolveGeneric(const Symbol &symbol,
1804     const ActualArguments &actuals, const AdjustActuals &adjustActuals,
1805     bool mightBeStructureConstructor) {
1806   const Symbol *elemental{nullptr}; // matching elemental specific proc
1807   const auto &details{symbol.GetUltimate().get<semantics::GenericDetails>()};
1808   for (const Symbol &specific : details.specificProcs()) {
1809     if (!ResolveForward(specific)) {
1810       continue;
1811     }
1812     if (std::optional<characteristics::Procedure> procedure{
1813             characteristics::Procedure::Characterize(
1814                 ProcedureDesignator{specific}, context_.intrinsics())}) {
1815       ActualArguments localActuals{actuals};
1816       if (specific.has<semantics::ProcBindingDetails>()) {
1817         if (!adjustActuals.value()(specific, localActuals)) {
1818           continue;
1819         }
1820       }
1821       if (semantics::CheckInterfaceForGeneric(
1822               *procedure, localActuals, GetFoldingContext())) {
1823         if (CheckCompatibleArguments(*procedure, localActuals)) {
1824           if (!procedure->IsElemental()) {
1825             return &specific; // takes priority over elemental match
1826           }
1827           elemental = &specific;
1828         }
1829       }
1830     }
1831   }
1832   if (elemental) {
1833     return elemental;
1834   }
1835   // Check parent derived type
1836   if (const auto *parentScope{symbol.owner().GetDerivedTypeParent()}) {
1837     if (const Symbol * extended{parentScope->FindComponent(symbol.name())}) {
1838       if (extended->GetUltimate().has<semantics::GenericDetails>()) {
1839         if (const Symbol *
1840             result{ResolveGeneric(*extended, actuals, adjustActuals, false)}) {
1841           return result;
1842         }
1843       }
1844     }
1845   }
1846   if (mightBeStructureConstructor && details.derivedType()) {
1847     return details.derivedType();
1848   }
1849   return nullptr;
1850 }
1851 
1852 void ExpressionAnalyzer::EmitGenericResolutionError(const Symbol &symbol) {
1853   if (semantics::IsGenericDefinedOp(symbol)) {
1854     Say("No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US,
1855         symbol.name());
1856   } else {
1857     Say("No specific procedure of generic '%s' matches the actual arguments"_err_en_US,
1858         symbol.name());
1859   }
1860 }
1861 
1862 auto ExpressionAnalyzer::GetCalleeAndArguments(
1863     const parser::ProcedureDesignator &pd, ActualArguments &&arguments,
1864     bool isSubroutine, bool mightBeStructureConstructor)
1865     -> std::optional<CalleeAndArguments> {
1866   return std::visit(
1867       common::visitors{
1868           [&](const parser::Name &name) {
1869             return GetCalleeAndArguments(name, std::move(arguments),
1870                 isSubroutine, mightBeStructureConstructor);
1871           },
1872           [&](const parser::ProcComponentRef &pcr) {
1873             return AnalyzeProcedureComponentRef(pcr, std::move(arguments));
1874           },
1875       },
1876       pd.u);
1877 }
1878 
1879 auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name,
1880     ActualArguments &&arguments, bool isSubroutine,
1881     bool mightBeStructureConstructor) -> std::optional<CalleeAndArguments> {
1882   const Symbol *symbol{name.symbol};
1883   if (context_.HasError(symbol)) {
1884     return std::nullopt; // also handles null symbol
1885   }
1886   const Symbol &ultimate{DEREF(symbol).GetUltimate()};
1887   if (ultimate.attrs().test(semantics::Attr::INTRINSIC)) {
1888     if (std::optional<SpecificCall> specificCall{context_.intrinsics().Probe(
1889             CallCharacteristics{ultimate.name().ToString(), isSubroutine},
1890             arguments, GetFoldingContext())}) {
1891       return CalleeAndArguments{
1892           ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
1893           std::move(specificCall->arguments)};
1894     }
1895   } else {
1896     CheckForBadRecursion(name.source, ultimate);
1897     if (ultimate.has<semantics::GenericDetails>()) {
1898       ExpressionAnalyzer::AdjustActuals noAdjustment;
1899       symbol = ResolveGeneric(
1900           *symbol, arguments, noAdjustment, mightBeStructureConstructor);
1901     }
1902     if (symbol) {
1903       if (symbol->GetUltimate().has<semantics::DerivedTypeDetails>()) {
1904         if (mightBeStructureConstructor) {
1905           return CalleeAndArguments{
1906               semantics::SymbolRef{*symbol}, std::move(arguments)};
1907         }
1908       } else {
1909         return CalleeAndArguments{
1910             ProcedureDesignator{*symbol}, std::move(arguments)};
1911       }
1912     } else if (std::optional<SpecificCall> specificCall{
1913                    context_.intrinsics().Probe(
1914                        CallCharacteristics{
1915                            ultimate.name().ToString(), isSubroutine},
1916                        arguments, GetFoldingContext())}) {
1917       // Generics can extend intrinsics
1918       return CalleeAndArguments{
1919           ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
1920           std::move(specificCall->arguments)};
1921     } else {
1922       EmitGenericResolutionError(*name.symbol);
1923     }
1924   }
1925   return std::nullopt;
1926 }
1927 
1928 void ExpressionAnalyzer::CheckForBadRecursion(
1929     parser::CharBlock callSite, const semantics::Symbol &proc) {
1930   if (const auto *scope{proc.scope()}) {
1931     if (scope->sourceRange().Contains(callSite)) {
1932       parser::Message *msg{nullptr};
1933       if (proc.attrs().test(semantics::Attr::NON_RECURSIVE)) { // 15.6.2.1(3)
1934         msg = Say("NON_RECURSIVE procedure '%s' cannot call itself"_err_en_US,
1935             callSite);
1936       } else if (IsAssumedLengthCharacter(proc) && IsExternal(proc)) {
1937         msg = Say( // 15.6.2.1(3)
1938             "Assumed-length CHARACTER(*) function '%s' cannot call itself"_err_en_US,
1939             callSite);
1940       }
1941       AttachDeclaration(msg, proc);
1942     }
1943   }
1944 }
1945 
1946 template <typename A> static const Symbol *AssumedTypeDummy(const A &x) {
1947   if (const auto *designator{
1948           std::get_if<common::Indirection<parser::Designator>>(&x.u)}) {
1949     if (const auto *dataRef{
1950             std::get_if<parser::DataRef>(&designator->value().u)}) {
1951       if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) {
1952         if (const Symbol * symbol{name->symbol}) {
1953           if (const auto *type{symbol->GetType()}) {
1954             if (type->category() == semantics::DeclTypeSpec::TypeStar) {
1955               return symbol;
1956             }
1957           }
1958         }
1959       }
1960     }
1961   }
1962   return nullptr;
1963 }
1964 
1965 MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef,
1966     std::optional<parser::StructureConstructor> *structureConstructor) {
1967   const parser::Call &call{funcRef.v};
1968   auto restorer{GetContextualMessages().SetLocation(call.source)};
1969   ArgumentAnalyzer analyzer{*this, call.source, true /* allowAssumedType */};
1970   for (const auto &arg : std::get<std::list<parser::ActualArgSpec>>(call.t)) {
1971     analyzer.Analyze(arg, false /* not subroutine call */);
1972   }
1973   if (analyzer.fatalErrors()) {
1974     return std::nullopt;
1975   }
1976   if (std::optional<CalleeAndArguments> callee{
1977           GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t),
1978               analyzer.GetActuals(), false /* not subroutine */,
1979               true /* might be structure constructor */)}) {
1980     if (auto *proc{std::get_if<ProcedureDesignator>(&callee->u)}) {
1981       return MakeFunctionRef(
1982           call.source, std::move(*proc), std::move(callee->arguments));
1983     } else if (structureConstructor) {
1984       // Structure constructor misparsed as function reference?
1985       CHECK(std::holds_alternative<semantics::SymbolRef>(callee->u));
1986       const Symbol &derivedType{*std::get<semantics::SymbolRef>(callee->u)};
1987       const auto &designator{std::get<parser::ProcedureDesignator>(call.t)};
1988       if (const auto *name{std::get_if<parser::Name>(&designator.u)}) {
1989         semantics::Scope &scope{context_.FindScope(name->source)};
1990         const semantics::DeclTypeSpec &type{
1991             semantics::FindOrInstantiateDerivedType(scope,
1992                 semantics::DerivedTypeSpec{
1993                     name->source, derivedType.GetUltimate()},
1994                 context_)};
1995         auto &mutableRef{const_cast<parser::FunctionReference &>(funcRef)};
1996         *structureConstructor =
1997             mutableRef.ConvertToStructureConstructor(type.derivedTypeSpec());
1998         return Analyze(structureConstructor->value());
1999       }
2000     }
2001   }
2002   return std::nullopt;
2003 }
2004 
2005 void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
2006   const parser::Call &call{callStmt.v};
2007   auto restorer{GetContextualMessages().SetLocation(call.source)};
2008   ArgumentAnalyzer analyzer{*this, call.source, true /* allowAssumedType */};
2009   for (const auto &arg : std::get<std::list<parser::ActualArgSpec>>(call.t)) {
2010     analyzer.Analyze(arg, true /* is subroutine call */);
2011   }
2012   if (!analyzer.fatalErrors()) {
2013     if (std::optional<CalleeAndArguments> callee{
2014             GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t),
2015                 analyzer.GetActuals(), true /* subroutine */)}) {
2016       ProcedureDesignator *proc{std::get_if<ProcedureDesignator>(&callee->u)};
2017       CHECK(proc);
2018       if (CheckCall(call.source, *proc, callee->arguments)) {
2019         callStmt.typedCall.reset(
2020             new ProcedureRef{std::move(*proc), std::move(callee->arguments)});
2021       }
2022     }
2023   }
2024 }
2025 
2026 const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) {
2027   if (!x.typedAssignment) {
2028     ArgumentAnalyzer analyzer{*this};
2029     analyzer.Analyze(std::get<parser::Variable>(x.t));
2030     analyzer.Analyze(std::get<parser::Expr>(x.t));
2031     if (analyzer.fatalErrors()) {
2032       x.typedAssignment.reset(new GenericAssignmentWrapper{});
2033     } else {
2034       std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()};
2035       Assignment assignment{
2036           Fold(analyzer.MoveExpr(0)), Fold(analyzer.MoveExpr(1))};
2037       if (procRef) {
2038         assignment.u = std::move(*procRef);
2039       }
2040       x.typedAssignment.reset(
2041           new GenericAssignmentWrapper{std::move(assignment)});
2042     }
2043   }
2044   return common::GetPtrFromOptional(x.typedAssignment->v);
2045 }
2046 
2047 const Assignment *ExpressionAnalyzer::Analyze(
2048     const parser::PointerAssignmentStmt &x) {
2049   if (!x.typedAssignment) {
2050     MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))};
2051     MaybeExpr rhs{Analyze(std::get<parser::Expr>(x.t))};
2052     if (!lhs || !rhs) {
2053       x.typedAssignment.reset(new GenericAssignmentWrapper{});
2054     } else {
2055       Assignment assignment{std::move(*lhs), std::move(*rhs)};
2056       std::visit(common::visitors{
2057                      [&](const std::list<parser::BoundsRemapping> &list) {
2058                        Assignment::BoundsRemapping bounds;
2059                        for (const auto &elem : list) {
2060                          auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
2061                          auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
2062                          if (lower && upper) {
2063                            bounds.emplace_back(Fold(std::move(*lower)),
2064                                Fold(std::move(*upper)));
2065                          }
2066                        }
2067                        assignment.u = std::move(bounds);
2068                      },
2069                      [&](const std::list<parser::BoundsSpec> &list) {
2070                        Assignment::BoundsSpec bounds;
2071                        for (const auto &bound : list) {
2072                          if (auto lower{AsSubscript(Analyze(bound.v))}) {
2073                            bounds.emplace_back(Fold(std::move(*lower)));
2074                          }
2075                        }
2076                        assignment.u = std::move(bounds);
2077                      },
2078                  },
2079           std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
2080       x.typedAssignment.reset(
2081           new GenericAssignmentWrapper{std::move(assignment)});
2082     }
2083   }
2084   return common::GetPtrFromOptional(x.typedAssignment->v);
2085 }
2086 
2087 static bool IsExternalCalledImplicitly(
2088     parser::CharBlock callSite, const ProcedureDesignator &proc) {
2089   if (const auto *symbol{proc.GetSymbol()}) {
2090     return symbol->has<semantics::SubprogramDetails>() &&
2091         symbol->owner().IsGlobal() &&
2092         (!symbol->scope() /*ENTRY*/ ||
2093             !symbol->scope()->sourceRange().Contains(callSite));
2094   } else {
2095     return false;
2096   }
2097 }
2098 
2099 std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
2100     parser::CharBlock callSite, const ProcedureDesignator &proc,
2101     ActualArguments &arguments) {
2102   auto chars{
2103       characteristics::Procedure::Characterize(proc, context_.intrinsics())};
2104   if (chars) {
2105     bool treatExternalAsImplicit{IsExternalCalledImplicitly(callSite, proc)};
2106     if (treatExternalAsImplicit && !chars->CanBeCalledViaImplicitInterface()) {
2107       Say(callSite,
2108           "References to the procedure '%s' require an explicit interface"_en_US,
2109           DEREF(proc.GetSymbol()).name());
2110     }
2111     semantics::CheckArguments(*chars, arguments, GetFoldingContext(),
2112         context_.FindScope(callSite), treatExternalAsImplicit);
2113     const Symbol *procSymbol{proc.GetSymbol()};
2114     if (procSymbol && !IsPureProcedure(*procSymbol)) {
2115       if (const semantics::Scope *
2116           pure{semantics::FindPureProcedureContaining(
2117               context_.FindScope(callSite))}) {
2118         Say(callSite,
2119             "Procedure '%s' referenced in pure subprogram '%s' must be pure too"_err_en_US,
2120             procSymbol->name(), DEREF(pure->symbol()).name());
2121       }
2122     }
2123   }
2124   return chars;
2125 }
2126 
2127 // Unary operations
2128 
2129 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Parentheses &x) {
2130   if (MaybeExpr operand{Analyze(x.v.value())}) {
2131     if (const semantics::Symbol * symbol{GetLastSymbol(*operand)}) {
2132       if (const semantics::Symbol * result{FindFunctionResult(*symbol)}) {
2133         if (semantics::IsProcedurePointer(*result)) {
2134           Say("A function reference that returns a procedure "
2135               "pointer may not be parenthesized"_err_en_US); // C1003
2136         }
2137       }
2138     }
2139     return Parenthesize(std::move(*operand));
2140   }
2141   return std::nullopt;
2142 }
2143 
2144 static MaybeExpr NumericUnaryHelper(ExpressionAnalyzer &context,
2145     NumericOperator opr, const parser::Expr::IntrinsicUnary &x) {
2146   ArgumentAnalyzer analyzer{context};
2147   analyzer.Analyze(x.v);
2148   if (analyzer.fatalErrors()) {
2149     return std::nullopt;
2150   } else if (analyzer.IsIntrinsicNumeric(opr)) {
2151     if (opr == NumericOperator::Add) {
2152       return analyzer.MoveExpr(0);
2153     } else {
2154       return Negation(context.GetContextualMessages(), analyzer.MoveExpr(0));
2155     }
2156   } else {
2157     return analyzer.TryDefinedOp(AsFortran(opr),
2158         "Operand of unary %s must be numeric; have %s"_err_en_US);
2159   }
2160 }
2161 
2162 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::UnaryPlus &x) {
2163   return NumericUnaryHelper(*this, NumericOperator::Add, x);
2164 }
2165 
2166 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Negate &x) {
2167   return NumericUnaryHelper(*this, NumericOperator::Subtract, x);
2168 }
2169 
2170 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NOT &x) {
2171   ArgumentAnalyzer analyzer{*this};
2172   analyzer.Analyze(x.v);
2173   if (analyzer.fatalErrors()) {
2174     return std::nullopt;
2175   } else if (analyzer.IsIntrinsicLogical()) {
2176     return AsGenericExpr(
2177         LogicalNegation(std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u)));
2178   } else {
2179     return analyzer.TryDefinedOp(LogicalOperator::Not,
2180         "Operand of %s must be LOGICAL; have %s"_err_en_US);
2181   }
2182 }
2183 
2184 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::PercentLoc &x) {
2185   // Represent %LOC() exactly as if it had been a call to the LOC() extension
2186   // intrinsic function.
2187   // Use the actual source for the name of the call for error reporting.
2188   std::optional<ActualArgument> arg;
2189   if (const Symbol * assumedTypeDummy{AssumedTypeDummy(x.v.value())}) {
2190     arg = ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
2191   } else if (MaybeExpr argExpr{Analyze(x.v.value())}) {
2192     arg = ActualArgument{std::move(*argExpr)};
2193   } else {
2194     return std::nullopt;
2195   }
2196   parser::CharBlock at{GetContextualMessages().at()};
2197   CHECK(at.size() >= 4);
2198   parser::CharBlock loc{at.begin() + 1, 3};
2199   CHECK(loc == "loc");
2200   return MakeFunctionRef(loc, ActualArguments{std::move(*arg)});
2201 }
2202 
2203 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &x) {
2204   const auto &name{std::get<parser::DefinedOpName>(x.t).v};
2205   ArgumentAnalyzer analyzer{*this, name.source};
2206   analyzer.Analyze(std::get<1>(x.t));
2207   return analyzer.TryDefinedOp(name.source.ToString().c_str(),
2208       "No operator %s defined for %s"_err_en_US, true);
2209 }
2210 
2211 // Binary (dyadic) operations
2212 
2213 template <template <typename> class OPR>
2214 MaybeExpr NumericBinaryHelper(ExpressionAnalyzer &context, NumericOperator opr,
2215     const parser::Expr::IntrinsicBinary &x) {
2216   ArgumentAnalyzer analyzer{context};
2217   analyzer.Analyze(std::get<0>(x.t));
2218   analyzer.Analyze(std::get<1>(x.t));
2219   if (analyzer.fatalErrors()) {
2220     return std::nullopt;
2221   } else if (analyzer.IsIntrinsicNumeric(opr)) {
2222     return NumericOperation<OPR>(context.GetContextualMessages(),
2223         analyzer.MoveExpr(0), analyzer.MoveExpr(1),
2224         context.GetDefaultKind(TypeCategory::Real));
2225   } else {
2226     return analyzer.TryDefinedOp(AsFortran(opr),
2227         "Operands of %s must be numeric; have %s and %s"_err_en_US);
2228   }
2229 }
2230 
2231 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Power &x) {
2232   return NumericBinaryHelper<Power>(*this, NumericOperator::Power, x);
2233 }
2234 
2235 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Multiply &x) {
2236   return NumericBinaryHelper<Multiply>(*this, NumericOperator::Multiply, x);
2237 }
2238 
2239 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Divide &x) {
2240   return NumericBinaryHelper<Divide>(*this, NumericOperator::Divide, x);
2241 }
2242 
2243 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Add &x) {
2244   return NumericBinaryHelper<Add>(*this, NumericOperator::Add, x);
2245 }
2246 
2247 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Subtract &x) {
2248   return NumericBinaryHelper<Subtract>(*this, NumericOperator::Subtract, x);
2249 }
2250 
2251 MaybeExpr ExpressionAnalyzer::Analyze(
2252     const parser::Expr::ComplexConstructor &x) {
2253   auto re{Analyze(std::get<0>(x.t).value())};
2254   auto im{Analyze(std::get<1>(x.t).value())};
2255   if (re && im) {
2256     ConformabilityCheck(GetContextualMessages(), *re, *im);
2257   }
2258   return AsMaybeExpr(ConstructComplex(GetContextualMessages(), std::move(re),
2259       std::move(im), GetDefaultKind(TypeCategory::Real)));
2260 }
2261 
2262 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
2263   ArgumentAnalyzer analyzer{*this};
2264   analyzer.Analyze(std::get<0>(x.t));
2265   analyzer.Analyze(std::get<1>(x.t));
2266   if (analyzer.fatalErrors()) {
2267     return std::nullopt;
2268   } else if (analyzer.IsIntrinsicConcat()) {
2269     return std::visit(
2270         [&](auto &&x, auto &&y) -> MaybeExpr {
2271           using T = ResultType<decltype(x)>;
2272           if constexpr (std::is_same_v<T, ResultType<decltype(y)>>) {
2273             return AsGenericExpr(Concat<T::kind>{std::move(x), std::move(y)});
2274           } else {
2275             DIE("different types for intrinsic concat");
2276           }
2277         },
2278         std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(0).u).u),
2279         std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(1).u).u));
2280   } else {
2281     return analyzer.TryDefinedOp("//",
2282         "Operands of %s must be CHARACTER with the same kind; have %s and %s"_err_en_US);
2283   }
2284 }
2285 
2286 // The Name represents a user-defined intrinsic operator.
2287 // If the actuals match one of the specific procedures, return a function ref.
2288 // Otherwise report the error in messages.
2289 MaybeExpr ExpressionAnalyzer::AnalyzeDefinedOp(
2290     const parser::Name &name, ActualArguments &&actuals) {
2291   if (auto callee{GetCalleeAndArguments(name, std::move(actuals))}) {
2292     CHECK(std::holds_alternative<ProcedureDesignator>(callee->u));
2293     return MakeFunctionRef(name.source,
2294         std::move(std::get<ProcedureDesignator>(callee->u)),
2295         std::move(callee->arguments));
2296   } else {
2297     return std::nullopt;
2298   }
2299 }
2300 
2301 MaybeExpr RelationHelper(ExpressionAnalyzer &context, RelationalOperator opr,
2302     const parser::Expr::IntrinsicBinary &x) {
2303   ArgumentAnalyzer analyzer{context};
2304   analyzer.Analyze(std::get<0>(x.t));
2305   analyzer.Analyze(std::get<1>(x.t));
2306   if (analyzer.fatalErrors()) {
2307     return std::nullopt;
2308   } else if (analyzer.IsIntrinsicRelational(opr)) {
2309     return AsMaybeExpr(Relate(context.GetContextualMessages(), opr,
2310         analyzer.MoveExpr(0), analyzer.MoveExpr(1)));
2311   } else {
2312     return analyzer.TryDefinedOp(opr,
2313         "Operands of %s must have comparable types; have %s and %s"_err_en_US);
2314   }
2315 }
2316 
2317 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LT &x) {
2318   return RelationHelper(*this, RelationalOperator::LT, x);
2319 }
2320 
2321 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LE &x) {
2322   return RelationHelper(*this, RelationalOperator::LE, x);
2323 }
2324 
2325 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQ &x) {
2326   return RelationHelper(*this, RelationalOperator::EQ, x);
2327 }
2328 
2329 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NE &x) {
2330   return RelationHelper(*this, RelationalOperator::NE, x);
2331 }
2332 
2333 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GE &x) {
2334   return RelationHelper(*this, RelationalOperator::GE, x);
2335 }
2336 
2337 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GT &x) {
2338   return RelationHelper(*this, RelationalOperator::GT, x);
2339 }
2340 
2341 MaybeExpr LogicalBinaryHelper(ExpressionAnalyzer &context, LogicalOperator opr,
2342     const parser::Expr::IntrinsicBinary &x) {
2343   ArgumentAnalyzer analyzer{context};
2344   analyzer.Analyze(std::get<0>(x.t));
2345   analyzer.Analyze(std::get<1>(x.t));
2346   if (analyzer.fatalErrors()) {
2347     return std::nullopt;
2348   } else if (analyzer.IsIntrinsicLogical()) {
2349     return AsGenericExpr(BinaryLogicalOperation(opr,
2350         std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u),
2351         std::get<Expr<SomeLogical>>(analyzer.MoveExpr(1).u)));
2352   } else {
2353     return analyzer.TryDefinedOp(
2354         opr, "Operands of %s must be LOGICAL; have %s and %s"_err_en_US);
2355   }
2356 }
2357 
2358 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::AND &x) {
2359   return LogicalBinaryHelper(*this, LogicalOperator::And, x);
2360 }
2361 
2362 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::OR &x) {
2363   return LogicalBinaryHelper(*this, LogicalOperator::Or, x);
2364 }
2365 
2366 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQV &x) {
2367   return LogicalBinaryHelper(*this, LogicalOperator::Eqv, x);
2368 }
2369 
2370 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NEQV &x) {
2371   return LogicalBinaryHelper(*this, LogicalOperator::Neqv, x);
2372 }
2373 
2374 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &x) {
2375   const auto &name{std::get<parser::DefinedOpName>(x.t).v};
2376   ArgumentAnalyzer analyzer{*this, name.source};
2377   analyzer.Analyze(std::get<1>(x.t));
2378   analyzer.Analyze(std::get<2>(x.t));
2379   return analyzer.TryDefinedOp(name.source.ToString().c_str(),
2380       "No operator %s defined for %s and %s"_err_en_US, true);
2381 }
2382 
2383 static void CheckFuncRefToArrayElementRefHasSubscripts(
2384     semantics::SemanticsContext &context,
2385     const parser::FunctionReference &funcRef) {
2386   // Emit message if the function reference fix will end up an array element
2387   // reference with no subscripts because it will not be possible to later tell
2388   // the difference in expressions between empty subscript list due to bad
2389   // subscripts error recovery or because the user did not put any.
2390   if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) {
2391     auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
2392     const auto *name{std::get_if<parser::Name>(&proc.u)};
2393     if (!name) {
2394       name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component;
2395     }
2396     auto &msg{context.Say(funcRef.v.source,
2397         name->symbol && name->symbol->Rank() == 0
2398             ? "'%s' is not a function"_err_en_US
2399             : "Reference to array '%s' with empty subscript list"_err_en_US,
2400         name->source)};
2401     if (name->symbol) {
2402       if (semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)) {
2403         msg.Attach(name->source,
2404             "A result variable must be declared with RESULT to allow recursive "
2405             "function calls"_en_US);
2406       } else {
2407         AttachDeclaration(&msg, *name->symbol);
2408       }
2409     }
2410   }
2411 }
2412 
2413 // Converts, if appropriate, an original misparse of ambiguous syntax like
2414 // A(1) as a function reference into an array reference.
2415 // Misparse structure constructors are detected elsewhere after generic
2416 // function call resolution fails.
2417 template <typename... A>
2418 static void FixMisparsedFunctionReference(
2419     semantics::SemanticsContext &context, const std::variant<A...> &constU) {
2420   // The parse tree is updated in situ when resolving an ambiguous parse.
2421   using uType = std::decay_t<decltype(constU)>;
2422   auto &u{const_cast<uType &>(constU)};
2423   if (auto *func{
2424           std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
2425     parser::FunctionReference &funcRef{func->value()};
2426     auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
2427     if (Symbol *
2428         origSymbol{
2429             std::visit(common::visitors{
2430                            [&](parser::Name &name) { return name.symbol; },
2431                            [&](parser::ProcComponentRef &pcr) {
2432                              return pcr.v.thing.component.symbol;
2433                            },
2434                        },
2435                 proc.u)}) {
2436       Symbol &symbol{origSymbol->GetUltimate()};
2437       if (symbol.has<semantics::ObjectEntityDetails>() ||
2438           symbol.has<semantics::AssocEntityDetails>()) {
2439         // Note that expression in AssocEntityDetails cannot be a procedure
2440         // pointer as per C1105 so this cannot be a function reference.
2441         if constexpr (common::HasMember<common::Indirection<parser::Designator>,
2442                           uType>) {
2443           CheckFuncRefToArrayElementRefHasSubscripts(context, funcRef);
2444           u = common::Indirection{funcRef.ConvertToArrayElementRef()};
2445         } else {
2446           DIE("can't fix misparsed function as array reference");
2447         }
2448       }
2449     }
2450   }
2451 }
2452 
2453 // Common handling of parse tree node types that retain the
2454 // representation of the analyzed expression.
2455 template <typename PARSED>
2456 MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) {
2457   if (x.typedExpr) {
2458     return x.typedExpr->v;
2459   }
2460   if constexpr (std::is_same_v<PARSED, parser::Expr> ||
2461       std::is_same_v<PARSED, parser::Variable>) {
2462     FixMisparsedFunctionReference(context_, x.u);
2463   }
2464   if (AssumedTypeDummy(x)) { // C710
2465     Say("TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
2466   } else if (MaybeExpr result{evaluate::Fold(foldingContext_, Analyze(x.u))}) {
2467     SetExpr(x, std::move(*result));
2468     return x.typedExpr->v;
2469   }
2470   ResetExpr(x);
2471   if (!context_.AnyFatalError()) {
2472     std::string buf;
2473     llvm::raw_string_ostream dump{buf};
2474     parser::DumpTree(dump, x);
2475     Say("Internal error: Expression analysis failed on: %s"_err_en_US,
2476         dump.str());
2477   }
2478   fatalErrors_ = true;
2479   return std::nullopt;
2480 }
2481 
2482 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) {
2483   auto restorer{GetContextualMessages().SetLocation(expr.source)};
2484   return ExprOrVariable(expr);
2485 }
2486 
2487 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) {
2488   auto restorer{GetContextualMessages().SetLocation(variable.GetSource())};
2489   return ExprOrVariable(variable);
2490 }
2491 
2492 MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) {
2493   auto restorer{GetContextualMessages().SetLocation(x.source)};
2494   return ExprOrVariable(x);
2495 }
2496 
2497 Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
2498     TypeCategory category,
2499     const std::optional<parser::KindSelector> &selector) {
2500   int defaultKind{GetDefaultKind(category)};
2501   if (!selector) {
2502     return Expr<SubscriptInteger>{defaultKind};
2503   }
2504   return std::visit(
2505       common::visitors{
2506           [&](const parser::ScalarIntConstantExpr &x) {
2507             if (MaybeExpr kind{Analyze(x)}) {
2508               Expr<SomeType> folded{Fold(std::move(*kind))};
2509               if (std::optional<std::int64_t> code{ToInt64(folded)}) {
2510                 if (CheckIntrinsicKind(category, *code)) {
2511                   return Expr<SubscriptInteger>{*code};
2512                 }
2513               } else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(folded)}) {
2514                 return ConvertToType<SubscriptInteger>(std::move(*intExpr));
2515               }
2516             }
2517             return Expr<SubscriptInteger>{defaultKind};
2518           },
2519           [&](const parser::KindSelector::StarSize &x) {
2520             std::intmax_t size = x.v;
2521             if (!CheckIntrinsicSize(category, size)) {
2522               size = defaultKind;
2523             } else if (category == TypeCategory::Complex) {
2524               size /= 2;
2525             }
2526             return Expr<SubscriptInteger>{size};
2527           },
2528       },
2529       selector->u);
2530 }
2531 
2532 int ExpressionAnalyzer::GetDefaultKind(common::TypeCategory category) {
2533   return context_.GetDefaultKind(category);
2534 }
2535 
2536 DynamicType ExpressionAnalyzer::GetDefaultKindOfType(
2537     common::TypeCategory category) {
2538   return {category, GetDefaultKind(category)};
2539 }
2540 
2541 bool ExpressionAnalyzer::CheckIntrinsicKind(
2542     TypeCategory category, std::int64_t kind) {
2543   if (IsValidKindOfIntrinsicType(category, kind)) { // C712, C714, C715, C727
2544     return true;
2545   } else {
2546     Say("%s(KIND=%jd) is not a supported type"_err_en_US,
2547         ToUpperCase(EnumToString(category)), kind);
2548     return false;
2549   }
2550 }
2551 
2552 bool ExpressionAnalyzer::CheckIntrinsicSize(
2553     TypeCategory category, std::int64_t size) {
2554   if (category == TypeCategory::Complex) {
2555     // COMPLEX*16 == COMPLEX(KIND=8)
2556     if (size % 2 == 0 && IsValidKindOfIntrinsicType(category, size / 2)) {
2557       return true;
2558     }
2559   } else if (IsValidKindOfIntrinsicType(category, size)) {
2560     return true;
2561   }
2562   Say("%s*%jd is not a supported type"_err_en_US,
2563       ToUpperCase(EnumToString(category)), size);
2564   return false;
2565 }
2566 
2567 bool ExpressionAnalyzer::AddImpliedDo(parser::CharBlock name, int kind) {
2568   return impliedDos_.insert(std::make_pair(name, kind)).second;
2569 }
2570 
2571 void ExpressionAnalyzer::RemoveImpliedDo(parser::CharBlock name) {
2572   auto iter{impliedDos_.find(name)};
2573   if (iter != impliedDos_.end()) {
2574     impliedDos_.erase(iter);
2575   }
2576 }
2577 
2578 std::optional<int> ExpressionAnalyzer::IsImpliedDo(
2579     parser::CharBlock name) const {
2580   auto iter{impliedDos_.find(name)};
2581   if (iter != impliedDos_.cend()) {
2582     return {iter->second};
2583   } else {
2584     return std::nullopt;
2585   }
2586 }
2587 
2588 bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at,
2589     const MaybeExpr &result, TypeCategory category, bool defaultKind) {
2590   if (result) {
2591     if (auto type{result->GetType()}) {
2592       if (type->category() != category) { // C885
2593         Say(at, "Must have %s type, but is %s"_err_en_US,
2594             ToUpperCase(EnumToString(category)),
2595             ToUpperCase(type->AsFortran()));
2596         return false;
2597       } else if (defaultKind) {
2598         int kind{context_.GetDefaultKind(category)};
2599         if (type->kind() != kind) {
2600           Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US,
2601               kind, ToUpperCase(EnumToString(category)),
2602               ToUpperCase(type->AsFortran()));
2603           return false;
2604         }
2605       }
2606     } else {
2607       Say(at, "Must have %s type, but is typeless"_err_en_US,
2608           ToUpperCase(EnumToString(category)));
2609       return false;
2610     }
2611   }
2612   return true;
2613 }
2614 
2615 MaybeExpr ExpressionAnalyzer::MakeFunctionRef(parser::CharBlock callSite,
2616     ProcedureDesignator &&proc, ActualArguments &&arguments) {
2617   if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&proc.u)}) {
2618     if (intrinsic->name == "null" && arguments.empty()) {
2619       return Expr<SomeType>{NullPointer{}};
2620     }
2621   }
2622   if (const Symbol * symbol{proc.GetSymbol()}) {
2623     if (!ResolveForward(*symbol)) {
2624       return std::nullopt;
2625     }
2626   }
2627   if (auto chars{CheckCall(callSite, proc, arguments)}) {
2628     if (chars->functionResult) {
2629       const auto &result{*chars->functionResult};
2630       if (result.IsProcedurePointer()) {
2631         return Expr<SomeType>{
2632             ProcedureRef{std::move(proc), std::move(arguments)}};
2633       } else {
2634         // Not a procedure pointer, so type and shape are known.
2635         return TypedWrapper<FunctionRef, ProcedureRef>(
2636             DEREF(result.GetTypeAndShape()).type(),
2637             ProcedureRef{std::move(proc), std::move(arguments)});
2638       }
2639     }
2640   }
2641   return std::nullopt;
2642 }
2643 
2644 MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
2645     parser::CharBlock intrinsic, ActualArguments &&arguments) {
2646   if (std::optional<SpecificCall> specificCall{
2647           context_.intrinsics().Probe(CallCharacteristics{intrinsic.ToString()},
2648               arguments, context_.foldingContext())}) {
2649     return MakeFunctionRef(intrinsic,
2650         ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
2651         std::move(specificCall->arguments));
2652   } else {
2653     return std::nullopt;
2654   }
2655 }
2656 
2657 void ArgumentAnalyzer::Analyze(const parser::Variable &x) {
2658   source_.ExtendToCover(x.GetSource());
2659   if (MaybeExpr expr{context_.Analyze(x)}) {
2660     if (!IsConstantExpr(*expr)) {
2661       actuals_.emplace_back(std::move(*expr));
2662       return;
2663     }
2664     const Symbol *symbol{GetFirstSymbol(*expr)};
2665     context_.Say(x.GetSource(),
2666         "Assignment to constant '%s' is not allowed"_err_en_US,
2667         symbol ? symbol->name() : x.GetSource());
2668   }
2669   fatalErrors_ = true;
2670 }
2671 
2672 void ArgumentAnalyzer::Analyze(
2673     const parser::ActualArgSpec &arg, bool isSubroutine) {
2674   // TODO: C1002: Allow a whole assumed-size array to appear if the dummy
2675   // argument would accept it.  Handle by special-casing the context
2676   // ActualArg -> Variable -> Designator.
2677   // TODO: Actual arguments that are procedures and procedure pointers need to
2678   // be detected and represented (they're not expressions).
2679   // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
2680   std::optional<ActualArgument> actual;
2681   std::visit(common::visitors{
2682                  [&](const common::Indirection<parser::Expr> &x) {
2683                    // TODO: Distinguish & handle procedure name and
2684                    // proc-component-ref
2685                    actual = AnalyzeExpr(x.value());
2686                  },
2687                  [&](const parser::AltReturnSpec &) {
2688                    if (!isSubroutine) {
2689                      context_.Say(
2690                          "alternate return specification may not appear on"
2691                          " function reference"_err_en_US);
2692                    }
2693                  },
2694                  [&](const parser::ActualArg::PercentRef &) {
2695                    context_.Say("TODO: %REF() argument"_err_en_US);
2696                  },
2697                  [&](const parser::ActualArg::PercentVal &) {
2698                    context_.Say("TODO: %VAL() argument"_err_en_US);
2699                  },
2700              },
2701       std::get<parser::ActualArg>(arg.t).u);
2702   if (actual) {
2703     if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) {
2704       actual->set_keyword(argKW->v.source);
2705     }
2706     actuals_.emplace_back(std::move(*actual));
2707   } else {
2708     fatalErrors_ = true;
2709   }
2710 }
2711 
2712 bool ArgumentAnalyzer::IsIntrinsicRelational(RelationalOperator opr) const {
2713   CHECK(actuals_.size() == 2);
2714   return semantics::IsIntrinsicRelational(
2715       opr, *GetType(0), GetRank(0), *GetType(1), GetRank(1));
2716 }
2717 
2718 bool ArgumentAnalyzer::IsIntrinsicNumeric(NumericOperator opr) const {
2719   std::optional<DynamicType> type0{GetType(0)};
2720   if (actuals_.size() == 1) {
2721     if (IsBOZLiteral(0)) {
2722       return opr == NumericOperator::Add;
2723     } else {
2724       return type0 && semantics::IsIntrinsicNumeric(*type0);
2725     }
2726   } else {
2727     std::optional<DynamicType> type1{GetType(1)};
2728     if (IsBOZLiteral(0) && type1) {
2729       auto cat1{type1->category()};
2730       return cat1 == TypeCategory::Integer || cat1 == TypeCategory::Real;
2731     } else if (IsBOZLiteral(1) && type0) { // Integer/Real opr BOZ
2732       auto cat0{type0->category()};
2733       return cat0 == TypeCategory::Integer || cat0 == TypeCategory::Real;
2734     } else {
2735       return type0 && type1 &&
2736           semantics::IsIntrinsicNumeric(*type0, GetRank(0), *type1, GetRank(1));
2737     }
2738   }
2739 }
2740 
2741 bool ArgumentAnalyzer::IsIntrinsicLogical() const {
2742   if (actuals_.size() == 1) {
2743     return semantics::IsIntrinsicLogical(*GetType(0));
2744     return GetType(0)->category() == TypeCategory::Logical;
2745   } else {
2746     return semantics::IsIntrinsicLogical(
2747         *GetType(0), GetRank(0), *GetType(1), GetRank(1));
2748   }
2749 }
2750 
2751 bool ArgumentAnalyzer::IsIntrinsicConcat() const {
2752   return semantics::IsIntrinsicConcat(
2753       *GetType(0), GetRank(0), *GetType(1), GetRank(1));
2754 }
2755 
2756 MaybeExpr ArgumentAnalyzer::TryDefinedOp(
2757     const char *opr, parser::MessageFixedText &&error, bool isUserOp) {
2758   if (AnyUntypedOperand()) {
2759     context_.Say(
2760         std::move(error), ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
2761     return std::nullopt;
2762   }
2763   {
2764     auto restorer{context_.GetContextualMessages().DiscardMessages()};
2765     std::string oprNameString{
2766         isUserOp ? std::string{opr} : "operator("s + opr + ')'};
2767     parser::CharBlock oprName{oprNameString};
2768     const auto &scope{context_.context().FindScope(source_)};
2769     if (Symbol * symbol{scope.FindSymbol(oprName)}) {
2770       parser::Name name{symbol->name(), symbol};
2771       if (auto result{context_.AnalyzeDefinedOp(name, GetActuals())}) {
2772         return result;
2773       }
2774       sawDefinedOp_ = symbol;
2775     }
2776     for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) {
2777       if (const Symbol * symbol{FindBoundOp(oprName, passIndex)}) {
2778         if (MaybeExpr result{TryBoundOp(*symbol, passIndex)}) {
2779           return result;
2780         }
2781       }
2782     }
2783   }
2784   if (sawDefinedOp_) {
2785     SayNoMatch(ToUpperCase(sawDefinedOp_->name().ToString()));
2786   } else if (actuals_.size() == 1 || AreConformable()) {
2787     context_.Say(
2788         std::move(error), ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
2789   } else {
2790     context_.Say(
2791         "Operands of %s are not conformable; have rank %d and rank %d"_err_en_US,
2792         ToUpperCase(opr), actuals_[0]->Rank(), actuals_[1]->Rank());
2793   }
2794   return std::nullopt;
2795 }
2796 
2797 MaybeExpr ArgumentAnalyzer::TryDefinedOp(
2798     std::vector<const char *> oprs, parser::MessageFixedText &&error) {
2799   for (std::size_t i{1}; i < oprs.size(); ++i) {
2800     auto restorer{context_.GetContextualMessages().DiscardMessages()};
2801     if (auto result{TryDefinedOp(oprs[i], std::move(error))}) {
2802       return result;
2803     }
2804   }
2805   return TryDefinedOp(oprs[0], std::move(error));
2806 }
2807 
2808 MaybeExpr ArgumentAnalyzer::TryBoundOp(const Symbol &symbol, int passIndex) {
2809   ActualArguments localActuals{actuals_};
2810   const Symbol *proc{GetBindingResolution(GetType(passIndex), symbol)};
2811   if (!proc) {
2812     proc = &symbol;
2813     localActuals.at(passIndex).value().set_isPassedObject();
2814   }
2815   return context_.MakeFunctionRef(
2816       source_, ProcedureDesignator{*proc}, std::move(localActuals));
2817 }
2818 
2819 std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
2820   using semantics::Tristate;
2821   const Expr<SomeType> &lhs{GetExpr(0)};
2822   const Expr<SomeType> &rhs{GetExpr(1)};
2823   std::optional<DynamicType> lhsType{lhs.GetType()};
2824   std::optional<DynamicType> rhsType{rhs.GetType()};
2825   int lhsRank{lhs.Rank()};
2826   int rhsRank{rhs.Rank()};
2827   Tristate isDefined{
2828       semantics::IsDefinedAssignment(lhsType, lhsRank, rhsType, rhsRank)};
2829   if (isDefined == Tristate::No) {
2830     if (lhsType && rhsType) {
2831       AddAssignmentConversion(*lhsType, *rhsType);
2832     }
2833     return std::nullopt; // user-defined assignment not allowed for these args
2834   }
2835   auto restorer{context_.GetContextualMessages().SetLocation(source_)};
2836   if (std::optional<ProcedureRef> procRef{GetDefinedAssignmentProc()}) {
2837     context_.CheckCall(source_, procRef->proc(), procRef->arguments());
2838     return std::move(*procRef);
2839   }
2840   if (isDefined == Tristate::Yes) {
2841     if (!lhsType || !rhsType || (lhsRank != rhsRank && rhsRank != 0) ||
2842         !OkLogicalIntegerAssignment(lhsType->category(), rhsType->category())) {
2843       SayNoMatch("ASSIGNMENT(=)", true);
2844     }
2845   }
2846   return std::nullopt;
2847 }
2848 
2849 bool ArgumentAnalyzer::OkLogicalIntegerAssignment(
2850     TypeCategory lhs, TypeCategory rhs) {
2851   if (!context_.context().languageFeatures().IsEnabled(
2852           common::LanguageFeature::LogicalIntegerAssignment)) {
2853     return false;
2854   }
2855   std::optional<parser::MessageFixedText> msg;
2856   if (lhs == TypeCategory::Integer && rhs == TypeCategory::Logical) {
2857     // allow assignment to LOGICAL from INTEGER as a legacy extension
2858     msg = "nonstandard usage: assignment of LOGICAL to INTEGER"_en_US;
2859   } else if (lhs == TypeCategory::Logical && rhs == TypeCategory::Integer) {
2860     // ... and assignment to LOGICAL from INTEGER
2861     msg = "nonstandard usage: assignment of INTEGER to LOGICAL"_en_US;
2862   } else {
2863     return false;
2864   }
2865   if (context_.context().languageFeatures().ShouldWarn(
2866           common::LanguageFeature::LogicalIntegerAssignment)) {
2867     context_.Say(std::move(*msg));
2868   }
2869   return true;
2870 }
2871 
2872 std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
2873   auto restorer{context_.GetContextualMessages().DiscardMessages()};
2874   std::string oprNameString{"assignment(=)"};
2875   parser::CharBlock oprName{oprNameString};
2876   const Symbol *proc{nullptr};
2877   const auto &scope{context_.context().FindScope(source_)};
2878   if (const Symbol * symbol{scope.FindSymbol(oprName)}) {
2879     ExpressionAnalyzer::AdjustActuals noAdjustment;
2880     if (const Symbol *
2881         specific{context_.ResolveGeneric(*symbol, actuals_, noAdjustment)}) {
2882       proc = specific;
2883     } else {
2884       context_.EmitGenericResolutionError(*symbol);
2885     }
2886   }
2887   for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) {
2888     if (const Symbol * specific{FindBoundOp(oprName, passIndex)}) {
2889       proc = specific;
2890     }
2891   }
2892   if (proc) {
2893     ActualArguments actualsCopy{actuals_};
2894     actualsCopy[1]->Parenthesize();
2895     return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)};
2896   } else {
2897     return std::nullopt;
2898   }
2899 }
2900 
2901 void ArgumentAnalyzer::Dump(llvm::raw_ostream &os) {
2902   os << "source_: " << source_.ToString() << " fatalErrors_ = " << fatalErrors_
2903      << '\n';
2904   for (const auto &actual : actuals_) {
2905     if (!actual.has_value()) {
2906       os << "- error\n";
2907     } else if (const Symbol * symbol{actual->GetAssumedTypeDummy()}) {
2908       os << "- assumed type: " << symbol->name().ToString() << '\n';
2909     } else if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) {
2910       expr->AsFortran(os << "- expr: ") << '\n';
2911     } else {
2912       DIE("bad ActualArgument");
2913     }
2914   }
2915 }
2916 std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr(
2917     const parser::Expr &expr) {
2918   source_.ExtendToCover(expr.source);
2919   if (const Symbol * assumedTypeDummy{AssumedTypeDummy(expr)}) {
2920     expr.typedExpr.reset(new GenericExprWrapper{});
2921     if (allowAssumedType_) {
2922       return ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
2923     } else {
2924       context_.SayAt(expr.source,
2925           "TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
2926       return std::nullopt;
2927     }
2928   } else if (MaybeExpr argExpr{context_.Analyze(expr)}) {
2929     return ActualArgument{context_.Fold(std::move(*argExpr))};
2930   } else {
2931     return std::nullopt;
2932   }
2933 }
2934 
2935 bool ArgumentAnalyzer::AreConformable() const {
2936   CHECK(!fatalErrors_ && actuals_.size() == 2);
2937   return evaluate::AreConformable(*actuals_[0], *actuals_[1]);
2938 }
2939 
2940 // Look for a type-bound operator in the type of arg number passIndex.
2941 const Symbol *ArgumentAnalyzer::FindBoundOp(
2942     parser::CharBlock oprName, int passIndex) {
2943   const auto *type{GetDerivedTypeSpec(GetType(passIndex))};
2944   if (!type || !type->scope()) {
2945     return nullptr;
2946   }
2947   const Symbol *symbol{type->scope()->FindComponent(oprName)};
2948   if (!symbol) {
2949     return nullptr;
2950   }
2951   sawDefinedOp_ = symbol;
2952   ExpressionAnalyzer::AdjustActuals adjustment{
2953       [&](const Symbol &proc, ActualArguments &) {
2954         return passIndex == GetPassIndex(proc);
2955       }};
2956   const Symbol *result{context_.ResolveGeneric(*symbol, actuals_, adjustment)};
2957   if (!result) {
2958     context_.EmitGenericResolutionError(*symbol);
2959   }
2960   return result;
2961 }
2962 
2963 // If there is an implicit conversion between intrinsic types, make it explicit
2964 void ArgumentAnalyzer::AddAssignmentConversion(
2965     const DynamicType &lhsType, const DynamicType &rhsType) {
2966   if (lhsType.category() == rhsType.category() &&
2967       lhsType.kind() == rhsType.kind()) {
2968     // no conversion necessary
2969   } else if (auto rhsExpr{evaluate::ConvertToType(lhsType, MoveExpr(1))}) {
2970     actuals_[1] = ActualArgument{*rhsExpr};
2971   } else {
2972     actuals_[1] = std::nullopt;
2973   }
2974 }
2975 
2976 std::optional<DynamicType> ArgumentAnalyzer::GetType(std::size_t i) const {
2977   return i < actuals_.size() ? actuals_[i].value().GetType() : std::nullopt;
2978 }
2979 int ArgumentAnalyzer::GetRank(std::size_t i) const {
2980   return i < actuals_.size() ? actuals_[i].value().Rank() : 0;
2981 }
2982 
2983 // Report error resolving opr when there is a user-defined one available
2984 void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) {
2985   std::string type0{TypeAsFortran(0)};
2986   auto rank0{actuals_[0]->Rank()};
2987   if (actuals_.size() == 1) {
2988     if (rank0 > 0) {
2989       context_.Say("No intrinsic or user-defined %s matches "
2990                    "rank %d array of %s"_err_en_US,
2991           opr, rank0, type0);
2992     } else {
2993       context_.Say("No intrinsic or user-defined %s matches "
2994                    "operand type %s"_err_en_US,
2995           opr, type0);
2996     }
2997   } else {
2998     std::string type1{TypeAsFortran(1)};
2999     auto rank1{actuals_[1]->Rank()};
3000     if (rank0 > 0 && rank1 > 0 && rank0 != rank1) {
3001       context_.Say("No intrinsic or user-defined %s matches "
3002                    "rank %d array of %s and rank %d array of %s"_err_en_US,
3003           opr, rank0, type0, rank1, type1);
3004     } else if (isAssignment && rank0 != rank1) {
3005       if (rank0 == 0) {
3006         context_.Say("No intrinsic or user-defined %s matches "
3007                      "scalar %s and rank %d array of %s"_err_en_US,
3008             opr, type0, rank1, type1);
3009       } else {
3010         context_.Say("No intrinsic or user-defined %s matches "
3011                      "rank %d array of %s and scalar %s"_err_en_US,
3012             opr, rank0, type0, type1);
3013       }
3014     } else {
3015       context_.Say("No intrinsic or user-defined %s matches "
3016                    "operand types %s and %s"_err_en_US,
3017           opr, type0, type1);
3018     }
3019   }
3020 }
3021 
3022 std::string ArgumentAnalyzer::TypeAsFortran(std::size_t i) {
3023   if (std::optional<DynamicType> type{GetType(i)}) {
3024     return type->category() == TypeCategory::Derived
3025         ? "TYPE("s + type->AsFortran() + ')'
3026     : type->category() == TypeCategory::Character
3027         ? "CHARACTER(KIND="s + std::to_string(type->kind()) + ')'
3028         : ToUpperCase(type->AsFortran());
3029   } else {
3030     return "untyped";
3031   }
3032 }
3033 
3034 bool ArgumentAnalyzer::AnyUntypedOperand() {
3035   for (const auto &actual : actuals_) {
3036     if (!actual.value().GetType()) {
3037       return true;
3038     }
3039   }
3040   return false;
3041 }
3042 
3043 } // namespace Fortran::evaluate
3044 
3045 namespace Fortran::semantics {
3046 evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
3047     SemanticsContext &context, common::TypeCategory category,
3048     const std::optional<parser::KindSelector> &selector) {
3049   evaluate::ExpressionAnalyzer analyzer{context};
3050   auto restorer{
3051       analyzer.GetContextualMessages().SetLocation(context.location().value())};
3052   return analyzer.AnalyzeKindSelector(category, selector);
3053 }
3054 
3055 void AnalyzeCallStmt(SemanticsContext &context, const parser::CallStmt &call) {
3056   evaluate::ExpressionAnalyzer{context}.Analyze(call);
3057 }
3058 
3059 const evaluate::Assignment *AnalyzeAssignmentStmt(
3060     SemanticsContext &context, const parser::AssignmentStmt &stmt) {
3061   return evaluate::ExpressionAnalyzer{context}.Analyze(stmt);
3062 }
3063 const evaluate::Assignment *AnalyzePointerAssignmentStmt(
3064     SemanticsContext &context, const parser::PointerAssignmentStmt &stmt) {
3065   return evaluate::ExpressionAnalyzer{context}.Analyze(stmt);
3066 }
3067 
3068 ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {}
3069 
3070 bool ExprChecker::Pre(const parser::DataImpliedDo &ido) {
3071   parser::Walk(std::get<parser::DataImpliedDo::Bounds>(ido.t), *this);
3072   const auto &bounds{std::get<parser::DataImpliedDo::Bounds>(ido.t)};
3073   auto name{bounds.name.thing.thing};
3074   int kind{evaluate::ResultType<evaluate::ImpliedDoIndex>::kind};
3075   if (const auto dynamicType{evaluate::DynamicType::From(*name.symbol)}) {
3076     if (dynamicType->category() == TypeCategory::Integer) {
3077       kind = dynamicType->kind();
3078     }
3079   }
3080   exprAnalyzer_.AddImpliedDo(name.source, kind);
3081   parser::Walk(std::get<std::list<parser::DataIDoObject>>(ido.t), *this);
3082   exprAnalyzer_.RemoveImpliedDo(name.source);
3083   return false;
3084 }
3085 
3086 bool ExprChecker::Walk(const parser::Program &program) {
3087   parser::Walk(program, *this);
3088   return !context_.AnyFatalError();
3089 }
3090 } // namespace Fortran::semantics
3091