1 // Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "expression.h"
16 #include "assignment.h"
17 #include "scope.h"
18 #include "semantics.h"
19 #include "symbol.h"
20 #include "tools.h"
21 #include "../common/idioms.h"
22 #include "../evaluate/check-call.h"
23 #include "../evaluate/common.h"
24 #include "../evaluate/fold.h"
25 #include "../evaluate/tools.h"
26 #include "../parser/characters.h"
27 #include "../parser/parse-tree-visitor.h"
28 #include "../parser/parse-tree.h"
29 #include <algorithm>
30 #include <functional>
31 #include <optional>
32 #include <set>
33
34 // #define DUMP_ON_FAILURE 1
35 // #define CRASH_ON_FAILURE 1
36 #if DUMP_ON_FAILURE
37 #include "../parser/dump-parse-tree.h"
38 #include <iostream>
39 #endif
40
41 // Typedef for optional generic expressions (ubiquitous in this file)
42 using MaybeExpr =
43 std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>;
44
45 // Much of the code that implements semantic analysis of expressions is
46 // tightly coupled with their typed representations in lib/evaluate,
47 // and appears here in namespace Fortran::evaluate for convenience.
48 namespace Fortran::evaluate {
49
50 using common::TypeCategory;
51
52 struct DynamicTypeWithLength : public DynamicType {
DynamicTypeWithLengthFortran::evaluate::DynamicTypeWithLength53 explicit DynamicTypeWithLength(const DynamicType &t) : DynamicType{t} {}
54 std::optional<Expr<SubscriptInteger>> LEN() const;
55 std::optional<Expr<SubscriptInteger>> length;
56 };
57
LEN() const58 std::optional<Expr<SubscriptInteger>> DynamicTypeWithLength::LEN() const {
59 if (length.has_value()) {
60 return length;
61 }
62 if (auto *lengthParam{charLength()}) {
63 if (const auto &len{lengthParam->GetExplicit()}) {
64 return ConvertToType<SubscriptInteger>(common::Clone(*len));
65 }
66 }
67 return std::nullopt;
68 }
69
AnalyzeTypeSpec(const std::optional<parser::TypeSpec> & spec)70 static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
71 const std::optional<parser::TypeSpec> &spec) {
72 if (spec.has_value()) {
73 if (const semantics::DeclTypeSpec * typeSpec{spec->declTypeSpec}) {
74 // Name resolution sets TypeSpec::declTypeSpec only when it's valid
75 // (viz., an intrinsic type with valid known kind or a non-polymorphic
76 // & non-ABSTRACT derived type).
77 if (const semantics::IntrinsicTypeSpec *
78 intrinsic{typeSpec->AsIntrinsic()}) {
79 TypeCategory category{intrinsic->category()};
80 if (auto optKind{ToInt64(intrinsic->kind())}) {
81 int kind{static_cast<int>(*optKind)};
82 if (category == TypeCategory::Character) {
83 const semantics::CharacterTypeSpec &cts{
84 typeSpec->characterTypeSpec()};
85 const semantics::ParamValue &len{cts.length()};
86 // N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() &
87 // type guards, but not in array constructors.
88 return DynamicTypeWithLength{DynamicType{kind, len}};
89 } else {
90 return DynamicTypeWithLength{DynamicType{category, kind}};
91 }
92 }
93 } else if (const semantics::DerivedTypeSpec *
94 derived{typeSpec->AsDerived()}) {
95 return DynamicTypeWithLength{DynamicType{*derived}};
96 }
97 }
98 }
99 return std::nullopt;
100 }
101
102 // Wraps a object in an explicitly typed representation (e.g., Designator<>
103 // or FunctionRef<>) that has been instantiated on a dynamically chosen type.
104 template<TypeCategory CATEGORY, template<typename> typename WRAPPER,
105 typename WRAPPED>
WrapperHelper(int kind,WRAPPED && x)106 common::IfNoLvalue<MaybeExpr, WRAPPED> WrapperHelper(int kind, WRAPPED &&x) {
107 return common::SearchTypes(
108 TypeKindVisitor<CATEGORY, WRAPPER, WRAPPED>{kind, std::move(x)});
109 }
110
111 template<template<typename> typename WRAPPER, typename WRAPPED>
TypedWrapper(const DynamicType & dyType,WRAPPED && x)112 common::IfNoLvalue<MaybeExpr, WRAPPED> TypedWrapper(
113 const DynamicType &dyType, WRAPPED &&x) {
114 switch (dyType.category()) {
115 SWITCH_COVERS_ALL_CASES
116 case TypeCategory::Integer:
117 return WrapperHelper<TypeCategory::Integer, WRAPPER, WRAPPED>(
118 dyType.kind(), std::move(x));
119 case TypeCategory::Real:
120 return WrapperHelper<TypeCategory::Real, WRAPPER, WRAPPED>(
121 dyType.kind(), std::move(x));
122 case TypeCategory::Complex:
123 return WrapperHelper<TypeCategory::Complex, WRAPPER, WRAPPED>(
124 dyType.kind(), std::move(x));
125 case TypeCategory::Character:
126 return WrapperHelper<TypeCategory::Character, WRAPPER, WRAPPED>(
127 dyType.kind(), std::move(x));
128 case TypeCategory::Logical:
129 return WrapperHelper<TypeCategory::Logical, WRAPPER, WRAPPED>(
130 dyType.kind(), std::move(x));
131 case TypeCategory::Derived:
132 return AsGenericExpr(Expr<SomeDerived>{WRAPPER<SomeDerived>{std::move(x)}});
133 }
134 }
135
136 // Wraps a data reference in a typed Designator<>, and a procedure
137 // or procedure pointer reference in a ProcedureDesignator.
Designate(DataRef && ref)138 MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
139 const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
140 if (semantics::IsProcedure(symbol)) {
141 if (auto *component{std::get_if<Component>(&ref.u)}) {
142 return Expr<SomeType>{ProcedureDesignator{std::move(*component)}};
143 } else {
144 CHECK(std::holds_alternative<const Symbol *>(ref.u));
145 return Expr<SomeType>{ProcedureDesignator{symbol}};
146 }
147 } else if (auto dyType{DynamicType::From(symbol)}) {
148 return TypedWrapper<Designator, DataRef>(*dyType, std::move(ref));
149 }
150 return std::nullopt;
151 }
152
153 // Some subscript semantic checks must be deferred until all of the
154 // subscripts are in hand.
CompleteSubscripts(ArrayRef && ref)155 MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
156 const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
157 const auto *object{symbol.detailsIf<semantics::ObjectEntityDetails>()};
158 int symbolRank{symbol.Rank()};
159 int subscripts{static_cast<int>(ref.size())};
160 if (subscripts == 0) {
161 // nothing to check
162 } else if (subscripts != symbolRank) {
163 Say("Reference to rank-%d object '%s' has %d subscripts"_err_en_US,
164 symbolRank, symbol.name(), subscripts);
165 return std::nullopt;
166 } else if (Component * component{ref.base().UnwrapComponent()}) {
167 int baseRank{component->base().Rank()};
168 if (baseRank > 0) {
169 int subscriptRank{0};
170 for (const auto &expr : ref.subscript()) {
171 subscriptRank += expr.Rank();
172 }
173 if (subscriptRank > 0) {
174 Say("Subscripts of component '%s' of rank-%d derived type "
175 "array have rank %d but must all be scalar"_err_en_US,
176 symbol.name(), baseRank, subscriptRank);
177 return std::nullopt;
178 }
179 }
180 } else if (object != nullptr) {
181 // C928 & C1002
182 if (Triplet * last{std::get_if<Triplet>(&ref.subscript().back().u)}) {
183 if (!last->upper().has_value() && object->IsAssumedSize()) {
184 Say("Assumed-size array '%s' must have explicit final "
185 "subscript upper bound value"_err_en_US,
186 symbol.name());
187 return std::nullopt;
188 }
189 }
190 }
191 return Designate(DataRef{std::move(ref)});
192 }
193
194 // Applies subscripts to a data reference.
ApplySubscripts(DataRef && dataRef,std::vector<Subscript> && subscripts)195 MaybeExpr ExpressionAnalyzer::ApplySubscripts(
196 DataRef &&dataRef, std::vector<Subscript> &&subscripts) {
197 return std::visit(
198 common::visitors{
199 [&](const Symbol *symbol) {
200 return CompleteSubscripts(ArrayRef{*symbol, std::move(subscripts)});
201 },
202 [&](Component &&c) {
203 return CompleteSubscripts(
204 ArrayRef{std::move(c), std::move(subscripts)});
205 },
206 [&](auto &&) -> MaybeExpr {
207 DIE("bad base for ArrayRef");
208 return std::nullopt;
209 },
210 },
211 std::move(dataRef.u));
212 }
213
214 // Top-level checks for data references.
TopLevelChecks(DataRef && dataRef)215 MaybeExpr ExpressionAnalyzer::TopLevelChecks(DataRef &&dataRef) {
216 if (Component * component{std::get_if<Component>(&dataRef.u)}) {
217 const Symbol &symbol{component->GetLastSymbol()};
218 int componentRank{symbol.Rank()};
219 if (componentRank > 0) {
220 int baseRank{component->base().Rank()};
221 if (baseRank > 0) {
222 Say("Reference to whole rank-%d component '%%%s' of "
223 "rank-%d array of derived type is not allowed"_err_en_US,
224 componentRank, symbol.name(), baseRank);
225 }
226 }
227 }
228 return Designate(std::move(dataRef));
229 }
230
231 // Parse tree correction after a substring S(j:k) was misparsed as an
232 // array section. N.B. Fortran substrings have to have a range, not a
233 // single index.
FixMisparsedSubstring(const parser::Designator & d)234 static void FixMisparsedSubstring(const parser::Designator &d) {
235 auto &mutate{const_cast<parser::Designator &>(d)};
236 if (auto *dataRef{std::get_if<parser::DataRef>(&mutate.u)}) {
237 if (auto *ae{std::get_if<common::Indirection<parser::ArrayElement>>(
238 &dataRef->u)}) {
239 parser::ArrayElement &arrElement{ae->value()};
240 if (!arrElement.subscripts.empty()) {
241 auto iter{arrElement.subscripts.begin()};
242 if (auto *triplet{std::get_if<parser::SubscriptTriplet>(&iter->u)}) {
243 if (!std::get<2>(triplet->t).has_value() /* no stride */ &&
244 ++iter == arrElement.subscripts.end() /* one subscript */) {
245 if (Symbol *
246 symbol{std::visit(
247 common::visitors{
248 [](parser::Name &n) { return n.symbol; },
249 [](common::Indirection<parser::StructureComponent>
250 &sc) { return sc.value().component.symbol; },
251 [](auto &) -> Symbol * { return nullptr; },
252 },
253 arrElement.base.u)}) {
254 const Symbol &ultimate{symbol->GetUltimate()};
255 if (const semantics::DeclTypeSpec * type{ultimate.GetType()}) {
256 if (!ultimate.IsObjectArray() &&
257 type->category() == semantics::DeclTypeSpec::Character) {
258 // The ambiguous S(j:k) was parsed as an array section
259 // reference, but it's now clear that it's a substring.
260 // Fix the parse tree in situ.
261 mutate.u = arrElement.ConvertToSubstring();
262 }
263 }
264 }
265 }
266 }
267 }
268 }
269 }
270 }
271
Analyze(const parser::Designator & d)272 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
273 auto save{GetContextualMessages().SetLocation(d.source)};
274 FixMisparsedSubstring(d);
275 // These checks have to be deferred to these "top level" data-refs where
276 // we can be sure that there are no following subscripts (yet).
277 if (MaybeExpr result{Analyze(d.u)}) {
278 if (std::optional<evaluate::DataRef> dataRef{
279 evaluate::ExtractDataRef(std::move(result))}) {
280 return TopLevelChecks(std::move(*dataRef));
281 }
282 return result;
283 }
284 return std::nullopt;
285 }
286
287 // A utility subroutine to repackage optional expressions of various levels
288 // of type specificity as fully general MaybeExpr values.
AsMaybeExpr(A && x)289 template<typename A> common::IfNoLvalue<MaybeExpr, A> AsMaybeExpr(A &&x) {
290 return std::make_optional(AsGenericExpr(std::move(x)));
291 }
AsMaybeExpr(std::optional<A> && x)292 template<typename A> MaybeExpr AsMaybeExpr(std::optional<A> &&x) {
293 if (x.has_value()) {
294 return AsMaybeExpr(std::move(*x));
295 }
296 return std::nullopt;
297 }
298
299 // Type kind parameter values for literal constants.
AnalyzeKindParam(const std::optional<parser::KindParam> & kindParam,int defaultKind)300 int ExpressionAnalyzer::AnalyzeKindParam(
301 const std::optional<parser::KindParam> &kindParam, int defaultKind) {
302 if (!kindParam.has_value()) {
303 return defaultKind;
304 }
305 return std::visit(
306 common::visitors{
307 [](std::uint64_t k) { return static_cast<int>(k); },
308 [&](const parser::Scalar<
309 parser::Integer<parser::Constant<parser::Name>>> &n) {
310 if (MaybeExpr ie{Analyze(n)}) {
311 if (std::optional<std::int64_t> i64{ToInt64(*ie)}) {
312 int iv = *i64;
313 if (iv == *i64) {
314 return iv;
315 }
316 }
317 }
318 return defaultKind;
319 },
320 },
321 kindParam->u);
322 }
323
324 // Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant
325 struct IntTypeVisitor {
326 using Result = MaybeExpr;
327 using Types = IntegerTypes;
TestFortran::evaluate::IntTypeVisitor328 template<typename T> Result Test() {
329 if (T::kind >= kind) {
330 const char *p{digits.begin()};
331 auto value{T::Scalar::Read(p, 10, true /*signed*/)};
332 if (!value.overflow) {
333 if (T::kind > kind) {
334 if (!isDefaultKind ||
335 !analyzer.context().IsEnabled(
336 parser::LanguageFeature::BigIntLiterals)) {
337 return std::nullopt;
338 } else if (analyzer.context().ShouldWarn(
339 parser::LanguageFeature::BigIntLiterals)) {
340 analyzer.Say(digits,
341 "Integer literal is too large for default INTEGER(KIND=%d); "
342 "assuming INTEGER(KIND=%d)"_en_US,
343 kind, T::kind);
344 }
345 }
346 return Expr<SomeType>{
347 Expr<SomeInteger>{Expr<T>{Constant<T>{std::move(value.value)}}}};
348 }
349 }
350 return std::nullopt;
351 }
352 ExpressionAnalyzer &analyzer;
353 parser::CharBlock digits;
354 int kind;
355 bool isDefaultKind;
356 };
357
358 template<typename PARSED>
IntLiteralConstant(const PARSED & x)359 MaybeExpr ExpressionAnalyzer::IntLiteralConstant(const PARSED &x) {
360 const auto &kindParam{std::get<std::optional<parser::KindParam>>(x.t)};
361 bool isDefaultKind{!kindParam.has_value()};
362 int kind{AnalyzeKindParam(kindParam, GetDefaultKind(TypeCategory::Integer))};
363 if (CheckIntrinsicKind(TypeCategory::Integer, kind)) {
364 auto digits{std::get<parser::CharBlock>(x.t)};
365 if (MaybeExpr result{common::SearchTypes(
366 IntTypeVisitor{*this, digits, kind, isDefaultKind})}) {
367 return result;
368 } else if (isDefaultKind) {
369 Say(digits,
370 "Integer literal is too large for any allowable "
371 "kind of INTEGER"_err_en_US);
372 } else {
373 Say(digits, "Integer literal is too large for INTEGER(KIND=%d)"_err_en_US,
374 kind);
375 }
376 }
377 return std::nullopt;
378 }
379
Analyze(const parser::IntLiteralConstant & x)380 MaybeExpr ExpressionAnalyzer::Analyze(const parser::IntLiteralConstant &x) {
381 return IntLiteralConstant(x);
382 }
383
Analyze(const parser::SignedIntLiteralConstant & x)384 MaybeExpr ExpressionAnalyzer::Analyze(
385 const parser::SignedIntLiteralConstant &x) {
386 return IntLiteralConstant(x);
387 }
388
389 template<typename TYPE>
ReadRealLiteral(parser::CharBlock source,FoldingContext & context)390 Constant<TYPE> ReadRealLiteral(
391 parser::CharBlock source, FoldingContext &context) {
392 const char *p{source.begin()};
393 auto valWithFlags{Scalar<TYPE>::Read(p, context.rounding())};
394 CHECK(p == source.end());
395 RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
396 auto value{valWithFlags.value};
397 if (context.flushSubnormalsToZero()) {
398 value = value.FlushSubnormalToZero();
399 }
400 return {value};
401 }
402
403 struct RealTypeVisitor {
404 using Result = std::optional<Expr<SomeReal>>;
405 using Types = RealTypes;
406
RealTypeVisitorFortran::evaluate::RealTypeVisitor407 RealTypeVisitor(int k, parser::CharBlock lit, FoldingContext &ctx)
408 : kind{k}, literal{lit}, context{ctx} {}
409
TestFortran::evaluate::RealTypeVisitor410 template<typename T> Result Test() {
411 if (kind == T::kind) {
412 return {AsCategoryExpr(ReadRealLiteral<T>(literal, context))};
413 }
414 return std::nullopt;
415 }
416
417 int kind;
418 parser::CharBlock literal;
419 FoldingContext &context;
420 };
421
422 // Reads a real literal constant and encodes it with the right kind.
Analyze(const parser::RealLiteralConstant & x)423 MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
424 // Use a local message context around the real literal for better
425 // provenance on any messages.
426 auto save{GetContextualMessages().SetLocation(x.real.source)};
427 // If a kind parameter appears, it defines the kind of the literal and any
428 // letter used in an exponent part (e.g., the 'E' in "6.02214E+23")
429 // should agree. In the absence of an explicit kind parameter, any exponent
430 // letter determines the kind. Otherwise, defaults apply.
431 auto &defaults{context_.defaultKinds()};
432 int defaultKind{defaults.GetDefaultKind(TypeCategory::Real)};
433 const char *end{x.real.source.end()};
434 char expoLetter{' '};
435 std::optional<int> letterKind;
436 for (const char *p{x.real.source.begin()}; p < end; ++p) {
437 if (parser::IsLetter(*p)) {
438 expoLetter = *p;
439 switch (expoLetter) {
440 case 'e': letterKind = defaults.GetDefaultKind(TypeCategory::Real); break;
441 case 'd': letterKind = defaults.doublePrecisionKind(); break;
442 case 'q': letterKind = defaults.quadPrecisionKind(); break;
443 default: Say("Unknown exponent letter '%c'"_err_en_US, expoLetter);
444 }
445 break;
446 }
447 }
448 if (letterKind.has_value()) {
449 defaultKind = *letterKind;
450 }
451 auto kind{AnalyzeKindParam(x.kind, defaultKind)};
452 if (letterKind.has_value() && kind != *letterKind && expoLetter != 'e') {
453 Say("Explicit kind parameter on real constant disagrees with "
454 "exponent letter '%c'"_en_US,
455 expoLetter);
456 }
457 auto result{common::SearchTypes(
458 RealTypeVisitor{kind, x.real.source, GetFoldingContext()})};
459 if (!result.has_value()) {
460 Say("Unsupported REAL(KIND=%d)"_err_en_US, kind);
461 }
462 return AsMaybeExpr(std::move(result));
463 }
464
Analyze(const parser::SignedRealLiteralConstant & x)465 MaybeExpr ExpressionAnalyzer::Analyze(
466 const parser::SignedRealLiteralConstant &x) {
467 if (auto result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) {
468 auto &realExpr{std::get<Expr<SomeReal>>(result->u)};
469 if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
470 if (sign == parser::Sign::Negative) {
471 return {AsGenericExpr(-std::move(realExpr))};
472 }
473 }
474 return result;
475 }
476 return std::nullopt;
477 }
478
Analyze(const parser::ComplexPart & x)479 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexPart &x) {
480 return Analyze(x.u);
481 }
482
Analyze(const parser::ComplexLiteralConstant & z)483 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexLiteralConstant &z) {
484 return AsMaybeExpr(
485 ConstructComplex(GetContextualMessages(), Analyze(std::get<0>(z.t)),
486 Analyze(std::get<1>(z.t)), GetDefaultKind(TypeCategory::Real)));
487 }
488
489 // CHARACTER literal processing.
AnalyzeString(std::string && string,int kind)490 MaybeExpr ExpressionAnalyzer::AnalyzeString(std::string &&string, int kind) {
491 if (!CheckIntrinsicKind(TypeCategory::Character, kind)) {
492 return std::nullopt;
493 }
494 switch (kind) {
495 case 1:
496 return AsGenericExpr(Constant<Type<TypeCategory::Character, 1>>{
497 parser::DecodeString<std::string, parser::Encoding::LATIN_1>(
498 string, true)});
499 case 2:
500 return AsGenericExpr(Constant<Type<TypeCategory::Character, 2>>{
501 parser::DecodeString<std::u16string, parser::Encoding::UTF_8>(
502 string, true)});
503 case 4:
504 return AsGenericExpr(Constant<Type<TypeCategory::Character, 4>>{
505 parser::DecodeString<std::u32string, parser::Encoding::UTF_8>(
506 string, true)});
507 default: CRASH_NO_CASE;
508 }
509 }
510
Analyze(const parser::CharLiteralConstant & x)511 MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) {
512 int kind{
513 AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t), 1)};
514 auto value{std::get<std::string>(x.t)};
515 return AnalyzeString(std::move(value), kind);
516 }
517
Analyze(const parser::HollerithLiteralConstant & x)518 MaybeExpr ExpressionAnalyzer::Analyze(
519 const parser::HollerithLiteralConstant &x) {
520 int kind{GetDefaultKind(TypeCategory::Character)};
521 auto value{x.v};
522 return AnalyzeString(std::move(value), kind);
523 }
524
525 // .TRUE. and .FALSE. of various kinds
Analyze(const parser::LogicalLiteralConstant & x)526 MaybeExpr ExpressionAnalyzer::Analyze(const parser::LogicalLiteralConstant &x) {
527 auto kind{AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t),
528 GetDefaultKind(TypeCategory::Logical))};
529 bool value{std::get<bool>(x.t)};
530 auto result{common::SearchTypes(
531 TypeKindVisitor<TypeCategory::Logical, Constant, bool>{
532 kind, std::move(value)})};
533 if (!result.has_value()) {
534 Say("unsupported LOGICAL(KIND=%d)"_err_en_US, kind);
535 }
536 return result;
537 }
538
539 // BOZ typeless literals
Analyze(const parser::BOZLiteralConstant & x)540 MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
541 const char *p{x.v.c_str()};
542 std::uint64_t base{16};
543 switch (*p++) {
544 case 'b': base = 2; break;
545 case 'o': base = 8; break;
546 case 'z': break;
547 case 'x': break;
548 default: CRASH_NO_CASE;
549 }
550 CHECK(*p == '"');
551 ++p;
552 auto value{BOZLiteralConstant::Read(p, base, false /*unsigned*/)};
553 if (*p != '"') {
554 Say("Invalid digit ('%c') in BOZ literal '%s'"_err_en_US, *p, x.v);
555 return std::nullopt;
556 }
557 if (value.overflow) {
558 Say("BOZ literal '%s' too large"_err_en_US, x.v);
559 return std::nullopt;
560 }
561 return {AsGenericExpr(std::move(value.value))};
562 }
563
564 // For use with SearchTypes to create a TypeParamInquiry with the
565 // right integer kind.
566 struct TypeParamInquiryVisitor {
567 using Result = std::optional<Expr<SomeInteger>>;
568 using Types = IntegerTypes;
TypeParamInquiryVisitorFortran::evaluate::TypeParamInquiryVisitor569 TypeParamInquiryVisitor(int k, NamedEntity &&b, const Symbol ¶m)
570 : kind{k}, base{std::move(b)}, parameter{param} {}
TypeParamInquiryVisitorFortran::evaluate::TypeParamInquiryVisitor571 TypeParamInquiryVisitor(int k, const Symbol ¶m)
572 : kind{k}, parameter{param} {}
TestFortran::evaluate::TypeParamInquiryVisitor573 template<typename T> Result Test() {
574 if (kind == T::kind) {
575 return Expr<SomeInteger>{
576 Expr<T>{TypeParamInquiry<T::kind>{std::move(base), parameter}}};
577 }
578 return std::nullopt;
579 }
580 int kind;
581 std::optional<NamedEntity> base;
582 const Symbol ¶meter;
583 };
584
MakeBareTypeParamInquiry(const Symbol * symbol)585 static std::optional<Expr<SomeInteger>> MakeBareTypeParamInquiry(
586 const Symbol *symbol) {
587 if (std::optional<DynamicType> dyType{DynamicType::From(symbol)}) {
588 if (dyType->category() == TypeCategory::Integer) {
589 return common::SearchTypes(
590 TypeParamInquiryVisitor{dyType->kind(), *symbol});
591 }
592 }
593 return std::nullopt;
594 }
595
596 // Names and named constants
Analyze(const parser::Name & n)597 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
598 if (std::optional<int> kind{IsAcImpliedDo(n.source)}) {
599 return AsMaybeExpr(ConvertToKind<TypeCategory::Integer>(
600 *kind, AsExpr(ImpliedDoIndex{n.source})));
601 } else if (context_.HasError(n)) {
602 return std::nullopt;
603 } else {
604 const Symbol &ultimate{n.symbol->GetUltimate()};
605 if (ultimate.has<semantics::TypeParamDetails>()) {
606 // A bare reference to a derived type parameter (within a parameterized
607 // derived type definition)
608 return AsMaybeExpr(MakeBareTypeParamInquiry(&ultimate));
609 } else {
610 return Designate(DataRef{*n.symbol});
611 }
612 }
613 }
614
Analyze(const parser::NamedConstant & n)615 MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) {
616 if (MaybeExpr value{Analyze(n.v)}) {
617 Expr<SomeType> folded{Fold(GetFoldingContext(), std::move(*value))};
618 if (IsConstantExpr(folded)) {
619 return {folded};
620 }
621 Say(n.v.source, "must be a constant"_err_en_US);
622 }
623 return std::nullopt;
624 }
625
626 // Substring references
GetSubstringBound(const std::optional<parser::ScalarIntExpr> & bound)627 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::GetSubstringBound(
628 const std::optional<parser::ScalarIntExpr> &bound) {
629 if (bound.has_value()) {
630 if (MaybeExpr expr{Analyze(*bound)}) {
631 if (expr->Rank() > 1) {
632 Say("substring bound expression has rank %d"_err_en_US, expr->Rank());
633 }
634 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
635 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
636 return {std::move(*ssIntExpr)};
637 }
638 return {Expr<SubscriptInteger>{
639 Convert<SubscriptInteger, TypeCategory::Integer>{
640 std::move(*intExpr)}}};
641 } else {
642 Say("substring bound expression is not INTEGER"_err_en_US);
643 }
644 }
645 }
646 return std::nullopt;
647 }
648
Analyze(const parser::Substring & ss)649 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
650 if (MaybeExpr baseExpr{Analyze(std::get<parser::DataRef>(ss.t))}) {
651 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) {
652 if (MaybeExpr newBaseExpr{TopLevelChecks(std::move(*dataRef))}) {
653 if (std::optional<DataRef> checked{
654 ExtractDataRef(std::move(*newBaseExpr))}) {
655 const parser::SubstringRange &range{
656 std::get<parser::SubstringRange>(ss.t)};
657 std::optional<Expr<SubscriptInteger>> first{
658 GetSubstringBound(std::get<0>(range.t))};
659 std::optional<Expr<SubscriptInteger>> last{
660 GetSubstringBound(std::get<1>(range.t))};
661 const Symbol &symbol{checked->GetLastSymbol()};
662 if (std::optional<DynamicType> dynamicType{
663 DynamicType::From(symbol)}) {
664 if (dynamicType->category() == TypeCategory::Character) {
665 return WrapperHelper<TypeCategory::Character, Designator,
666 Substring>(dynamicType->kind(),
667 Substring{std::move(checked.value()), std::move(first),
668 std::move(last)});
669 }
670 }
671 Say("substring may apply only to CHARACTER"_err_en_US);
672 }
673 }
674 }
675 }
676 return std::nullopt;
677 }
678
679 // CHARACTER literal substrings
Analyze(const parser::CharLiteralConstantSubstring & x)680 MaybeExpr ExpressionAnalyzer::Analyze(
681 const parser::CharLiteralConstantSubstring &x) {
682 const parser::SubstringRange &range{std::get<parser::SubstringRange>(x.t)};
683 std::optional<Expr<SubscriptInteger>> lower{
684 GetSubstringBound(std::get<0>(range.t))};
685 std::optional<Expr<SubscriptInteger>> upper{
686 GetSubstringBound(std::get<1>(range.t))};
687 if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) {
688 if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) {
689 Expr<SubscriptInteger> length{
690 std::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); },
691 charExpr->u)};
692 if (!lower.has_value()) {
693 lower = Expr<SubscriptInteger>{1};
694 }
695 if (!upper.has_value()) {
696 upper = Expr<SubscriptInteger>{
697 static_cast<std::int64_t>(ToInt64(length).value())};
698 }
699 return std::visit(
700 [&](auto &&ckExpr) -> MaybeExpr {
701 using Result = ResultType<decltype(ckExpr)>;
702 auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)};
703 CHECK(DEREF(cp).size() == 1);
704 StaticDataObject::Pointer staticData{StaticDataObject::Create()};
705 staticData->set_alignment(Result::kind)
706 .set_itemBytes(Result::kind)
707 .Push(cp->GetScalarValue().value());
708 Substring substring{std::move(staticData), std::move(lower.value()),
709 std::move(upper.value())};
710 return AsGenericExpr(Expr<SomeCharacter>{
711 Expr<Result>{Designator<Result>{std::move(substring)}}});
712 },
713 std::move(charExpr->u));
714 }
715 }
716 return std::nullopt;
717 }
718
719 // Subscripted array references
AsSubscript(MaybeExpr && expr)720 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::AsSubscript(
721 MaybeExpr &&expr) {
722 if (expr.has_value()) {
723 if (expr->Rank() > 1) {
724 Say("subscript expression has rank %d"_err_en_US, expr->Rank());
725 }
726 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
727 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
728 return {std::move(*ssIntExpr)};
729 }
730 return {Expr<SubscriptInteger>{
731 Convert<SubscriptInteger, TypeCategory::Integer>{
732 std::move(*intExpr)}}};
733 } else {
734 Say("subscript expression is not INTEGER"_err_en_US);
735 }
736 }
737 return std::nullopt;
738 }
739
TripletPart(const std::optional<parser::Subscript> & s)740 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
741 const std::optional<parser::Subscript> &s) {
742 if (s.has_value()) {
743 return AsSubscript(Analyze(*s));
744 }
745 return std::nullopt;
746 }
747
AnalyzeSectionSubscript(const parser::SectionSubscript & ss)748 std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
749 const parser::SectionSubscript &ss) {
750 return std::visit(
751 common::visitors{
752 [&](const parser::SubscriptTriplet &t) {
753 return std::make_optional(Subscript{Triplet{
754 TripletPart(std::get<0>(t.t)), TripletPart(std::get<1>(t.t)),
755 TripletPart(std::get<2>(t.t))}});
756 },
757 [&](const auto &s) -> std::optional<Subscript> {
758 if (auto subscriptExpr{AsSubscript(Analyze(s))}) {
759 return Subscript{std::move(*subscriptExpr)};
760 } else {
761 return std::nullopt;
762 }
763 },
764 },
765 ss.u);
766 }
767
768 // Empty result means an error occurred
AnalyzeSectionSubscripts(const std::list<parser::SectionSubscript> & sss)769 std::vector<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscripts(
770 const std::list<parser::SectionSubscript> &sss) {
771 bool error{false};
772 std::vector<Subscript> subscripts;
773 for (const auto &s : sss) {
774 if (auto subscript{AnalyzeSectionSubscript(s)}) {
775 subscripts.emplace_back(std::move(*subscript));
776 } else {
777 error = true;
778 }
779 }
780 return !error ? subscripts : std::vector<Subscript>{};
781 }
782
Analyze(const parser::ArrayElement & ae)783 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {
784 std::vector<Subscript> subscripts{AnalyzeSectionSubscripts(ae.subscripts)};
785 if (MaybeExpr baseExpr{Analyze(ae.base)}) {
786 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) {
787 if (!subscripts.empty()) {
788 return ApplySubscripts(std::move(*dataRef), std::move(subscripts));
789 }
790 } else {
791 Say("Subscripts may be applied only to an object, component, or array constant"_err_en_US);
792 }
793 }
794 return std::nullopt;
795 }
796
797 // Type parameter inquiries apply to data references, but don't depend
798 // on any trailing (co)subscripts.
IgnoreAnySubscripts(Designator<SomeDerived> && designator)799 static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) {
800 return std::visit(
801 common::visitors{
802 [](const Symbol *symbol) { return NamedEntity{*symbol}; },
803 [](Component &&component) {
804 return NamedEntity{std::move(component)};
805 },
806 [](ArrayRef &&arrayRef) { return std::move(arrayRef.base()); },
807 [](CoarrayRef &&coarrayRef) {
808 return NamedEntity{coarrayRef.GetLastSymbol()};
809 },
810 },
811 std::move(designator.u));
812 }
813
814 // Components of parent derived types are explicitly represented as such.
CreateComponent(DataRef && base,const Symbol & component,const semantics::Scope & scope)815 static std::optional<Component> CreateComponent(
816 DataRef &&base, const Symbol &component, const semantics::Scope &scope) {
817 if (&component.owner() == &scope) {
818 return Component{std::move(base), component};
819 }
820 if (const semantics::Scope * parentScope{scope.GetDerivedTypeParent()}) {
821 if (const Symbol * parentComponent{parentScope->GetSymbol()}) {
822 return CreateComponent(
823 DataRef{Component{std::move(base), *parentComponent}}, component,
824 *parentScope);
825 }
826 }
827 return std::nullopt;
828 }
829
830 // Derived type component references and type parameter inquiries
Analyze(const parser::StructureComponent & sc)831 MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
832 MaybeExpr base{Analyze(sc.base)};
833 if (!base) {
834 return std::nullopt;
835 }
836 Symbol *sym{sc.component.symbol};
837 if (context_.HasError(sym)) {
838 return std::nullopt;
839 }
840 const auto &name{sc.component.source};
841 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
842 const semantics::DerivedTypeSpec *dtSpec{nullptr};
843 if (std::optional<DynamicType> dtDyTy{dtExpr->GetType()}) {
844 if (!dtDyTy->IsUnlimitedPolymorphic()) {
845 dtSpec = &dtDyTy->GetDerivedTypeSpec();
846 }
847 }
848 if (sym->detailsIf<semantics::TypeParamDetails>()) {
849 if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
850 if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
851 if (dyType->category() == TypeCategory::Integer) {
852 return AsMaybeExpr(
853 common::SearchTypes(TypeParamInquiryVisitor{dyType->kind(),
854 IgnoreAnySubscripts(std::move(*designator)), *sym}));
855 }
856 }
857 Say(name, "Type parameter is not INTEGER"_err_en_US);
858 } else {
859 Say(name,
860 "A type parameter inquiry must be applied to "
861 "a designator"_err_en_US);
862 }
863 } else if (dtSpec == nullptr || dtSpec->scope() == nullptr) {
864 CHECK(context_.AnyFatalError());
865 return std::nullopt;
866 } else if (std::optional<DataRef> dataRef{
867 ExtractDataRef(std::move(*dtExpr))}) {
868 if (auto component{
869 CreateComponent(std::move(*dataRef), *sym, *dtSpec->scope())}) {
870 return Designate(DataRef{std::move(*component)});
871 } else {
872 Say(name, "Component is not in scope of derived TYPE(%s)"_err_en_US,
873 dtSpec->typeSymbol().name());
874 }
875 } else {
876 Say(name,
877 "Base of component reference must be a data reference"_err_en_US);
878 }
879 } else if (auto *details{sym->detailsIf<semantics::MiscDetails>()}) {
880 // special part-ref: %re, %im, %kind, %len
881 // Type errors are detected and reported in semantics.
882 using MiscKind = semantics::MiscDetails::Kind;
883 MiscKind kind{details->kind()};
884 if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) {
885 if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) {
886 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*zExpr))}) {
887 Expr<SomeReal> realExpr{std::visit(
888 [&](const auto &z) {
889 using PartType = typename ResultType<decltype(z)>::Part;
890 auto part{kind == MiscKind::ComplexPartRe
891 ? ComplexPart::Part::RE
892 : ComplexPart::Part::IM};
893 return AsCategoryExpr(Designator<PartType>{
894 ComplexPart{std::move(*dataRef), part}});
895 },
896 zExpr->u)};
897 return {AsGenericExpr(std::move(realExpr))};
898 }
899 }
900 } else if (kind == MiscKind::KindParamInquiry ||
901 kind == MiscKind::LenParamInquiry) {
902 // Convert x%KIND -> intrinsic KIND(x), x%LEN -> intrinsic LEN(x)
903 return MakeFunctionRef(
904 name, ActualArguments{ActualArgument{std::move(*base)}});
905 } else {
906 DIE("unexpected MiscDetails::Kind");
907 }
908 } else {
909 Say(name, "derived type required before component reference"_err_en_US);
910 }
911 return std::nullopt;
912 }
913
Analyze(const parser::CoindexedNamedObject & x)914 MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) {
915 if (auto dataRef{ExtractDataRef(Analyze(x.base))}) {
916 std::vector<Subscript> subscripts;
917 std::vector<const Symbol *> reversed;
918 if (auto *aRef{std::get_if<ArrayRef>(&dataRef->u)}) {
919 subscripts = std::move(aRef->subscript());
920 reversed.push_back(&aRef->GetLastSymbol());
921 if (Component * component{aRef->base().UnwrapComponent()}) {
922 *dataRef = std::move(component->base());
923 } else {
924 dataRef.reset();
925 }
926 }
927 if (dataRef.has_value()) {
928 while (auto *component{std::get_if<Component>(&dataRef->u)}) {
929 reversed.push_back(&component->GetLastSymbol());
930 *dataRef = std::move(component->base());
931 }
932 if (auto *baseSym{std::get_if<const Symbol *>(&dataRef->u)}) {
933 reversed.push_back(*baseSym);
934 } else {
935 Say("Base of coindexed named object has subscripts or cosubscripts"_err_en_US);
936 }
937 }
938 std::vector<Expr<SubscriptInteger>> cosubscripts;
939 bool cosubsOk{true};
940 for (const auto &cosub :
941 std::get<std::list<parser::Cosubscript>>(x.imageSelector.t)) {
942 MaybeExpr coex{Analyze(cosub)};
943 if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(coex)}) {
944 cosubscripts.push_back(
945 ConvertToType<SubscriptInteger>(std::move(*intExpr)));
946 } else {
947 cosubsOk = false;
948 }
949 }
950 if (cosubsOk && !reversed.empty()) {
951 int numCosubscripts{static_cast<int>(cosubscripts.size())};
952 const Symbol &symbol{*reversed.front()};
953 if (numCosubscripts != symbol.Corank()) {
954 Say("'%s' has corank %d, but coindexed reference has %d cosubscripts"_err_en_US,
955 symbol.name(), symbol.Corank(), numCosubscripts);
956 }
957 }
958 // TODO: stat=/team=/team_number=
959 // Reverse the chain of symbols so that the base is first and coarray
960 // ultimate component is last.
961 return Designate(DataRef{CoarrayRef{
962 std::vector<const Symbol *>{reversed.crbegin(), reversed.crend()},
963 std::move(subscripts), std::move(cosubscripts)}});
964 }
965 return std::nullopt;
966 }
967
IntegerTypeSpecKind(const parser::IntegerTypeSpec & spec)968 int ExpressionAnalyzer::IntegerTypeSpecKind(
969 const parser::IntegerTypeSpec &spec) {
970 Expr<SubscriptInteger> value{
971 AnalyzeKindSelector(TypeCategory::Integer, spec.v)};
972 if (auto kind{ToInt64(value)}) {
973 return static_cast<int>(*kind);
974 }
975 SayAt(spec, "Constant INTEGER kind value required here"_err_en_US);
976 return GetDefaultKind(TypeCategory::Integer);
977 }
978
979 // Array constructors
980
981 class ArrayConstructorContext : private ExpressionAnalyzer {
982 public:
ArrayConstructorContext(ExpressionAnalyzer & c,std::optional<DynamicTypeWithLength> & t)983 ArrayConstructorContext(
984 ExpressionAnalyzer &c, std::optional<DynamicTypeWithLength> &t)
985 : ExpressionAnalyzer{c}, type_{t} {}
986 ArrayConstructorContext(ArrayConstructorContext &) = default;
987 void Push(MaybeExpr &&);
988 void Add(const parser::AcValue &);
type() const989 std::optional<DynamicTypeWithLength> &type() const { return type_; }
values()990 const ArrayConstructorValues<SomeType> &values() { return values_; }
991
992 private:
993 template<int KIND, typename A>
GetSpecificIntExpr(const A & x)994 std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr(
995 const A &x) {
996 if (MaybeExpr y{Analyze(x)}) {
997 Expr<SomeInteger> *intExpr{UnwrapExpr<Expr<SomeInteger>>(*y)};
998 CHECK(intExpr != nullptr);
999 return ConvertToType<Type<TypeCategory::Integer, KIND>>(
1000 std::move(*intExpr));
1001 }
1002 return std::nullopt;
1003 }
1004
1005 std::optional<DynamicTypeWithLength> &type_;
1006 bool explicitType_{type_.has_value()};
1007 std::optional<std::int64_t> constantLength_;
1008 ArrayConstructorValues<SomeType> values_;
1009 };
1010
Push(MaybeExpr && x)1011 void ArrayConstructorContext::Push(MaybeExpr &&x) {
1012 if (!x.has_value()) {
1013 return;
1014 }
1015 if (auto dyType{x->GetType()}) {
1016 DynamicTypeWithLength xType{*dyType};
1017 if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) {
1018 CHECK(xType.category() == TypeCategory::Character);
1019 xType.length =
1020 std::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
1021 }
1022 if (!type_.has_value()) {
1023 // If there is no explicit type-spec in an array constructor, the type
1024 // of the array is the declared type of all of the elements, which must
1025 // be well-defined and all match.
1026 // TODO: Possible language extension: use the most general type of
1027 // the values as the type of a numeric constructed array, convert all
1028 // of the other values to that type. Alternative: let the first value
1029 // determine the type, and convert the others to that type.
1030 CHECK(!explicitType_);
1031 type_ = std::move(xType);
1032 constantLength_ = ToInt64(type_->length);
1033 values_.Push(std::move(*x));
1034 } else if (!explicitType_) {
1035 if (static_cast<const DynamicType &>(*type_) ==
1036 static_cast<const DynamicType &>(xType)) {
1037 values_.Push(std::move(*x));
1038 if (auto thisLen{ToInt64(xType.LEN())}) {
1039 if (constantLength_.has_value()) {
1040 if (context().warnOnNonstandardUsage() &&
1041 *thisLen != *constantLength_) {
1042 Say("Character literal in array constructor without explicit "
1043 "type has different length than earlier element"_en_US);
1044 }
1045 if (*thisLen > *constantLength_) {
1046 // Language extension: use the longest literal to determine the
1047 // length of the array constructor's character elements, not the
1048 // first, when there is no explicit type.
1049 *constantLength_ = *thisLen;
1050 type_->length = xType.LEN();
1051 }
1052 } else {
1053 constantLength_ = *thisLen;
1054 type_->length = xType.LEN();
1055 }
1056 }
1057 } else {
1058 Say("Values in array constructor must have the same declared type "
1059 "when no explicit type appears"_err_en_US);
1060 }
1061 } else {
1062 if (auto cast{ConvertToType(*type_, std::move(*x))}) {
1063 values_.Push(std::move(*cast));
1064 } else {
1065 Say("Value in array constructor could not be converted to the type "
1066 "of the array"_err_en_US);
1067 }
1068 }
1069 }
1070 }
1071
Add(const parser::AcValue & x)1072 void ArrayConstructorContext::Add(const parser::AcValue &x) {
1073 using IntType = ResultType<ImpliedDoIndex>;
1074 std::visit(
1075 common::visitors{
1076 [&](const parser::AcValue::Triplet &triplet) {
1077 // Transform l:u(:s) into (_,_=l,u(,s)) with an anonymous index '_'
1078 std::optional<Expr<IntType>> lower{
1079 GetSpecificIntExpr<IntType::kind>(std::get<0>(triplet.t))};
1080 std::optional<Expr<IntType>> upper{
1081 GetSpecificIntExpr<IntType::kind>(std::get<1>(triplet.t))};
1082 std::optional<Expr<IntType>> stride{
1083 GetSpecificIntExpr<IntType::kind>(std::get<2>(triplet.t))};
1084 if (lower.has_value() && upper.has_value()) {
1085 if (!stride.has_value()) {
1086 stride = Expr<IntType>{1};
1087 }
1088 if (!type_.has_value()) {
1089 type_ = DynamicTypeWithLength{IntType::GetType()};
1090 }
1091 ArrayConstructorContext nested{*this};
1092 parser::CharBlock name;
1093 nested.Push(Expr<SomeType>{
1094 Expr<SomeInteger>{Expr<IntType>{ImpliedDoIndex{name}}}});
1095 values_.Push(ImpliedDo<SomeType>{name, std::move(*lower),
1096 std::move(*upper), std::move(*stride),
1097 std::move(nested.values_)});
1098 }
1099 },
1100 [&](const common::Indirection<parser::Expr> &expr) {
1101 auto restorer{
1102 GetContextualMessages().SetLocation(expr.value().source)};
1103 if (MaybeExpr v{Analyze(expr.value())}) {
1104 Push(std::move(*v));
1105 }
1106 },
1107 [&](const common::Indirection<parser::AcImpliedDo> &impliedDo) {
1108 const auto &control{
1109 std::get<parser::AcImpliedDoControl>(impliedDo.value().t)};
1110 const auto &bounds{
1111 std::get<parser::AcImpliedDoControl::Bounds>(control.t)};
1112 Analyze(bounds.name);
1113 parser::CharBlock name{bounds.name.thing.thing.source};
1114 const Symbol *symbol{bounds.name.thing.thing.symbol};
1115 int kind{IntType::kind};
1116 if (const auto dynamicType{DynamicType::From(symbol)}) {
1117 kind = dynamicType->kind();
1118 }
1119 bool inserted{AddAcImpliedDo(name, kind)};
1120 if (!inserted) {
1121 SayAt(name,
1122 "Implied DO index is active in surrounding implied DO loop "
1123 "and may not have the same name"_err_en_US);
1124 }
1125 std::optional<Expr<IntType>> lower{
1126 GetSpecificIntExpr<IntType::kind>(bounds.lower)};
1127 std::optional<Expr<IntType>> upper{
1128 GetSpecificIntExpr<IntType::kind>(bounds.upper)};
1129 std::optional<Expr<IntType>> stride{
1130 GetSpecificIntExpr<IntType::kind>(bounds.step)};
1131 ArrayConstructorContext nested{*this};
1132 for (const auto &value :
1133 std::get<std::list<parser::AcValue>>(impliedDo.value().t)) {
1134 nested.Add(value);
1135 }
1136 if (lower.has_value() && upper.has_value()) {
1137 if (!stride.has_value()) {
1138 stride = Expr<IntType>{1};
1139 }
1140 values_.Push(ImpliedDo<SomeType>{name, std::move(*lower),
1141 std::move(*upper), std::move(*stride),
1142 std::move(nested.values_)});
1143 }
1144 if (inserted) {
1145 RemoveAcImpliedDo(name);
1146 }
1147 },
1148 },
1149 x.u);
1150 }
1151
1152 // Inverts a collection of generic ArrayConstructorValues<SomeType> that
1153 // all happen to have the same actual type T into one ArrayConstructor<T>.
1154 template<typename T>
MakeSpecific(ArrayConstructorValues<SomeType> && from)1155 ArrayConstructorValues<T> MakeSpecific(
1156 ArrayConstructorValues<SomeType> &&from) {
1157 ArrayConstructorValues<T> to;
1158 for (ArrayConstructorValue<SomeType> &x : from) {
1159 std::visit(
1160 common::visitors{
1161 [&](common::CopyableIndirection<Expr<SomeType>> &&expr) {
1162 auto *typed{UnwrapExpr<Expr<T>>(expr.value())};
1163 CHECK(typed != nullptr);
1164 to.Push(std::move(*typed));
1165 },
1166 [&](ImpliedDo<SomeType> &&impliedDo) {
1167 to.Push(ImpliedDo<T>{impliedDo.name(),
1168 std::move(impliedDo.lower()), std::move(impliedDo.upper()),
1169 std::move(impliedDo.stride()),
1170 MakeSpecific<T>(std::move(impliedDo.values()))});
1171 },
1172 },
1173 std::move(x.u));
1174 }
1175 return to;
1176 }
1177
1178 struct ArrayConstructorTypeVisitor {
1179 using Result = MaybeExpr;
1180 using Types = AllTypes;
TestFortran::evaluate::ArrayConstructorTypeVisitor1181 template<typename T> Result Test() {
1182 if (type.category() == T::category) {
1183 if constexpr (T::category == TypeCategory::Derived) {
1184 return AsMaybeExpr(ArrayConstructor<T>{
1185 type.GetDerivedTypeSpec(), MakeSpecific<T>(std::move(values))});
1186 } else if (type.kind() == T::kind) {
1187 if constexpr (T::category == TypeCategory::Character) {
1188 if (auto len{type.LEN()}) {
1189 return AsMaybeExpr(ArrayConstructor<T>{
1190 *std::move(len), MakeSpecific<T>(std::move(values))});
1191 }
1192 } else {
1193 return AsMaybeExpr(
1194 ArrayConstructor<T>{MakeSpecific<T>(std::move(values))});
1195 }
1196 }
1197 }
1198 return std::nullopt;
1199 }
1200 DynamicTypeWithLength type;
1201 ArrayConstructorValues<SomeType> values;
1202 };
1203
Analyze(const parser::ArrayConstructor & array)1204 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
1205 const parser::AcSpec &acSpec{array.v};
1206 std::optional<DynamicTypeWithLength> type{AnalyzeTypeSpec(acSpec.type)};
1207 ArrayConstructorContext context{*this, type};
1208 for (const parser::AcValue &value : acSpec.values) {
1209 context.Add(value);
1210 }
1211 if (type.has_value()) {
1212 ArrayConstructorTypeVisitor visitor{
1213 std::move(*type), std::move(context.values())};
1214 return common::SearchTypes(std::move(visitor));
1215 }
1216 return std::nullopt;
1217 }
1218
Analyze(const parser::StructureConstructor & structure)1219 MaybeExpr ExpressionAnalyzer::Analyze(
1220 const parser::StructureConstructor &structure) {
1221 auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)};
1222 parser::CharBlock typeName{std::get<parser::Name>(parsedType.t).source};
1223 if (parsedType.derivedTypeSpec == nullptr) {
1224 return std::nullopt;
1225 }
1226 const auto &spec{*parsedType.derivedTypeSpec};
1227 const Symbol &typeSymbol{spec.typeSymbol()};
1228 if (spec.scope() == nullptr ||
1229 !typeSymbol.has<semantics::DerivedTypeDetails>()) {
1230 return std::nullopt; // error recovery
1231 }
1232 const auto &typeDetails{typeSymbol.get<semantics::DerivedTypeDetails>()};
1233 const Symbol *parentComponent{typeDetails.GetParentComponent(*spec.scope())};
1234
1235 if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796
1236 if (auto *msg{Say(typeName,
1237 "ABSTRACT derived type '%s' may not be used in a "
1238 "structure constructor"_err_en_US,
1239 typeName)}) {
1240 msg->Attach(
1241 typeSymbol.name(), "Declaration of ABSTRACT derived type"_en_US);
1242 }
1243 }
1244
1245 // This iterator traverses all of the components in the derived type and its
1246 // parents. The symbols for whole parent components appear after their
1247 // own components and before the components of the types that extend them.
1248 // E.g., TYPE :: A; REAL X; END TYPE
1249 // TYPE, EXTENDS(A) :: B; REAL Y; END TYPE
1250 // produces the component list X, A, Y.
1251 // The order is important below because a structure constructor can
1252 // initialize X or A by name, but not both.
1253 auto components{semantics::OrderedComponentIterator{spec}};
1254 auto nextAnonymous{components.begin()};
1255
1256 std::set<parser::CharBlock> unavailable;
1257 bool anyKeyword{false};
1258 StructureConstructor result{spec};
1259 bool checkConflicts{true}; // until we hit one
1260
1261 for (const auto &component :
1262 std::get<std::list<parser::ComponentSpec>>(structure.t)) {
1263 const parser::Expr &expr{
1264 std::get<parser::ComponentDataSource>(component.t).v.value()};
1265 parser::CharBlock source{expr.source};
1266 auto &messages{GetContextualMessages()};
1267 auto restorer{messages.SetLocation(source)};
1268 const Symbol *symbol{nullptr};
1269 MaybeExpr value{Analyze(expr)};
1270 std::optional<DynamicType> valueType{DynamicType::From(value)};
1271 if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
1272 anyKeyword = true;
1273 source = kw->v.source;
1274 symbol = kw->v.symbol;
1275 if (symbol == nullptr) {
1276 auto componentIter{std::find_if(components.begin(), components.end(),
1277 [=](const Symbol *symbol) { return symbol->name() == source; })};
1278 if (componentIter != components.end()) {
1279 symbol = *componentIter;
1280 }
1281 }
1282 if (symbol == nullptr) { // C7101
1283 Say(source,
1284 "Keyword '%s=' does not name a component of derived type '%s'"_err_en_US,
1285 source, typeName);
1286 }
1287 } else {
1288 if (anyKeyword) { // C7100
1289 Say(source,
1290 "Value in structure constructor lacks a component name"_err_en_US);
1291 checkConflicts = false; // stem cascade
1292 }
1293 // Here's a regrettably common extension of the standard: anonymous
1294 // initialization of parent components, e.g., T(PT(1)) rather than
1295 // T(1) or T(PT=PT(1)).
1296 if (nextAnonymous == components.begin() && parentComponent != nullptr &&
1297 valueType == DynamicType::From(*parentComponent) &&
1298 context().IsEnabled(parser::LanguageFeature::AnonymousParents)) {
1299 auto iter{
1300 std::find(components.begin(), components.end(), parentComponent)};
1301 if (iter != components.end()) {
1302 symbol = parentComponent;
1303 nextAnonymous = ++iter;
1304 if (context().ShouldWarn(parser::LanguageFeature::AnonymousParents)) {
1305 Say(source,
1306 "Whole parent component '%s' in structure "
1307 "constructor should not be anonymous"_en_US,
1308 symbol->name());
1309 }
1310 }
1311 }
1312 while (symbol == nullptr && nextAnonymous != components.end()) {
1313 const Symbol *nextSymbol{*nextAnonymous++};
1314 if (!nextSymbol->test(Symbol::Flag::ParentComp)) {
1315 symbol = nextSymbol;
1316 }
1317 }
1318 if (symbol == nullptr) {
1319 Say(source, "Unexpected value in structure constructor"_err_en_US);
1320 }
1321 }
1322 if (symbol != nullptr) {
1323 if (checkConflicts) {
1324 auto componentIter{
1325 std::find(components.begin(), components.end(), symbol)};
1326 if (unavailable.find(symbol->name()) != unavailable.cend()) {
1327 // C797, C798
1328 Say(source,
1329 "Component '%s' conflicts with another component earlier in "
1330 "this structure constructor"_err_en_US,
1331 symbol->name());
1332 } else if (symbol->test(Symbol::Flag::ParentComp)) {
1333 // Make earlier components unavailable once a whole parent appears.
1334 for (auto it{components.begin()}; it != componentIter; ++it) {
1335 unavailable.insert((*it)->name());
1336 }
1337 } else {
1338 // Make whole parent components unavailable after any of their
1339 // constituents appear.
1340 for (auto it{componentIter}; it != components.end(); ++it) {
1341 if ((*it)->test(Symbol::Flag::ParentComp)) {
1342 unavailable.insert((*it)->name());
1343 }
1344 }
1345 }
1346 }
1347 unavailable.insert(symbol->name());
1348 if (value.has_value()) {
1349 if (symbol->has<semantics::ProcEntityDetails>()) {
1350 CHECK(IsPointer(*symbol));
1351 } else if (symbol->has<semantics::ObjectEntityDetails>()) {
1352 // C1594(4)
1353 const auto &innermost{context_.FindScope(expr.source)};
1354 if (const auto *pureProc{
1355 semantics::FindPureProcedureContaining(&innermost)}) {
1356 if (const Symbol *
1357 pointer{semantics::FindPointerComponent(*symbol)}) {
1358 if (const Symbol *
1359 object{semantics::FindExternallyVisibleObject(
1360 *value, *pureProc)}) {
1361 if (auto *msg{Say(expr.source,
1362 "Externally visible object '%s' must not be "
1363 "associated with pointer component '%s' in a "
1364 "PURE procedure"_err_en_US,
1365 object->name(), pointer->name())}) {
1366 msg->Attach(object->name(), "Object declaration"_en_US)
1367 .Attach(pointer->name(), "Pointer declaration"_en_US);
1368 }
1369 }
1370 }
1371 }
1372 } else if (symbol->has<semantics::TypeParamDetails>()) {
1373 Say(expr.source,
1374 "Type parameter '%s' may not appear as a component "
1375 "of a structure constructor"_err_en_US,
1376 symbol->name());
1377 continue;
1378 } else {
1379 Say(expr.source,
1380 "Component '%s' is neither a procedure pointer "
1381 "nor a data object"_err_en_US,
1382 symbol->name());
1383 continue;
1384 }
1385 if (IsPointer(*symbol)) {
1386 CheckPointerAssignment(messages, context_.intrinsics(), *symbol,
1387 *value); // C7104, C7105
1388 result.Add(*symbol, Fold(GetFoldingContext(), std::move(*value)));
1389 } else if (MaybeExpr converted{
1390 ConvertToType(*symbol, std::move(*value))}) {
1391 result.Add(*symbol, std::move(*converted));
1392 } else if (IsAllocatable(*symbol) &&
1393 std::holds_alternative<NullPointer>(value->u)) {
1394 // NULL() with no arguments allowed by 7.5.10 para 6 for ALLOCATABLE
1395 } else if (auto symType{DynamicType::From(symbol)}) {
1396 if (valueType.has_value()) {
1397 if (auto *msg{Say(expr.source,
1398 "Value in structure constructor of type %s is "
1399 "incompatible with component '%s' of type %s"_err_en_US,
1400 valueType->AsFortran(), symbol->name(),
1401 symType->AsFortran())}) {
1402 msg->Attach(symbol->name(), "Component declaration"_en_US);
1403 }
1404 } else {
1405 if (auto *msg{Say(expr.source,
1406 "Value in structure constructor is incompatible with "
1407 " component '%s' of type %s"_err_en_US,
1408 symbol->name(), symType->AsFortran())}) {
1409 msg->Attach(symbol->name(), "Component declaration"_en_US);
1410 }
1411 }
1412 }
1413 }
1414 }
1415 }
1416
1417 // Ensure that unmentioned component objects have default initializers.
1418 for (const Symbol *symbol : components) {
1419 if (!symbol->test(Symbol::Flag::ParentComp) &&
1420 unavailable.find(symbol->name()) == unavailable.cend() &&
1421 !IsAllocatable(*symbol)) {
1422 if (const auto *details{
1423 symbol->detailsIf<semantics::ObjectEntityDetails>()}) {
1424 if (details->init().has_value()) {
1425 result.Add(*symbol, common::Clone(*details->init()));
1426 } else { // C799
1427 if (auto *msg{Say(typeName,
1428 "Structure constructor lacks a value for "
1429 "component '%s'"_err_en_US,
1430 symbol->name())}) {
1431 msg->Attach(symbol->name(), "Absent component"_en_US);
1432 }
1433 }
1434 }
1435 }
1436 }
1437
1438 return AsMaybeExpr(Expr<SomeDerived>{std::move(result)});
1439 }
1440
GetPassInfo(const semantics::Symbol & symbol)1441 static const semantics::WithPassArg *GetPassInfo(
1442 const semantics::Symbol &symbol) {
1443 if (const auto *binding{symbol.detailsIf<semantics::ProcBindingDetails>()}) {
1444 return binding;
1445 } else if (const auto *proc{
1446 symbol.detailsIf<semantics::ProcEntityDetails>()}) {
1447 return proc;
1448 } else {
1449 return nullptr;
1450 }
1451 }
1452
AnalyzeProcedureComponentRef(const parser::ProcComponentRef & pcr,ActualArguments && arguments)1453 auto ExpressionAnalyzer::AnalyzeProcedureComponentRef(
1454 const parser::ProcComponentRef &pcr, ActualArguments &&arguments)
1455 -> std::optional<CalleeAndArguments> {
1456 const parser::StructureComponent &sc{pcr.v.thing};
1457 const auto &name{sc.component.source};
1458 if (MaybeExpr base{Analyze(sc.base)}) {
1459 if (Symbol * sym{sc.component.symbol}) {
1460 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
1461 const semantics::DerivedTypeSpec *dtSpec{nullptr};
1462 if (std::optional<DynamicType> dtDyTy{dtExpr->GetType()}) {
1463 if (!dtDyTy->IsUnlimitedPolymorphic()) {
1464 dtSpec = &dtDyTy->GetDerivedTypeSpec();
1465 }
1466 }
1467 if (dtSpec != nullptr && dtSpec->scope() != nullptr) {
1468 if (std::optional<DataRef> dataRef{
1469 ExtractDataRef(std::move(*dtExpr))}) {
1470 if (auto component{CreateComponent(
1471 std::move(*dataRef), *sym, *dtSpec->scope())}) {
1472 if (const auto *pass{GetPassInfo(*sym)}) {
1473 if (auto passIndex{pass->passIndex()}) {
1474 // There's a PASS argument by which the base of the procedure
1475 // component reference must be passed. Append or insert it to
1476 // the list of effective arguments.
1477 auto iter{arguments.begin()};
1478 int at{0};
1479 while (iter < arguments.end() && at < *passIndex) {
1480 if (iter->has_value() && (*iter)->keyword.has_value()) {
1481 iter = arguments.end();
1482 break;
1483 }
1484 ++iter;
1485 ++at;
1486 }
1487 ActualArgument passed{AsGenericExpr(std::move(*dtExpr))};
1488 if (iter == arguments.end() && pass->passName().has_value()) {
1489 passed.keyword = *pass->passName();
1490 }
1491 arguments.emplace(iter, std::move(passed));
1492 }
1493 }
1494 return CalleeAndArguments{
1495 ProcedureDesignator{std::move(*component)},
1496 std::move(arguments)};
1497 } else {
1498 Say(name,
1499 "Procedure component is not in scope of derived TYPE(%s)"_err_en_US,
1500 dtSpec->typeSymbol().name());
1501 }
1502 } else {
1503 Say(name,
1504 "Base of procedure component reference must be a data reference"_err_en_US);
1505 }
1506 }
1507 } else {
1508 Say(name,
1509 "Base of procedure component reference is not a derived type object"_err_en_US);
1510 }
1511 }
1512 }
1513 CHECK(context_.messages().AnyFatalError());
1514 return std::nullopt;
1515 }
1516
1517 // Can actual be argument associated with dummy?
CheckCompatibleArgument(bool isElemental,const ActualArgument & actual,const characteristics::DummyArgument & dummy)1518 static bool CheckCompatibleArgument(bool isElemental,
1519 const ActualArgument &actual, const characteristics::DummyArgument &dummy) {
1520 return std::visit(
1521 common::visitors{
1522 [&](const characteristics::DummyDataObject &x) {
1523 characteristics::TypeAndShape dummyTypeAndShape{x.type};
1524 if (!isElemental && actual.Rank() != dummyTypeAndShape.Rank()) {
1525 return false;
1526 } else if (auto actualType{actual.GetType()}) {
1527 return dummyTypeAndShape.type().IsTkCompatibleWith(*actualType);
1528 } else {
1529 return false;
1530 }
1531 },
1532 [&](const characteristics::DummyProcedure &) {
1533 const auto *expr{actual.UnwrapExpr()};
1534 return expr && IsProcedurePointer(*expr);
1535 },
1536 [&](const characteristics::AlternateReturn &) {
1537 return actual.isAlternateReturn;
1538 },
1539 },
1540 dummy.u);
1541 }
1542
1543 // Are the actual arguments compatible with the dummy arguments of procedure?
CheckCompatibleArguments(const characteristics::Procedure & procedure,const ActualArguments & actuals)1544 static bool CheckCompatibleArguments(
1545 const characteristics::Procedure &procedure,
1546 const ActualArguments &actuals) {
1547 bool isElemental{procedure.IsElemental()};
1548 const auto &dummies{procedure.dummyArguments};
1549 CHECK(dummies.size() == actuals.size());
1550 for (std::size_t i{0}; i < dummies.size(); ++i) {
1551 const characteristics::DummyArgument &dummy{dummies[i]};
1552 const std::optional<ActualArgument> &actual{actuals[i]};
1553 if (actual && !CheckCompatibleArgument(isElemental, *actual, dummy)) {
1554 return false;
1555 }
1556 }
1557 return true;
1558 }
1559
ResolveGeneric(const Symbol & symbol,ActualArguments & actuals)1560 const Symbol *ExpressionAnalyzer::ResolveGeneric(
1561 const Symbol &symbol, ActualArguments &actuals) {
1562 const Symbol *elemental{nullptr}; // matching elemental specific proc
1563 const auto &details{symbol.get<semantics::GenericDetails>()};
1564 for (const Symbol *specific : details.specificProcs()) {
1565 if (std::optional<characteristics::Procedure> procedure{
1566 characteristics::Procedure::Characterize(
1567 ProcedureDesignator{*specific}, context_.intrinsics())}) {
1568 parser::Messages buffer;
1569 parser::ContextualMessages messages{
1570 context_.foldingContext().messages().at(), &buffer};
1571 FoldingContext localContext{context_.foldingContext(), messages};
1572 ActualArguments localActuals{actuals};
1573 if (CheckExplicitInterface(*procedure, localActuals, localContext) &&
1574 CheckCompatibleArguments(*procedure, localActuals)) {
1575 if (!procedure->IsElemental()) {
1576 return specific; // takes priority over elemental match
1577 }
1578 elemental = specific;
1579 }
1580 }
1581 }
1582 if (elemental) {
1583 return elemental;
1584 } else {
1585 Say("No specific procedure of generic '%s' matches the actual arguments"_err_en_US,
1586 symbol.name());
1587 return nullptr;
1588 }
1589 }
1590
GetCalleeAndArguments(const parser::ProcedureDesignator & pd,ActualArguments && arguments,bool isSubroutine)1591 auto ExpressionAnalyzer::GetCalleeAndArguments(
1592 const parser::ProcedureDesignator &pd, ActualArguments &&arguments,
1593 bool isSubroutine) -> std::optional<CalleeAndArguments> {
1594 return std::visit(
1595 common::visitors{
1596 [&](const parser::Name &n) -> std::optional<CalleeAndArguments> {
1597 const Symbol *symbol{n.symbol};
1598 if (context_.HasError(symbol)) {
1599 return std::nullopt;
1600 }
1601 const Symbol &ultimate{symbol->GetUltimate()};
1602 if (ultimate.attrs().test(semantics::Attr::INTRINSIC)) {
1603 if (std::optional<SpecificCall> specificCall{
1604 context_.intrinsics().Probe(
1605 CallCharacteristics{n.source, isSubroutine},
1606 arguments, GetFoldingContext())}) {
1607 return CalleeAndArguments{ProcedureDesignator{std::move(
1608 specificCall->specificIntrinsic)},
1609 std::move(specificCall->arguments)};
1610 } else {
1611 return std::nullopt;
1612 }
1613 }
1614 CheckForBadRecursion(n.source, ultimate);
1615 if (ultimate.has<semantics::GenericDetails>()) {
1616 symbol = ResolveGeneric(ultimate, arguments);
1617 }
1618 if (symbol) {
1619 return CalleeAndArguments{
1620 ProcedureDesignator{*symbol}, std::move(arguments)};
1621 } else {
1622 return std::nullopt;
1623 }
1624 },
1625 [&](const parser::ProcComponentRef &pcr) {
1626 return AnalyzeProcedureComponentRef(pcr, std::move(arguments));
1627 },
1628 },
1629 pd.u);
1630 }
1631
CheckForBadRecursion(parser::CharBlock callSite,const semantics::Symbol & proc)1632 void ExpressionAnalyzer::CheckForBadRecursion(
1633 parser::CharBlock callSite, const semantics::Symbol &proc) {
1634 if (const auto *scope{proc.scope()}) {
1635 if (scope->sourceRange().Contains(callSite)) {
1636 parser::Message *msg{nullptr};
1637 if (proc.attrs().test(semantics::Attr::NON_RECURSIVE)) { // 15.6.2.1(3)
1638 msg = Say("NON_RECURSIVE procedure '%s' cannot call itself"_err_en_US,
1639 callSite);
1640 } else if (IsAssumedLengthCharacterFunction(proc)) { // 15.6.2.1(3)
1641 msg = Say(
1642 "Assumed-length CHARACTER(*) function '%s' cannot call itself"_err_en_US,
1643 callSite);
1644 }
1645 if (msg != nullptr) {
1646 msg->Attach(proc.name(), "definition of '%s'"_en_US, callSite);
1647 }
1648 }
1649 }
1650 }
1651
AssumedTypeDummy(const A & x)1652 template<typename A> static const Symbol *AssumedTypeDummy(const A &x) {
1653 if (const auto *designator{
1654 std::get_if<common::Indirection<parser::Designator>>(&x.u)}) {
1655 if (const auto *dataRef{
1656 std::get_if<parser::DataRef>(&designator->value().u)}) {
1657 if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) {
1658 if (const Symbol * symbol{name->symbol}) {
1659 if (const auto *type{symbol->GetType()}) {
1660 if (type->category() == semantics::DeclTypeSpec::TypeStar) {
1661 return symbol;
1662 }
1663 }
1664 }
1665 }
1666 }
1667 }
1668 return nullptr;
1669 }
1670
AnalyzeActualArgument(const parser::Expr & expr)1671 std::optional<ActualArgument> ExpressionAnalyzer::AnalyzeActualArgument(
1672 const parser::Expr &expr) {
1673 if (const Symbol * assumedTypeDummy{AssumedTypeDummy(expr)}) {
1674 return ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
1675 } else if (MaybeExpr argExpr{Analyze(expr)}) {
1676 Expr<SomeType> x{Fold(GetFoldingContext(), std::move(*argExpr))};
1677 if (const auto *proc{std::get_if<ProcedureDesignator>(&x.u)}) {
1678 if (!std::holds_alternative<SpecificIntrinsic>(proc->u) &&
1679 proc->IsElemental()) { // C1533
1680 Say(expr.source,
1681 "Non-intrinsic ELEMENTAL procedure cannot be passed as argument"_err_en_US);
1682 }
1683 }
1684 if (auto coarrayRef{ExtractCoarrayRef(x)}) {
1685 const Symbol &coarray{coarrayRef->GetLastSymbol()};
1686 if (const semantics::DeclTypeSpec * type{coarray.GetType()}) {
1687 if (const semantics::DerivedTypeSpec * derived{type->AsDerived()}) {
1688 if (auto ptr{semantics::FindPointerUltimateComponent(*derived)}) {
1689 if (auto *msg{Say(expr.source,
1690 "Coindexed object '%s' with POINTER ultimate component '%s' cannot be passed as argument"_err_en_US,
1691 coarray.name(), (*ptr)->name())}) {
1692 msg->Attach((*ptr)->name(),
1693 "Declaration of POINTER '%s' component of %s"_en_US,
1694 (*ptr)->name(), type->AsFortran());
1695 }
1696 }
1697 }
1698 }
1699 }
1700 return ActualArgument{std::move(x)};
1701 } else {
1702 return std::nullopt;
1703 }
1704 }
1705
Analyze(const parser::FunctionReference & funcRef)1706 MaybeExpr ExpressionAnalyzer::Analyze(
1707 const parser::FunctionReference &funcRef) {
1708 return AnalyzeCall(funcRef.v, false);
1709 }
1710
Analyze(const parser::CallStmt & call)1711 void ExpressionAnalyzer::Analyze(const parser::CallStmt &call) {
1712 AnalyzeCall(call.v, true);
1713 }
1714
AnalyzeCall(const parser::Call & call,bool isSubroutine)1715 MaybeExpr ExpressionAnalyzer::AnalyzeCall(
1716 const parser::Call &call, bool isSubroutine) {
1717 auto save{GetContextualMessages().SetLocation(call.source)};
1718 if (auto arguments{AnalyzeArguments(call, isSubroutine)}) {
1719 // TODO: map non-intrinsic generic procedure to specific procedure
1720 if (std::optional<CalleeAndArguments> callee{
1721 GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t),
1722 std::move(*arguments), isSubroutine)}) {
1723 if (isSubroutine) {
1724 CheckCall(call.source, callee->procedureDesignator, callee->arguments);
1725 // TODO: Package the subroutine call as an expr in the parse tree
1726 } else {
1727 return MakeFunctionRef(call.source,
1728 std::move(callee->procedureDesignator),
1729 std::move(callee->arguments));
1730 }
1731 }
1732 }
1733 return std::nullopt;
1734 }
1735
AnalyzeArguments(const parser::Call & call,bool isSubroutine)1736 std::optional<ActualArguments> ExpressionAnalyzer::AnalyzeArguments(
1737 const parser::Call &call, bool isSubroutine) {
1738 evaluate::ActualArguments arguments;
1739 // TODO: C1002: Allow a whole assumed-size array to appear if the dummy
1740 // argument would accept it. Handle by special-casing the context
1741 // ActualArg -> Variable -> Designator.
1742 // TODO: Actual arguments that are procedures and procedure pointers need to
1743 // be detected and represented (they're not expressions).
1744 // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
1745 // TODO: map non-intrinsic generic procedure to specific procedure
1746 for (const auto &arg : std::get<std::list<parser::ActualArgSpec>>(call.t)) {
1747 std::optional<evaluate::ActualArgument> actual;
1748 std::visit(
1749 common::visitors{
1750 [&](const common::Indirection<parser::Expr> &x) {
1751 // TODO: Distinguish & handle procedure name and
1752 // proc-component-ref
1753 actual = AnalyzeActualArgument(x.value());
1754 },
1755 [&](const parser::AltReturnSpec &) {
1756 if (!isSubroutine) {
1757 Say("alternate return specification may not appear on function reference"_err_en_US);
1758 }
1759 },
1760 [&](const parser::ActualArg::PercentRef &) {
1761 Say("TODO: %REF() argument"_err_en_US);
1762 },
1763 [&](const parser::ActualArg::PercentVal &) {
1764 Say("TODO: %VAL() argument"_err_en_US);
1765 },
1766 },
1767 std::get<parser::ActualArg>(arg.t).u);
1768 if (actual.has_value()) {
1769 arguments.emplace_back(std::move(actual));
1770 if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) {
1771 arguments.back()->keyword = argKW->v.source;
1772 }
1773 } else {
1774 return std::nullopt;
1775 }
1776 }
1777 return arguments;
1778 }
1779
IsExternalCalledImplicitly(parser::CharBlock callSite,const ProcedureDesignator & proc)1780 static bool IsExternalCalledImplicitly(
1781 parser::CharBlock callSite, const ProcedureDesignator &proc) {
1782 if (const auto *symbol{proc.GetSymbol()}) {
1783 return symbol->has<semantics::SubprogramDetails>() &&
1784 symbol->owner().IsGlobal() &&
1785 !symbol->scope()->sourceRange().Contains(callSite);
1786 } else {
1787 return false;
1788 }
1789 }
1790
CheckCall(parser::CharBlock callSite,const ProcedureDesignator & proc,ActualArguments & arguments)1791 std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall(
1792 parser::CharBlock callSite, const ProcedureDesignator &proc,
1793 ActualArguments &arguments) {
1794 auto chars{
1795 characteristics::Procedure::Characterize(proc, context_.intrinsics())};
1796 if (chars.has_value()) {
1797 bool treatExternalAsImplicit{IsExternalCalledImplicitly(callSite, proc)};
1798 if (treatExternalAsImplicit && !chars->CanBeCalledViaImplicitInterface()) {
1799 Say(callSite,
1800 "References to the procedure '%s' require an explicit interface"_en_US,
1801 DEREF(proc.GetSymbol()).name());
1802 }
1803 CheckArguments(
1804 *chars, arguments, GetFoldingContext(), treatExternalAsImplicit);
1805 }
1806 return chars;
1807 }
1808
1809 // Unary operations
1810
Analyze(const parser::Expr::Parentheses & x)1811 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Parentheses &x) {
1812 if (MaybeExpr operand{Analyze(x.v.value())}) {
1813 if (const semantics::Symbol * symbol{GetLastSymbol(*operand)}) {
1814 if (const semantics::Symbol * result{FindFunctionResult(*symbol)}) {
1815 if (semantics::IsProcedurePointer(*result)) {
1816 Say("A function reference that returns a procedure "
1817 "pointer may not be parenthesized"_err_en_US); // C1003
1818 }
1819 }
1820 }
1821 return std::visit(
1822 [&](auto &&x) -> MaybeExpr {
1823 using xTy = std::decay_t<decltype(x)>;
1824 if constexpr (common::HasMember<xTy, TypelessExpression>) {
1825 return operand; // ignore parentheses around typeless
1826 } else if constexpr (std::is_same_v<xTy, Expr<SomeDerived>>) {
1827 return operand; // ignore parentheses around derived type
1828 } else {
1829 return std::visit(
1830 [](auto &&y) -> MaybeExpr {
1831 using Ty = ResultType<decltype(y)>;
1832 return {AsGenericExpr(Parentheses<Ty>{std::move(y)})};
1833 },
1834 std::move(x.u));
1835 }
1836 },
1837 std::move(operand->u));
1838 }
1839 return std::nullopt;
1840 }
1841
Analyze(const parser::Expr::UnaryPlus & x)1842 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::UnaryPlus &x) {
1843 MaybeExpr value{Analyze(x.v.value())};
1844 if (value.has_value()) {
1845 if (!std::visit(
1846 [&](const auto &y) {
1847 using yTy = std::decay_t<decltype(y)>;
1848 if constexpr (std::is_same_v<yTy, BOZLiteralConstant>) {
1849 // allow and ignore +Z'1', it's harmless
1850 return true;
1851 } else if constexpr (!IsNumericCategoryExpr<yTy>()) {
1852 Say("Operand of unary + must have numeric type"_err_en_US);
1853 return false;
1854 } else {
1855 return true;
1856 }
1857 },
1858 value->u)) {
1859 return std::nullopt;
1860 }
1861 }
1862 return value;
1863 }
1864
Analyze(const parser::Expr::Negate & x)1865 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Negate &x) {
1866 if (MaybeExpr operand{Analyze(x.v.value())}) {
1867 return Negation(GetContextualMessages(), std::move(*operand));
1868 }
1869 return std::nullopt;
1870 }
1871
Analyze(const parser::Expr::NOT & x)1872 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NOT &x) {
1873 if (MaybeExpr operand{Analyze(x.v.value())}) {
1874 return std::visit(
1875 common::visitors{
1876 [](Expr<SomeLogical> &&lx) -> MaybeExpr {
1877 return {AsGenericExpr(LogicalNegation(std::move(lx)))};
1878 },
1879 [&](auto &&) -> MaybeExpr {
1880 Say("Operand of .NOT. must be LOGICAL"_err_en_US);
1881 return std::nullopt;
1882 },
1883 },
1884 std::move(operand->u));
1885 }
1886 return std::nullopt;
1887 }
1888
Analyze(const parser::Expr::PercentLoc & x)1889 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::PercentLoc &x) {
1890 // Represent %LOC() exactly as if it had been a call to the LOC() extension
1891 // intrinsic function.
1892 // Use the actual source for the name of the call for error reporting.
1893 std::optional<ActualArgument> arg;
1894 if (const Symbol * assumedTypeDummy{AssumedTypeDummy(x.v.value())}) {
1895 arg = ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}};
1896 } else if (MaybeExpr argExpr{Analyze(x.v.value())}) {
1897 arg = ActualArgument{std::move(*argExpr)};
1898 } else {
1899 return std::nullopt;
1900 }
1901 parser::CharBlock at{GetContextualMessages().at()};
1902 CHECK(at.size() >= 4);
1903 parser::CharBlock loc{at.begin() + 1, 3};
1904 CHECK(loc == "loc");
1905 return MakeFunctionRef(loc, ActualArguments{std::move(*arg)});
1906 }
1907
Analyze(const parser::Expr::DefinedUnary &)1908 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &) {
1909 Say("TODO: DefinedUnary unimplemented"_err_en_US);
1910 return std::nullopt;
1911 }
1912
1913 // Binary (dyadic) operations
1914
1915 // TODO: check defined operators for illegal intrinsic operator cases
1916 template<template<typename> class OPR, typename PARSED>
BinaryOperationHelper(ExpressionAnalyzer & context,const PARSED & x)1917 MaybeExpr BinaryOperationHelper(ExpressionAnalyzer &context, const PARSED &x) {
1918 if (auto both{common::AllPresent(context.Analyze(std::get<0>(x.t).value()),
1919 context.Analyze(std::get<1>(x.t).value()))}) {
1920 ConformabilityCheck(context.GetContextualMessages(), std::get<0>(*both),
1921 std::get<1>(*both));
1922 return NumericOperation<OPR>(context.GetContextualMessages(),
1923 std::get<0>(std::move(*both)), std::get<1>(std::move(*both)),
1924 context.GetDefaultKind(TypeCategory::Real));
1925 }
1926 return std::nullopt;
1927 }
1928
Analyze(const parser::Expr::Power & x)1929 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Power &x) {
1930 return BinaryOperationHelper<Power>(*this, x);
1931 }
1932
Analyze(const parser::Expr::Multiply & x)1933 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Multiply &x) {
1934 return BinaryOperationHelper<Multiply>(*this, x);
1935 }
1936
Analyze(const parser::Expr::Divide & x)1937 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Divide &x) {
1938 return BinaryOperationHelper<Divide>(*this, x);
1939 }
1940
Analyze(const parser::Expr::Add & x)1941 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Add &x) {
1942 return BinaryOperationHelper<Add>(*this, x);
1943 }
1944
Analyze(const parser::Expr::Subtract & x)1945 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Subtract &x) {
1946 return BinaryOperationHelper<Subtract>(*this, x);
1947 }
1948
Analyze(const parser::Expr::ComplexConstructor & x)1949 MaybeExpr ExpressionAnalyzer::Analyze(
1950 const parser::Expr::ComplexConstructor &x) {
1951 auto re{Analyze(std::get<0>(x.t).value())};
1952 auto im{Analyze(std::get<1>(x.t).value())};
1953 if (re.has_value() && im.has_value()) {
1954 ConformabilityCheck(GetContextualMessages(), *re, *im);
1955 }
1956 return AsMaybeExpr(ConstructComplex(GetContextualMessages(), std::move(re),
1957 std::move(im), GetDefaultKind(TypeCategory::Real)));
1958 }
1959
Analyze(const parser::Expr::Concat & x)1960 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
1961 if (auto both{common::AllPresent(Analyze(std::get<0>(x.t).value()),
1962 Analyze(std::get<1>(x.t).value()))}) {
1963 ConformabilityCheck(
1964 GetContextualMessages(), std::get<0>(*both), std::get<1>(*both));
1965 return std::visit(
1966 common::visitors{
1967 [&](Expr<SomeCharacter> &&cx, Expr<SomeCharacter> &&cy) {
1968 return std::visit(
1969 [&](auto &&cxk, auto &&cyk) -> MaybeExpr {
1970 using Ty = ResultType<decltype(cxk)>;
1971 if constexpr (std::is_same_v<Ty,
1972 ResultType<decltype(cyk)>>) {
1973 return {AsGenericExpr(
1974 Concat<Ty::kind>{std::move(cxk), std::move(cyk)})};
1975 } else {
1976 Say("Operands of // must be the same kind of CHARACTER"_err_en_US);
1977 return std::nullopt;
1978 }
1979 },
1980 std::move(cx.u), std::move(cy.u));
1981 },
1982 [&](auto &&, auto &&) -> MaybeExpr {
1983 Say("Operands of // must be CHARACTER"_err_en_US);
1984 return std::nullopt;
1985 },
1986 },
1987 std::move(std::get<0>(*both).u), std::move(std::get<1>(*both).u));
1988 }
1989 return std::nullopt;
1990 }
1991
1992 // TODO: check defined operators for illegal intrinsic operator cases
1993 template<typename PARSED>
RelationHelper(ExpressionAnalyzer & context,RelationalOperator opr,const PARSED & x)1994 MaybeExpr RelationHelper(
1995 ExpressionAnalyzer &context, RelationalOperator opr, const PARSED &x) {
1996 if (auto both{common::AllPresent(context.Analyze(std::get<0>(x.t).value()),
1997 context.Analyze(std::get<1>(x.t).value()))}) {
1998 ConformabilityCheck(context.GetContextualMessages(), std::get<0>(*both),
1999 std::get<1>(*both));
2000 return AsMaybeExpr(Relate(context.GetContextualMessages(), opr,
2001 std::get<0>(std::move(*both)), std::get<1>(std::move(*both))));
2002 }
2003 return std::nullopt;
2004 }
2005
Analyze(const parser::Expr::LT & x)2006 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LT &x) {
2007 return RelationHelper(*this, RelationalOperator::LT, x);
2008 }
2009
Analyze(const parser::Expr::LE & x)2010 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LE &x) {
2011 return RelationHelper(*this, RelationalOperator::LE, x);
2012 }
2013
Analyze(const parser::Expr::EQ & x)2014 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQ &x) {
2015 return RelationHelper(*this, RelationalOperator::EQ, x);
2016 }
2017
Analyze(const parser::Expr::NE & x)2018 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NE &x) {
2019 return RelationHelper(*this, RelationalOperator::NE, x);
2020 }
2021
Analyze(const parser::Expr::GE & x)2022 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GE &x) {
2023 return RelationHelper(*this, RelationalOperator::GE, x);
2024 }
2025
Analyze(const parser::Expr::GT & x)2026 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GT &x) {
2027 return RelationHelper(*this, RelationalOperator::GT, x);
2028 }
2029
2030 // TODO: check defined operators for illegal intrinsic operator cases
2031 template<typename PARSED>
LogicalHelper(ExpressionAnalyzer & context,LogicalOperator opr,const PARSED & x)2032 MaybeExpr LogicalHelper(
2033 ExpressionAnalyzer &context, LogicalOperator opr, const PARSED &x) {
2034 if (auto both{common::AllPresent(context.Analyze(std::get<0>(x.t).value()),
2035 context.Analyze(std::get<1>(x.t).value()))}) {
2036 return std::visit(
2037 common::visitors{
2038 [&](Expr<SomeLogical> &&lx, Expr<SomeLogical> &&ly) -> MaybeExpr {
2039 ConformabilityCheck(context.GetContextualMessages(), lx, ly);
2040 return {AsGenericExpr(
2041 BinaryLogicalOperation(opr, std::move(lx), std::move(ly)))};
2042 },
2043 [&](auto &&, auto &&) -> MaybeExpr {
2044 // TODO: extension: INTEGER and typeless operands
2045 // ifort and PGI accept them if not overridden
2046 // need to define IAND, IOR, IEOR intrinsic representation
2047 context.Say(
2048 "operands to LOGICAL operation must be LOGICAL"_err_en_US);
2049 return {};
2050 },
2051 },
2052 std::move(std::get<0>(*both).u), std::move(std::get<1>(*both).u));
2053 }
2054 return std::nullopt;
2055 }
2056
Analyze(const parser::Expr::AND & x)2057 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::AND &x) {
2058 return LogicalHelper(*this, LogicalOperator::And, x);
2059 }
2060
Analyze(const parser::Expr::OR & x)2061 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::OR &x) {
2062 return LogicalHelper(*this, LogicalOperator::Or, x);
2063 }
2064
Analyze(const parser::Expr::EQV & x)2065 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQV &x) {
2066 return LogicalHelper(*this, LogicalOperator::Eqv, x);
2067 }
2068
Analyze(const parser::Expr::NEQV & x)2069 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NEQV &x) {
2070 return LogicalHelper(*this, LogicalOperator::Neqv, x);
2071 }
2072
Analyze(const parser::Expr::XOR & x)2073 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::XOR &x) {
2074 return LogicalHelper(*this, LogicalOperator::Neqv, x);
2075 }
2076
Analyze(const parser::Expr::DefinedBinary &)2077 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &) {
2078 Say("TODO: DefinedBinary unimplemented"_err_en_US);
2079 return std::nullopt;
2080 }
2081
CheckFuncRefToArrayElementRefHasSubscripts(semantics::SemanticsContext & context,const parser::FunctionReference & funcRef)2082 static void CheckFuncRefToArrayElementRefHasSubscripts(
2083 semantics::SemanticsContext &context,
2084 const parser::FunctionReference &funcRef) {
2085 // Emit message if the function reference fix will end-up an array element
2086 // reference with no subscripts because it will not be possible to later tell
2087 // the difference in expressions between empty subscript list due to bad
2088 // subscripts error recovery or because the user did not put any.
2089 if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) {
2090 auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
2091 const auto *name{std::get_if<parser::Name>(&proc.u)};
2092 if (name == nullptr) {
2093 name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component;
2094 }
2095 auto &msg{context.Say(funcRef.v.source,
2096 "Reference to array '%s' with empty subscript list"_err_en_US,
2097 name->source)};
2098 if (name->symbol) {
2099 if (semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)) {
2100 msg.Attach(name->source,
2101 "A result variable must be declared with RESULT to allow recursive "
2102 "function calls"_en_US);
2103 } else {
2104 msg.Attach(
2105 name->symbol->name(), "'%s' was declared here"_en_US, name->source);
2106 }
2107 }
2108 }
2109 }
2110
2111 // Converts, if appropriate, an original misparse of ambiguous syntax like
2112 // A(1) as a function reference into an array reference or a structure
2113 // constructor.
2114 template<typename... A>
FixMisparsedFunctionReference(semantics::SemanticsContext & context,const std::variant<A...> & constU)2115 static void FixMisparsedFunctionReference(
2116 semantics::SemanticsContext &context, const std::variant<A...> &constU) {
2117 // The parse tree is updated in situ when resolving an ambiguous parse.
2118 using uType = std::decay_t<decltype(constU)>;
2119 auto &u{const_cast<uType &>(constU)};
2120 if (auto *func{
2121 std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
2122 parser::FunctionReference &funcRef{func->value()};
2123 auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
2124 if (Symbol *
2125 origSymbol{std::visit(
2126 common::visitors{
2127 [&](parser::Name &name) { return name.symbol; },
2128 [&](parser::ProcComponentRef &pcr) {
2129 return pcr.v.thing.component.symbol;
2130 },
2131 },
2132 proc.u)}) {
2133 Symbol &symbol{origSymbol->GetUltimate()};
2134 if (symbol.has<semantics::ObjectEntityDetails>() ||
2135 symbol.has<semantics::AssocEntityDetails>()) {
2136 // Note that expression in AssocEntityDetails cannot be a procedure
2137 // pointer as per C1105 so this cannot be a function reference.
2138 if constexpr (common::HasMember<common::Indirection<parser::Designator>,
2139 uType>) {
2140 CheckFuncRefToArrayElementRefHasSubscripts(context, funcRef);
2141 u = common::Indirection{funcRef.ConvertToArrayElementRef()};
2142 } else {
2143 DIE("can't fix misparsed function as array reference");
2144 }
2145 } else if (const auto *name{std::get_if<parser::Name>(&proc.u)}) {
2146 // A procedure component reference can't be a structure
2147 // constructor; only check calls to bare names.
2148 const Symbol *derivedType{nullptr};
2149 if (symbol.has<semantics::DerivedTypeDetails>()) {
2150 derivedType = &symbol;
2151 } else if (const auto *generic{
2152 symbol.detailsIf<semantics::GenericDetails>()}) {
2153 derivedType = generic->derivedType();
2154 }
2155 if (derivedType != nullptr) {
2156 if constexpr (common::HasMember<parser::StructureConstructor,
2157 uType>) {
2158 auto &scope{context.FindScope(name->source)};
2159 const semantics::DeclTypeSpec &type{
2160 semantics::FindOrInstantiateDerivedType(scope,
2161 semantics::DerivedTypeSpec{
2162 origSymbol->name(), *derivedType},
2163 context)};
2164 u = funcRef.ConvertToStructureConstructor(type.derivedTypeSpec());
2165 } else {
2166 DIE("can't fix misparsed function as structure constructor");
2167 }
2168 }
2169 }
2170 }
2171 }
2172 }
2173
2174 // Common handling of parser::Expr and parser::Variable
2175 template<typename PARSED>
ExprOrVariable(const PARSED & x)2176 MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) {
2177 if (!x.typedExpr) { // not yet analyzed
2178 FixMisparsedFunctionReference(context_, x.u);
2179 MaybeExpr result;
2180 if constexpr (std::is_same_v<PARSED, parser::Expr>) {
2181 // Analyze the expression in a specified source position context for
2182 // better error reporting.
2183 auto save{GetContextualMessages().SetLocation(x.source)};
2184 result = Analyze(x.u);
2185 result = Fold(GetFoldingContext(), std::move(result));
2186 } else {
2187 result = Analyze(x.u);
2188 }
2189 x.typedExpr.reset(new GenericExprWrapper{std::move(result)});
2190 if (!x.typedExpr->v.has_value()) {
2191 if (!context_.AnyFatalError()) {
2192 #if DUMP_ON_FAILURE
2193 parser::DumpTree(std::cout << "Expression analysis failed on: ", x);
2194 #elif CRASH_ON_FAILURE
2195 common::die("Expression analysis failed without emitting an error");
2196 #endif
2197 }
2198 fatalErrors_ = true;
2199 }
2200 }
2201 return x.typedExpr->v;
2202 }
2203
Analyze(const parser::Expr & expr)2204 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) {
2205 return ExprOrVariable(expr);
2206 }
2207
Analyze(const parser::Variable & variable)2208 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) {
2209 return ExprOrVariable(variable);
2210 }
2211
AnalyzeKindSelector(TypeCategory category,const std::optional<parser::KindSelector> & selector)2212 Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
2213 TypeCategory category,
2214 const std::optional<parser::KindSelector> &selector) {
2215 int defaultKind{GetDefaultKind(category)};
2216 if (!selector.has_value()) {
2217 return Expr<SubscriptInteger>{defaultKind};
2218 }
2219 return std::visit(
2220 common::visitors{
2221 [&](const parser::ScalarIntConstantExpr &x)
2222 -> Expr<SubscriptInteger> {
2223 if (MaybeExpr kind{Analyze(x)}) {
2224 Expr<SomeType> folded{
2225 Fold(GetFoldingContext(), std::move(*kind))};
2226 if (std::optional<std::int64_t> code{ToInt64(folded)}) {
2227 if (CheckIntrinsicKind(category, *code)) {
2228 return Expr<SubscriptInteger>{*code};
2229 }
2230 } else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(folded)}) {
2231 return ConvertToType<SubscriptInteger>(std::move(*intExpr));
2232 }
2233 }
2234 return Expr<SubscriptInteger>{defaultKind};
2235 },
2236 [&](const parser::KindSelector::StarSize &x)
2237 -> Expr<SubscriptInteger> {
2238 std::intmax_t size = x.v;
2239 if (!CheckIntrinsicSize(category, size)) {
2240 size = defaultKind;
2241 } else if (category == TypeCategory::Complex) {
2242 size /= 2;
2243 }
2244 return Expr<SubscriptInteger>{size};
2245 },
2246 },
2247 selector->u);
2248 }
2249
GetDefaultKind(common::TypeCategory category)2250 int ExpressionAnalyzer::GetDefaultKind(common::TypeCategory category) {
2251 return context_.GetDefaultKind(category);
2252 }
2253
GetDefaultKindOfType(common::TypeCategory category)2254 DynamicType ExpressionAnalyzer::GetDefaultKindOfType(
2255 common::TypeCategory category) {
2256 return {category, GetDefaultKind(category)};
2257 }
2258
CheckIntrinsicKind(TypeCategory category,std::int64_t kind)2259 bool ExpressionAnalyzer::CheckIntrinsicKind(
2260 TypeCategory category, std::int64_t kind) {
2261 if (IsValidKindOfIntrinsicType(category, kind)) {
2262 return true;
2263 } else {
2264 Say("%s(KIND=%jd) is not a supported type"_err_en_US,
2265 parser::ToUpperCaseLetters(EnumToString(category)), kind);
2266 return false;
2267 }
2268 }
2269
CheckIntrinsicSize(TypeCategory category,std::int64_t size)2270 bool ExpressionAnalyzer::CheckIntrinsicSize(
2271 TypeCategory category, std::int64_t size) {
2272 if (category == TypeCategory::Complex) {
2273 // COMPLEX*16 == COMPLEX(KIND=8)
2274 if (size % 2 == 0 && IsValidKindOfIntrinsicType(category, size / 2)) {
2275 return true;
2276 }
2277 } else if (IsValidKindOfIntrinsicType(category, size)) {
2278 return true;
2279 }
2280 Say("%s*%jd is not a supported type"_err_en_US,
2281 parser::ToUpperCaseLetters(EnumToString(category)), size);
2282 return false;
2283 }
2284
AddAcImpliedDo(parser::CharBlock name,int kind)2285 bool ExpressionAnalyzer::AddAcImpliedDo(parser::CharBlock name, int kind) {
2286 return acImpliedDos_.insert(std::make_pair(name, kind)).second;
2287 }
2288
RemoveAcImpliedDo(parser::CharBlock name)2289 void ExpressionAnalyzer::RemoveAcImpliedDo(parser::CharBlock name) {
2290 auto iter{acImpliedDos_.find(name)};
2291 if (iter != acImpliedDos_.end()) {
2292 acImpliedDos_.erase(iter);
2293 }
2294 }
2295
IsAcImpliedDo(parser::CharBlock name) const2296 std::optional<int> ExpressionAnalyzer::IsAcImpliedDo(
2297 parser::CharBlock name) const {
2298 auto iter{acImpliedDos_.find(name)};
2299 if (iter != acImpliedDos_.cend()) {
2300 return {iter->second};
2301 } else {
2302 return std::nullopt;
2303 }
2304 }
2305
EnforceTypeConstraint(parser::CharBlock at,const MaybeExpr & result,TypeCategory category,bool defaultKind)2306 bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at,
2307 const MaybeExpr &result, TypeCategory category, bool defaultKind) {
2308 if (result.has_value()) {
2309 if (auto type{result->GetType()}) {
2310 if (type->category() != category) {
2311 Say(at, "Must have %s type, but is %s"_err_en_US,
2312 parser::ToUpperCaseLetters(EnumToString(category)),
2313 parser::ToUpperCaseLetters(type->AsFortran()));
2314 return false;
2315 } else if (defaultKind) {
2316 int kind{context_.GetDefaultKind(category)};
2317 if (type->kind() != kind) {
2318 Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US,
2319 kind, parser::ToUpperCaseLetters(EnumToString(category)),
2320 parser::ToUpperCaseLetters(type->AsFortran()));
2321 return false;
2322 }
2323 }
2324 } else {
2325 Say(at, "Must have %s type, but is typeless"_err_en_US,
2326 parser::ToUpperCaseLetters(EnumToString(category)));
2327 return false;
2328 }
2329 }
2330 return true;
2331 }
2332
MakeFunctionRef(parser::CharBlock callSite,ProcedureDesignator && proc,ActualArguments && arguments)2333 MaybeExpr ExpressionAnalyzer::MakeFunctionRef(parser::CharBlock callSite,
2334 ProcedureDesignator &&proc, ActualArguments &&arguments) {
2335 if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&proc.u)}) {
2336 if (intrinsic->name == "null" && arguments.empty()) {
2337 return Expr<SomeType>{NullPointer{}};
2338 }
2339 }
2340 if (auto chars{CheckCall(callSite, proc, arguments)}) {
2341 if (chars->functionResult.has_value()) {
2342 const auto &result{*chars->functionResult};
2343 if (result.IsProcedurePointer()) {
2344 return Expr<SomeType>{
2345 ProcedureRef{std::move(proc), std::move(arguments)}};
2346 } else {
2347 // Not a procedure pointer, so type and shape are known.
2348 return TypedWrapper<FunctionRef, ProcedureRef>(
2349 DEREF(result.GetTypeAndShape()).type(),
2350 ProcedureRef{std::move(proc), std::move(arguments)});
2351 }
2352 }
2353 }
2354 if (const Symbol * symbol{proc.GetSymbol()}) {
2355 if (const auto *details{
2356 symbol->detailsIf<semantics::SubprogramNameDetails>()}) {
2357 // If this symbol is still a SubprogramNameDetails, we must be
2358 // checking a specification expression in a sibling module or internal
2359 // procedure. Since recursion is disallowed in specification
2360 // expressions, we should handle such references by processing the
2361 // sibling procedure's specification part right now (recursively),
2362 // but until we can do so, just complain about the forward reference.
2363 // TODO: recursively process sibling's specification part.
2364 if (details->kind() == semantics::SubprogramKind::Module) {
2365 Say("The module function '%s' must have been previously defined "
2366 "when referenced in a specification expression"_err_en_US,
2367 symbol->name());
2368 } else {
2369 Say("The internal function '%s' cannot be referenced in "
2370 "a specification expression"_err_en_US,
2371 symbol->name());
2372 }
2373 return std::nullopt;
2374 }
2375 }
2376 return std::nullopt;
2377 }
2378
MakeFunctionRef(parser::CharBlock intrinsic,ActualArguments && arguments)2379 MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
2380 parser::CharBlock intrinsic, ActualArguments &&arguments) {
2381 if (std::optional<SpecificCall> specificCall{
2382 context_.intrinsics().Probe(CallCharacteristics{intrinsic}, arguments,
2383 context_.foldingContext())}) {
2384 return MakeFunctionRef(intrinsic,
2385 ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
2386 std::move(specificCall->arguments));
2387 } else {
2388 return std::nullopt;
2389 }
2390 }
2391 }
2392
2393 namespace Fortran::semantics {
AnalyzeKindSelector(SemanticsContext & context,common::TypeCategory category,const std::optional<parser::KindSelector> & selector)2394 evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
2395 SemanticsContext &context, common::TypeCategory category,
2396 const std::optional<parser::KindSelector> &selector) {
2397 evaluate::ExpressionAnalyzer analyzer{context};
2398 auto save{
2399 analyzer.GetContextualMessages().SetLocation(context.location().value())};
2400 return analyzer.AnalyzeKindSelector(category, selector);
2401 }
2402
AnalyzeCallStmt(SemanticsContext & context,const parser::CallStmt & call)2403 void AnalyzeCallStmt(SemanticsContext &context, const parser::CallStmt &call) {
2404 evaluate::ExpressionAnalyzer{context}.Analyze(call);
2405 }
2406
ExprChecker(SemanticsContext & context)2407 ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {}
2408
Walk(const parser::Program & program)2409 bool ExprChecker::Walk(const parser::Program &program) {
2410 parser::Walk(program, *this);
2411 return !context_.AnyFatalError();
2412 }
2413 }
2414