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   const auto &actualArgList{std::get<std::list<parser::ActualArgSpec>>(call.t)};
2010   for (const auto &arg : actualArgList) {
2011     analyzer.Analyze(arg, true /* is subroutine call */);
2012   }
2013   if (!analyzer.fatalErrors()) {
2014     if (std::optional<CalleeAndArguments> callee{
2015             GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t),
2016                 analyzer.GetActuals(), true /* subroutine */)}) {
2017       ProcedureDesignator *proc{std::get_if<ProcedureDesignator>(&callee->u)};
2018       CHECK(proc);
2019       if (CheckCall(call.source, *proc, callee->arguments)) {
2020         bool hasAlternateReturns{
2021             callee->arguments.size() < actualArgList.size()};
2022         callStmt.typedCall.reset(new ProcedureRef{std::move(*proc),
2023             std::move(callee->arguments), hasAlternateReturns});
2024       }
2025     }
2026   }
2027 }
2028 
2029 const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) {
2030   if (!x.typedAssignment) {
2031     ArgumentAnalyzer analyzer{*this};
2032     analyzer.Analyze(std::get<parser::Variable>(x.t));
2033     analyzer.Analyze(std::get<parser::Expr>(x.t));
2034     if (analyzer.fatalErrors()) {
2035       x.typedAssignment.reset(new GenericAssignmentWrapper{});
2036     } else {
2037       std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()};
2038       Assignment assignment{
2039           Fold(analyzer.MoveExpr(0)), Fold(analyzer.MoveExpr(1))};
2040       if (procRef) {
2041         assignment.u = std::move(*procRef);
2042       }
2043       x.typedAssignment.reset(
2044           new GenericAssignmentWrapper{std::move(assignment)});
2045     }
2046   }
2047   return common::GetPtrFromOptional(x.typedAssignment->v);
2048 }
2049 
2050 const Assignment *ExpressionAnalyzer::Analyze(
2051     const parser::PointerAssignmentStmt &x) {
2052   if (!x.typedAssignment) {
2053     MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))};
2054     MaybeExpr rhs{Analyze(std::get<parser::Expr>(x.t))};
2055     if (!lhs || !rhs) {
2056       x.typedAssignment.reset(new GenericAssignmentWrapper{});
2057     } else {
2058       Assignment assignment{std::move(*lhs), std::move(*rhs)};
2059       std::visit(common::visitors{
2060                      [&](const std::list<parser::BoundsRemapping> &list) {
2061                        Assignment::BoundsRemapping bounds;
2062                        for (const auto &elem : list) {
2063                          auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))};
2064                          auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))};
2065                          if (lower && upper) {
2066                            bounds.emplace_back(Fold(std::move(*lower)),
2067                                Fold(std::move(*upper)));
2068                          }
2069                        }
2070                        assignment.u = std::move(bounds);
2071                      },
2072                      [&](const std::list<parser::BoundsSpec> &list) {
2073                        Assignment::BoundsSpec bounds;
2074                        for (const auto &bound : list) {
2075                          if (auto lower{AsSubscript(Analyze(bound.v))}) {
2076                            bounds.emplace_back(Fold(std::move(*lower)));
2077                          }
2078                        }
2079                        assignment.u = std::move(bounds);
2080                      },
2081                  },
2082           std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u);
2083       x.typedAssignment.reset(
2084           new GenericAssignmentWrapper{std::move(assignment)});
2085     }
2086   }
2087   return common::GetPtrFromOptional(x.typedAssignment->v);
2088 }
2089 
2090 static bool IsExternalCalledImplicitly(
2091     parser::CharBlock callSite, const ProcedureDesignator &proc) {
2092   if (const auto *symbol{proc.GetSymbol()}) {
2093     return symbol->has<semantics::SubprogramDetails>() &&
2094         symbol->owner().IsGlobal() &&
2095         (!symbol->scope() /*ENTRY*/ ||
2096             !symbol->scope()->sourceRange().Contains(callSite));
2097   } else {
2098     return false;
2099   }
2100 }
2101 
2102 std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
2103     parser::CharBlock callSite, const ProcedureDesignator &proc,
2104     ActualArguments &arguments) {
2105   auto chars{
2106       characteristics::Procedure::Characterize(proc, context_.intrinsics())};
2107   if (chars) {
2108     bool treatExternalAsImplicit{IsExternalCalledImplicitly(callSite, proc)};
2109     if (treatExternalAsImplicit && !chars->CanBeCalledViaImplicitInterface()) {
2110       Say(callSite,
2111           "References to the procedure '%s' require an explicit interface"_en_US,
2112           DEREF(proc.GetSymbol()).name());
2113     }
2114     semantics::CheckArguments(*chars, arguments, GetFoldingContext(),
2115         context_.FindScope(callSite), treatExternalAsImplicit);
2116     const Symbol *procSymbol{proc.GetSymbol()};
2117     if (procSymbol && !IsPureProcedure(*procSymbol)) {
2118       if (const semantics::Scope *
2119           pure{semantics::FindPureProcedureContaining(
2120               context_.FindScope(callSite))}) {
2121         Say(callSite,
2122             "Procedure '%s' referenced in pure subprogram '%s' must be pure too"_err_en_US,
2123             procSymbol->name(), DEREF(pure->symbol()).name());
2124       }
2125     }
2126   }
2127   return chars;
2128 }
2129 
2130 // Unary operations
2131 
2132 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Parentheses &x) {
2133   if (MaybeExpr operand{Analyze(x.v.value())}) {
2134     if (const semantics::Symbol * symbol{GetLastSymbol(*operand)}) {
2135       if (const semantics::Symbol * result{FindFunctionResult(*symbol)}) {
2136         if (semantics::IsProcedurePointer(*result)) {
2137           Say("A function reference that returns a procedure "
2138               "pointer may not be parenthesized"_err_en_US); // C1003
2139         }
2140       }
2141     }
2142     return Parenthesize(std::move(*operand));
2143   }
2144   return std::nullopt;
2145 }
2146 
2147 static MaybeExpr NumericUnaryHelper(ExpressionAnalyzer &context,
2148     NumericOperator opr, const parser::Expr::IntrinsicUnary &x) {
2149   ArgumentAnalyzer analyzer{context};
2150   analyzer.Analyze(x.v);
2151   if (analyzer.fatalErrors()) {
2152     return std::nullopt;
2153   } else if (analyzer.IsIntrinsicNumeric(opr)) {
2154     if (opr == NumericOperator::Add) {
2155       return analyzer.MoveExpr(0);
2156     } else {
2157       return Negation(context.GetContextualMessages(), analyzer.MoveExpr(0));
2158     }
2159   } else {
2160     return analyzer.TryDefinedOp(AsFortran(opr),
2161         "Operand of unary %s must be numeric; have %s"_err_en_US);
2162   }
2163 }
2164 
2165 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::UnaryPlus &x) {
2166   return NumericUnaryHelper(*this, NumericOperator::Add, x);
2167 }
2168 
2169 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Negate &x) {
2170   return NumericUnaryHelper(*this, NumericOperator::Subtract, x);
2171 }
2172 
2173 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NOT &x) {
2174   ArgumentAnalyzer analyzer{*this};
2175   analyzer.Analyze(x.v);
2176   if (analyzer.fatalErrors()) {
2177     return std::nullopt;
2178   } else if (analyzer.IsIntrinsicLogical()) {
2179     return AsGenericExpr(
2180         LogicalNegation(std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u)));
2181   } else {
2182     return analyzer.TryDefinedOp(LogicalOperator::Not,
2183         "Operand of %s must be LOGICAL; have %s"_err_en_US);
2184   }
2185 }
2186 
2187 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::PercentLoc &x) {
2188   // Represent %LOC() exactly as if it had been a call to the LOC() extension
2189   // intrinsic function.
2190   // Use the actual source for the name of the call for error reporting.
2191   std::optional<ActualArgument> arg;
2192   if (const Symbol * assumedTypeDummy{AssumedTypeDummy(x.v.value())}) {
2193     arg = ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
2194   } else if (MaybeExpr argExpr{Analyze(x.v.value())}) {
2195     arg = ActualArgument{std::move(*argExpr)};
2196   } else {
2197     return std::nullopt;
2198   }
2199   parser::CharBlock at{GetContextualMessages().at()};
2200   CHECK(at.size() >= 4);
2201   parser::CharBlock loc{at.begin() + 1, 3};
2202   CHECK(loc == "loc");
2203   return MakeFunctionRef(loc, ActualArguments{std::move(*arg)});
2204 }
2205 
2206 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &x) {
2207   const auto &name{std::get<parser::DefinedOpName>(x.t).v};
2208   ArgumentAnalyzer analyzer{*this, name.source};
2209   analyzer.Analyze(std::get<1>(x.t));
2210   return analyzer.TryDefinedOp(name.source.ToString().c_str(),
2211       "No operator %s defined for %s"_err_en_US, true);
2212 }
2213 
2214 // Binary (dyadic) operations
2215 
2216 template <template <typename> class OPR>
2217 MaybeExpr NumericBinaryHelper(ExpressionAnalyzer &context, NumericOperator opr,
2218     const parser::Expr::IntrinsicBinary &x) {
2219   ArgumentAnalyzer analyzer{context};
2220   analyzer.Analyze(std::get<0>(x.t));
2221   analyzer.Analyze(std::get<1>(x.t));
2222   if (analyzer.fatalErrors()) {
2223     return std::nullopt;
2224   } else if (analyzer.IsIntrinsicNumeric(opr)) {
2225     return NumericOperation<OPR>(context.GetContextualMessages(),
2226         analyzer.MoveExpr(0), analyzer.MoveExpr(1),
2227         context.GetDefaultKind(TypeCategory::Real));
2228   } else {
2229     return analyzer.TryDefinedOp(AsFortran(opr),
2230         "Operands of %s must be numeric; have %s and %s"_err_en_US);
2231   }
2232 }
2233 
2234 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Power &x) {
2235   return NumericBinaryHelper<Power>(*this, NumericOperator::Power, x);
2236 }
2237 
2238 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Multiply &x) {
2239   return NumericBinaryHelper<Multiply>(*this, NumericOperator::Multiply, x);
2240 }
2241 
2242 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Divide &x) {
2243   return NumericBinaryHelper<Divide>(*this, NumericOperator::Divide, x);
2244 }
2245 
2246 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Add &x) {
2247   return NumericBinaryHelper<Add>(*this, NumericOperator::Add, x);
2248 }
2249 
2250 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Subtract &x) {
2251   return NumericBinaryHelper<Subtract>(*this, NumericOperator::Subtract, x);
2252 }
2253 
2254 MaybeExpr ExpressionAnalyzer::Analyze(
2255     const parser::Expr::ComplexConstructor &x) {
2256   auto re{Analyze(std::get<0>(x.t).value())};
2257   auto im{Analyze(std::get<1>(x.t).value())};
2258   if (re && im) {
2259     ConformabilityCheck(GetContextualMessages(), *re, *im);
2260   }
2261   return AsMaybeExpr(ConstructComplex(GetContextualMessages(), std::move(re),
2262       std::move(im), GetDefaultKind(TypeCategory::Real)));
2263 }
2264 
2265 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
2266   ArgumentAnalyzer analyzer{*this};
2267   analyzer.Analyze(std::get<0>(x.t));
2268   analyzer.Analyze(std::get<1>(x.t));
2269   if (analyzer.fatalErrors()) {
2270     return std::nullopt;
2271   } else if (analyzer.IsIntrinsicConcat()) {
2272     return std::visit(
2273         [&](auto &&x, auto &&y) -> MaybeExpr {
2274           using T = ResultType<decltype(x)>;
2275           if constexpr (std::is_same_v<T, ResultType<decltype(y)>>) {
2276             return AsGenericExpr(Concat<T::kind>{std::move(x), std::move(y)});
2277           } else {
2278             DIE("different types for intrinsic concat");
2279           }
2280         },
2281         std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(0).u).u),
2282         std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(1).u).u));
2283   } else {
2284     return analyzer.TryDefinedOp("//",
2285         "Operands of %s must be CHARACTER with the same kind; have %s and %s"_err_en_US);
2286   }
2287 }
2288 
2289 // The Name represents a user-defined intrinsic operator.
2290 // If the actuals match one of the specific procedures, return a function ref.
2291 // Otherwise report the error in messages.
2292 MaybeExpr ExpressionAnalyzer::AnalyzeDefinedOp(
2293     const parser::Name &name, ActualArguments &&actuals) {
2294   if (auto callee{GetCalleeAndArguments(name, std::move(actuals))}) {
2295     CHECK(std::holds_alternative<ProcedureDesignator>(callee->u));
2296     return MakeFunctionRef(name.source,
2297         std::move(std::get<ProcedureDesignator>(callee->u)),
2298         std::move(callee->arguments));
2299   } else {
2300     return std::nullopt;
2301   }
2302 }
2303 
2304 MaybeExpr RelationHelper(ExpressionAnalyzer &context, RelationalOperator opr,
2305     const parser::Expr::IntrinsicBinary &x) {
2306   ArgumentAnalyzer analyzer{context};
2307   analyzer.Analyze(std::get<0>(x.t));
2308   analyzer.Analyze(std::get<1>(x.t));
2309   if (analyzer.fatalErrors()) {
2310     return std::nullopt;
2311   } else if (analyzer.IsIntrinsicRelational(opr)) {
2312     return AsMaybeExpr(Relate(context.GetContextualMessages(), opr,
2313         analyzer.MoveExpr(0), analyzer.MoveExpr(1)));
2314   } else {
2315     return analyzer.TryDefinedOp(opr,
2316         "Operands of %s must have comparable types; have %s and %s"_err_en_US);
2317   }
2318 }
2319 
2320 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LT &x) {
2321   return RelationHelper(*this, RelationalOperator::LT, x);
2322 }
2323 
2324 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LE &x) {
2325   return RelationHelper(*this, RelationalOperator::LE, x);
2326 }
2327 
2328 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQ &x) {
2329   return RelationHelper(*this, RelationalOperator::EQ, x);
2330 }
2331 
2332 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NE &x) {
2333   return RelationHelper(*this, RelationalOperator::NE, x);
2334 }
2335 
2336 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GE &x) {
2337   return RelationHelper(*this, RelationalOperator::GE, x);
2338 }
2339 
2340 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GT &x) {
2341   return RelationHelper(*this, RelationalOperator::GT, x);
2342 }
2343 
2344 MaybeExpr LogicalBinaryHelper(ExpressionAnalyzer &context, LogicalOperator opr,
2345     const parser::Expr::IntrinsicBinary &x) {
2346   ArgumentAnalyzer analyzer{context};
2347   analyzer.Analyze(std::get<0>(x.t));
2348   analyzer.Analyze(std::get<1>(x.t));
2349   if (analyzer.fatalErrors()) {
2350     return std::nullopt;
2351   } else if (analyzer.IsIntrinsicLogical()) {
2352     return AsGenericExpr(BinaryLogicalOperation(opr,
2353         std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u),
2354         std::get<Expr<SomeLogical>>(analyzer.MoveExpr(1).u)));
2355   } else {
2356     return analyzer.TryDefinedOp(
2357         opr, "Operands of %s must be LOGICAL; have %s and %s"_err_en_US);
2358   }
2359 }
2360 
2361 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::AND &x) {
2362   return LogicalBinaryHelper(*this, LogicalOperator::And, x);
2363 }
2364 
2365 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::OR &x) {
2366   return LogicalBinaryHelper(*this, LogicalOperator::Or, x);
2367 }
2368 
2369 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQV &x) {
2370   return LogicalBinaryHelper(*this, LogicalOperator::Eqv, x);
2371 }
2372 
2373 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NEQV &x) {
2374   return LogicalBinaryHelper(*this, LogicalOperator::Neqv, x);
2375 }
2376 
2377 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &x) {
2378   const auto &name{std::get<parser::DefinedOpName>(x.t).v};
2379   ArgumentAnalyzer analyzer{*this, name.source};
2380   analyzer.Analyze(std::get<1>(x.t));
2381   analyzer.Analyze(std::get<2>(x.t));
2382   return analyzer.TryDefinedOp(name.source.ToString().c_str(),
2383       "No operator %s defined for %s and %s"_err_en_US, true);
2384 }
2385 
2386 static void CheckFuncRefToArrayElementRefHasSubscripts(
2387     semantics::SemanticsContext &context,
2388     const parser::FunctionReference &funcRef) {
2389   // Emit message if the function reference fix will end up an array element
2390   // reference with no subscripts because it will not be possible to later tell
2391   // the difference in expressions between empty subscript list due to bad
2392   // subscripts error recovery or because the user did not put any.
2393   if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) {
2394     auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
2395     const auto *name{std::get_if<parser::Name>(&proc.u)};
2396     if (!name) {
2397       name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component;
2398     }
2399     auto &msg{context.Say(funcRef.v.source,
2400         name->symbol && name->symbol->Rank() == 0
2401             ? "'%s' is not a function"_err_en_US
2402             : "Reference to array '%s' with empty subscript list"_err_en_US,
2403         name->source)};
2404     if (name->symbol) {
2405       if (semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)) {
2406         msg.Attach(name->source,
2407             "A result variable must be declared with RESULT to allow recursive "
2408             "function calls"_en_US);
2409       } else {
2410         AttachDeclaration(&msg, *name->symbol);
2411       }
2412     }
2413   }
2414 }
2415 
2416 // Converts, if appropriate, an original misparse of ambiguous syntax like
2417 // A(1) as a function reference into an array reference.
2418 // Misparse structure constructors are detected elsewhere after generic
2419 // function call resolution fails.
2420 template <typename... A>
2421 static void FixMisparsedFunctionReference(
2422     semantics::SemanticsContext &context, const std::variant<A...> &constU) {
2423   // The parse tree is updated in situ when resolving an ambiguous parse.
2424   using uType = std::decay_t<decltype(constU)>;
2425   auto &u{const_cast<uType &>(constU)};
2426   if (auto *func{
2427           std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
2428     parser::FunctionReference &funcRef{func->value()};
2429     auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
2430     if (Symbol *
2431         origSymbol{
2432             std::visit(common::visitors{
2433                            [&](parser::Name &name) { return name.symbol; },
2434                            [&](parser::ProcComponentRef &pcr) {
2435                              return pcr.v.thing.component.symbol;
2436                            },
2437                        },
2438                 proc.u)}) {
2439       Symbol &symbol{origSymbol->GetUltimate()};
2440       if (symbol.has<semantics::ObjectEntityDetails>() ||
2441           symbol.has<semantics::AssocEntityDetails>()) {
2442         // Note that expression in AssocEntityDetails cannot be a procedure
2443         // pointer as per C1105 so this cannot be a function reference.
2444         if constexpr (common::HasMember<common::Indirection<parser::Designator>,
2445                           uType>) {
2446           CheckFuncRefToArrayElementRefHasSubscripts(context, funcRef);
2447           u = common::Indirection{funcRef.ConvertToArrayElementRef()};
2448         } else {
2449           DIE("can't fix misparsed function as array reference");
2450         }
2451       }
2452     }
2453   }
2454 }
2455 
2456 // Common handling of parse tree node types that retain the
2457 // representation of the analyzed expression.
2458 template <typename PARSED>
2459 MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) {
2460   if (x.typedExpr) {
2461     return x.typedExpr->v;
2462   }
2463   if constexpr (std::is_same_v<PARSED, parser::Expr> ||
2464       std::is_same_v<PARSED, parser::Variable>) {
2465     FixMisparsedFunctionReference(context_, x.u);
2466   }
2467   if (AssumedTypeDummy(x)) { // C710
2468     Say("TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
2469   } else if (MaybeExpr result{evaluate::Fold(foldingContext_, Analyze(x.u))}) {
2470     SetExpr(x, std::move(*result));
2471     return x.typedExpr->v;
2472   }
2473   ResetExpr(x);
2474   if (!context_.AnyFatalError()) {
2475     std::string buf;
2476     llvm::raw_string_ostream dump{buf};
2477     parser::DumpTree(dump, x);
2478     Say("Internal error: Expression analysis failed on: %s"_err_en_US,
2479         dump.str());
2480   }
2481   fatalErrors_ = true;
2482   return std::nullopt;
2483 }
2484 
2485 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) {
2486   auto restorer{GetContextualMessages().SetLocation(expr.source)};
2487   return ExprOrVariable(expr);
2488 }
2489 
2490 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) {
2491   auto restorer{GetContextualMessages().SetLocation(variable.GetSource())};
2492   return ExprOrVariable(variable);
2493 }
2494 
2495 MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) {
2496   auto restorer{GetContextualMessages().SetLocation(x.source)};
2497   return ExprOrVariable(x);
2498 }
2499 
2500 Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
2501     TypeCategory category,
2502     const std::optional<parser::KindSelector> &selector) {
2503   int defaultKind{GetDefaultKind(category)};
2504   if (!selector) {
2505     return Expr<SubscriptInteger>{defaultKind};
2506   }
2507   return std::visit(
2508       common::visitors{
2509           [&](const parser::ScalarIntConstantExpr &x) {
2510             if (MaybeExpr kind{Analyze(x)}) {
2511               Expr<SomeType> folded{Fold(std::move(*kind))};
2512               if (std::optional<std::int64_t> code{ToInt64(folded)}) {
2513                 if (CheckIntrinsicKind(category, *code)) {
2514                   return Expr<SubscriptInteger>{*code};
2515                 }
2516               } else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(folded)}) {
2517                 return ConvertToType<SubscriptInteger>(std::move(*intExpr));
2518               }
2519             }
2520             return Expr<SubscriptInteger>{defaultKind};
2521           },
2522           [&](const parser::KindSelector::StarSize &x) {
2523             std::intmax_t size = x.v;
2524             if (!CheckIntrinsicSize(category, size)) {
2525               size = defaultKind;
2526             } else if (category == TypeCategory::Complex) {
2527               size /= 2;
2528             }
2529             return Expr<SubscriptInteger>{size};
2530           },
2531       },
2532       selector->u);
2533 }
2534 
2535 int ExpressionAnalyzer::GetDefaultKind(common::TypeCategory category) {
2536   return context_.GetDefaultKind(category);
2537 }
2538 
2539 DynamicType ExpressionAnalyzer::GetDefaultKindOfType(
2540     common::TypeCategory category) {
2541   return {category, GetDefaultKind(category)};
2542 }
2543 
2544 bool ExpressionAnalyzer::CheckIntrinsicKind(
2545     TypeCategory category, std::int64_t kind) {
2546   if (IsValidKindOfIntrinsicType(category, kind)) { // C712, C714, C715, C727
2547     return true;
2548   } else {
2549     Say("%s(KIND=%jd) is not a supported type"_err_en_US,
2550         ToUpperCase(EnumToString(category)), kind);
2551     return false;
2552   }
2553 }
2554 
2555 bool ExpressionAnalyzer::CheckIntrinsicSize(
2556     TypeCategory category, std::int64_t size) {
2557   if (category == TypeCategory::Complex) {
2558     // COMPLEX*16 == COMPLEX(KIND=8)
2559     if (size % 2 == 0 && IsValidKindOfIntrinsicType(category, size / 2)) {
2560       return true;
2561     }
2562   } else if (IsValidKindOfIntrinsicType(category, size)) {
2563     return true;
2564   }
2565   Say("%s*%jd is not a supported type"_err_en_US,
2566       ToUpperCase(EnumToString(category)), size);
2567   return false;
2568 }
2569 
2570 bool ExpressionAnalyzer::AddImpliedDo(parser::CharBlock name, int kind) {
2571   return impliedDos_.insert(std::make_pair(name, kind)).second;
2572 }
2573 
2574 void ExpressionAnalyzer::RemoveImpliedDo(parser::CharBlock name) {
2575   auto iter{impliedDos_.find(name)};
2576   if (iter != impliedDos_.end()) {
2577     impliedDos_.erase(iter);
2578   }
2579 }
2580 
2581 std::optional<int> ExpressionAnalyzer::IsImpliedDo(
2582     parser::CharBlock name) const {
2583   auto iter{impliedDos_.find(name)};
2584   if (iter != impliedDos_.cend()) {
2585     return {iter->second};
2586   } else {
2587     return std::nullopt;
2588   }
2589 }
2590 
2591 bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at,
2592     const MaybeExpr &result, TypeCategory category, bool defaultKind) {
2593   if (result) {
2594     if (auto type{result->GetType()}) {
2595       if (type->category() != category) { // C885
2596         Say(at, "Must have %s type, but is %s"_err_en_US,
2597             ToUpperCase(EnumToString(category)),
2598             ToUpperCase(type->AsFortran()));
2599         return false;
2600       } else if (defaultKind) {
2601         int kind{context_.GetDefaultKind(category)};
2602         if (type->kind() != kind) {
2603           Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US,
2604               kind, ToUpperCase(EnumToString(category)),
2605               ToUpperCase(type->AsFortran()));
2606           return false;
2607         }
2608       }
2609     } else {
2610       Say(at, "Must have %s type, but is typeless"_err_en_US,
2611           ToUpperCase(EnumToString(category)));
2612       return false;
2613     }
2614   }
2615   return true;
2616 }
2617 
2618 MaybeExpr ExpressionAnalyzer::MakeFunctionRef(parser::CharBlock callSite,
2619     ProcedureDesignator &&proc, ActualArguments &&arguments) {
2620   if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&proc.u)}) {
2621     if (intrinsic->name == "null" && arguments.empty()) {
2622       return Expr<SomeType>{NullPointer{}};
2623     }
2624   }
2625   if (const Symbol * symbol{proc.GetSymbol()}) {
2626     if (!ResolveForward(*symbol)) {
2627       return std::nullopt;
2628     }
2629   }
2630   if (auto chars{CheckCall(callSite, proc, arguments)}) {
2631     if (chars->functionResult) {
2632       const auto &result{*chars->functionResult};
2633       if (result.IsProcedurePointer()) {
2634         return Expr<SomeType>{
2635             ProcedureRef{std::move(proc), std::move(arguments)}};
2636       } else {
2637         // Not a procedure pointer, so type and shape are known.
2638         return TypedWrapper<FunctionRef, ProcedureRef>(
2639             DEREF(result.GetTypeAndShape()).type(),
2640             ProcedureRef{std::move(proc), std::move(arguments)});
2641       }
2642     }
2643   }
2644   return std::nullopt;
2645 }
2646 
2647 MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
2648     parser::CharBlock intrinsic, ActualArguments &&arguments) {
2649   if (std::optional<SpecificCall> specificCall{
2650           context_.intrinsics().Probe(CallCharacteristics{intrinsic.ToString()},
2651               arguments, context_.foldingContext())}) {
2652     return MakeFunctionRef(intrinsic,
2653         ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
2654         std::move(specificCall->arguments));
2655   } else {
2656     return std::nullopt;
2657   }
2658 }
2659 
2660 void ArgumentAnalyzer::Analyze(const parser::Variable &x) {
2661   source_.ExtendToCover(x.GetSource());
2662   if (MaybeExpr expr{context_.Analyze(x)}) {
2663     if (!IsConstantExpr(*expr)) {
2664       actuals_.emplace_back(std::move(*expr));
2665       return;
2666     }
2667     const Symbol *symbol{GetFirstSymbol(*expr)};
2668     context_.Say(x.GetSource(),
2669         "Assignment to constant '%s' is not allowed"_err_en_US,
2670         symbol ? symbol->name() : x.GetSource());
2671   }
2672   fatalErrors_ = true;
2673 }
2674 
2675 void ArgumentAnalyzer::Analyze(
2676     const parser::ActualArgSpec &arg, bool isSubroutine) {
2677   // TODO: C1002: Allow a whole assumed-size array to appear if the dummy
2678   // argument would accept it.  Handle by special-casing the context
2679   // ActualArg -> Variable -> Designator.
2680   // TODO: Actual arguments that are procedures and procedure pointers need to
2681   // be detected and represented (they're not expressions).
2682   // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
2683   std::optional<ActualArgument> actual;
2684   bool isAltReturn{false};
2685   std::visit(common::visitors{
2686                  [&](const common::Indirection<parser::Expr> &x) {
2687                    // TODO: Distinguish & handle procedure name and
2688                    // proc-component-ref
2689                    actual = AnalyzeExpr(x.value());
2690                  },
2691                  [&](const parser::AltReturnSpec &) {
2692                    if (!isSubroutine) {
2693                      context_.Say(
2694                          "alternate return specification may not appear on"
2695                          " function reference"_err_en_US);
2696                    }
2697                    isAltReturn = true;
2698                  },
2699                  [&](const parser::ActualArg::PercentRef &) {
2700                    context_.Say("TODO: %REF() argument"_err_en_US);
2701                  },
2702                  [&](const parser::ActualArg::PercentVal &) {
2703                    context_.Say("TODO: %VAL() argument"_err_en_US);
2704                  },
2705              },
2706       std::get<parser::ActualArg>(arg.t).u);
2707   if (actual) {
2708     if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) {
2709       actual->set_keyword(argKW->v.source);
2710     }
2711     actuals_.emplace_back(std::move(*actual));
2712   } else if (!isAltReturn) {
2713     fatalErrors_ = true;
2714   }
2715 }
2716 
2717 bool ArgumentAnalyzer::IsIntrinsicRelational(RelationalOperator opr) const {
2718   CHECK(actuals_.size() == 2);
2719   return semantics::IsIntrinsicRelational(
2720       opr, *GetType(0), GetRank(0), *GetType(1), GetRank(1));
2721 }
2722 
2723 bool ArgumentAnalyzer::IsIntrinsicNumeric(NumericOperator opr) const {
2724   std::optional<DynamicType> type0{GetType(0)};
2725   if (actuals_.size() == 1) {
2726     if (IsBOZLiteral(0)) {
2727       return opr == NumericOperator::Add;
2728     } else {
2729       return type0 && semantics::IsIntrinsicNumeric(*type0);
2730     }
2731   } else {
2732     std::optional<DynamicType> type1{GetType(1)};
2733     if (IsBOZLiteral(0) && type1) {
2734       auto cat1{type1->category()};
2735       return cat1 == TypeCategory::Integer || cat1 == TypeCategory::Real;
2736     } else if (IsBOZLiteral(1) && type0) { // Integer/Real opr BOZ
2737       auto cat0{type0->category()};
2738       return cat0 == TypeCategory::Integer || cat0 == TypeCategory::Real;
2739     } else {
2740       return type0 && type1 &&
2741           semantics::IsIntrinsicNumeric(*type0, GetRank(0), *type1, GetRank(1));
2742     }
2743   }
2744 }
2745 
2746 bool ArgumentAnalyzer::IsIntrinsicLogical() const {
2747   if (actuals_.size() == 1) {
2748     return semantics::IsIntrinsicLogical(*GetType(0));
2749     return GetType(0)->category() == TypeCategory::Logical;
2750   } else {
2751     return semantics::IsIntrinsicLogical(
2752         *GetType(0), GetRank(0), *GetType(1), GetRank(1));
2753   }
2754 }
2755 
2756 bool ArgumentAnalyzer::IsIntrinsicConcat() const {
2757   return semantics::IsIntrinsicConcat(
2758       *GetType(0), GetRank(0), *GetType(1), GetRank(1));
2759 }
2760 
2761 MaybeExpr ArgumentAnalyzer::TryDefinedOp(
2762     const char *opr, parser::MessageFixedText &&error, bool isUserOp) {
2763   if (AnyUntypedOperand()) {
2764     context_.Say(
2765         std::move(error), ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
2766     return std::nullopt;
2767   }
2768   {
2769     auto restorer{context_.GetContextualMessages().DiscardMessages()};
2770     std::string oprNameString{
2771         isUserOp ? std::string{opr} : "operator("s + opr + ')'};
2772     parser::CharBlock oprName{oprNameString};
2773     const auto &scope{context_.context().FindScope(source_)};
2774     if (Symbol * symbol{scope.FindSymbol(oprName)}) {
2775       parser::Name name{symbol->name(), symbol};
2776       if (auto result{context_.AnalyzeDefinedOp(name, GetActuals())}) {
2777         return result;
2778       }
2779       sawDefinedOp_ = symbol;
2780     }
2781     for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) {
2782       if (const Symbol * symbol{FindBoundOp(oprName, passIndex)}) {
2783         if (MaybeExpr result{TryBoundOp(*symbol, passIndex)}) {
2784           return result;
2785         }
2786       }
2787     }
2788   }
2789   if (sawDefinedOp_) {
2790     SayNoMatch(ToUpperCase(sawDefinedOp_->name().ToString()));
2791   } else if (actuals_.size() == 1 || AreConformable()) {
2792     context_.Say(
2793         std::move(error), ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1));
2794   } else {
2795     context_.Say(
2796         "Operands of %s are not conformable; have rank %d and rank %d"_err_en_US,
2797         ToUpperCase(opr), actuals_[0]->Rank(), actuals_[1]->Rank());
2798   }
2799   return std::nullopt;
2800 }
2801 
2802 MaybeExpr ArgumentAnalyzer::TryDefinedOp(
2803     std::vector<const char *> oprs, parser::MessageFixedText &&error) {
2804   for (std::size_t i{1}; i < oprs.size(); ++i) {
2805     auto restorer{context_.GetContextualMessages().DiscardMessages()};
2806     if (auto result{TryDefinedOp(oprs[i], std::move(error))}) {
2807       return result;
2808     }
2809   }
2810   return TryDefinedOp(oprs[0], std::move(error));
2811 }
2812 
2813 MaybeExpr ArgumentAnalyzer::TryBoundOp(const Symbol &symbol, int passIndex) {
2814   ActualArguments localActuals{actuals_};
2815   const Symbol *proc{GetBindingResolution(GetType(passIndex), symbol)};
2816   if (!proc) {
2817     proc = &symbol;
2818     localActuals.at(passIndex).value().set_isPassedObject();
2819   }
2820   return context_.MakeFunctionRef(
2821       source_, ProcedureDesignator{*proc}, std::move(localActuals));
2822 }
2823 
2824 std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
2825   using semantics::Tristate;
2826   const Expr<SomeType> &lhs{GetExpr(0)};
2827   const Expr<SomeType> &rhs{GetExpr(1)};
2828   std::optional<DynamicType> lhsType{lhs.GetType()};
2829   std::optional<DynamicType> rhsType{rhs.GetType()};
2830   int lhsRank{lhs.Rank()};
2831   int rhsRank{rhs.Rank()};
2832   Tristate isDefined{
2833       semantics::IsDefinedAssignment(lhsType, lhsRank, rhsType, rhsRank)};
2834   if (isDefined == Tristate::No) {
2835     if (lhsType && rhsType) {
2836       AddAssignmentConversion(*lhsType, *rhsType);
2837     }
2838     return std::nullopt; // user-defined assignment not allowed for these args
2839   }
2840   auto restorer{context_.GetContextualMessages().SetLocation(source_)};
2841   if (std::optional<ProcedureRef> procRef{GetDefinedAssignmentProc()}) {
2842     context_.CheckCall(source_, procRef->proc(), procRef->arguments());
2843     return std::move(*procRef);
2844   }
2845   if (isDefined == Tristate::Yes) {
2846     if (!lhsType || !rhsType || (lhsRank != rhsRank && rhsRank != 0) ||
2847         !OkLogicalIntegerAssignment(lhsType->category(), rhsType->category())) {
2848       SayNoMatch("ASSIGNMENT(=)", true);
2849     }
2850   }
2851   return std::nullopt;
2852 }
2853 
2854 bool ArgumentAnalyzer::OkLogicalIntegerAssignment(
2855     TypeCategory lhs, TypeCategory rhs) {
2856   if (!context_.context().languageFeatures().IsEnabled(
2857           common::LanguageFeature::LogicalIntegerAssignment)) {
2858     return false;
2859   }
2860   std::optional<parser::MessageFixedText> msg;
2861   if (lhs == TypeCategory::Integer && rhs == TypeCategory::Logical) {
2862     // allow assignment to LOGICAL from INTEGER as a legacy extension
2863     msg = "nonstandard usage: assignment of LOGICAL to INTEGER"_en_US;
2864   } else if (lhs == TypeCategory::Logical && rhs == TypeCategory::Integer) {
2865     // ... and assignment to LOGICAL from INTEGER
2866     msg = "nonstandard usage: assignment of INTEGER to LOGICAL"_en_US;
2867   } else {
2868     return false;
2869   }
2870   if (context_.context().languageFeatures().ShouldWarn(
2871           common::LanguageFeature::LogicalIntegerAssignment)) {
2872     context_.Say(std::move(*msg));
2873   }
2874   return true;
2875 }
2876 
2877 std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() {
2878   auto restorer{context_.GetContextualMessages().DiscardMessages()};
2879   std::string oprNameString{"assignment(=)"};
2880   parser::CharBlock oprName{oprNameString};
2881   const Symbol *proc{nullptr};
2882   const auto &scope{context_.context().FindScope(source_)};
2883   if (const Symbol * symbol{scope.FindSymbol(oprName)}) {
2884     ExpressionAnalyzer::AdjustActuals noAdjustment;
2885     if (const Symbol *
2886         specific{context_.ResolveGeneric(*symbol, actuals_, noAdjustment)}) {
2887       proc = specific;
2888     } else {
2889       context_.EmitGenericResolutionError(*symbol);
2890     }
2891   }
2892   for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) {
2893     if (const Symbol * specific{FindBoundOp(oprName, passIndex)}) {
2894       proc = specific;
2895     }
2896   }
2897   if (proc) {
2898     ActualArguments actualsCopy{actuals_};
2899     actualsCopy[1]->Parenthesize();
2900     return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)};
2901   } else {
2902     return std::nullopt;
2903   }
2904 }
2905 
2906 void ArgumentAnalyzer::Dump(llvm::raw_ostream &os) {
2907   os << "source_: " << source_.ToString() << " fatalErrors_ = " << fatalErrors_
2908      << '\n';
2909   for (const auto &actual : actuals_) {
2910     if (!actual.has_value()) {
2911       os << "- error\n";
2912     } else if (const Symbol * symbol{actual->GetAssumedTypeDummy()}) {
2913       os << "- assumed type: " << symbol->name().ToString() << '\n';
2914     } else if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) {
2915       expr->AsFortran(os << "- expr: ") << '\n';
2916     } else {
2917       DIE("bad ActualArgument");
2918     }
2919   }
2920 }
2921 std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr(
2922     const parser::Expr &expr) {
2923   source_.ExtendToCover(expr.source);
2924   if (const Symbol * assumedTypeDummy{AssumedTypeDummy(expr)}) {
2925     expr.typedExpr.reset(new GenericExprWrapper{});
2926     if (allowAssumedType_) {
2927       return ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
2928     } else {
2929       context_.SayAt(expr.source,
2930           "TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
2931       return std::nullopt;
2932     }
2933   } else if (MaybeExpr argExpr{context_.Analyze(expr)}) {
2934     return ActualArgument{context_.Fold(std::move(*argExpr))};
2935   } else {
2936     return std::nullopt;
2937   }
2938 }
2939 
2940 bool ArgumentAnalyzer::AreConformable() const {
2941   CHECK(!fatalErrors_ && actuals_.size() == 2);
2942   return evaluate::AreConformable(*actuals_[0], *actuals_[1]);
2943 }
2944 
2945 // Look for a type-bound operator in the type of arg number passIndex.
2946 const Symbol *ArgumentAnalyzer::FindBoundOp(
2947     parser::CharBlock oprName, int passIndex) {
2948   const auto *type{GetDerivedTypeSpec(GetType(passIndex))};
2949   if (!type || !type->scope()) {
2950     return nullptr;
2951   }
2952   const Symbol *symbol{type->scope()->FindComponent(oprName)};
2953   if (!symbol) {
2954     return nullptr;
2955   }
2956   sawDefinedOp_ = symbol;
2957   ExpressionAnalyzer::AdjustActuals adjustment{
2958       [&](const Symbol &proc, ActualArguments &) {
2959         return passIndex == GetPassIndex(proc);
2960       }};
2961   const Symbol *result{context_.ResolveGeneric(*symbol, actuals_, adjustment)};
2962   if (!result) {
2963     context_.EmitGenericResolutionError(*symbol);
2964   }
2965   return result;
2966 }
2967 
2968 // If there is an implicit conversion between intrinsic types, make it explicit
2969 void ArgumentAnalyzer::AddAssignmentConversion(
2970     const DynamicType &lhsType, const DynamicType &rhsType) {
2971   if (lhsType.category() == rhsType.category() &&
2972       lhsType.kind() == rhsType.kind()) {
2973     // no conversion necessary
2974   } else if (auto rhsExpr{evaluate::ConvertToType(lhsType, MoveExpr(1))}) {
2975     actuals_[1] = ActualArgument{*rhsExpr};
2976   } else {
2977     actuals_[1] = std::nullopt;
2978   }
2979 }
2980 
2981 std::optional<DynamicType> ArgumentAnalyzer::GetType(std::size_t i) const {
2982   return i < actuals_.size() ? actuals_[i].value().GetType() : std::nullopt;
2983 }
2984 int ArgumentAnalyzer::GetRank(std::size_t i) const {
2985   return i < actuals_.size() ? actuals_[i].value().Rank() : 0;
2986 }
2987 
2988 // Report error resolving opr when there is a user-defined one available
2989 void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) {
2990   std::string type0{TypeAsFortran(0)};
2991   auto rank0{actuals_[0]->Rank()};
2992   if (actuals_.size() == 1) {
2993     if (rank0 > 0) {
2994       context_.Say("No intrinsic or user-defined %s matches "
2995                    "rank %d array of %s"_err_en_US,
2996           opr, rank0, type0);
2997     } else {
2998       context_.Say("No intrinsic or user-defined %s matches "
2999                    "operand type %s"_err_en_US,
3000           opr, type0);
3001     }
3002   } else {
3003     std::string type1{TypeAsFortran(1)};
3004     auto rank1{actuals_[1]->Rank()};
3005     if (rank0 > 0 && rank1 > 0 && rank0 != rank1) {
3006       context_.Say("No intrinsic or user-defined %s matches "
3007                    "rank %d array of %s and rank %d array of %s"_err_en_US,
3008           opr, rank0, type0, rank1, type1);
3009     } else if (isAssignment && rank0 != rank1) {
3010       if (rank0 == 0) {
3011         context_.Say("No intrinsic or user-defined %s matches "
3012                      "scalar %s and rank %d array of %s"_err_en_US,
3013             opr, type0, rank1, type1);
3014       } else {
3015         context_.Say("No intrinsic or user-defined %s matches "
3016                      "rank %d array of %s and scalar %s"_err_en_US,
3017             opr, rank0, type0, type1);
3018       }
3019     } else {
3020       context_.Say("No intrinsic or user-defined %s matches "
3021                    "operand types %s and %s"_err_en_US,
3022           opr, type0, type1);
3023     }
3024   }
3025 }
3026 
3027 std::string ArgumentAnalyzer::TypeAsFortran(std::size_t i) {
3028   if (std::optional<DynamicType> type{GetType(i)}) {
3029     return type->category() == TypeCategory::Derived
3030         ? "TYPE("s + type->AsFortran() + ')'
3031         : type->category() == TypeCategory::Character
3032         ? "CHARACTER(KIND="s + std::to_string(type->kind()) + ')'
3033         : ToUpperCase(type->AsFortran());
3034   } else {
3035     return "untyped";
3036   }
3037 }
3038 
3039 bool ArgumentAnalyzer::AnyUntypedOperand() {
3040   for (const auto &actual : actuals_) {
3041     if (!actual.value().GetType()) {
3042       return true;
3043     }
3044   }
3045   return false;
3046 }
3047 
3048 } // namespace Fortran::evaluate
3049 
3050 namespace Fortran::semantics {
3051 evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
3052     SemanticsContext &context, common::TypeCategory category,
3053     const std::optional<parser::KindSelector> &selector) {
3054   evaluate::ExpressionAnalyzer analyzer{context};
3055   auto restorer{
3056       analyzer.GetContextualMessages().SetLocation(context.location().value())};
3057   return analyzer.AnalyzeKindSelector(category, selector);
3058 }
3059 
3060 void AnalyzeCallStmt(SemanticsContext &context, const parser::CallStmt &call) {
3061   evaluate::ExpressionAnalyzer{context}.Analyze(call);
3062 }
3063 
3064 const evaluate::Assignment *AnalyzeAssignmentStmt(
3065     SemanticsContext &context, const parser::AssignmentStmt &stmt) {
3066   return evaluate::ExpressionAnalyzer{context}.Analyze(stmt);
3067 }
3068 const evaluate::Assignment *AnalyzePointerAssignmentStmt(
3069     SemanticsContext &context, const parser::PointerAssignmentStmt &stmt) {
3070   return evaluate::ExpressionAnalyzer{context}.Analyze(stmt);
3071 }
3072 
3073 ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {}
3074 
3075 bool ExprChecker::Pre(const parser::DataImpliedDo &ido) {
3076   parser::Walk(std::get<parser::DataImpliedDo::Bounds>(ido.t), *this);
3077   const auto &bounds{std::get<parser::DataImpliedDo::Bounds>(ido.t)};
3078   auto name{bounds.name.thing.thing};
3079   int kind{evaluate::ResultType<evaluate::ImpliedDoIndex>::kind};
3080   if (const auto dynamicType{evaluate::DynamicType::From(*name.symbol)}) {
3081     if (dynamicType->category() == TypeCategory::Integer) {
3082       kind = dynamicType->kind();
3083     }
3084   }
3085   exprAnalyzer_.AddImpliedDo(name.source, kind);
3086   parser::Walk(std::get<std::list<parser::DataIDoObject>>(ido.t), *this);
3087   exprAnalyzer_.RemoveImpliedDo(name.source);
3088   return false;
3089 }
3090 
3091 bool ExprChecker::Walk(const parser::Program &program) {
3092   parser::Walk(program, *this);
3093   return !context_.AnyFatalError();
3094 }
3095 } // namespace Fortran::semantics
3096