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