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