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