blob: d729ba56cd3b983bda50381cb1b867297ff5a780 [file] [log] [blame]
peter klauslere760aaa2019-01-07 23:50:041// Copyright (c) 2018-2019, NVIDIA CORPORATION. All rights reserved.
peter klausleraa6c6f92018-07-13 23:55:112//
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"
peter klausler5a18e792019-03-11 22:39:1116#include "assignment.h"
peter klauslerbe3b7652018-12-04 18:55:3217#include "scope.h"
Tim Keith16980c72018-10-22 14:37:3818#include "semantics.h"
peter klausler2e68aff2018-08-10 18:44:4319#include "symbol.h"
peter klausler8a574332019-03-02 01:33:2020#include "tools.h"
peter klausleraa6c6f92018-07-13 23:55:1121#include "../common/idioms.h"
peter klauslerce231b92018-08-08 18:29:0522#include "../evaluate/common.h"
peter klauslerabac2282018-10-26 22:10:2423#include "../evaluate/fold.h"
peter klausler2e68aff2018-08-10 18:44:4324#include "../evaluate/tools.h"
peter klausler10aa1ea2018-11-05 21:48:0025#include "../parser/characters.h"
peter klausler003c8322018-09-07 17:33:3226#include "../parser/parse-tree-visitor.h"
27#include "../parser/parse-tree.h"
peter klausler5a18e792019-03-11 22:39:1128#include <algorithm>
peter klausler8b9efa22018-08-13 20:33:3129#include <functional>
peter klausler79408f92018-08-31 20:28:2130#include <optional>
peter klauslerf5bc9fd2019-02-14 20:51:2031#include <set>
peter klausleraa6c6f92018-07-13 23:55:1132
peter klausler754c88f2019-06-10 16:26:0233// #define DUMP_ON_FAILURE 1
peter klauslerd49aa3c2019-05-29 23:00:3134// #define CRASH_ON_FAILURE 1
peter klauslerba2ef032019-04-12 23:50:5835#if DUMP_ON_FAILURE
36#include "../parser/dump-parse-tree.h"
37#include <iostream>
38#endif
peter klauslerba2ef032019-04-12 23:50:5839
peter klausler4da74f52018-11-30 23:23:3340// Typedef for optional generic expressions (ubiquitous in this file)
peter klausler659c3292018-11-30 22:03:0541using MaybeExpr =
42 std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>;
43
peter klausler6c6234b2018-09-12 18:20:3044// Much of the code that implements semantic analysis of expressions is
45// tightly coupled with their typed representations in lib/evaluate,
46// and appears here in namespace Fortran::evaluate for convenience.
peter klausler79408f92018-08-31 20:28:2147namespace Fortran::evaluate {
peter klausleraa6c6f92018-07-13 23:55:1148
peter klauslerd986a352018-08-14 21:35:5149using common::TypeCategory;
50
peter klausler0ae3d432019-01-23 00:30:3251struct DynamicTypeWithLength : public DynamicType {
peter klausler5a18e792019-03-11 22:39:1152 explicit DynamicTypeWithLength(const DynamicType &t) : DynamicType{t} {}
peter klausler4eccba92019-02-26 23:59:2553 std::optional<Expr<SubscriptInteger>> LEN() const;
peter klausler0ae3d432019-01-23 00:30:3254 std::optional<Expr<SubscriptInteger>> length;
55};
56
peter klausler4eccba92019-02-26 23:59:2557std::optional<Expr<SubscriptInteger>> DynamicTypeWithLength::LEN() const {
58 if (length.has_value()) {
59 return length;
60 }
peter klausler59342b02019-05-13 16:33:1861 if (auto *lengthParam{charLength()}) {
62 if (const auto &len{lengthParam->GetExplicit()}) {
peter klausler4eccba92019-02-26 23:59:2563 return ConvertToType<SubscriptInteger>(common::Clone(*len));
64 }
65 }
66 return std::nullopt;
67}
68
peter klausler972b3af2019-03-07 22:46:3169static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
peter klausler0ae3d432019-01-23 00:30:3270 const std::optional<parser::TypeSpec> &spec) {
71 if (spec.has_value()) {
72 if (const semantics::DeclTypeSpec * typeSpec{spec->declTypeSpec}) {
73 // Name resolution sets TypeSpec::declTypeSpec only when it's valid
74 // (viz., an intrinsic type with valid known kind or a non-polymorphic
75 // & non-ABSTRACT derived type).
76 if (const semantics::IntrinsicTypeSpec *
77 intrinsic{typeSpec->AsIntrinsic()}) {
78 TypeCategory category{intrinsic->category()};
peter klausler4eccba92019-02-26 23:59:2579 if (auto optKind{ToInt64(intrinsic->kind())}) {
80 int kind{static_cast<int>(*optKind)};
peter klausler0ae3d432019-01-23 00:30:3281 if (category == TypeCategory::Character) {
82 const semantics::CharacterTypeSpec &cts{
83 typeSpec->characterTypeSpec()};
peter klausler4eccba92019-02-26 23:59:2584 const semantics::ParamValue &len{cts.length()};
peter klausler0ae3d432019-01-23 00:30:3285 // N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() &
86 // type guards, but not in array constructors.
peter klausler4eccba92019-02-26 23:59:2587 return DynamicTypeWithLength{DynamicType{kind, len}};
88 } else {
89 return DynamicTypeWithLength{DynamicType{category, kind}};
peter klausler0ae3d432019-01-23 00:30:3290 }
peter klausler0ae3d432019-01-23 00:30:3291 }
92 } else if (const semantics::DerivedTypeSpec *
93 derived{typeSpec->AsDerived()}) {
peter klausler4eccba92019-02-26 23:59:2594 return DynamicTypeWithLength{DynamicType{*derived}};
peter klausler0ae3d432019-01-23 00:30:3295 }
96 }
97 }
98 return std::nullopt;
99}
100
peter klauslerd9694642018-09-20 19:34:29101// Wraps a object in an explicitly typed representation (e.g., Designator<>
peter klausler1089f012018-12-03 19:40:53102// or FunctionRef<>) that has been instantiated on a dynamically chosen type.
peter klauslerd9694642018-09-20 19:34:29103template<TypeCategory CATEGORY, template<typename> typename WRAPPER,
peter klausler4950dfa2019-04-09 20:29:40104 typename WRAPPED>
105common::IfNoLvalue<MaybeExpr, WRAPPED> WrapperHelper(int kind, WRAPPED &&x) {
peter klausler0ae3d432019-01-23 00:30:32106 return common::SearchTypes(
peter klauslerd9694642018-09-20 19:34:29107 TypeKindVisitor<CATEGORY, WRAPPER, WRAPPED>{kind, std::move(x)});
108}
109
peter klausler4950dfa2019-04-09 20:29:40110template<template<typename> typename WRAPPER, typename WRAPPED>
111common::IfNoLvalue<MaybeExpr, WRAPPED> TypedWrapper(
112 const DynamicType &dyType, WRAPPED &&x) {
peter klausler59342b02019-05-13 16:33:18113 switch (dyType.category()) {
peter klauslerd9694642018-09-20 19:34:29114 case TypeCategory::Integer:
115 return WrapperHelper<TypeCategory::Integer, WRAPPER, WRAPPED>(
peter klausler59342b02019-05-13 16:33:18116 dyType.kind(), std::move(x));
peter klauslerd9694642018-09-20 19:34:29117 case TypeCategory::Real:
118 return WrapperHelper<TypeCategory::Real, WRAPPER, WRAPPED>(
peter klausler59342b02019-05-13 16:33:18119 dyType.kind(), std::move(x));
peter klauslerd9694642018-09-20 19:34:29120 case TypeCategory::Complex:
121 return WrapperHelper<TypeCategory::Complex, WRAPPER, WRAPPED>(
peter klausler59342b02019-05-13 16:33:18122 dyType.kind(), std::move(x));
peter klauslerd9694642018-09-20 19:34:29123 case TypeCategory::Character:
124 return WrapperHelper<TypeCategory::Character, WRAPPER, WRAPPED>(
peter klausler59342b02019-05-13 16:33:18125 dyType.kind(), std::move(x));
peter klauslerd9694642018-09-20 19:34:29126 case TypeCategory::Logical:
127 return WrapperHelper<TypeCategory::Logical, WRAPPER, WRAPPED>(
peter klausler59342b02019-05-13 16:33:18128 dyType.kind(), std::move(x));
peter klauslerd9694642018-09-20 19:34:29129 case TypeCategory::Derived:
peter klauslera62636f2018-10-08 22:35:19130 return AsGenericExpr(Expr<SomeDerived>{WRAPPER<SomeDerived>{std::move(x)}});
peter klauslerd9694642018-09-20 19:34:29131 default: CRASH_NO_CASE;
132 }
133}
134
peter klausler5a18e792019-03-11 22:39:11135// Wraps a data reference in a typed Designator<>, and a procedure
136// or procedure pointer reference in a ProcedureDesignator.
137MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) {
138 const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
139 if (semantics::IsProcedure(symbol)) {
140 if (auto *component{std::get_if<Component>(&ref.u)}) {
141 return Expr<SomeType>{ProcedureDesignator{std::move(*component)}};
142 } else {
143 CHECK(std::holds_alternative<const Symbol *>(ref.u));
144 return Expr<SomeType>{ProcedureDesignator{symbol}};
145 }
146 } else if (auto dyType{DynamicType::From(symbol)}) {
peter klausler59342b02019-05-13 16:33:18147 return TypedWrapper<Designator, DataRef>(*dyType, std::move(ref));
peter klausler5a18e792019-03-11 22:39:11148 } else if (const auto *declTypeSpec{symbol.GetType()}) {
149 if (declTypeSpec->category() == semantics::DeclTypeSpec::TypeStar) {
150 Say("TYPE(*) assumed-type dummy argument '%s' may not be "
151 "used except as an actual argument"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:45152 symbol.name());
peter klausler5a18e792019-03-11 22:39:11153 }
peter klauslerad2fda82018-09-19 21:27:13154 }
peter klauslerad2fda82018-09-19 21:27:13155 return std::nullopt;
156}
157
peter klausler1089f012018-12-03 19:40:53158// Some subscript semantic checks must be deferred until all of the
peter klauslerf3abed62019-03-09 00:35:39159// subscripts are in hand.
peter klausler972b3af2019-03-07 22:46:31160MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) {
peter klausler64ea4622019-03-08 20:55:57161 const Symbol &symbol{ref.GetLastSymbol().GetUltimate()};
peter klauslera5687fd2018-09-18 16:34:59162 int symbolRank{symbol.Rank()};
peter klausler00e128e2019-06-25 20:07:32163 int subscripts{static_cast<int>(ref.size())};
peter klausler6d8aecf2019-02-01 00:04:17164 if (subscripts == 0) {
peter klauslera5687fd2018-09-18 16:34:59165 // A -> A(:,:)
peter klausler6d8aecf2019-02-01 00:04:17166 for (; subscripts < symbolRank; ++subscripts) {
167 ref.emplace_back(Triplet{});
peter klauslera5687fd2018-09-18 16:34:59168 }
169 }
peter klauslera5687fd2018-09-18 16:34:59170 if (subscripts != symbolRank) {
peter klausler972b3af2019-03-07 22:46:31171 Say("Reference to rank-%d object '%s' has %d subscripts"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:45172 symbolRank, symbol.name(), subscripts);
peter klauslerd29530e2019-05-21 23:58:46173 return std::nullopt;
peter klauslera75f28a2019-01-18 19:47:16174 } else if (subscripts == 0) {
175 // nothing to check
peter klausler00e128e2019-06-25 20:07:32176 } else if (Component * component{ref.base().UnwrapComponent()}) {
peter klausler140b4ad2019-01-31 17:58:40177 int baseRank{component->base().Rank()};
peter klauslera5687fd2018-09-18 16:34:59178 if (baseRank > 0) {
peter klausler140b4ad2019-01-31 17:58:40179 int subscriptRank{0};
peter klausler6d8aecf2019-02-01 00:04:17180 for (const auto &expr : ref.subscript()) {
peter klausler140b4ad2019-01-31 17:58:40181 subscriptRank += expr.Rank();
182 }
183 if (subscriptRank > 0) {
peter klausler972b3af2019-03-07 22:46:31184 Say("Subscripts of component '%s' of rank-%d derived type "
185 "array have rank %d but must all be scalar"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:45186 symbol.name(), baseRank, subscriptRank);
peter klauslerd29530e2019-05-21 23:58:46187 return std::nullopt;
peter klausler84af9c22018-09-15 00:01:55188 }
189 }
peter klauslerad2fda82018-09-19 21:27:13190 } else if (const auto *details{
191 symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
192 // C928 & C1002
peter klausler6d8aecf2019-02-01 00:04:17193 if (Triplet * last{std::get_if<Triplet>(&ref.subscript().back().u)}) {
peter klausler03618fd2018-10-29 22:25:35194 if (!last->upper().has_value() && details->IsAssumedSize()) {
peter klausler972b3af2019-03-07 22:46:31195 Say("Assumed-size array '%s' must have explicit final "
196 "subscript upper bound value"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:45197 symbol.name());
peter klauslerd29530e2019-05-21 23:58:46198 return std::nullopt;
peter klauslerad2fda82018-09-19 21:27:13199 }
200 }
peter klausler84af9c22018-09-15 00:01:55201 }
peter klauslerad2fda82018-09-19 21:27:13202 return Designate(DataRef{std::move(ref)});
peter klausler84af9c22018-09-15 00:01:55203}
204
peter klausler1089f012018-12-03 19:40:53205// Applies subscripts to a data reference.
peter klausler972b3af2019-03-07 22:46:31206MaybeExpr ExpressionAnalyzer::ApplySubscripts(
peter klausler1089f012018-12-03 19:40:53207 DataRef &&dataRef, std::vector<Subscript> &&subscripts) {
208 return std::visit(
209 common::visitors{
210 [&](const Symbol *symbol) {
peter klausler972b3af2019-03-07 22:46:31211 return CompleteSubscripts(ArrayRef{*symbol, std::move(subscripts)});
peter klausler1089f012018-12-03 19:40:53212 },
peter klausler6d8aecf2019-02-01 00:04:17213 [&](Component &&c) {
214 return CompleteSubscripts(
peter klausler972b3af2019-03-07 22:46:31215 ArrayRef{std::move(c), std::move(subscripts)});
peter klausler6d8aecf2019-02-01 00:04:17216 },
217 [&](auto &&) -> MaybeExpr {
218 CHECK(!"bad base for ArrayRef");
peter klausler1089f012018-12-03 19:40:53219 return std::nullopt;
220 },
221 },
222 std::move(dataRef.u));
223}
224
peter klausler1089f012018-12-03 19:40:53225// Top-level checks for data references. Unsubscripted whole array references
226// get expanded -- e.g., MATRIX becomes MATRIX(:,:).
peter klausler972b3af2019-03-07 22:46:31227MaybeExpr ExpressionAnalyzer::TopLevelChecks(DataRef &&dataRef) {
peter klausler56bf4f82019-02-04 21:06:21228 bool addSubscripts{false};
peter klausler1089f012018-12-03 19:40:53229 if (Component * component{std::get_if<Component>(&dataRef.u)}) {
peter klausler56bf4f82019-02-04 21:06:21230 const Symbol &symbol{component->GetLastSymbol()};
231 int componentRank{symbol.Rank()};
232 if (componentRank > 0) {
233 int baseRank{component->base().Rank()};
234 if (baseRank > 0) {
peter klausler7c71e2f2019-03-16 17:04:18235 Say("Reference to whole rank-%d component '%%%s' of "
peter klausler972b3af2019-03-07 22:46:31236 "rank-%d array of derived type is not allowed"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:45237 componentRank, symbol.name(), baseRank);
peter klausler56bf4f82019-02-04 21:06:21238 } else {
239 addSubscripts = true;
240 }
241 }
242 } else if (const Symbol **symbol{std::get_if<const Symbol *>(&dataRef.u)}) {
243 addSubscripts = (*symbol)->Rank() > 0;
peter klausler1089f012018-12-03 19:40:53244 }
peter klausler56bf4f82019-02-04 21:06:21245 if (addSubscripts) {
peter klausler972b3af2019-03-07 22:46:31246 if (MaybeExpr subscripted{
247 ApplySubscripts(std::move(dataRef), std::vector<Subscript>{})}) {
peter klausler1089f012018-12-03 19:40:53248 return subscripted;
249 }
250 }
251 return Designate(std::move(dataRef));
252}
253
peter klauslerf3abed62019-03-09 00:35:39254// Parse tree correction after a substring S(j:k) was misparsed as an
255// array section. N.B. Fortran substrings have to have a range, not a
256// single index.
257static void FixMisparsedSubstring(const parser::Designator &d) {
258 auto &mutate{const_cast<parser::Designator &>(d)};
259 if (auto *dataRef{std::get_if<parser::DataRef>(&mutate.u)}) {
260 if (auto *ae{std::get_if<common::Indirection<parser::ArrayElement>>(
261 &dataRef->u)}) {
262 parser::ArrayElement &arrElement{ae->value()};
263 if (!arrElement.subscripts.empty()) {
264 auto iter{arrElement.subscripts.begin()};
265 if (auto *triplet{std::get_if<parser::SubscriptTriplet>(&iter->u)}) {
266 if (!std::get<2>(triplet->t).has_value() /* no stride */ &&
267 ++iter == arrElement.subscripts.end() /* one subscript */) {
268 if (Symbol *
269 symbol{std::visit(
270 common::visitors{
271 [](parser::Name &n) { return n.symbol; },
272 [](common::Indirection<parser::StructureComponent>
273 &sc) { return sc.value().component.symbol; },
274 [](auto &) -> Symbol * { return nullptr; },
275 },
276 arrElement.base.u)}) {
277 const Symbol &ultimate{symbol->GetUltimate()};
peter klausler615ba772019-03-14 23:28:06278 if (const semantics::DeclTypeSpec * type{ultimate.GetType()}) {
peter klauslerc57fda82019-03-09 18:24:27279 if (!ultimate.IsObjectArray() &&
280 type->category() == semantics::DeclTypeSpec::Character) {
281 // The ambiguous S(j:k) was parsed as an array section
282 // reference, but it's now clear that it's a substring.
283 // Fix the parse tree in situ.
284 mutate.u = arrElement.ConvertToSubstring();
peter klauslerf3abed62019-03-09 00:35:39285 }
286 }
287 }
288 }
289 }
290 }
291 }
292 }
293}
294
peter klausler972b3af2019-03-07 22:46:31295MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) {
peter klauslerce9716d2019-04-15 22:18:07296 auto save{GetContextualMessages().SetLocation(d.source)};
peter klauslerf3abed62019-03-09 00:35:39297 FixMisparsedSubstring(d);
peter klausler1089f012018-12-03 19:40:53298 // These checks have to be deferred to these "top level" data-refs where
299 // we can be sure that there are no following subscripts (yet).
peter klausler972b3af2019-03-07 22:46:31300 if (MaybeExpr result{Analyze(d.u)}) {
peter klausler1089f012018-12-03 19:40:53301 if (std::optional<evaluate::DataRef> dataRef{
302 evaluate::ExtractDataRef(std::move(result))}) {
peter klausler972b3af2019-03-07 22:46:31303 return TopLevelChecks(std::move(*dataRef));
peter klausler1089f012018-12-03 19:40:53304 }
305 return result;
306 }
peter klausler6c6234b2018-09-12 18:20:30307 return std::nullopt;
308}
309
peter klausler1089f012018-12-03 19:40:53310// A utility subroutine to repackage optional expressions of various levels
311// of type specificity as fully general MaybeExpr values.
peter klausler4950dfa2019-04-09 20:29:40312template<typename A> common::IfNoLvalue<MaybeExpr, A> AsMaybeExpr(A &&x) {
peter klausler1089f012018-12-03 19:40:53313 return std::make_optional(AsGenericExpr(std::move(x)));
314}
315template<typename A> MaybeExpr AsMaybeExpr(std::optional<A> &&x) {
316 if (x.has_value()) {
317 return AsMaybeExpr(std::move(*x));
318 }
319 return std::nullopt;
320}
321
peter klauslerdc9faa22019-01-09 23:06:07322// Type kind parameter values for literal constants.
peter klausler972b3af2019-03-07 22:46:31323int ExpressionAnalyzer::AnalyzeKindParam(
peter klauslerdbb202c2019-06-28 18:16:37324 const std::optional<parser::KindParam> &kindParam, int defaultKind) {
peter klausler1089f012018-12-03 19:40:53325 if (!kindParam.has_value()) {
326 return defaultKind;
327 }
328 return std::visit(
329 common::visitors{
330 [](std::uint64_t k) { return static_cast<int>(k); },
331 [&](const parser::Scalar<
332 parser::Integer<parser::Constant<parser::Name>>> &n) {
peter klausler972b3af2019-03-07 22:46:31333 if (MaybeExpr ie{Analyze(n)}) {
peter klausler1089f012018-12-03 19:40:53334 if (std::optional<std::int64_t> i64{ToInt64(*ie)}) {
335 int iv = *i64;
336 if (iv == *i64) {
337 return iv;
338 }
339 }
340 }
peter klausler1089f012018-12-03 19:40:53341 return defaultKind;
342 },
peter klausler1089f012018-12-03 19:40:53343 },
344 kindParam->u);
345}
346
347// Common handling of parser::IntLiteralConstant and SignedIntLiteralConstant
peter klausler822810f2019-03-22 21:27:18348struct IntTypeVisitor {
349 using Result = MaybeExpr;
350 using Types = IntegerTypes;
351 template<typename T> Result Test() {
peter klauslerd3b23e92019-05-30 20:31:11352 if (T::kind >= kind) {
peter klausler822810f2019-03-22 21:27:18353 const char *p{digits.begin()};
peter klauslerd3b23e92019-05-30 20:31:11354 auto value{T::Scalar::Read(p, 10, true /*signed*/)};
peter klausler822810f2019-03-22 21:27:18355 if (!value.overflow) {
peter klauslerd3b23e92019-05-30 20:31:11356 if (T::kind > kind) {
357 if (!isDefaultKind ||
358 !analyzer.context().IsEnabled(
359 parser::LanguageFeature::BigIntLiterals)) {
360 return std::nullopt;
361 } else if (analyzer.context().ShouldWarn(
362 parser::LanguageFeature::BigIntLiterals)) {
363 analyzer.Say(digits,
364 "Integer literal is too large for default INTEGER(KIND=%d); "
365 "assuming INTEGER(KIND=%d)"_en_US,
366 kind, T::kind);
367 }
368 }
peter klausler822810f2019-03-22 21:27:18369 return Expr<SomeType>{
370 Expr<SomeInteger>{Expr<T>{Constant<T>{std::move(value.value)}}}};
371 }
372 }
373 return std::nullopt;
374 }
peter klauslerd3b23e92019-05-30 20:31:11375 ExpressionAnalyzer &analyzer;
peter klausler822810f2019-03-22 21:27:18376 parser::CharBlock digits;
377 int kind;
peter klauslerd3b23e92019-05-30 20:31:11378 bool isDefaultKind;
peter klausler822810f2019-03-22 21:27:18379};
380
peter klausler1089f012018-12-03 19:40:53381template<typename PARSED>
peter klausler972b3af2019-03-07 22:46:31382MaybeExpr ExpressionAnalyzer::IntLiteralConstant(const PARSED &x) {
peter klauslerd3b23e92019-05-30 20:31:11383 const auto &kindParam{std::get<std::optional<parser::KindParam>>(x.t)};
384 bool isDefaultKind{!kindParam.has_value()};
385 int kind{AnalyzeKindParam(kindParam, GetDefaultKind(TypeCategory::Integer))};
peter klausler822810f2019-03-22 21:27:18386 if (CheckIntrinsicKind(TypeCategory::Integer, kind)) {
387 auto digits{std::get<parser::CharBlock>(x.t)};
peter klauslerd3b23e92019-05-30 20:31:11388 if (MaybeExpr result{common::SearchTypes(
389 IntTypeVisitor{*this, digits, kind, isDefaultKind})}) {
peter klausler822810f2019-03-22 21:27:18390 return result;
peter klauslerd3b23e92019-05-30 20:31:11391 } else if (isDefaultKind) {
392 Say(digits,
393 "Integer literal is too large for any allowable "
394 "kind of INTEGER"_err_en_US);
peter klausler822810f2019-03-22 21:27:18395 } else {
peter klauslerd3b23e92019-05-30 20:31:11396 Say(digits, "Integer literal is too large for INTEGER(KIND=%d)"_err_en_US,
peter klausler822810f2019-03-22 21:27:18397 kind);
398 }
peter klausler1089f012018-12-03 19:40:53399 }
peter klausler822810f2019-03-22 21:27:18400 return std::nullopt;
peter klausler1089f012018-12-03 19:40:53401}
402
peter klausler972b3af2019-03-07 22:46:31403MaybeExpr ExpressionAnalyzer::Analyze(const parser::IntLiteralConstant &x) {
404 return IntLiteralConstant(x);
peter klausler1089f012018-12-03 19:40:53405}
406
peter klausler972b3af2019-03-07 22:46:31407MaybeExpr ExpressionAnalyzer::Analyze(
peter klausler1089f012018-12-03 19:40:53408 const parser::SignedIntLiteralConstant &x) {
peter klausler972b3af2019-03-07 22:46:31409 return IntLiteralConstant(x);
peter klausler1089f012018-12-03 19:40:53410}
411
412template<typename TYPE>
413Constant<TYPE> ReadRealLiteral(
414 parser::CharBlock source, FoldingContext &context) {
415 const char *p{source.begin()};
peter klausler6d8aecf2019-02-01 00:04:17416 auto valWithFlags{Scalar<TYPE>::Read(p, context.rounding())};
peter klausler1089f012018-12-03 19:40:53417 CHECK(p == source.end());
418 RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal");
419 auto value{valWithFlags.value};
peter klausler6d8aecf2019-02-01 00:04:17420 if (context.flushSubnormalsToZero()) {
peter klausler74a77dd2019-01-30 00:47:41421 value = value.FlushSubnormalToZero();
peter klausler1089f012018-12-03 19:40:53422 }
423 return {value};
424}
425
426struct RealTypeVisitor {
427 using Result = std::optional<Expr<SomeReal>>;
peter klausler0ae3d432019-01-23 00:30:32428 using Types = RealTypes;
peter klausler1089f012018-12-03 19:40:53429
430 RealTypeVisitor(int k, parser::CharBlock lit, FoldingContext &ctx)
431 : kind{k}, literal{lit}, context{ctx} {}
432
peter klausler0ae3d432019-01-23 00:30:32433 template<typename T> Result Test() {
434 if (kind == T::kind) {
435 return {AsCategoryExpr(ReadRealLiteral<T>(literal, context))};
peter klausler1089f012018-12-03 19:40:53436 }
437 return std::nullopt;
438 }
439
440 int kind;
441 parser::CharBlock literal;
442 FoldingContext &context;
443};
444
445// Reads a real literal constant and encodes it with the right kind.
peter klausler972b3af2019-03-07 22:46:31446MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
peter klausler1089f012018-12-03 19:40:53447 // Use a local message context around the real literal for better
448 // provenance on any messages.
peter klausler972b3af2019-03-07 22:46:31449 auto save{GetContextualMessages().SetLocation(x.real.source)};
peter klausler1089f012018-12-03 19:40:53450 // If a kind parameter appears, it defines the kind of the literal and any
451 // letter used in an exponent part (e.g., the 'E' in "6.02214E+23")
452 // should agree. In the absence of an explicit kind parameter, any exponent
453 // letter determines the kind. Otherwise, defaults apply.
Tim Keith9d125622019-06-12 19:38:04454 auto &defaults{context_.defaultKinds()};
455 int defaultKind{defaults.GetDefaultKind(TypeCategory::Real)};
peter klausler1089f012018-12-03 19:40:53456 const char *end{x.real.source.end()};
457 std::optional<int> letterKind;
458 for (const char *p{x.real.source.begin()}; p < end; ++p) {
459 if (parser::IsLetter(*p)) {
460 switch (*p) {
Tim Keith9d125622019-06-12 19:38:04461 case 'e': letterKind = defaults.GetDefaultKind(TypeCategory::Real); break;
462 case 'd': letterKind = defaults.doublePrecisionKind(); break;
463 case 'q': letterKind = defaults.quadPrecisionKind(); break;
peter klausler59342b02019-05-13 16:33:18464 default: Say("Unknown exponent letter '%c'"_err_en_US, *p);
peter klauslera62636f2018-10-08 22:35:19465 }
peter klausler1089f012018-12-03 19:40:53466 break;
467 }
468 }
469 if (letterKind.has_value()) {
470 defaultKind = *letterKind;
471 }
peter klausler972b3af2019-03-07 22:46:31472 auto kind{AnalyzeKindParam(x.kind, defaultKind)};
peter klausler1089f012018-12-03 19:40:53473 if (letterKind.has_value() && kind != *letterKind) {
peter klausler59342b02019-05-13 16:33:18474 Say("Explicit kind parameter on real constant disagrees with "
peter klausler972b3af2019-03-07 22:46:31475 "exponent letter"_en_US);
peter klausler1089f012018-12-03 19:40:53476 }
peter klausler0ae3d432019-01-23 00:30:32477 auto result{common::SearchTypes(
peter klausler972b3af2019-03-07 22:46:31478 RealTypeVisitor{kind, x.real.source, GetFoldingContext()})};
peter klausler1089f012018-12-03 19:40:53479 if (!result.has_value()) {
peter klausler59342b02019-05-13 16:33:18480 Say("Unsupported REAL(KIND=%d)"_err_en_US, kind);
peter klausler1089f012018-12-03 19:40:53481 }
482 return AsMaybeExpr(std::move(result));
483}
484
peter klausler972b3af2019-03-07 22:46:31485MaybeExpr ExpressionAnalyzer::Analyze(
peter klausler1089f012018-12-03 19:40:53486 const parser::SignedRealLiteralConstant &x) {
peter klausler972b3af2019-03-07 22:46:31487 if (auto result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) {
488 auto &realExpr{std::get<Expr<SomeReal>>(result->u)};
peter klausler1089f012018-12-03 19:40:53489 if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
490 if (sign == parser::Sign::Negative) {
peter klausler972b3af2019-03-07 22:46:31491 return {AsGenericExpr(-std::move(realExpr))};
peter klausler1089f012018-12-03 19:40:53492 }
493 }
494 return result;
495 }
496 return std::nullopt;
497}
498
peter klausler972b3af2019-03-07 22:46:31499MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexPart &x) {
500 return Analyze(x.u);
peter klausler1089f012018-12-03 19:40:53501}
502
peter klausler972b3af2019-03-07 22:46:31503MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexLiteralConstant &z) {
504 return AsMaybeExpr(
505 ConstructComplex(GetContextualMessages(), Analyze(std::get<0>(z.t)),
506 Analyze(std::get<1>(z.t)), GetDefaultKind(TypeCategory::Real)));
peter klausler1089f012018-12-03 19:40:53507}
508
509// CHARACTER literal processing.
peter klausler972b3af2019-03-07 22:46:31510MaybeExpr ExpressionAnalyzer::AnalyzeString(std::string &&string, int kind) {
511 if (!CheckIntrinsicKind(TypeCategory::Character, kind)) {
peter klausler1089f012018-12-03 19:40:53512 return std::nullopt;
513 }
peter klauslerfdcdd502019-06-18 19:34:23514 switch (kind) {
515 case 1:
516 return AsGenericExpr(Constant<Type<TypeCategory::Character, 1>>{
peter klauslerdbb202c2019-06-28 18:16:37517 parser::DecodeString<std::string, parser::Encoding::LATIN_1>(
518 string, true)});
peter klauslerfdcdd502019-06-18 19:34:23519 case 2:
peter klausler94a667b2019-06-17 23:12:28520 return AsGenericExpr(Constant<Type<TypeCategory::Character, 2>>{
peter klauslerdbb202c2019-06-28 18:16:37521 parser::DecodeString<std::u16string, parser::Encoding::UTF_8>(
522 string, true)});
peter klauslerfdcdd502019-06-18 19:34:23523 case 4:
peter klausler94a667b2019-06-17 23:12:28524 return AsGenericExpr(Constant<Type<TypeCategory::Character, 4>>{
peter klauslerdbb202c2019-06-28 18:16:37525 parser::DecodeString<std::u32string, parser::Encoding::UTF_8>(
526 string, true)});
peter klauslerfdcdd502019-06-18 19:34:23527 default: CRASH_NO_CASE;
peter klausler1089f012018-12-03 19:40:53528 }
529}
530
peter klausler972b3af2019-03-07 22:46:31531MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) {
532 int kind{
533 AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t), 1)};
peter klausler1089f012018-12-03 19:40:53534 auto value{std::get<std::string>(x.t)};
peter klausler972b3af2019-03-07 22:46:31535 return AnalyzeString(std::move(value), kind);
peter klausler1089f012018-12-03 19:40:53536}
537
peter klausler972b3af2019-03-07 22:46:31538MaybeExpr ExpressionAnalyzer::Analyze(
peter klausler1089f012018-12-03 19:40:53539 const parser::HollerithLiteralConstant &x) {
peter klausler972b3af2019-03-07 22:46:31540 int kind{GetDefaultKind(TypeCategory::Character)};
peter klausler1089f012018-12-03 19:40:53541 auto value{x.v};
peter klausler972b3af2019-03-07 22:46:31542 return AnalyzeString(std::move(value), kind);
peter klausler1089f012018-12-03 19:40:53543}
544
545// .TRUE. and .FALSE. of various kinds
peter klausler972b3af2019-03-07 22:46:31546MaybeExpr ExpressionAnalyzer::Analyze(const parser::LogicalLiteralConstant &x) {
547 auto kind{AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t),
548 GetDefaultKind(TypeCategory::Logical))};
peter klausler1089f012018-12-03 19:40:53549 bool value{std::get<bool>(x.t)};
peter klausler0ae3d432019-01-23 00:30:32550 auto result{common::SearchTypes(
peter klausler1089f012018-12-03 19:40:53551 TypeKindVisitor<TypeCategory::Logical, Constant, bool>{
552 kind, std::move(value)})};
553 if (!result.has_value()) {
peter klausler972b3af2019-03-07 22:46:31554 Say("unsupported LOGICAL(KIND=%d)"_err_en_US, kind);
peter klausler1089f012018-12-03 19:40:53555 }
556 return result;
557}
558
559// BOZ typeless literals
peter klausler972b3af2019-03-07 22:46:31560MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
peter klauslerec6cf762019-05-06 16:33:45561 const char *p{x.v.c_str()};
peter klausler1089f012018-12-03 19:40:53562 std::uint64_t base{16};
563 switch (*p++) {
564 case 'b': base = 2; break;
565 case 'o': base = 8; break;
566 case 'z': break;
567 case 'x': break;
568 default: CRASH_NO_CASE;
569 }
570 CHECK(*p == '"');
peter klausler822810f2019-03-22 21:27:18571 ++p;
572 auto value{BOZLiteralConstant::Read(p, base, false /*unsigned*/)};
peter klausler1089f012018-12-03 19:40:53573 if (*p != '"') {
peter klauslerec6cf762019-05-06 16:33:45574 Say("Invalid digit ('%c') in BOZ literal '%s'"_err_en_US, *p, x.v);
peter klausler1089f012018-12-03 19:40:53575 return std::nullopt;
576 }
577 if (value.overflow) {
peter klauslerec6cf762019-05-06 16:33:45578 Say("BOZ literal '%s' too large"_err_en_US, x.v);
peter klausler1089f012018-12-03 19:40:53579 return std::nullopt;
580 }
581 return {AsGenericExpr(std::move(value.value))};
582}
583
peter klausler0ae3d432019-01-23 00:30:32584// For use with SearchTypes to create a TypeParamInquiry with the
peter klauslerdc9faa22019-01-09 23:06:07585// right integer kind.
586struct TypeParamInquiryVisitor {
587 using Result = std::optional<Expr<SomeInteger>>;
peter klausler0ae3d432019-01-23 00:30:32588 using Types = IntegerTypes;
peter klausler00e128e2019-06-25 20:07:32589 TypeParamInquiryVisitor(int k, NamedEntity &&b, const Symbol &param)
peter klauslerdc9faa22019-01-09 23:06:07590 : kind{k}, base{std::move(b)}, parameter{param} {}
peter klausler00e128e2019-06-25 20:07:32591 TypeParamInquiryVisitor(int k, const Symbol &param)
592 : kind{k}, parameter{param} {}
peter klausler0ae3d432019-01-23 00:30:32593 template<typename T> Result Test() {
594 if (kind == T::kind) {
peter klauslerdc9faa22019-01-09 23:06:07595 return Expr<SomeInteger>{
peter klausler0ae3d432019-01-23 00:30:32596 Expr<T>{TypeParamInquiry<T::kind>{std::move(base), parameter}}};
peter klauslerdc9faa22019-01-09 23:06:07597 }
598 return std::nullopt;
599 }
600 int kind;
peter klausler00e128e2019-06-25 20:07:32601 std::optional<NamedEntity> base;
peter klauslerdc9faa22019-01-09 23:06:07602 const Symbol &parameter;
603};
604
peter klausler59342b02019-05-13 16:33:18605static std::optional<Expr<SomeInteger>> MakeBareTypeParamInquiry(
peter klauslerbe3b7652018-12-04 18:55:32606 const Symbol *symbol) {
peter klausler25e6f032019-05-03 18:29:15607 if (std::optional<DynamicType> dyType{DynamicType::From(symbol)}) {
peter klausler59342b02019-05-13 16:33:18608 if (dyType->category() == TypeCategory::Integer) {
peter klausler00e128e2019-06-25 20:07:32609 return common::SearchTypes(
610 TypeParamInquiryVisitor{dyType->kind(), *symbol});
peter klauslerbe3b7652018-12-04 18:55:32611 }
612 }
613 return std::nullopt;
614}
615
peter klausler1089f012018-12-03 19:40:53616// Names and named constants
peter klausler972b3af2019-03-07 22:46:31617MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
618 if (std::optional<int> kind{IsAcImpliedDo(n.source)}) {
peter klausler0ae3d432019-01-23 00:30:32619 return AsMaybeExpr(ConvertToKind<TypeCategory::Integer>(
620 *kind, AsExpr(ImpliedDoIndex{n.source})));
Tim Keith77614542019-04-25 21:47:39621 } else if (!context_.HasError(n)) {
peter klausler64ea4622019-03-08 20:55:57622 const Symbol &ultimate{n.symbol->GetUltimate()};
peter klausler59342b02019-05-13 16:33:18623 if (ultimate.detailsIf<semantics::TypeParamDetails>()) {
peter klausler64ea4622019-03-08 20:55:57624 // A bare reference to a derived type parameter (within a parameterized
625 // derived type definition)
peter klausler59342b02019-05-13 16:33:18626 return AsMaybeExpr(MakeBareTypeParamInquiry(&ultimate));
peter klausler64ea4622019-03-08 20:55:57627 } else {
peter klauslerd72fd342019-06-03 17:51:51628 return Designate(DataRef{ultimate});
peter klausler1089f012018-12-03 19:40:53629 }
peter klausler1089f012018-12-03 19:40:53630 }
631 return std::nullopt;
632}
633
peter klausler972b3af2019-03-07 22:46:31634MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) {
635 if (MaybeExpr value{Analyze(n.v)}) {
636 Expr<SomeType> folded{Fold(GetFoldingContext(), std::move(*value))};
peter klauslerfe3acf5f2019-01-07 18:15:27637 if (IsConstantExpr(folded)) {
peter klausler1089f012018-12-03 19:40:53638 return {folded};
639 }
peter klausler972b3af2019-03-07 22:46:31640 Say(n.v.source, "must be a constant"_err_en_US);
peter klausler1089f012018-12-03 19:40:53641 }
642 return std::nullopt;
643}
644
645// Substring references
peter klausler972b3af2019-03-07 22:46:31646std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::GetSubstringBound(
peter klausler1089f012018-12-03 19:40:53647 const std::optional<parser::ScalarIntExpr> &bound) {
648 if (bound.has_value()) {
peter klausler972b3af2019-03-07 22:46:31649 if (MaybeExpr expr{Analyze(*bound)}) {
peter klausler1089f012018-12-03 19:40:53650 if (expr->Rank() > 1) {
peter klausler972b3af2019-03-07 22:46:31651 Say("substring bound expression has rank %d"_err_en_US, expr->Rank());
peter klausler1089f012018-12-03 19:40:53652 }
653 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
654 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
655 return {std::move(*ssIntExpr)};
656 }
657 return {Expr<SubscriptInteger>{
658 Convert<SubscriptInteger, TypeCategory::Integer>{
659 std::move(*intExpr)}}};
peter klausler93a7f1f2018-09-14 22:48:40660 } else {
peter klausler972b3af2019-03-07 22:46:31661 Say("substring bound expression is not INTEGER"_err_en_US);
peter klausler93a7f1f2018-09-14 22:48:40662 }
peter klausler93a7f1f2018-09-14 22:48:40663 }
664 }
peter klausler935f0a22018-09-11 18:13:40665 return std::nullopt;
666}
667
peter klausler972b3af2019-03-07 22:46:31668MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) {
669 if (MaybeExpr baseExpr{Analyze(std::get<parser::DataRef>(ss.t))}) {
peter klausler1089f012018-12-03 19:40:53670 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) {
peter klausler972b3af2019-03-07 22:46:31671 if (MaybeExpr newBaseExpr{TopLevelChecks(std::move(*dataRef))}) {
peter klausler1089f012018-12-03 19:40:53672 if (std::optional<DataRef> checked{
673 ExtractDataRef(std::move(*newBaseExpr))}) {
674 const parser::SubstringRange &range{
675 std::get<parser::SubstringRange>(ss.t)};
676 std::optional<Expr<SubscriptInteger>> first{
peter klausler972b3af2019-03-07 22:46:31677 GetSubstringBound(std::get<0>(range.t))};
peter klausler1089f012018-12-03 19:40:53678 std::optional<Expr<SubscriptInteger>> last{
peter klausler972b3af2019-03-07 22:46:31679 GetSubstringBound(std::get<1>(range.t))};
peter klausler1089f012018-12-03 19:40:53680 const Symbol &symbol{checked->GetLastSymbol()};
peter klauslerec6cf762019-05-06 16:33:45681 if (std::optional<DynamicType> dynamicType{
682 DynamicType::From(symbol)}) {
peter klausler59342b02019-05-13 16:33:18683 if (dynamicType->category() == TypeCategory::Character) {
peter klausler1089f012018-12-03 19:40:53684 return WrapperHelper<TypeCategory::Character, Designator,
peter klausler59342b02019-05-13 16:33:18685 Substring>(dynamicType->kind(),
peter klausler1b1f60f2018-12-05 21:03:39686 Substring{std::move(checked.value()), std::move(first),
687 std::move(last)});
peter klausler1089f012018-12-03 19:40:53688 }
689 }
peter klausler972b3af2019-03-07 22:46:31690 Say("substring may apply only to CHARACTER"_err_en_US);
peter klausler1089f012018-12-03 19:40:53691 }
692 }
693 }
694 }
peter klausler935f0a22018-09-11 18:13:40695 return std::nullopt;
peter klausler8b9efa22018-08-13 20:33:31696}
697
peter klausler1089f012018-12-03 19:40:53698// CHARACTER literal substrings
peter klausler972b3af2019-03-07 22:46:31699MaybeExpr ExpressionAnalyzer::Analyze(
peter klausler1089f012018-12-03 19:40:53700 const parser::CharLiteralConstantSubstring &x) {
peter klauslercfb57cd2018-11-01 18:18:12701 const parser::SubstringRange &range{std::get<parser::SubstringRange>(x.t)};
702 std::optional<Expr<SubscriptInteger>> lower{
peter klausler972b3af2019-03-07 22:46:31703 GetSubstringBound(std::get<0>(range.t))};
peter klauslercfb57cd2018-11-01 18:18:12704 std::optional<Expr<SubscriptInteger>> upper{
peter klausler972b3af2019-03-07 22:46:31705 GetSubstringBound(std::get<1>(range.t))};
706 if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) {
peter klauslercfb57cd2018-11-01 18:18:12707 if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) {
708 Expr<SubscriptInteger> length{std::visit(
709 [](const auto &ckExpr) { return ckExpr.LEN(); }, charExpr->u)};
710 if (!lower.has_value()) {
711 lower = Expr<SubscriptInteger>{1};
712 }
713 if (!upper.has_value()) {
peter klausler1b1f60f2018-12-05 21:03:39714 upper = Expr<SubscriptInteger>{
715 static_cast<std::int64_t>(ToInt64(length).value())};
peter klauslercfb57cd2018-11-01 18:18:12716 }
717 return std::visit(
718 [&](auto &&ckExpr) -> MaybeExpr {
719 using Result = ResultType<decltype(ckExpr)>;
720 auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)};
721 CHECK(cp != nullptr); // the parent was parsed as a constant string
peter klausler650b32e2019-01-28 22:38:17722 CHECK(cp->size() == 1);
peter klausler4e566002018-11-02 23:42:45723 StaticDataObject::Pointer staticData{StaticDataObject::Create()};
724 staticData->set_alignment(Result::kind)
725 .set_itemBytes(Result::kind)
peter klausler59342b02019-05-13 16:33:18726 .Push(cp->GetScalarValue().value());
peter klausler1b1f60f2018-12-05 21:03:39727 Substring substring{std::move(staticData), std::move(lower.value()),
728 std::move(upper.value())};
peter klausler4e566002018-11-02 23:42:45729 return AsGenericExpr(Expr<SomeCharacter>{
730 Expr<Result>{Designator<Result>{std::move(substring)}}});
peter klauslercfb57cd2018-11-01 18:18:12731 },
732 std::move(charExpr->u));
733 }
734 }
peter klausler003c8322018-09-07 17:33:32735 return std::nullopt;
736}
737
peter klausler1089f012018-12-03 19:40:53738// Subscripted array references
peter klausler972b3af2019-03-07 22:46:31739std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::AsSubscript(
740 MaybeExpr &&expr) {
peter klausler1089f012018-12-03 19:40:53741 if (expr.has_value()) {
742 if (expr->Rank() > 1) {
peter klausler972b3af2019-03-07 22:46:31743 Say("subscript expression has rank %d"_err_en_US, expr->Rank());
peter klausler1089f012018-12-03 19:40:53744 }
745 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) {
746 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) {
747 return {std::move(*ssIntExpr)};
748 }
749 return {Expr<SubscriptInteger>{
750 Convert<SubscriptInteger, TypeCategory::Integer>{
751 std::move(*intExpr)}}};
752 } else {
peter klausler972b3af2019-03-07 22:46:31753 Say("subscript expression is not INTEGER"_err_en_US);
peter klausler1089f012018-12-03 19:40:53754 }
755 }
peter klausler003c8322018-09-07 17:33:32756 return std::nullopt;
757}
758
peter klausler972b3af2019-03-07 22:46:31759std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart(
peter klausler1089f012018-12-03 19:40:53760 const std::optional<parser::Subscript> &s) {
761 if (s.has_value()) {
peter klausler972b3af2019-03-07 22:46:31762 return AsSubscript(Analyze(*s));
peter klausler1089f012018-12-03 19:40:53763 }
peter klausler003c8322018-09-07 17:33:32764 return std::nullopt;
765}
766
peter klausler972b3af2019-03-07 22:46:31767std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript(
768 const parser::SectionSubscript &ss) {
peter klausler1089f012018-12-03 19:40:53769 return std::visit(
770 common::visitors{
771 [&](const parser::SubscriptTriplet &t) {
peter klausler972b3af2019-03-07 22:46:31772 return std::make_optional(Subscript{Triplet{
773 TripletPart(std::get<0>(t.t)), TripletPart(std::get<1>(t.t)),
774 TripletPart(std::get<2>(t.t))}});
peter klausler1089f012018-12-03 19:40:53775 },
776 [&](const auto &s) -> std::optional<Subscript> {
peter klausler972b3af2019-03-07 22:46:31777 if (auto subscriptExpr{AsSubscript(Analyze(s))}) {
peter klausler1089f012018-12-03 19:40:53778 return {Subscript{std::move(*subscriptExpr)}};
779 } else {
780 return std::nullopt;
781 }
782 },
783 },
784 ss.u);
785}
786
Tim Keith0df7fa02019-04-25 20:18:33787// Empty result means an error occurred
peter klausler972b3af2019-03-07 22:46:31788std::vector<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscripts(
peter klausler1089f012018-12-03 19:40:53789 const std::list<parser::SectionSubscript> &sss) {
Tim Keith0df7fa02019-04-25 20:18:33790 bool error{false};
peter klausler1089f012018-12-03 19:40:53791 std::vector<Subscript> subscripts;
792 for (const auto &s : sss) {
peter klausler972b3af2019-03-07 22:46:31793 if (auto subscript{AnalyzeSectionSubscript(s)}) {
peter klausler1089f012018-12-03 19:40:53794 subscripts.emplace_back(std::move(*subscript));
Tim Keith0df7fa02019-04-25 20:18:33795 } else {
796 error = true;
peter klausler1089f012018-12-03 19:40:53797 }
798 }
Tim Keith0df7fa02019-04-25 20:18:33799 return !error ? subscripts : std::vector<Subscript>{};
peter klausler1089f012018-12-03 19:40:53800}
801
peter klausler972b3af2019-03-07 22:46:31802MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) {
803 std::vector<Subscript> subscripts{AnalyzeSectionSubscripts(ae.subscripts)};
804 if (MaybeExpr baseExpr{Analyze(ae.base)}) {
peter klausler1089f012018-12-03 19:40:53805 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) {
Tim Keith0df7fa02019-04-25 20:18:33806 if (!subscripts.empty()) {
807 return ApplySubscripts(std::move(*dataRef), std::move(subscripts));
peter klausler1089f012018-12-03 19:40:53808 }
Tim Keith0df7fa02019-04-25 20:18:33809 } else {
peter klausler59342b02019-05-13 16:33:18810 Say("Subscripts may be applied only to an object, component, or array constant"_err_en_US);
peter klausler1089f012018-12-03 19:40:53811 }
812 }
peter klausler1089f012018-12-03 19:40:53813 return std::nullopt;
814}
815
peter klauslerdc9faa22019-01-09 23:06:07816// Type parameter inquiries apply to data references, but don't depend
817// on any trailing (co)subscripts.
peter klausler00e128e2019-06-25 20:07:32818static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) {
peter klauslerdc9faa22019-01-09 23:06:07819 return std::visit(
820 common::visitors{
peter klausler00e128e2019-06-25 20:07:32821 [](const Symbol *symbol) { return NamedEntity{*symbol}; },
822 [](Component &&component) {
823 return NamedEntity{std::move(component)};
824 },
peter klausler6d8aecf2019-02-01 00:04:17825 [](ArrayRef &&arrayRef) { return std::move(arrayRef.base()); },
peter klauslerdc9faa22019-01-09 23:06:07826 [](CoarrayRef &&coarrayRef) {
peter klausler00e128e2019-06-25 20:07:32827 return NamedEntity{coarrayRef.GetLastSymbol()};
peter klauslerdc9faa22019-01-09 23:06:07828 },
829 },
830 std::move(designator.u));
831}
832
peter klauslerbe3b7652018-12-04 18:55:32833// Components of parent derived types are explicitly represented as such.
834static std::optional<Component> CreateComponent(
835 DataRef &&base, const Symbol &component, const semantics::Scope &scope) {
836 if (&component.owner() == &scope) {
peter klausler59342b02019-05-13 16:33:18837 return Component{std::move(base), component};
peter klauslerbe3b7652018-12-04 18:55:32838 }
839 if (const semantics::Scope * parentScope{scope.GetDerivedTypeParent()}) {
840 if (const Symbol * parentComponent{parentScope->GetSymbol()}) {
841 return CreateComponent(
842 DataRef{Component{std::move(base), *parentComponent}}, component,
843 *parentScope);
844 }
845 }
846 return std::nullopt;
847}
848
peter klauslerdc9faa22019-01-09 23:06:07849// Derived type component references and type parameter inquiries
peter klausler972b3af2019-03-07 22:46:31850MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
Tim Keith0df7fa02019-04-25 20:18:33851 MaybeExpr base{Analyze(sc.base)};
852 if (!base) {
853 return std::nullopt;
854 }
855 Symbol *sym{sc.component.symbol};
Tim Keith77614542019-04-25 21:47:39856 if (context_.HasError(sym)) {
Tim Keith0df7fa02019-04-25 20:18:33857 return std::nullopt;
858 }
peter klauslerdc9faa22019-01-09 23:06:07859 const auto &name{sc.component.source};
Tim Keith0df7fa02019-04-25 20:18:33860 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
861 const semantics::DerivedTypeSpec *dtSpec{nullptr};
862 if (std::optional<DynamicType> dtDyTy{dtExpr->GetType()}) {
peter klausler59342b02019-05-13 16:33:18863 if (!dtDyTy->IsUnlimitedPolymorphic()) {
864 dtSpec = &dtDyTy->GetDerivedTypeSpec();
865 }
Tim Keith0df7fa02019-04-25 20:18:33866 }
867 if (sym->detailsIf<semantics::TypeParamDetails>()) {
868 if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
peter klausler25e6f032019-05-03 18:29:15869 if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
peter klausler59342b02019-05-13 16:33:18870 if (dyType->category() == TypeCategory::Integer) {
Tim Keith0df7fa02019-04-25 20:18:33871 return AsMaybeExpr(
peter klausler59342b02019-05-13 16:33:18872 common::SearchTypes(TypeParamInquiryVisitor{dyType->kind(),
Tim Keith0df7fa02019-04-25 20:18:33873 IgnoreAnySubscripts(std::move(*designator)), *sym}));
Tim Keith7ec08302019-01-07 21:31:50874 }
875 }
peter klauslerc3ce68c2019-05-30 23:14:24876 Say(name, "Type parameter is not INTEGER"_err_en_US);
Tim Keith7ec08302019-01-07 21:31:50877 } else {
Tim Keith0df7fa02019-04-25 20:18:33878 Say(name,
peter klauslerc3ce68c2019-05-30 23:14:24879 "A type parameter inquiry must be applied to "
Tim Keith0df7fa02019-04-25 20:18:33880 "a designator"_err_en_US);
881 }
882 } else if (dtSpec == nullptr || dtSpec->scope() == nullptr) {
peter klausler5a18e792019-03-11 22:39:11883 CHECK(context_.AnyFatalError());
884 return std::nullopt;
Tim Keith0df7fa02019-04-25 20:18:33885 } else if (std::optional<DataRef> dataRef{
886 ExtractDataRef(std::move(*dtExpr))}) {
887 if (auto component{
888 CreateComponent(std::move(*dataRef), *sym, *dtSpec->scope())}) {
889 return Designate(DataRef{std::move(*component)});
890 } else {
peter klauslerc3ce68c2019-05-30 23:14:24891 Say(name, "Component is not in scope of derived TYPE(%s)"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:45892 dtSpec->typeSymbol().name());
peter klausler1089f012018-12-03 19:40:53893 }
894 } else {
Tim Keith0df7fa02019-04-25 20:18:33895 Say(name,
peter klauslerc3ce68c2019-05-30 23:14:24896 "Base of component reference must be a data reference"_err_en_US);
peter klausler1089f012018-12-03 19:40:53897 }
Tim Keith0df7fa02019-04-25 20:18:33898 } else if (auto *details{sym->detailsIf<semantics::MiscDetails>()}) {
899 // special part-ref: %re, %im, %kind, %len
900 // Type errors are detected and reported in semantics.
901 using MiscKind = semantics::MiscDetails::Kind;
902 MiscKind kind{details->kind()};
903 if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) {
904 if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) {
905 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*zExpr))}) {
906 Expr<SomeReal> realExpr{std::visit(
907 [&](const auto &z) {
908 using PartType = typename ResultType<decltype(z)>::Part;
909 auto part{kind == MiscKind::ComplexPartRe
910 ? ComplexPart::Part::RE
911 : ComplexPart::Part::IM};
912 return AsCategoryExpr(Designator<PartType>{
913 ComplexPart{std::move(*dataRef), part}});
914 },
915 zExpr->u)};
916 return {AsGenericExpr(std::move(realExpr))};
917 }
918 }
919 } else if (kind == MiscKind::KindParamInquiry ||
920 kind == MiscKind::LenParamInquiry) {
921 // Convert x%KIND -> intrinsic KIND(x), x%LEN -> intrinsic LEN(x)
peter klausler5a18e792019-03-11 22:39:11922 return MakeFunctionRef(
923 name, ActualArguments{ActualArgument{std::move(*base)}});
Tim Keith0df7fa02019-04-25 20:18:33924 } else {
peter klausler5a18e792019-03-11 22:39:11925 common::die("unexpected MiscDetails::Kind");
Tim Keith0df7fa02019-04-25 20:18:33926 }
927 } else {
928 Say(name, "derived type required before component reference"_err_en_US);
peter klausler1089f012018-12-03 19:40:53929 }
930 return std::nullopt;
931}
932
peter klausler972b3af2019-03-07 22:46:31933MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &co) {
934 Say("TODO: CoindexedNamedObject unimplemented"_err_en_US);
peter klausler1089f012018-12-03 19:40:53935 return std::nullopt;
936}
937
peter klausler972b3af2019-03-07 22:46:31938int ExpressionAnalyzer::IntegerTypeSpecKind(
939 const parser::IntegerTypeSpec &spec) {
940 Expr<SubscriptInteger> value{
941 AnalyzeKindSelector(TypeCategory::Integer, spec.v)};
peter klausler0ae3d432019-01-23 00:30:32942 if (auto kind{ToInt64(value)}) {
943 return static_cast<int>(*kind);
944 }
peter klausler972b3af2019-03-07 22:46:31945 SayAt(spec, "Constant INTEGER kind value required here"_err_en_US);
946 return GetDefaultKind(TypeCategory::Integer);
peter klausler0ae3d432019-01-23 00:30:32947}
948
949// Array constructors
950
peter klausler972b3af2019-03-07 22:46:31951class ArrayConstructorContext : private ExpressionAnalyzer {
peter klausler44174432019-02-15 20:20:30952public:
953 ArrayConstructorContext(
peter klausler972b3af2019-03-07 22:46:31954 ExpressionAnalyzer &c, std::optional<DynamicTypeWithLength> &t)
955 : ExpressionAnalyzer{c}, type_{t} {}
956 ArrayConstructorContext(ArrayConstructorContext &) = default;
peter klausler0ae3d432019-01-23 00:30:32957 void Push(MaybeExpr &&);
958 void Add(const parser::AcValue &);
peter klausler44174432019-02-15 20:20:30959 std::optional<DynamicTypeWithLength> &type() const { return type_; }
960 const ArrayConstructorValues<SomeType> &values() { return values_; }
961
962private:
peter klausler972b3af2019-03-07 22:46:31963 template<int KIND, typename A>
964 std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr(
965 const A &x) {
966 if (MaybeExpr y{Analyze(x)}) {
967 Expr<SomeInteger> *intExpr{UnwrapExpr<Expr<SomeInteger>>(*y)};
968 CHECK(intExpr != nullptr);
969 return ConvertToType<Type<TypeCategory::Integer, KIND>>(
970 std::move(*intExpr));
971 }
972 return std::nullopt;
973 }
974
peter klausler44174432019-02-15 20:20:30975 std::optional<DynamicTypeWithLength> &type_;
976 bool explicitType_{type_.has_value()};
977 std::optional<std::int64_t> constantLength_;
978 ArrayConstructorValues<SomeType> values_;
peter klausler0ae3d432019-01-23 00:30:32979};
980
981void ArrayConstructorContext::Push(MaybeExpr &&x) {
peter klausler5a18e792019-03-11 22:39:11982 if (!x.has_value()) {
983 return;
984 }
985 if (auto dyType{x->GetType()}) {
986 DynamicTypeWithLength xType{*dyType};
peter klausler0ae3d432019-01-23 00:30:32987 if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) {
peter klausler59342b02019-05-13 16:33:18988 CHECK(xType.category() == TypeCategory::Character);
peter klausler0ae3d432019-01-23 00:30:32989 xType.length =
990 std::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u);
991 }
peter klausler44174432019-02-15 20:20:30992 if (!type_.has_value()) {
peter klausler0ae3d432019-01-23 00:30:32993 // If there is no explicit type-spec in an array constructor, the type
994 // of the array is the declared type of all of the elements, which must
peter klausler44174432019-02-15 20:20:30995 // be well-defined and all match.
peter klausler0ae3d432019-01-23 00:30:32996 // TODO: Possible language extension: use the most general type of
997 // the values as the type of a numeric constructed array, convert all
998 // of the other values to that type. Alternative: let the first value
999 // determine the type, and convert the others to that type.
peter klausler44174432019-02-15 20:20:301000 CHECK(!explicitType_);
1001 type_ = std::move(xType);
1002 constantLength_ = ToInt64(type_->length);
1003 values_.Push(std::move(*x));
1004 } else if (!explicitType_) {
1005 if (static_cast<const DynamicType &>(*type_) ==
peter klausler0ae3d432019-01-23 00:30:321006 static_cast<const DynamicType &>(xType)) {
peter klausler44174432019-02-15 20:20:301007 values_.Push(std::move(*x));
peter klausler4eccba92019-02-26 23:59:251008 if (auto thisLen{ToInt64(xType.LEN())}) {
peter klausler44174432019-02-15 20:20:301009 if (constantLength_.has_value()) {
peter klausler972b3af2019-03-07 22:46:311010 if (context().warnOnNonstandardUsage() &&
peter klausler44174432019-02-15 20:20:301011 *thisLen != *constantLength_) {
peter klausler972b3af2019-03-07 22:46:311012 Say("Character literal in array constructor without explicit "
peter klausler475d72f2019-02-15 22:26:231013 "type has different length than earlier element"_en_US);
peter klausler44174432019-02-15 20:20:301014 }
1015 if (*thisLen > *constantLength_) {
peter klausler475d72f2019-02-15 22:26:231016 // Language extension: use the longest literal to determine the
1017 // length of the array constructor's character elements, not the
1018 // first, when there is no explicit type.
peter klausler44174432019-02-15 20:20:301019 *constantLength_ = *thisLen;
peter klausler4eccba92019-02-26 23:59:251020 type_->length = xType.LEN();
peter klausler44174432019-02-15 20:20:301021 }
1022 } else {
1023 constantLength_ = *thisLen;
peter klausler4eccba92019-02-26 23:59:251024 type_->length = xType.LEN();
peter klausler44174432019-02-15 20:20:301025 }
1026 }
peter klausler0ae3d432019-01-23 00:30:321027 } else {
peter klausler972b3af2019-03-07 22:46:311028 Say("Values in array constructor must have the same declared type "
peter klausler475d72f2019-02-15 22:26:231029 "when no explicit type appears"_err_en_US);
peter klausler0ae3d432019-01-23 00:30:321030 }
1031 } else {
peter klausler44174432019-02-15 20:20:301032 if (auto cast{ConvertToType(*type_, std::move(*x))}) {
1033 values_.Push(std::move(*cast));
peter klausler0ae3d432019-01-23 00:30:321034 } else {
peter klausler972b3af2019-03-07 22:46:311035 Say("Value in array constructor could not be converted to the type "
peter klausler475d72f2019-02-15 22:26:231036 "of the array"_err_en_US);
peter klausler0ae3d432019-01-23 00:30:321037 }
1038 }
1039 }
1040}
1041
1042void ArrayConstructorContext::Add(const parser::AcValue &x) {
1043 using IntType = ResultType<ImpliedDoIndex>;
1044 std::visit(
1045 common::visitors{
1046 [&](const parser::AcValue::Triplet &triplet) {
1047 // Transform l:u(:s) into (_,_=l,u(,s)) with an anonymous index '_'
1048 std::optional<Expr<IntType>> lower{
peter klausler972b3af2019-03-07 22:46:311049 GetSpecificIntExpr<IntType::kind>(std::get<0>(triplet.t))};
peter klausler0ae3d432019-01-23 00:30:321050 std::optional<Expr<IntType>> upper{
peter klausler972b3af2019-03-07 22:46:311051 GetSpecificIntExpr<IntType::kind>(std::get<1>(triplet.t))};
peter klausler0ae3d432019-01-23 00:30:321052 std::optional<Expr<IntType>> stride{
peter klausler972b3af2019-03-07 22:46:311053 GetSpecificIntExpr<IntType::kind>(std::get<2>(triplet.t))};
peter klausler0ae3d432019-01-23 00:30:321054 if (lower.has_value() && upper.has_value()) {
1055 if (!stride.has_value()) {
1056 stride = Expr<IntType>{1};
1057 }
peter klausler44174432019-02-15 20:20:301058 if (!type_.has_value()) {
1059 type_ = DynamicTypeWithLength{IntType::GetType()};
peter klausler0ae3d432019-01-23 00:30:321060 }
peter klausler44174432019-02-15 20:20:301061 ArrayConstructorContext nested{*this};
peter klausler0ae3d432019-01-23 00:30:321062 parser::CharBlock name;
1063 nested.Push(Expr<SomeType>{
1064 Expr<SomeInteger>{Expr<IntType>{ImpliedDoIndex{name}}}});
peter klausler44174432019-02-15 20:20:301065 values_.Push(ImpliedDo<SomeType>{name, std::move(*lower),
peter klausler0ae3d432019-01-23 00:30:321066 std::move(*upper), std::move(*stride),
peter klausler44174432019-02-15 20:20:301067 std::move(nested.values_)});
peter klausler0ae3d432019-01-23 00:30:321068 }
1069 },
1070 [&](const common::Indirection<parser::Expr> &expr) {
peter klausler972b3af2019-03-07 22:46:311071 auto restorer{
1072 GetContextualMessages().SetLocation(expr.value().source)};
1073 if (MaybeExpr v{Analyze(expr.value())}) {
peter klausler0ae3d432019-01-23 00:30:321074 Push(std::move(*v));
1075 }
1076 },
1077 [&](const common::Indirection<parser::AcImpliedDo> &impliedDo) {
1078 const auto &control{
peter klausler6a0f9472019-03-05 20:28:081079 std::get<parser::AcImpliedDoControl>(impliedDo.value().t)};
peter klausler0ae3d432019-01-23 00:30:321080 const auto &bounds{
Tim Keith351dc982019-05-09 15:32:271081 std::get<parser::AcImpliedDoControl::Bounds>(control.t)};
Tim Keith0df7fa02019-04-25 20:18:331082 Analyze(bounds.name);
peter klausler0ae3d432019-01-23 00:30:321083 parser::CharBlock name{bounds.name.thing.thing.source};
1084 int kind{IntType::kind};
1085 if (auto &its{std::get<std::optional<parser::IntegerTypeSpec>>(
1086 control.t)}) {
peter klausler972b3af2019-03-07 22:46:311087 kind = IntegerTypeSpecKind(*its);
peter klausler0ae3d432019-01-23 00:30:321088 }
peter klausler972b3af2019-03-07 22:46:311089 bool inserted{AddAcImpliedDo(name, kind)};
peter klausler0ae3d432019-01-23 00:30:321090 if (!inserted) {
peter klausler972b3af2019-03-07 22:46:311091 SayAt(name,
peter klausler475d72f2019-02-15 22:26:231092 "Implied DO index is active in surrounding implied DO loop "
peter klausler5a18e792019-03-11 22:39:111093 "and may not have the same name"_err_en_US);
peter klausler0ae3d432019-01-23 00:30:321094 }
1095 std::optional<Expr<IntType>> lower{
peter klausler972b3af2019-03-07 22:46:311096 GetSpecificIntExpr<IntType::kind>(bounds.lower)};
peter klausler0ae3d432019-01-23 00:30:321097 std::optional<Expr<IntType>> upper{
peter klausler972b3af2019-03-07 22:46:311098 GetSpecificIntExpr<IntType::kind>(bounds.upper)};
peter klausler0ae3d432019-01-23 00:30:321099 std::optional<Expr<IntType>> stride{
peter klausler972b3af2019-03-07 22:46:311100 GetSpecificIntExpr<IntType::kind>(bounds.step)};
peter klausler44174432019-02-15 20:20:301101 ArrayConstructorContext nested{*this};
peter klausler0ae3d432019-01-23 00:30:321102 for (const auto &value :
peter klausler6a0f9472019-03-05 20:28:081103 std::get<std::list<parser::AcValue>>(impliedDo.value().t)) {
peter klausler0ae3d432019-01-23 00:30:321104 nested.Add(value);
1105 }
1106 if (lower.has_value() && upper.has_value()) {
1107 if (!stride.has_value()) {
1108 stride = Expr<IntType>{1};
1109 }
peter klausler44174432019-02-15 20:20:301110 values_.Push(ImpliedDo<SomeType>{name, std::move(*lower),
peter klausler0ae3d432019-01-23 00:30:321111 std::move(*upper), std::move(*stride),
peter klausler44174432019-02-15 20:20:301112 std::move(nested.values_)});
peter klausler0ae3d432019-01-23 00:30:321113 }
1114 if (inserted) {
peter klausler972b3af2019-03-07 22:46:311115 RemoveAcImpliedDo(name);
peter klausler0ae3d432019-01-23 00:30:321116 }
1117 },
1118 },
1119 x.u);
1120}
1121
1122// Inverts a collection of generic ArrayConstructorValues<SomeType> that
peter klausler140b4ad2019-01-31 17:58:401123// all happen to have the same actual type T into one ArrayConstructor<T>.
peter klausler0ae3d432019-01-23 00:30:321124template<typename T>
1125ArrayConstructorValues<T> MakeSpecific(
1126 ArrayConstructorValues<SomeType> &&from) {
1127 ArrayConstructorValues<T> to;
peter klausler146e13c2019-04-18 21:11:151128 for (ArrayConstructorValue<SomeType> &x : from) {
peter klausler0ae3d432019-01-23 00:30:321129 std::visit(
1130 common::visitors{
peter klauslerdfc16432019-03-20 20:44:001131 [&](common::CopyableIndirection<Expr<SomeType>> &&expr) {
peter klausler6a0f9472019-03-05 20:28:081132 auto *typed{UnwrapExpr<Expr<T>>(expr.value())};
peter klausler0ae3d432019-01-23 00:30:321133 CHECK(typed != nullptr);
1134 to.Push(std::move(*typed));
1135 },
1136 [&](ImpliedDo<SomeType> &&impliedDo) {
peter klausler6a0f9472019-03-05 20:28:081137 to.Push(ImpliedDo<T>{impliedDo.name(),
1138 std::move(impliedDo.lower()), std::move(impliedDo.upper()),
1139 std::move(impliedDo.stride()),
1140 MakeSpecific<T>(std::move(impliedDo.values()))});
peter klausler0ae3d432019-01-23 00:30:321141 },
1142 },
1143 std::move(x.u));
1144 }
1145 return to;
1146}
1147
1148struct ArrayConstructorTypeVisitor {
1149 using Result = MaybeExpr;
peter klausler4313f4c72019-02-08 18:39:101150 using Types = AllTypes;
peter klausler0ae3d432019-01-23 00:30:321151 template<typename T> Result Test() {
peter klausler59342b02019-05-13 16:33:181152 if (type.category() == T::category) {
peter klausler4313f4c72019-02-08 18:39:101153 if constexpr (T::category == TypeCategory::Derived) {
peter klausler0ae3d432019-01-23 00:30:321154 return AsMaybeExpr(ArrayConstructor<T>{
peter klausler59342b02019-05-13 16:33:181155 type.GetDerivedTypeSpec(), MakeSpecific<T>(std::move(values))});
1156 } else if (type.kind() == T::kind) {
peter klausler4313f4c72019-02-08 18:39:101157 if constexpr (T::category == TypeCategory::Character) {
peter klausler4313f4c72019-02-08 18:39:101158 return AsMaybeExpr(ArrayConstructor<T>{
peter klausler4eccba92019-02-26 23:59:251159 type.LEN().value(), MakeSpecific<T>(std::move(values))});
peter klausler4313f4c72019-02-08 18:39:101160 } else {
1161 return AsMaybeExpr(
1162 ArrayConstructor<T>{MakeSpecific<T>(std::move(values))});
1163 }
peter klausler0ae3d432019-01-23 00:30:321164 }
peter klausler0ae3d432019-01-23 00:30:321165 }
peter klausler4313f4c72019-02-08 18:39:101166 return std::nullopt;
peter klausler0ae3d432019-01-23 00:30:321167 }
1168 DynamicTypeWithLength type;
1169 ArrayConstructorValues<SomeType> values;
1170};
1171
peter klausler972b3af2019-03-07 22:46:311172MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) {
peter klausler0ae3d432019-01-23 00:30:321173 const parser::AcSpec &acSpec{array.v};
peter klausler972b3af2019-03-07 22:46:311174 std::optional<DynamicTypeWithLength> type{AnalyzeTypeSpec(acSpec.type)};
1175 ArrayConstructorContext context{*this, type};
peter klausler0ae3d432019-01-23 00:30:321176 for (const parser::AcValue &value : acSpec.values) {
1177 context.Add(value);
1178 }
1179 if (type.has_value()) {
1180 ArrayConstructorTypeVisitor visitor{
peter klausler44174432019-02-15 20:20:301181 std::move(*type), std::move(context.values())};
peter klausler0ae3d432019-01-23 00:30:321182 return common::SearchTypes(std::move(visitor));
1183 }
peter klausler1089f012018-12-03 19:40:531184 return std::nullopt;
1185}
1186
peter klausler972b3af2019-03-07 22:46:311187MaybeExpr ExpressionAnalyzer::Analyze(
peter klausler5b79ffc5f2019-02-09 00:35:021188 const parser::StructureConstructor &structure) {
peter klauslerf5bc9fd2019-02-14 20:51:201189 auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)};
1190 parser::CharBlock typeName{std::get<parser::Name>(parsedType.t).source};
1191 if (parsedType.derivedTypeSpec == nullptr) {
peter klauslerf5bc9fd2019-02-14 20:51:201192 return std::nullopt;
1193 }
1194 const auto &spec{*parsedType.derivedTypeSpec};
peter klauslerf5bc9fd2019-02-14 20:51:201195 const Symbol &typeSymbol{spec.typeSymbol()};
peter klauslera53b11c2019-06-21 21:07:391196 if (spec.scope() == nullptr ||
1197 !typeSymbol.has<semantics::DerivedTypeDetails>()) {
1198 return std::nullopt; // error recovery
1199 }
1200 const auto &typeDetails{typeSymbol.get<semantics::DerivedTypeDetails>()};
1201 const Symbol *parentComponent{typeDetails.GetParentComponent(*spec.scope())};
peter klauslerf5bc9fd2019-02-14 20:51:201202
peter klausler2f12ee42019-02-14 22:37:551203 if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796
peter klausler972b3af2019-03-07 22:46:311204 if (auto *msg{Say(typeName,
peter klausler5a18e792019-03-11 22:39:111205 "ABSTRACT derived type '%s' may not be used in a "
peter klauslere3b63232019-03-08 23:16:301206 "structure constructor"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451207 typeName)}) {
peter klausler2f12ee42019-02-14 22:37:551208 msg->Attach(
1209 typeSymbol.name(), "Declaration of ABSTRACT derived type"_en_US);
1210 }
1211 }
1212
peter klauslerf5bc9fd2019-02-14 20:51:201213 // This list holds all of the components in the derived type and its
1214 // parents. The symbols for whole parent components appear after their
1215 // own components and before the components of the types that extend them.
1216 // E.g., TYPE :: A; REAL X; END TYPE
1217 // TYPE, EXTENDS(A) :: B; REAL Y; END TYPE
1218 // produces the component list X, A, Y.
1219 // The order is important below because a structure constructor can
1220 // initialize X or A by name, but not both.
1221 const auto &details{typeSymbol.get<semantics::DerivedTypeDetails>()};
1222 std::list<const Symbol *> components{details.OrderComponents(*spec.scope())};
peter klausler2f12ee42019-02-14 22:37:551223 auto nextAnonymous{components.begin()};
peter klauslerf5bc9fd2019-02-14 20:51:201224
1225 std::set<parser::CharBlock> unavailable;
1226 bool anyKeyword{false};
1227 StructureConstructor result{spec};
peter klausler5a18e792019-03-11 22:39:111228 bool checkConflicts{true}; // until we hit one
peter klauslerf5bc9fd2019-02-14 20:51:201229
1230 for (const auto &component :
1231 std::get<std::list<parser::ComponentSpec>>(structure.t)) {
1232 const parser::Expr &expr{
peter klausler6a0f9472019-03-05 20:28:081233 std::get<parser::ComponentDataSource>(component.t).v.value()};
peter klauslerf5bc9fd2019-02-14 20:51:201234 parser::CharBlock source{expr.source};
peter klausler5a18e792019-03-11 22:39:111235 auto &messages{GetContextualMessages()};
1236 auto restorer{messages.SetLocation(source)};
peter klausler2f12ee42019-02-14 22:37:551237 const Symbol *symbol{nullptr};
peter klauslera53b11c2019-06-21 21:07:391238 MaybeExpr value{Analyze(expr)};
1239 std::optional<DynamicType> valueType{DynamicType::From(value)};
peter klauslerf5bc9fd2019-02-14 20:51:201240 if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) {
peter klausler5a18e792019-03-11 22:39:111241 anyKeyword = true;
peter klauslerf5bc9fd2019-02-14 20:51:201242 source = kw->v.source;
peter klausler2f12ee42019-02-14 22:37:551243 symbol = kw->v.symbol;
peter klausler5a18e792019-03-11 22:39:111244 if (symbol == nullptr) {
1245 auto componentIter{std::find_if(components.begin(), components.end(),
1246 [=](const Symbol *symbol) { return symbol->name() == source; })};
1247 if (componentIter != components.end()) {
1248 symbol = *componentIter;
1249 }
1250 }
1251 if (symbol == nullptr) { // C7101
1252 Say(source,
1253 "Keyword '%s=' does not name a component of derived type '%s'"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451254 source, typeName);
peter klausler5a18e792019-03-11 22:39:111255 }
peter klausler2f12ee42019-02-14 22:37:551256 } else {
1257 if (anyKeyword) { // C7100
peter klausler972b3af2019-03-07 22:46:311258 Say(source,
peter klausler2f12ee42019-02-14 22:37:551259 "Value in structure constructor lacks a component name"_err_en_US);
1260 checkConflicts = false; // stem cascade
1261 }
peter klauslera53b11c2019-06-21 21:07:391262 // Here's a regrettably common extension of the standard: anonymous
1263 // initialization of parent components, e.g., T(PT(1)) rather than
1264 // T(1) or T(PT=PT(1)).
1265 if (nextAnonymous == components.begin() && parentComponent != nullptr &&
1266 valueType == DynamicType::From(*parentComponent) &&
1267 context().IsEnabled(parser::LanguageFeature::AnonymousParents)) {
1268 auto iter{
1269 std::find(components.begin(), components.end(), parentComponent)};
1270 if (iter != components.end()) {
1271 symbol = parentComponent;
1272 nextAnonymous = ++iter;
1273 if (context().ShouldWarn(parser::LanguageFeature::AnonymousParents)) {
1274 Say(source,
1275 "Whole parent component '%s' in structure "
1276 "constructor should not be anonymous"_en_US,
1277 symbol->name());
1278 }
1279 }
1280 }
1281 while (symbol == nullptr && nextAnonymous != components.end()) {
peter klausler5a18e792019-03-11 22:39:111282 const Symbol *nextSymbol{*nextAnonymous++};
1283 if (!nextSymbol->test(Symbol::Flag::ParentComp)) {
1284 symbol = nextSymbol;
peter klausler5b79ffc5f2019-02-09 00:35:021285 }
peter klausler2f12ee42019-02-14 22:37:551286 }
1287 if (symbol == nullptr) {
peter klausler972b3af2019-03-07 22:46:311288 Say(source, "Unexpected value in structure constructor"_err_en_US);
peter klausler2f12ee42019-02-14 22:37:551289 }
1290 }
1291 if (symbol != nullptr) {
peter klausler857da8c2019-02-19 23:38:551292 if (checkConflicts) {
peter klausler2f12ee42019-02-14 22:37:551293 auto componentIter{
1294 std::find(components.begin(), components.end(), symbol)};
1295 if (unavailable.find(symbol->name()) != unavailable.cend()) {
1296 // C797, C798
peter klausler972b3af2019-03-07 22:46:311297 Say(source,
peter klausler857da8c2019-02-19 23:38:551298 "Component '%s' conflicts with another component earlier in "
1299 "this structure constructor"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451300 symbol->name());
peter klausler2f12ee42019-02-14 22:37:551301 } else if (symbol->test(Symbol::Flag::ParentComp)) {
1302 // Make earlier components unavailable once a whole parent appears.
1303 for (auto it{components.begin()}; it != componentIter; ++it) {
peter klauslerf5bc9fd2019-02-14 20:51:201304 unavailable.insert((*it)->name());
1305 }
peter klausler2f12ee42019-02-14 22:37:551306 } else {
1307 // Make whole parent components unavailable after any of their
1308 // constituents appear.
1309 for (auto it{componentIter}; it != components.end(); ++it) {
1310 if ((*it)->test(Symbol::Flag::ParentComp)) {
1311 unavailable.insert((*it)->name());
1312 }
1313 }
peter klauslerf5bc9fd2019-02-14 20:51:201314 }
peter klausler5b79ffc5f2019-02-09 00:35:021315 }
peter klausler2f12ee42019-02-14 22:37:551316 unavailable.insert(symbol->name());
peter klauslera53b11c2019-06-21 21:07:391317 if (value.has_value()) {
peter klausler431b8482019-02-21 20:10:071318 if (symbol->has<semantics::ProcEntityDetails>()) {
peter klausler5a18e792019-03-11 22:39:111319 CHECK(IsPointer(*symbol));
1320 } else if (symbol->has<semantics::ObjectEntityDetails>()) {
peter klausler8a574332019-03-02 01:33:201321 // C1594(4)
peter klausler5a18e792019-03-11 22:39:111322 const auto &innermost{context_.FindScope(expr.source)};
1323 if (const auto *pureFunc{
1324 semantics::FindPureFunctionContaining(&innermost)}) {
1325 if (const Symbol *
1326 pointer{semantics::FindPointerComponent(*symbol)}) {
peter klauslerda2ebb62019-03-05 00:28:351327 if (const Symbol *
peter klausler5a18e792019-03-11 22:39:111328 object{semantics::FindExternallyVisibleObject(
1329 *value, *pureFunc)}) {
1330 if (auto *msg{Say(expr.source,
1331 "Externally visible object '%s' must not be "
1332 "associated with pointer component '%s' in a "
1333 "PURE function"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451334 object->name(), pointer->name())}) {
peter klausler5a18e792019-03-11 22:39:111335 msg->Attach(object->name(), "Object declaration"_en_US)
1336 .Attach(pointer->name(), "Pointer declaration"_en_US);
peter klauslerda2ebb62019-03-05 00:28:351337 }
peter klausler8a574332019-03-02 01:33:201338 }
1339 }
1340 }
peter klausler5a18e792019-03-11 22:39:111341 } else if (symbol->has<semantics::TypeParamDetails>()) {
1342 Say(expr.source,
1343 "Type parameter '%s' may not appear as a component "
1344 "of a structure constructor"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451345 symbol->name());
peter klausler5a18e792019-03-11 22:39:111346 continue;
1347 } else {
1348 Say(expr.source,
1349 "Component '%s' is neither a procedure pointer "
1350 "nor a data object"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451351 symbol->name());
peter klausler5a18e792019-03-11 22:39:111352 continue;
1353 }
1354 if (IsPointer(*symbol)) {
1355 CheckPointerAssignment(messages, context_.intrinsics(), *symbol,
1356 *value); // C7104, C7105
1357 } else if (MaybeExpr converted{
1358 ConvertToType(*symbol, std::move(*value))}) {
1359 result.Add(*symbol, std::move(*converted));
peter klausler59342b02019-05-13 16:33:181360 } else if (auto symType{DynamicType::From(symbol)}) {
peter klauslera53b11c2019-06-21 21:07:391361 if (valueType.has_value()) {
peter klausler59342b02019-05-13 16:33:181362 if (auto *msg{Say(expr.source,
1363 "Value in structure constructor of type %s is "
1364 "incompatible with component '%s' of type %s"_err_en_US,
peter klauslera53b11c2019-06-21 21:07:391365 valueType->AsFortran(), symbol->name(),
1366 symType->AsFortran())}) {
peter klausler59342b02019-05-13 16:33:181367 msg->Attach(symbol->name(), "Component declaration"_en_US);
1368 }
1369 } else {
1370 if (auto *msg{Say(expr.source,
1371 "Value in structure constructor is incompatible with "
1372 " component '%s' of type %s"_err_en_US,
1373 symbol->name(), symType->AsFortran())}) {
1374 msg->Attach(symbol->name(), "Component declaration"_en_US);
1375 }
peter klausler857da8c2019-02-19 23:38:551376 }
1377 }
peter klausler2f12ee42019-02-14 22:37:551378 }
peter klausler5b79ffc5f2019-02-09 00:35:021379 }
peter klausler5b79ffc5f2019-02-09 00:35:021380 }
peter klauslerf5bc9fd2019-02-14 20:51:201381
1382 // Ensure that unmentioned component objects have default initializers.
1383 for (const Symbol *symbol : components) {
1384 if (!symbol->test(Symbol::Flag::ParentComp) &&
1385 unavailable.find(symbol->name()) == unavailable.cend() &&
peter klausler5a18e792019-03-11 22:39:111386 !IsAllocatable(*symbol)) {
peter klauslerf5bc9fd2019-02-14 20:51:201387 if (const auto *details{
1388 symbol->detailsIf<semantics::ObjectEntityDetails>()}) {
1389 if (details->init().has_value()) {
1390 result.Add(*symbol, common::Clone(*details->init()));
1391 } else { // C799
peter klausler972b3af2019-03-07 22:46:311392 if (auto *msg{Say(typeName,
peter klausler857da8c2019-02-19 23:38:551393 "Structure constructor lacks a value for "
1394 "component '%s'"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451395 symbol->name())}) {
peter klauslerf5bc9fd2019-02-14 20:51:201396 msg->Attach(symbol->name(), "Absent component"_en_US);
1397 }
1398 }
1399 }
1400 }
1401 }
1402
peter klauslerf5bc9fd2019-02-14 20:51:201403 return AsMaybeExpr(Expr<SomeDerived>{std::move(result)});
peter klausler1089f012018-12-03 19:40:531404}
1405
peter klauslerba2ef032019-04-12 23:50:581406std::optional<ProcedureDesignator>
1407ExpressionAnalyzer::AnalyzeProcedureComponentRef(
1408 const parser::ProcComponentRef &pcr) {
1409 const parser::StructureComponent &sc{pcr.v.thing};
1410 const auto &name{sc.component.source};
1411 if (MaybeExpr base{Analyze(sc.base)}) {
peter klausler5a18e792019-03-11 22:39:111412 if (Symbol * sym{sc.component.symbol}) {
1413 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) {
1414 const semantics::DerivedTypeSpec *dtSpec{nullptr};
1415 if (std::optional<DynamicType> dtDyTy{dtExpr->GetType()}) {
peter klausler59342b02019-05-13 16:33:181416 if (!dtDyTy->IsUnlimitedPolymorphic()) {
1417 dtSpec = &dtDyTy->GetDerivedTypeSpec();
1418 }
peter klausler5a18e792019-03-11 22:39:111419 }
1420 if (dtSpec != nullptr && dtSpec->scope() != nullptr) {
1421 if (std::optional<DataRef> dataRef{
1422 ExtractDataRef(std::move(*dtExpr))}) {
1423 if (auto component{CreateComponent(
1424 std::move(*dataRef), *sym, *dtSpec->scope())}) {
1425 return ProcedureDesignator{std::move(*component)};
1426 } else {
1427 Say(name,
1428 "procedure component is not in scope of derived TYPE(%s)"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451429 dtSpec->typeSymbol().name());
peter klausler5a18e792019-03-11 22:39:111430 }
1431 } else {
1432 Say(name,
1433 "base of procedure component reference must be a data reference"_err_en_US);
1434 }
peter klauslerba2ef032019-04-12 23:50:581435 }
1436 } else {
1437 Say(name,
peter klausler5a18e792019-03-11 22:39:111438 "base of procedure component reference is not a derived type object"_err_en_US);
peter klauslerba2ef032019-04-12 23:50:581439 }
peter klauslerba2ef032019-04-12 23:50:581440 }
1441 }
peter klausler5a18e792019-03-11 22:39:111442 CHECK(context_.messages().AnyFatalError());
peter klauslerba2ef032019-04-12 23:50:581443 return std::nullopt;
1444}
1445
peter klausler972b3af2019-03-07 22:46:311446auto ExpressionAnalyzer::Procedure(const parser::ProcedureDesignator &pd,
peter klausler5a18e792019-03-11 22:39:111447 ActualArguments &arguments) -> std::optional<CalleeAndArguments> {
peter klauslerd9694642018-09-20 19:34:291448 return std::visit(
1449 common::visitors{
peter klausler5a18e792019-03-11 22:39:111450 [&](const parser::Name &n) -> std::optional<CalleeAndArguments> {
1451 if (context_.HasError(n.symbol)) {
peter klauslerd9694642018-09-20 19:34:291452 return std::nullopt;
1453 }
peter klauslerfc616322019-06-07 00:09:491454 const Symbol &symbol{n.symbol->GetUltimate()};
peter klausler5a18e792019-03-11 22:39:111455 if (!symbol.HasExplicitInterface() ||
1456 (symbol.has<semantics::MiscDetails>() &&
1457 symbol.get<semantics::MiscDetails>().kind() ==
1458 semantics::MiscDetails::Kind::SpecificIntrinsic)) {
1459 // Might be an intrinsic.
1460 if (std::optional<SpecificCall> specificCall{
1461 context_.intrinsics().Probe(CallCharacteristics{n.source},
1462 arguments, GetFoldingContext())}) {
1463 return CalleeAndArguments{ProcedureDesignator{std::move(
1464 specificCall->specificIntrinsic)},
1465 std::move(specificCall->arguments)};
peter klausler64ea4622019-03-08 20:55:571466 }
peter klausler64ea4622019-03-08 20:55:571467 }
peter klausler5a18e792019-03-11 22:39:111468 if (symbol.HasExplicitInterface()) {
1469 // TODO: check actual arguments vs. interface
1470 } else {
1471 // TODO: call with implicit interface
1472 }
1473 return CalleeAndArguments{
1474 ProcedureDesignator{symbol}, std::move(arguments)};
peter klauslerd9694642018-09-20 19:34:291475 },
1476 [&](const parser::ProcComponentRef &pcr)
peter klausler5a18e792019-03-11 22:39:111477 -> std::optional<CalleeAndArguments> {
peter klauslerba2ef032019-04-12 23:50:581478 if (std::optional<ProcedureDesignator> proc{
1479 AnalyzeProcedureComponentRef(pcr)}) {
peter klauslerd9694642018-09-20 19:34:291480 // TODO distinguish PCR from TBP
1481 // TODO optional PASS argument for TBP
peter klausler5a18e792019-03-11 22:39:111482 return CalleeAndArguments{std::move(*proc), std::move(arguments)};
peter klauslerd9694642018-09-20 19:34:291483 } else {
1484 return std::nullopt;
1485 }
1486 },
1487 },
1488 pd.u);
1489}
1490
peter klausler3e313d42019-06-03 19:18:521491static const Symbol *AssumedTypeDummy(const parser::Expr &x) {
peter klausler5a18e792019-03-11 22:39:111492 if (const auto *designator{
peter klausler3e313d42019-06-03 19:18:521493 std::get_if<common::Indirection<parser::Designator>>(&x.u)}) {
peter klausler5a18e792019-03-11 22:39:111494 if (const auto *dataRef{
1495 std::get_if<parser::DataRef>(&designator->value().u)}) {
1496 if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) {
1497 if (const Symbol * symbol{name->symbol}) {
1498 if (const auto *type{symbol->GetType()}) {
1499 if (type->category() == semantics::DeclTypeSpec::TypeStar) {
1500 return symbol;
1501 }
1502 }
1503 }
1504 }
1505 }
1506 }
1507 return nullptr;
1508}
1509
peter klausler972b3af2019-03-07 22:46:311510MaybeExpr ExpressionAnalyzer::Analyze(
peter klausler1089f012018-12-03 19:40:531511 const parser::FunctionReference &funcRef) {
peter klauslerad2fda82018-09-19 21:27:131512 // TODO: C1002: Allow a whole assumed-size array to appear if the dummy
1513 // argument would accept it. Handle by special-casing the context
1514 // ActualArg -> Variable -> Designator.
peter klauslerf9535832019-02-26 22:26:281515 // TODO: Actual arguments that are procedures and procedure pointers need to
1516 // be detected and represented (they're not expressions).
1517 // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
peter klauslerce9716d2019-04-15 22:18:071518 auto save{GetContextualMessages().SetLocation(funcRef.v.source)};
peter klausleref9dd9d2018-10-17 22:09:481519 ActualArguments arguments;
peter klauslerd9694642018-09-20 19:34:291520 for (const auto &arg :
1521 std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t)) {
peter klauslerd9694642018-09-20 19:34:291522 MaybeExpr actualArgExpr;
peter klausler5a18e792019-03-11 22:39:111523 const Symbol *assumedTypeDummy{nullptr};
peter klauslerd9694642018-09-20 19:34:291524 std::visit(
Tim Keithdaa0b052018-11-29 17:27:341525 common::visitors{
peter klauslerd9694642018-09-20 19:34:291526 [&](const common::Indirection<parser::Expr> &x) {
peter klausler3e313d42019-06-03 19:18:521527 // TODO: Distinguish & handle procedure name and
1528 // proc-component-ref
1529 if (!(assumedTypeDummy = AssumedTypeDummy(x.value()))) {
1530 actualArgExpr = Analyze(x.value());
1531 }
peter klauslerd9694642018-09-20 19:34:291532 },
1533 [&](const parser::AltReturnSpec &) {
peter klausler5a18e792019-03-11 22:39:111534 Say("alternate return specification may not appear on function reference"_err_en_US);
peter klauslerd9694642018-09-20 19:34:291535 },
1536 [&](const parser::ActualArg::PercentRef &) {
peter klausler972b3af2019-03-07 22:46:311537 Say("TODO: %REF() argument"_err_en_US);
peter klauslerd9694642018-09-20 19:34:291538 },
1539 [&](const parser::ActualArg::PercentVal &) {
peter klausler972b3af2019-03-07 22:46:311540 Say("TODO: %VAL() argument"_err_en_US);
Tim Keithdaa0b052018-11-29 17:27:341541 },
1542 },
peter klauslerd9694642018-09-20 19:34:291543 std::get<parser::ActualArg>(arg.t).u);
peter klausler5a18e792019-03-11 22:39:111544 if (assumedTypeDummy != nullptr) {
1545 arguments.emplace_back(
1546 std::make_optional(ActualArgument::AssumedType{*assumedTypeDummy}));
1547 } else if (actualArgExpr.has_value()) {
peter klauslerabac2282018-10-26 22:10:241548 arguments.emplace_back(std::make_optional(
peter klausler972b3af2019-03-07 22:46:311549 Fold(GetFoldingContext(), std::move(*actualArgExpr))));
peter klauslera62636f2018-10-08 22:35:191550 if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) {
peter klausleref9dd9d2018-10-17 22:09:481551 arguments.back()->keyword = argKW->v.source;
peter klauslera62636f2018-10-08 22:35:191552 }
peter klauslerd9694642018-09-20 19:34:291553 } else {
peter klauslera62636f2018-10-08 22:35:191554 return std::nullopt;
peter klauslerd9694642018-09-20 19:34:291555 }
1556 }
peter klauslercb308d32018-10-05 18:32:541557
peter klausler5a18e792019-03-11 22:39:111558 // TODO: map non-intrinsic generic procedure to specific procedure
1559 if (std::optional<CalleeAndArguments> callee{Procedure(
peter klauslerad9aede2018-10-11 21:51:141560 std::get<parser::ProcedureDesignator>(funcRef.v.t), arguments)}) {
peter klausler5a18e792019-03-11 22:39:111561 if (MaybeExpr funcRef{MakeFunctionRef(std::move(*callee))}) {
1562 return funcRef;
peter klauslerd9694642018-09-20 19:34:291563 }
peter klausler5a18e792019-03-11 22:39:111564 Say("Subroutine called as if it were a function"_err_en_US);
peter klauslerd9694642018-09-20 19:34:291565 }
peter klausler6c6234b2018-09-12 18:20:301566 return std::nullopt;
1567}
1568
peter klausler1089f012018-12-03 19:40:531569// Unary operations
1570
peter klausler972b3af2019-03-07 22:46:311571MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Parentheses &x) {
peter klausler972b3af2019-03-07 22:46:311572 if (MaybeExpr operand{Analyze(x.v.value())}) {
peter klausler25e6f032019-05-03 18:29:151573 if (const semantics::Symbol * symbol{GetLastSymbol(*operand)}) {
1574 if (const semantics::Symbol * result{FindFunctionResult(*symbol)}) {
1575 if (semantics::IsProcedurePointer(*result)) {
1576 Say("A function reference that returns a procedure "
1577 "pointer may not be parenthesized."_err_en_US); // C1003
1578 }
1579 }
1580 }
peter klausler6c6234b2018-09-12 18:20:301581 return std::visit(
peter klausler25e6f032019-05-03 18:29:151582 [&](auto &&x) -> MaybeExpr {
1583 using xTy = std::decay_t<decltype(x)>;
1584 if constexpr (common::HasMember<xTy, TypelessExpression>) {
1585 return operand; // ignore parentheses around typeless
1586 } else if constexpr (std::is_same_v<xTy, Expr<SomeDerived>>) {
1587 return operand; // ignore parentheses around derived type
1588 } else {
1589 return std::visit(
1590 [](auto &&y) -> MaybeExpr {
1591 using Ty = ResultType<decltype(y)>;
1592 return {AsGenericExpr(Parentheses<Ty>{std::move(y)})};
1593 },
1594 std::move(x.u));
1595 }
Tim Keithdaa0b052018-11-29 17:27:341596 },
peter klausler6c6234b2018-09-12 18:20:301597 std::move(operand->u));
1598 }
1599 return std::nullopt;
1600}
1601
peter klausler972b3af2019-03-07 22:46:311602MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::UnaryPlus &x) {
1603 MaybeExpr value{Analyze(x.v.value())};
peter klausler6c6234b2018-09-12 18:20:301604 if (value.has_value()) {
peter klausler25e6f032019-05-03 18:29:151605 if (!std::visit(
1606 [&](const auto &y) {
1607 using yTy = std::decay_t<decltype(y)>;
1608 if constexpr (std::is_same_v<yTy, BOZLiteralConstant>) {
1609 // allow and ignore +Z'1', it's harmless
1610 return true;
1611 } else if constexpr (!IsNumericCategoryExpr<yTy>()) {
1612 Say("Operand of unary + must have numeric type"_err_en_US);
1613 return false;
1614 } else {
1615 return true;
peter klausler6c6234b2018-09-12 18:20:301616 }
Tim Keithdaa0b052018-11-29 17:27:341617 },
peter klausler25e6f032019-05-03 18:29:151618 value->u)) {
1619 return std::nullopt;
1620 }
peter klausler6c6234b2018-09-12 18:20:301621 }
1622 return value;
1623}
1624
peter klausler972b3af2019-03-07 22:46:311625MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Negate &x) {
1626 if (MaybeExpr operand{Analyze(x.v.value())}) {
1627 return Negation(GetContextualMessages(), std::move(*operand));
peter klausler6c6234b2018-09-12 18:20:301628 }
1629 return std::nullopt;
1630}
1631
peter klausler972b3af2019-03-07 22:46:311632MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NOT &x) {
1633 if (MaybeExpr operand{Analyze(x.v.value())}) {
Tim Keithdaa0b052018-11-29 17:27:341634 return std::visit(
1635 common::visitors{
1636 [](Expr<SomeLogical> &&lx) -> MaybeExpr {
1637 return {AsGenericExpr(LogicalNegation(std::move(lx)))};
1638 },
peter klausler1089f012018-12-03 19:40:531639 [&](auto &&) -> MaybeExpr {
peter klausler972b3af2019-03-07 22:46:311640 Say("Operand of .NOT. must be LOGICAL"_err_en_US);
Tim Keithdaa0b052018-11-29 17:27:341641 return std::nullopt;
1642 },
1643 },
peter klausler6c6234b2018-09-12 18:20:301644 std::move(operand->u));
1645 }
1646 return std::nullopt;
1647}
1648
peter klausler972b3af2019-03-07 22:46:311649MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::PercentLoc &) {
1650 Say("TODO: %LOC unimplemented"_err_en_US);
peter klausler003c8322018-09-07 17:33:321651 return std::nullopt;
1652}
1653
peter klausler972b3af2019-03-07 22:46:311654MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &) {
1655 Say("TODO: DefinedUnary unimplemented"_err_en_US);
peter klausler003c8322018-09-07 17:33:321656 return std::nullopt;
1657}
1658
peter klausler1089f012018-12-03 19:40:531659// Binary (dyadic) operations
1660
peter klausler003c8322018-09-07 17:33:321661// TODO: check defined operators for illegal intrinsic operator cases
peter klausler5f43f782018-08-31 23:14:141662template<template<typename> class OPR, typename PARSED>
peter klausler972b3af2019-03-07 22:46:311663MaybeExpr BinaryOperationHelper(ExpressionAnalyzer &context, const PARSED &x) {
1664 if (auto both{common::AllPresent(context.Analyze(std::get<0>(x.t).value()),
1665 context.Analyze(std::get<1>(x.t).value()))}) {
peter klauslerdc9faa22019-01-09 23:06:071666 ConformabilityCheck(context.GetContextualMessages(), std::get<0>(*both),
1667 std::get<1>(*both));
1668 return NumericOperation<OPR>(context.GetContextualMessages(),
peter klausler7d24ceb2019-06-18 22:15:221669 std::get<0>(std::move(*both)), std::get<1>(std::move(*both)),
peter klauslerdc9faa22019-01-09 23:06:071670 context.GetDefaultKind(TypeCategory::Real));
peter klausler5f43f782018-08-31 23:14:141671 }
1672 return std::nullopt;
1673}
1674
peter klausler972b3af2019-03-07 22:46:311675MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Power &x) {
1676 return BinaryOperationHelper<Power>(*this, x);
peter klausler5f43f782018-08-31 23:14:141677}
1678
peter klausler972b3af2019-03-07 22:46:311679MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Multiply &x) {
1680 return BinaryOperationHelper<Multiply>(*this, x);
peter klausler5f43f782018-08-31 23:14:141681}
1682
peter klausler972b3af2019-03-07 22:46:311683MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Divide &x) {
1684 return BinaryOperationHelper<Divide>(*this, x);
peter klausler5f43f782018-08-31 23:14:141685}
1686
peter klausler972b3af2019-03-07 22:46:311687MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Add &x) {
1688 return BinaryOperationHelper<Add>(*this, x);
peter klauslerdc31b3d2018-09-07 22:25:101689}
1690
peter klausler972b3af2019-03-07 22:46:311691MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Subtract &x) {
1692 return BinaryOperationHelper<Subtract>(*this, x);
peter klauslerdc31b3d2018-09-07 22:25:101693}
1694
peter klausler972b3af2019-03-07 22:46:311695MaybeExpr ExpressionAnalyzer::Analyze(
peter klausler1089f012018-12-03 19:40:531696 const parser::Expr::ComplexConstructor &x) {
peter klausler972b3af2019-03-07 22:46:311697 auto re{Analyze(std::get<0>(x.t).value())};
1698 auto im{Analyze(std::get<1>(x.t).value())};
peter klauslerdc9faa22019-01-09 23:06:071699 if (re.has_value() && im.has_value()) {
peter klausler972b3af2019-03-07 22:46:311700 ConformabilityCheck(GetContextualMessages(), *re, *im);
peter klauslerdc9faa22019-01-09 23:06:071701 }
peter klausler972b3af2019-03-07 22:46:311702 return AsMaybeExpr(ConstructComplex(GetContextualMessages(), std::move(re),
1703 std::move(im), GetDefaultKind(TypeCategory::Real)));
peter klausler5f43f782018-08-31 23:14:141704}
peter klausler79408f92018-08-31 20:28:211705
peter klausler972b3af2019-03-07 22:46:311706MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) {
1707 if (auto both{common::AllPresent(Analyze(std::get<0>(x.t).value()),
1708 Analyze(std::get<1>(x.t).value()))}) {
1709 ConformabilityCheck(
1710 GetContextualMessages(), std::get<0>(*both), std::get<1>(*both));
peter klauslerf9d4cef2018-09-07 23:54:331711 return std::visit(
1712 common::visitors{
1713 [&](Expr<SomeCharacter> &&cx, Expr<SomeCharacter> &&cy) {
1714 return std::visit(
1715 [&](auto &&cxk, auto &&cyk) -> MaybeExpr {
1716 using Ty = ResultType<decltype(cxk)>;
1717 if constexpr (std::is_same_v<Ty,
1718 ResultType<decltype(cyk)>>) {
peter klauslerb74d4692018-09-17 18:31:381719 return {AsGenericExpr(
1720 Concat<Ty::kind>{std::move(cxk), std::move(cyk)})};
peter klauslerf9d4cef2018-09-07 23:54:331721 } else {
peter klausler972b3af2019-03-07 22:46:311722 Say("Operands of // must be the same kind of CHARACTER"_err_en_US);
peter klauslerf9d4cef2018-09-07 23:54:331723 return std::nullopt;
1724 }
1725 },
1726 std::move(cx.u), std::move(cy.u));
1727 },
1728 [&](auto &&, auto &&) -> MaybeExpr {
peter klausler972b3af2019-03-07 22:46:311729 Say("Operands of // must be CHARACTER"_err_en_US);
peter klauslerf9d4cef2018-09-07 23:54:331730 return std::nullopt;
1731 },
1732 },
1733 std::move(std::get<0>(*both).u), std::move(std::get<1>(*both).u));
1734 }
peter klausler003c8322018-09-07 17:33:321735 return std::nullopt;
1736}
1737
peter klauslerdc31b3d2018-09-07 22:25:101738// TODO: check defined operators for illegal intrinsic operator cases
1739template<typename PARSED>
peter klausler972b3af2019-03-07 22:46:311740MaybeExpr RelationHelper(
1741 ExpressionAnalyzer &context, RelationalOperator opr, const PARSED &x) {
1742 if (auto both{common::AllPresent(context.Analyze(std::get<0>(x.t).value()),
1743 context.Analyze(std::get<1>(x.t).value()))}) {
peter klauslerdc9faa22019-01-09 23:06:071744 ConformabilityCheck(context.GetContextualMessages(), std::get<0>(*both),
1745 std::get<1>(*both));
1746 return AsMaybeExpr(Relate(context.GetContextualMessages(), opr,
peter klausler7d24ceb2019-06-18 22:15:221747 std::get<0>(std::move(*both)), std::get<1>(std::move(*both))));
peter klauslerdc31b3d2018-09-07 22:25:101748 }
peter klausler003c8322018-09-07 17:33:321749 return std::nullopt;
1750}
1751
peter klausler972b3af2019-03-07 22:46:311752MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LT &x) {
1753 return RelationHelper(*this, RelationalOperator::LT, x);
peter klauslerdc31b3d2018-09-07 22:25:101754}
1755
peter klausler972b3af2019-03-07 22:46:311756MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LE &x) {
1757 return RelationHelper(*this, RelationalOperator::LE, x);
peter klauslerdc31b3d2018-09-07 22:25:101758}
1759
peter klausler972b3af2019-03-07 22:46:311760MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQ &x) {
1761 return RelationHelper(*this, RelationalOperator::EQ, x);
peter klauslerdc31b3d2018-09-07 22:25:101762}
1763
peter klausler972b3af2019-03-07 22:46:311764MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NE &x) {
1765 return RelationHelper(*this, RelationalOperator::NE, x);
peter klauslerdc31b3d2018-09-07 22:25:101766}
1767
peter klausler972b3af2019-03-07 22:46:311768MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GE &x) {
1769 return RelationHelper(*this, RelationalOperator::GE, x);
peter klauslerdc31b3d2018-09-07 22:25:101770}
1771
peter klausler972b3af2019-03-07 22:46:311772MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GT &x) {
1773 return RelationHelper(*this, RelationalOperator::GT, x);
peter klauslerdc31b3d2018-09-07 22:25:101774}
1775
1776// TODO: check defined operators for illegal intrinsic operator cases
1777template<typename PARSED>
1778MaybeExpr LogicalHelper(
peter klausler972b3af2019-03-07 22:46:311779 ExpressionAnalyzer &context, LogicalOperator opr, const PARSED &x) {
1780 if (auto both{common::AllPresent(context.Analyze(std::get<0>(x.t).value()),
1781 context.Analyze(std::get<1>(x.t).value()))}) {
peter klauslerdc31b3d2018-09-07 22:25:101782 return std::visit(
1783 common::visitors{
peter klauslerdc9faa22019-01-09 23:06:071784 [&](Expr<SomeLogical> &&lx, Expr<SomeLogical> &&ly) -> MaybeExpr {
1785 ConformabilityCheck(context.GetContextualMessages(), lx, ly);
peter klauslerdc31b3d2018-09-07 22:25:101786 return {AsGenericExpr(
1787 BinaryLogicalOperation(opr, std::move(lx), std::move(ly)))};
1788 },
1789 [&](auto &&, auto &&) -> MaybeExpr {
peter klausler6c6234b2018-09-12 18:20:301790 // TODO: extension: INTEGER and typeless operands
1791 // ifort and PGI accept them if not overridden
peter klauslerad2fda82018-09-19 21:27:131792 // need to define IAND, IOR, IEOR intrinsic representation
peter klausler1089f012018-12-03 19:40:531793 context.Say(
1794 "operands to LOGICAL operation must be LOGICAL"_err_en_US);
peter klauslerdc31b3d2018-09-07 22:25:101795 return {};
Tim Keithdaa0b052018-11-29 17:27:341796 },
1797 },
peter klauslerdc31b3d2018-09-07 22:25:101798 std::move(std::get<0>(*both).u), std::move(std::get<1>(*both).u));
1799 }
peter klausler003c8322018-09-07 17:33:321800 return std::nullopt;
1801}
1802
peter klausler972b3af2019-03-07 22:46:311803MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::AND &x) {
1804 return LogicalHelper(*this, LogicalOperator::And, x);
peter klausler003c8322018-09-07 17:33:321805}
1806
peter klausler972b3af2019-03-07 22:46:311807MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::OR &x) {
1808 return LogicalHelper(*this, LogicalOperator::Or, x);
peter klausler003c8322018-09-07 17:33:321809}
1810
peter klausler972b3af2019-03-07 22:46:311811MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQV &x) {
1812 return LogicalHelper(*this, LogicalOperator::Eqv, x);
peter klausler003c8322018-09-07 17:33:321813}
1814
peter klausler972b3af2019-03-07 22:46:311815MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NEQV &x) {
1816 return LogicalHelper(*this, LogicalOperator::Neqv, x);
peter klausler003c8322018-09-07 17:33:321817}
1818
peter klausler972b3af2019-03-07 22:46:311819MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::XOR &x) {
1820 return LogicalHelper(*this, LogicalOperator::Neqv, x);
peter klausler003c8322018-09-07 17:33:321821}
1822
peter klausler972b3af2019-03-07 22:46:311823MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &) {
1824 Say("TODO: DefinedBinary unimplemented"_err_en_US);
peter klausler003c8322018-09-07 17:33:321825 return std::nullopt;
1826}
peter klauslerd8f40722018-12-04 23:52:501827
peter klauslere3b63232019-03-08 23:16:301828// Converts, if appropriate, an original misparse of ambiguous syntax like
1829// A(1) as a function reference into an array reference or a structure
1830// constructor.
peter klausler64ea4622019-03-08 20:55:571831template<typename... A>
peter klausler59342b02019-05-13 16:33:181832static void FixMisparsedFunctionReference(
peter klauslerec244812019-04-02 17:34:451833 semantics::SemanticsContext &context, const std::variant<A...> &constU) {
peter klausler64ea4622019-03-08 20:55:571834 // The parse tree is updated in situ when resolving an ambiguous parse.
1835 using uType = std::decay_t<decltype(constU)>;
1836 auto &u{const_cast<uType &>(constU)};
1837 if (auto *func{
1838 std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) {
1839 parser::FunctionReference &funcRef{func->value()};
1840 auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
peter klauslereff41b82019-05-29 20:22:351841 if (Symbol *
1842 origSymbol{std::visit(
1843 common::visitors{
1844 [&](parser::Name &name) { return name.symbol; },
1845 [&](parser::ProcComponentRef &pcr) {
1846 return pcr.v.thing.component.symbol;
1847 },
1848 },
1849 proc.u)}) {
1850 Symbol &symbol{origSymbol->GetUltimate()};
peter klauslere3b63232019-03-08 23:16:301851 if (symbol.has<semantics::ObjectEntityDetails>()) {
1852 if constexpr (common::HasMember<common::Indirection<parser::Designator>,
1853 uType>) {
peter klausler64ea4622019-03-08 20:55:571854 u = common::Indirection{funcRef.ConvertToArrayElementRef()};
peter klauslere3b63232019-03-08 23:16:301855 } else {
1856 common::die("can't fix misparsed function as array reference");
peter klausler64ea4622019-03-08 20:55:571857 }
peter klauslereff41b82019-05-29 20:22:351858 } else if (const auto *name{std::get_if<parser::Name>(&proc.u)}) {
peter klausler3e313d42019-06-03 19:18:521859 // A procedure component reference can't be a structure
1860 // constructor; only check calls to bare names.
peter klausler5a18e792019-03-11 22:39:111861 const Symbol *derivedType{nullptr};
1862 if (symbol.has<semantics::DerivedTypeDetails>()) {
1863 derivedType = &symbol;
1864 } else if (const auto *generic{
1865 symbol.detailsIf<semantics::GenericDetails>()}) {
1866 derivedType = generic->derivedType();
1867 }
1868 if (derivedType != nullptr) {
1869 if constexpr (common::HasMember<parser::StructureConstructor,
1870 uType>) {
1871 CHECK(derivedType->has<semantics::DerivedTypeDetails>());
1872 auto &scope{context.FindScope(name->source)};
1873 const semantics::DeclTypeSpec &type{
1874 scope.FindOrInstantiateDerivedType(
1875 semantics::DerivedTypeSpec{*derivedType}, context)};
1876 u = funcRef.ConvertToStructureConstructor(type.derivedTypeSpec());
1877 } else {
1878 common::die(
1879 "can't fix misparsed function as structure constructor");
1880 }
peter klausler64ea4622019-03-08 20:55:571881 }
1882 }
1883 }
1884 }
1885}
1886
peter klausler5a18e792019-03-11 22:39:111887// Common handling of parser::Expr and parser::Variable
Tim Keithb12a1462019-04-19 19:55:361888template<typename PARSED>
1889MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) {
Tim Keith510671c2019-04-20 00:14:501890 if (!x.typedExpr) { // not yet analyzed
Tim Keithb12a1462019-04-19 19:55:361891 FixMisparsedFunctionReference(context_, x.u);
peter klauslerb39d0c52019-04-12 00:22:161892 MaybeExpr result;
Tim Keithb12a1462019-04-19 19:55:361893 if constexpr (std::is_same_v<PARSED, parser::Expr>) {
peter klausler64ea4622019-03-08 20:55:571894 // Analyze the expression in a specified source position context for
1895 // better error reporting.
peter klausler4f2c8fa2019-06-19 18:50:071896 auto save{GetContextualMessages().SetLocation(x.source)};
Tim Keithb12a1462019-04-19 19:55:361897 result = Analyze(x.u);
peter klausler00e128e2019-06-25 20:07:321898 result = Fold(GetFoldingContext(), std::move(result));
peter klausler64ea4622019-03-08 20:55:571899 } else {
Tim Keithb12a1462019-04-19 19:55:361900 result = Analyze(x.u);
peter klausler64ea4622019-03-08 20:55:571901 }
Tim Keith510671c2019-04-20 00:14:501902 x.typedExpr.reset(new GenericExprWrapper{std::move(result)});
1903 if (!x.typedExpr->v.has_value()) {
peter klauslerba2ef032019-04-12 23:50:581904 if (!context_.AnyFatalError()) {
1905#if DUMP_ON_FAILURE
Tim Keithb12a1462019-04-19 19:55:361906 parser::DumpTree(std::cout << "Expression analysis failed on: ", x);
peter klauslerba2ef032019-04-12 23:50:581907#elif CRASH_ON_FAILURE
1908 common::die("Expression analysis failed without emitting an error");
1909#endif
1910 }
peter klauslera9045502019-04-12 18:43:031911 fatalErrors_ = true;
peter klauslerb39d0c52019-04-12 00:22:161912 }
peter klauslerd8f40722018-12-04 23:52:501913 }
Tim Keith510671c2019-04-20 00:14:501914 return x.typedExpr->v;
peter klauslerd8f40722018-12-04 23:52:501915}
peter klauslerf5bc9fd2019-02-14 20:51:201916
Tim Keithb12a1462019-04-19 19:55:361917MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) {
1918 return ExprOrVariable(expr);
1919}
1920
peter klausler972b3af2019-03-07 22:46:311921MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) {
Tim Keithb12a1462019-04-19 19:55:361922 return ExprOrVariable(variable);
Tim Keith42d7ac32019-01-17 01:18:101923}
peter klauslerdc9faa22019-01-09 23:06:071924
peter klausler972b3af2019-03-07 22:46:311925Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
1926 TypeCategory category,
peter klauslerdc9faa22019-01-09 23:06:071927 const std::optional<parser::KindSelector> &selector) {
1928 int defaultKind{GetDefaultKind(category)};
1929 if (!selector.has_value()) {
peter klauslerbe3b7652018-12-04 18:55:321930 return Expr<SubscriptInteger>{defaultKind};
peter klauslerdc9faa22019-01-09 23:06:071931 }
1932 return std::visit(
1933 common::visitors{
peter klauslerbe3b7652018-12-04 18:55:321934 [&](const parser::ScalarIntConstantExpr &x)
1935 -> Expr<SubscriptInteger> {
peter klausler972b3af2019-03-07 22:46:311936 if (MaybeExpr kind{Analyze(x)}) {
peter klauslerbe3b7652018-12-04 18:55:321937 Expr<SomeType> folded{
1938 Fold(GetFoldingContext(), std::move(*kind))};
1939 if (std::optional<std::int64_t> code{ToInt64(folded)}) {
Tim Keithd396a882019-02-09 00:03:231940 if (CheckIntrinsicKind(category, *code)) {
peter klauslerbe3b7652018-12-04 18:55:321941 return Expr<SubscriptInteger>{*code};
peter klauslerdc9faa22019-01-09 23:06:071942 }
peter klauslerbe3b7652018-12-04 18:55:321943 } else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(folded)}) {
1944 return ConvertToType<SubscriptInteger>(std::move(*intExpr));
peter klauslerdc9faa22019-01-09 23:06:071945 }
1946 }
peter klauslerbe3b7652018-12-04 18:55:321947 return Expr<SubscriptInteger>{defaultKind};
peter klauslerdc9faa22019-01-09 23:06:071948 },
peter klauslerbe3b7652018-12-04 18:55:321949 [&](const parser::KindSelector::StarSize &x)
1950 -> Expr<SubscriptInteger> {
peter klauslerdc9faa22019-01-09 23:06:071951 std::intmax_t size = x.v;
Tim Keithd396a882019-02-09 00:03:231952 if (!CheckIntrinsicSize(category, size)) {
peter klauslerbe3b7652018-12-04 18:55:321953 size = defaultKind;
Tim Keithd396a882019-02-09 00:03:231954 } else if (category == TypeCategory::Complex) {
1955 size /= 2;
peter klauslerdc9faa22019-01-09 23:06:071956 }
peter klauslerbe3b7652018-12-04 18:55:321957 return Expr<SubscriptInteger>{size};
peter klauslerdc9faa22019-01-09 23:06:071958 },
1959 },
1960 selector->u);
1961}
1962
peter klausler972b3af2019-03-07 22:46:311963int ExpressionAnalyzer::GetDefaultKind(common::TypeCategory category) {
Tim Keith9ef62db2019-06-12 01:26:481964 return context_.GetDefaultKind(category);
peter klauslerdc9faa22019-01-09 23:06:071965}
1966
peter klausler972b3af2019-03-07 22:46:311967DynamicType ExpressionAnalyzer::GetDefaultKindOfType(
peter klauslerdc9faa22019-01-09 23:06:071968 common::TypeCategory category) {
1969 return {category, GetDefaultKind(category)};
1970}
peter klausler0ae3d432019-01-23 00:30:321971
peter klausler972b3af2019-03-07 22:46:311972bool ExpressionAnalyzer::CheckIntrinsicKind(
Tim Keithd396a882019-02-09 00:03:231973 TypeCategory category, std::int64_t kind) {
1974 if (IsValidKindOfIntrinsicType(category, kind)) {
1975 return true;
1976 } else {
1977 Say("%s(KIND=%jd) is not a supported type"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451978 parser::ToUpperCaseLetters(EnumToString(category)), kind);
Tim Keithd396a882019-02-09 00:03:231979 return false;
1980 }
1981}
1982
peter klausler972b3af2019-03-07 22:46:311983bool ExpressionAnalyzer::CheckIntrinsicSize(
Tim Keithd396a882019-02-09 00:03:231984 TypeCategory category, std::int64_t size) {
1985 if (category == TypeCategory::Complex) {
1986 // COMPLEX*16 == COMPLEX(KIND=8)
1987 if (size % 2 == 0 && IsValidKindOfIntrinsicType(category, size / 2)) {
1988 return true;
1989 }
1990 } else if (IsValidKindOfIntrinsicType(category, size)) {
1991 return true;
1992 }
1993 Say("%s*%jd is not a supported type"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:451994 parser::ToUpperCaseLetters(EnumToString(category)), size);
Tim Keithd396a882019-02-09 00:03:231995 return false;
1996}
1997
peter klausler972b3af2019-03-07 22:46:311998bool ExpressionAnalyzer::AddAcImpliedDo(parser::CharBlock name, int kind) {
peter klausler0ae3d432019-01-23 00:30:321999 return acImpliedDos_.insert(std::make_pair(name, kind)).second;
2000}
2001
peter klausler972b3af2019-03-07 22:46:312002void ExpressionAnalyzer::RemoveAcImpliedDo(parser::CharBlock name) {
peter klausler0ae3d432019-01-23 00:30:322003 auto iter{acImpliedDos_.find(name)};
2004 if (iter != acImpliedDos_.end()) {
2005 acImpliedDos_.erase(iter);
2006 }
2007}
2008
peter klausler972b3af2019-03-07 22:46:312009std::optional<int> ExpressionAnalyzer::IsAcImpliedDo(
peter klausler0ae3d432019-01-23 00:30:322010 parser::CharBlock name) const {
2011 auto iter{acImpliedDos_.find(name)};
2012 if (iter != acImpliedDos_.cend()) {
2013 return {iter->second};
2014 } else {
2015 return std::nullopt;
2016 }
2017}
peter klauslerb39d0c52019-04-12 00:22:162018
Tim Keith0df7fa02019-04-25 20:18:332019bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at,
peter klauslerb39d0c52019-04-12 00:22:162020 const MaybeExpr &result, TypeCategory category, bool defaultKind) {
2021 if (result.has_value()) {
2022 if (auto type{result->GetType()}) {
peter klausler59342b02019-05-13 16:33:182023 if (type->category() != category) {
peter klauslerb39d0c52019-04-12 00:22:162024 Say(at, "Must have %s type, but is %s"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:452025 parser::ToUpperCaseLetters(EnumToString(category)),
2026 parser::ToUpperCaseLetters(type->AsFortran()));
Tim Keith0df7fa02019-04-25 20:18:332027 return false;
peter klauslerb39d0c52019-04-12 00:22:162028 } else if (defaultKind) {
Tim Keith9ef62db2019-06-12 01:26:482029 int kind{context_.GetDefaultKind(category)};
peter klausler59342b02019-05-13 16:33:182030 if (type->kind() != kind) {
peter klauslerb39d0c52019-04-12 00:22:162031 Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:452032 kind, parser::ToUpperCaseLetters(EnumToString(category)),
2033 parser::ToUpperCaseLetters(type->AsFortran()));
Tim Keith0df7fa02019-04-25 20:18:332034 return false;
peter klauslerb39d0c52019-04-12 00:22:162035 }
2036 }
2037 } else {
2038 Say(at, "Must have %s type, but is typeless"_err_en_US,
peter klauslerec6cf762019-05-06 16:33:452039 parser::ToUpperCaseLetters(EnumToString(category)));
Tim Keith0df7fa02019-04-25 20:18:332040 return false;
peter klauslerb39d0c52019-04-12 00:22:162041 }
2042 }
Tim Keith0df7fa02019-04-25 20:18:332043 return true;
peter klauslerb39d0c52019-04-12 00:22:162044}
Tim Keith0df7fa02019-04-25 20:18:332045
peter klausler5a18e792019-03-11 22:39:112046MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
2047 ProcedureDesignator &&proc, ActualArguments &&arguments) {
2048 if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&proc.u)}) {
2049 if (intrinsic->name == "null" && arguments.empty()) {
2050 return Expr<SomeType>{NullPointer{}};
2051 }
2052 }
2053 if (auto chars{Characterize(proc, context_.intrinsics())}) {
2054 if (chars->functionResult.has_value()) {
2055 const auto &result{*chars->functionResult};
2056 if (result.IsProcedurePointer()) {
2057 return Expr<SomeType>{
2058 ProcedureRef{std::move(proc), std::move(arguments)}};
2059 } else {
2060 // Not a procedure pointer, so type and shape are known.
2061 const auto *typeAndShape{result.GetTypeAndShape()};
2062 CHECK(typeAndShape != nullptr);
2063 return TypedWrapper<FunctionRef, ProcedureRef>(typeAndShape->type(),
2064 ProcedureRef{std::move(proc), std::move(arguments)});
2065 }
2066 }
2067 }
2068 return std::nullopt;
2069}
2070
2071MaybeExpr ExpressionAnalyzer::MakeFunctionRef(CalleeAndArguments &&callee) {
2072 return MakeFunctionRef(
2073 std::move(callee.procedureDesignator), std::move(callee.arguments));
2074}
2075
2076MaybeExpr ExpressionAnalyzer::MakeFunctionRef(
2077 parser::CharBlock intrinsic, ActualArguments &&arguments) {
2078 if (std::optional<SpecificCall> specificCall{
2079 context_.intrinsics().Probe(CallCharacteristics{intrinsic}, arguments,
2080 context_.foldingContext())}) {
2081 return MakeFunctionRef(
2082 ProcedureDesignator{std::move(specificCall->specificIntrinsic)},
2083 std::move(specificCall->arguments));
2084 } else {
2085 return std::nullopt;
2086 }
2087}
2088
2089std::optional<characteristics::Procedure> Characterize(
2090 const ProcedureDesignator &proc, const IntrinsicProcTable &intrinsics) {
2091 if (const auto *symbol{proc.GetSymbol()}) {
2092 return characteristics::Procedure::Characterize(
2093 symbol->GetUltimate(), intrinsics);
2094 } else if (const auto *intrinsic{proc.GetSpecificIntrinsic()}) {
2095 return intrinsic->characteristics.value();
2096 } else {
2097 return std::nullopt;
2098 }
2099}
2100
2101std::optional<characteristics::Procedure> Characterize(
2102 const ProcedureRef &ref, const IntrinsicProcTable &intrinsics) {
2103 return Characterize(ref.proc(), intrinsics);
2104}
Jean Perierf7e7cb32018-10-25 12:55:232105}
peter klausler79408f92018-08-31 20:28:212106
2107namespace Fortran::semantics {
Tim Keith813e48d2019-03-06 00:52:502108evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector(
2109 SemanticsContext &context, common::TypeCategory category,
2110 const std::optional<parser::KindSelector> &selector) {
peter klausler972b3af2019-03-07 22:46:312111 evaluate::ExpressionAnalyzer analyzer{context};
2112 auto save{analyzer.GetContextualMessages().SetLocation(*context.location())};
2113 return analyzer.AnalyzeKindSelector(category, selector);
Tim Keith813e48d2019-03-06 00:52:502114}
peter klauslera9045502019-04-12 18:43:032115
peter klauslerb39d0c52019-04-12 00:22:162116bool ExprChecker::Walk(const parser::Program &program) {
2117 parser::Walk(program, *this);
2118 return !context_.AnyFatalError();
peter klausler64ea4622019-03-08 20:55:572119}
Jean Perierf7e7cb32018-10-25 12:55:232120}