1 //===-- lib/Semantics/expression.cpp --------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "flang/Semantics/expression.h" 10 #include "check-call.h" 11 #include "pointer-assignment.h" 12 #include "resolve-names-utils.h" 13 #include "resolve-names.h" 14 #include "flang/Common/Fortran.h" 15 #include "flang/Common/idioms.h" 16 #include "flang/Evaluate/common.h" 17 #include "flang/Evaluate/fold.h" 18 #include "flang/Evaluate/tools.h" 19 #include "flang/Parser/characters.h" 20 #include "flang/Parser/dump-parse-tree.h" 21 #include "flang/Parser/parse-tree-visitor.h" 22 #include "flang/Parser/parse-tree.h" 23 #include "flang/Semantics/scope.h" 24 #include "flang/Semantics/semantics.h" 25 #include "flang/Semantics/symbol.h" 26 #include "flang/Semantics/tools.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <algorithm> 29 #include <functional> 30 #include <optional> 31 #include <set> 32 #include <vector> 33 34 // Typedef for optional generic expressions (ubiquitous in this file) 35 using MaybeExpr = 36 std::optional<Fortran::evaluate::Expr<Fortran::evaluate::SomeType>>; 37 38 // Much of the code that implements semantic analysis of expressions is 39 // tightly coupled with their typed representations in lib/Evaluate, 40 // and appears here in namespace Fortran::evaluate for convenience. 41 namespace Fortran::evaluate { 42 43 using common::LanguageFeature; 44 using common::NumericOperator; 45 using common::TypeCategory; 46 47 static inline std::string ToUpperCase(std::string_view str) { 48 return parser::ToUpperCaseLetters(str); 49 } 50 51 struct DynamicTypeWithLength : public DynamicType { 52 explicit DynamicTypeWithLength(const DynamicType &t) : DynamicType{t} {} 53 std::optional<Expr<SubscriptInteger>> LEN() const; 54 std::optional<Expr<SubscriptInteger>> length; 55 }; 56 57 std::optional<Expr<SubscriptInteger>> DynamicTypeWithLength::LEN() const { 58 if (length) { 59 return length; 60 } else { 61 return GetCharLength(); 62 } 63 } 64 65 static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec( 66 const std::optional<parser::TypeSpec> &spec, FoldingContext &context) { 67 if (spec) { 68 if (const semantics::DeclTypeSpec *typeSpec{spec->declTypeSpec}) { 69 // Name resolution sets TypeSpec::declTypeSpec only when it's valid 70 // (viz., an intrinsic type with valid known kind or a non-polymorphic 71 // & non-ABSTRACT derived type). 72 if (const semantics::IntrinsicTypeSpec *intrinsic{ 73 typeSpec->AsIntrinsic()}) { 74 TypeCategory category{intrinsic->category()}; 75 if (auto optKind{ToInt64(intrinsic->kind())}) { 76 int kind{static_cast<int>(*optKind)}; 77 if (category == TypeCategory::Character) { 78 const semantics::CharacterTypeSpec &cts{ 79 typeSpec->characterTypeSpec()}; 80 const semantics::ParamValue &len{cts.length()}; 81 // N.B. CHARACTER(LEN=*) is allowed in type-specs in ALLOCATE() & 82 // type guards, but not in array constructors. 83 DynamicTypeWithLength type{DynamicType{kind, len}}; 84 if (auto lenExpr{type.LEN()}) { 85 type.length = Fold(context, 86 AsExpr(Extremum<SubscriptInteger>{Ordering::Greater, 87 Expr<SubscriptInteger>{0}, std::move(*lenExpr)})); 88 } 89 return type; 90 } else { 91 return DynamicTypeWithLength{DynamicType{category, kind}}; 92 } 93 } 94 } else if (const semantics::DerivedTypeSpec *derived{ 95 typeSpec->AsDerived()}) { 96 return DynamicTypeWithLength{DynamicType{*derived}}; 97 } 98 } 99 } 100 return std::nullopt; 101 } 102 103 // Utilities to set a source location, if we have one, on an actual argument, 104 // when it is statically present. 105 static void SetArgSourceLocation(ActualArgument &x, parser::CharBlock at) { 106 x.set_sourceLocation(at); 107 } 108 static void SetArgSourceLocation( 109 std::optional<ActualArgument> &x, parser::CharBlock at) { 110 if (x) { 111 x->set_sourceLocation(at); 112 } 113 } 114 static void SetArgSourceLocation( 115 std::optional<ActualArgument> &x, std::optional<parser::CharBlock> at) { 116 if (x && at) { 117 x->set_sourceLocation(*at); 118 } 119 } 120 121 class ArgumentAnalyzer { 122 public: 123 explicit ArgumentAnalyzer(ExpressionAnalyzer &context) 124 : context_{context}, source_{context.GetContextualMessages().at()}, 125 isProcedureCall_{false} {} 126 ArgumentAnalyzer(ExpressionAnalyzer &context, parser::CharBlock source, 127 bool isProcedureCall = false) 128 : context_{context}, source_{source}, isProcedureCall_{isProcedureCall} {} 129 bool fatalErrors() const { return fatalErrors_; } 130 ActualArguments &&GetActuals() { 131 CHECK(!fatalErrors_); 132 return std::move(actuals_); 133 } 134 const Expr<SomeType> &GetExpr(std::size_t i) const { 135 return DEREF(actuals_.at(i).value().UnwrapExpr()); 136 } 137 Expr<SomeType> &&MoveExpr(std::size_t i) { 138 return std::move(DEREF(actuals_.at(i).value().UnwrapExpr())); 139 } 140 void Analyze(const common::Indirection<parser::Expr> &x) { 141 Analyze(x.value()); 142 } 143 void Analyze(const parser::Expr &x) { 144 actuals_.emplace_back(AnalyzeExpr(x)); 145 SetArgSourceLocation(actuals_.back(), x.source); 146 fatalErrors_ |= !actuals_.back(); 147 } 148 void Analyze(const parser::Variable &); 149 void Analyze(const parser::ActualArgSpec &, bool isSubroutine); 150 void ConvertBOZ(std::optional<DynamicType> *thisType, std::size_t, 151 std::optional<DynamicType> otherType); 152 153 bool IsIntrinsicRelational( 154 RelationalOperator, const DynamicType &, const DynamicType &) const; 155 bool IsIntrinsicLogical() const; 156 bool IsIntrinsicNumeric(NumericOperator) const; 157 bool IsIntrinsicConcat() const; 158 159 bool CheckConformance(); 160 bool CheckAssignmentConformance(); 161 bool CheckForNullPointer(const char *where = "as an operand here"); 162 bool CheckForAssumedRank(const char *where = "as an operand here"); 163 164 // Find and return a user-defined operator or report an error. 165 // The provided message is used if there is no such operator. 166 // If a definedOpSymbolPtr is provided, the caller must check 167 // for its accessibility. 168 MaybeExpr TryDefinedOp( 169 const char *, parser::MessageFixedText, bool isUserOp = false); 170 template <typename E> 171 MaybeExpr TryDefinedOp(E opr, parser::MessageFixedText msg) { 172 return TryDefinedOp( 173 context_.context().languageFeatures().GetNames(opr), msg); 174 } 175 // Find and return a user-defined assignment 176 std::optional<ProcedureRef> TryDefinedAssignment(); 177 std::optional<ProcedureRef> GetDefinedAssignmentProc(); 178 std::optional<DynamicType> GetType(std::size_t) const; 179 void Dump(llvm::raw_ostream &); 180 181 private: 182 MaybeExpr TryDefinedOp( 183 const std::vector<const char *> &, parser::MessageFixedText); 184 MaybeExpr TryBoundOp(const Symbol &, int passIndex); 185 std::optional<ActualArgument> AnalyzeExpr(const parser::Expr &); 186 std::optional<ActualArgument> AnalyzeVariable(const parser::Variable &); 187 MaybeExpr AnalyzeExprOrWholeAssumedSizeArray(const parser::Expr &); 188 bool AreConformable() const; 189 const Symbol *FindBoundOp(parser::CharBlock, int passIndex, 190 const Symbol *&generic, bool isSubroutine); 191 void AddAssignmentConversion( 192 const DynamicType &lhsType, const DynamicType &rhsType); 193 bool OkLogicalIntegerAssignment(TypeCategory lhs, TypeCategory rhs); 194 int GetRank(std::size_t) const; 195 bool IsBOZLiteral(std::size_t i) const { 196 return evaluate::IsBOZLiteral(GetExpr(i)); 197 } 198 void SayNoMatch(const std::string &, bool isAssignment = false); 199 std::string TypeAsFortran(std::size_t); 200 bool AnyUntypedOrMissingOperand(); 201 202 ExpressionAnalyzer &context_; 203 ActualArguments actuals_; 204 parser::CharBlock source_; 205 bool fatalErrors_{false}; 206 const bool isProcedureCall_; // false for user-defined op or assignment 207 }; 208 209 // Wraps a data reference in a typed Designator<>, and a procedure 210 // or procedure pointer reference in a ProcedureDesignator. 211 MaybeExpr ExpressionAnalyzer::Designate(DataRef &&ref) { 212 const Symbol &last{ref.GetLastSymbol()}; 213 const Symbol &specific{BypassGeneric(last)}; 214 const Symbol &symbol{specific.GetUltimate()}; 215 if (semantics::IsProcedure(symbol)) { 216 if (symbol.attrs().test(semantics::Attr::ABSTRACT)) { 217 Say("Abstract procedure interface '%s' may not be used as a designator"_err_en_US, 218 last.name()); 219 } 220 if (auto *component{std::get_if<Component>(&ref.u)}) { 221 if (!CheckDataRef(ref)) { 222 return std::nullopt; 223 } 224 return Expr<SomeType>{ProcedureDesignator{std::move(*component)}}; 225 } else if (!std::holds_alternative<SymbolRef>(ref.u)) { 226 DIE("unexpected alternative in DataRef"); 227 } else if (!symbol.attrs().test(semantics::Attr::INTRINSIC)) { 228 if (symbol.has<semantics::GenericDetails>()) { 229 Say("'%s' is not a specific procedure"_err_en_US, last.name()); 230 } else if (IsProcedurePointer(specific)) { 231 // For procedure pointers, retain associations so that data accesses 232 // from client modules will work. 233 return Expr<SomeType>{ProcedureDesignator{specific}}; 234 } else { 235 return Expr<SomeType>{ProcedureDesignator{symbol}}; 236 } 237 } else if (auto interface{context_.intrinsics().IsSpecificIntrinsicFunction( 238 symbol.name().ToString())}; 239 interface && !interface->isRestrictedSpecific) { 240 SpecificIntrinsic intrinsic{ 241 symbol.name().ToString(), std::move(*interface)}; 242 intrinsic.isRestrictedSpecific = interface->isRestrictedSpecific; 243 return Expr<SomeType>{ProcedureDesignator{std::move(intrinsic)}}; 244 } else { 245 Say("'%s' is not an unrestricted specific intrinsic procedure"_err_en_US, 246 last.name()); 247 } 248 return std::nullopt; 249 } else if (MaybeExpr result{AsGenericExpr(std::move(ref))}) { 250 return result; 251 } else if (semantics::HadUseError( 252 context_, GetContextualMessages().at(), &symbol)) { 253 return std::nullopt; 254 } else { 255 if (!context_.HasError(last) && !context_.HasError(symbol)) { 256 AttachDeclaration( 257 Say("'%s' is not an object that can appear in an expression"_err_en_US, 258 last.name()), 259 symbol); 260 context_.SetError(last); 261 } 262 return std::nullopt; 263 } 264 } 265 266 // Some subscript semantic checks must be deferred until all of the 267 // subscripts are in hand. 268 MaybeExpr ExpressionAnalyzer::CompleteSubscripts(ArrayRef &&ref) { 269 const Symbol &symbol{ref.GetLastSymbol().GetUltimate()}; 270 int symbolRank{symbol.Rank()}; 271 int subscripts{static_cast<int>(ref.size())}; 272 if (subscripts == 0) { 273 return std::nullopt; // error recovery 274 } else if (subscripts != symbolRank) { 275 if (symbolRank != 0) { 276 Say("Reference to rank-%d object '%s' has %d subscripts"_err_en_US, 277 symbolRank, symbol.name(), subscripts); 278 } 279 return std::nullopt; 280 } else if (symbol.has<semantics::ObjectEntityDetails>() || 281 symbol.has<semantics::AssocEntityDetails>()) { 282 // C928 & C1002 283 if (Triplet *last{std::get_if<Triplet>(&ref.subscript().back().u)}) { 284 if (!last->upper() && IsAssumedSizeArray(symbol)) { 285 Say("Assumed-size array '%s' must have explicit final " 286 "subscript upper bound value"_err_en_US, 287 symbol.name()); 288 return std::nullopt; 289 } 290 } 291 } else { 292 // Shouldn't get here from Analyze(ArrayElement) without a valid base, 293 // which, if not an object, must be a construct entity from 294 // SELECT TYPE/RANK or ASSOCIATE. 295 CHECK(symbol.has<semantics::AssocEntityDetails>()); 296 } 297 if (!semantics::IsNamedConstant(symbol) && !inDataStmtObject_) { 298 // Subscripts of named constants are checked in folding. 299 // Subscripts of DATA statement objects are checked in data statement 300 // conversion to initializers. 301 CheckSubscripts(ref); 302 } 303 return Designate(DataRef{std::move(ref)}); 304 } 305 306 // Applies subscripts to a data reference. 307 MaybeExpr ExpressionAnalyzer::ApplySubscripts( 308 DataRef &&dataRef, std::vector<Subscript> &&subscripts) { 309 if (subscripts.empty()) { 310 return std::nullopt; // error recovery 311 } 312 return common::visit( 313 common::visitors{ 314 [&](SymbolRef &&symbol) { 315 return CompleteSubscripts(ArrayRef{symbol, std::move(subscripts)}); 316 }, 317 [&](Component &&c) { 318 return CompleteSubscripts( 319 ArrayRef{std::move(c), std::move(subscripts)}); 320 }, 321 [&](auto &&) -> MaybeExpr { 322 DIE("bad base for ArrayRef"); 323 return std::nullopt; 324 }, 325 }, 326 std::move(dataRef.u)); 327 } 328 329 void ExpressionAnalyzer::CheckSubscripts(ArrayRef &ref) { 330 // Fold subscript expressions and check for an empty triplet. 331 const Symbol &arraySymbol{ref.base().GetLastSymbol()}; 332 Shape lb{GetLBOUNDs(foldingContext_, NamedEntity{arraySymbol})}; 333 CHECK(lb.size() >= ref.subscript().size()); 334 Shape ub{GetUBOUNDs(foldingContext_, NamedEntity{arraySymbol})}; 335 CHECK(ub.size() >= ref.subscript().size()); 336 bool anyPossiblyEmptyDim{false}; 337 int dim{0}; 338 for (Subscript &ss : ref.subscript()) { 339 if (Triplet * triplet{std::get_if<Triplet>(&ss.u)}) { 340 auto expr{Fold(triplet->stride())}; 341 auto stride{ToInt64(expr)}; 342 triplet->set_stride(std::move(expr)); 343 std::optional<ConstantSubscript> lower, upper; 344 if (auto expr{triplet->lower()}) { 345 *expr = Fold(std::move(*expr)); 346 lower = ToInt64(*expr); 347 triplet->set_lower(std::move(*expr)); 348 } else { 349 lower = ToInt64(lb[dim]); 350 } 351 if (auto expr{triplet->upper()}) { 352 *expr = Fold(std::move(*expr)); 353 upper = ToInt64(*expr); 354 triplet->set_upper(std::move(*expr)); 355 } else { 356 upper = ToInt64(ub[dim]); 357 } 358 if (stride) { 359 if (*stride == 0) { 360 Say("Stride of triplet must not be zero"_err_en_US); 361 return; 362 } 363 if (lower && upper) { 364 if (*stride > 0) { 365 anyPossiblyEmptyDim |= *lower > *upper; 366 } else { 367 anyPossiblyEmptyDim |= *lower < *upper; 368 } 369 } else { 370 anyPossiblyEmptyDim = true; 371 } 372 } else { // non-constant stride 373 if (lower && upper && *lower == *upper) { 374 // stride is not relevant 375 } else { 376 anyPossiblyEmptyDim = true; 377 } 378 } 379 } else { // not triplet 380 auto &expr{std::get<IndirectSubscriptIntegerExpr>(ss.u).value()}; 381 expr = Fold(std::move(expr)); 382 anyPossiblyEmptyDim |= expr.Rank() > 0; // vector subscript 383 } 384 ++dim; 385 } 386 if (anyPossiblyEmptyDim) { 387 return; 388 } 389 dim = 0; 390 for (Subscript &ss : ref.subscript()) { 391 auto dimLB{ToInt64(lb[dim])}; 392 auto dimUB{ToInt64(ub[dim])}; 393 if (dimUB && dimLB && *dimUB < *dimLB) { 394 AttachDeclaration( 395 Warn(common::UsageWarning::SubscriptedEmptyArray, 396 "Empty array dimension %d should not be subscripted as an element or non-empty array section"_err_en_US, 397 dim + 1), 398 arraySymbol); 399 break; 400 } 401 std::optional<ConstantSubscript> val[2]; 402 int vals{0}; 403 if (auto *triplet{std::get_if<Triplet>(&ss.u)}) { 404 auto stride{ToInt64(triplet->stride())}; 405 std::optional<ConstantSubscript> lower, upper; 406 if (const auto *lowerExpr{triplet->GetLower()}) { 407 lower = ToInt64(*lowerExpr); 408 } else if (lb[dim]) { 409 lower = ToInt64(*lb[dim]); 410 } 411 if (const auto *upperExpr{triplet->GetUpper()}) { 412 upper = ToInt64(*upperExpr); 413 } else if (ub[dim]) { 414 upper = ToInt64(*ub[dim]); 415 } 416 if (lower) { 417 val[vals++] = *lower; 418 if (upper && *upper != lower && (stride && *stride != 0)) { 419 // Normalize upper bound for non-unit stride 420 // 1:10:2 -> 1:9:2, 10:1:-2 -> 10:2:-2 421 val[vals++] = *lower + *stride * ((*upper - *lower) / *stride); 422 } 423 } 424 } else { 425 val[vals++] = 426 ToInt64(std::get<IndirectSubscriptIntegerExpr>(ss.u).value()); 427 } 428 for (int j{0}; j < vals; ++j) { 429 if (val[j]) { 430 std::optional<parser::MessageFixedText> msg; 431 std::optional<ConstantSubscript> bound; 432 if (dimLB && *val[j] < *dimLB) { 433 msg = 434 "Subscript %jd is less than lower bound %jd for dimension %d of array"_err_en_US; 435 bound = *dimLB; 436 } else if (dimUB && *val[j] > *dimUB) { 437 msg = 438 "Subscript %jd is greater than upper bound %jd for dimension %d of array"_err_en_US; 439 bound = *dimUB; 440 if (dim + 1 == arraySymbol.Rank() && IsDummy(arraySymbol) && 441 *bound == 1) { 442 // Old-school overindexing of a dummy array isn't fatal when 443 // it's on the last dimension and the extent is 1. 444 msg->set_severity(parser::Severity::Warning); 445 } 446 } 447 if (msg) { 448 AttachDeclaration( 449 Say(std::move(*msg), static_cast<std::intmax_t>(*val[j]), 450 static_cast<std::intmax_t>(bound.value()), dim + 1), 451 arraySymbol); 452 } 453 } 454 } 455 ++dim; 456 } 457 } 458 459 // C919a - only one part-ref of a data-ref may have rank > 0 460 bool ExpressionAnalyzer::CheckRanks(const DataRef &dataRef) { 461 return common::visit( 462 common::visitors{ 463 [this](const Component &component) { 464 const Symbol &symbol{component.GetLastSymbol()}; 465 if (int componentRank{symbol.Rank()}; componentRank > 0) { 466 if (int baseRank{component.base().Rank()}; baseRank > 0) { 467 Say("Reference to whole rank-%d component '%s' of rank-%d array of derived type is not allowed"_err_en_US, 468 componentRank, symbol.name(), baseRank); 469 return false; 470 } 471 } else { 472 return CheckRanks(component.base()); 473 } 474 return true; 475 }, 476 [this](const ArrayRef &arrayRef) { 477 if (const auto *component{arrayRef.base().UnwrapComponent()}) { 478 int subscriptRank{0}; 479 for (const Subscript &subscript : arrayRef.subscript()) { 480 subscriptRank += subscript.Rank(); 481 } 482 if (subscriptRank > 0) { 483 if (int componentBaseRank{component->base().Rank()}; 484 componentBaseRank > 0) { 485 Say("Subscripts of component '%s' of rank-%d derived type array have rank %d but must all be scalar"_err_en_US, 486 component->GetLastSymbol().name(), componentBaseRank, 487 subscriptRank); 488 return false; 489 } 490 } else { 491 return CheckRanks(component->base()); 492 } 493 } 494 return true; 495 }, 496 [](const SymbolRef &) { return true; }, 497 [](const CoarrayRef &) { return true; }, 498 }, 499 dataRef.u); 500 } 501 502 // C911 - if the last name in a data-ref has an abstract derived type, 503 // it must also be polymorphic. 504 bool ExpressionAnalyzer::CheckPolymorphic(const DataRef &dataRef) { 505 if (auto type{DynamicType::From(dataRef.GetLastSymbol())}) { 506 if (type->category() == TypeCategory::Derived && !type->IsPolymorphic()) { 507 const Symbol &typeSymbol{ 508 type->GetDerivedTypeSpec().typeSymbol().GetUltimate()}; 509 if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { 510 AttachDeclaration( 511 Say("Reference to object with abstract derived type '%s' must be polymorphic"_err_en_US, 512 typeSymbol.name()), 513 typeSymbol); 514 return false; 515 } 516 } 517 } 518 return true; 519 } 520 521 bool ExpressionAnalyzer::CheckDataRef(const DataRef &dataRef) { 522 // Always check both, don't short-circuit 523 bool ranksOk{CheckRanks(dataRef)}; 524 bool polyOk{CheckPolymorphic(dataRef)}; 525 return ranksOk && polyOk; 526 } 527 528 // Parse tree correction after a substring S(j:k) was misparsed as an 529 // array section. Fortran substrings must have a range, not a 530 // single index. 531 static std::optional<parser::Substring> FixMisparsedSubstringDataRef( 532 parser::DataRef &dataRef) { 533 if (auto *ae{ 534 std::get_if<common::Indirection<parser::ArrayElement>>(&dataRef.u)}) { 535 // ...%a(j:k) and "a" is a character scalar 536 parser::ArrayElement &arrElement{ae->value()}; 537 if (arrElement.subscripts.size() == 1) { 538 if (auto *triplet{std::get_if<parser::SubscriptTriplet>( 539 &arrElement.subscripts.front().u)}) { 540 if (!std::get<2 /*stride*/>(triplet->t).has_value()) { 541 if (const Symbol *symbol{ 542 parser::GetLastName(arrElement.base).symbol}) { 543 const Symbol &ultimate{symbol->GetUltimate()}; 544 if (const semantics::DeclTypeSpec *type{ultimate.GetType()}) { 545 if (ultimate.Rank() == 0 && 546 type->category() == semantics::DeclTypeSpec::Character) { 547 // The ambiguous S(j:k) was parsed as an array section 548 // reference, but it's now clear that it's a substring. 549 // Fix the parse tree in situ. 550 return arrElement.ConvertToSubstring(); 551 } 552 } 553 } 554 } 555 } 556 } 557 } 558 return std::nullopt; 559 } 560 561 // When a designator is a misparsed type-param-inquiry of a misparsed 562 // substring -- it looks like a structure component reference of an array 563 // slice -- fix the substring and then convert to an intrinsic function 564 // call to KIND() or LEN(). And when the designator is a misparsed 565 // substring, convert it into a substring reference in place. 566 MaybeExpr ExpressionAnalyzer::FixMisparsedSubstring( 567 const parser::Designator &d) { 568 auto &mutate{const_cast<parser::Designator &>(d)}; 569 if (auto *dataRef{std::get_if<parser::DataRef>(&mutate.u)}) { 570 if (auto *sc{std::get_if<common::Indirection<parser::StructureComponent>>( 571 &dataRef->u)}) { 572 parser::StructureComponent &structComponent{sc->value()}; 573 parser::CharBlock which{structComponent.component.source}; 574 if (which == "kind" || which == "len") { 575 if (auto substring{ 576 FixMisparsedSubstringDataRef(structComponent.base)}) { 577 // ...%a(j:k)%kind or %len and "a" is a character scalar 578 mutate.u = std::move(*substring); 579 if (MaybeExpr substringExpr{Analyze(d)}) { 580 return MakeFunctionRef(which, 581 ActualArguments{ActualArgument{std::move(*substringExpr)}}); 582 } 583 } 584 } 585 } else if (auto substring{FixMisparsedSubstringDataRef(*dataRef)}) { 586 mutate.u = std::move(*substring); 587 } 588 } 589 return std::nullopt; 590 } 591 592 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Designator &d) { 593 auto restorer{GetContextualMessages().SetLocation(d.source)}; 594 if (auto substringInquiry{FixMisparsedSubstring(d)}) { 595 return substringInquiry; 596 } 597 // These checks have to be deferred to these "top level" data-refs where 598 // we can be sure that there are no following subscripts (yet). 599 MaybeExpr result{Analyze(d.u)}; 600 if (result) { 601 std::optional<DataRef> dataRef{ExtractDataRef(std::move(result))}; 602 if (!dataRef) { 603 dataRef = ExtractDataRef(std::move(result), /*intoSubstring=*/true); 604 } 605 if (!dataRef) { 606 dataRef = ExtractDataRef(std::move(result), 607 /*intoSubstring=*/false, /*intoComplexPart=*/true); 608 } 609 if (dataRef && !CheckDataRef(*dataRef)) { 610 result.reset(); 611 } 612 } 613 return result; 614 } 615 616 // A utility subroutine to repackage optional expressions of various levels 617 // of type specificity as fully general MaybeExpr values. 618 template <typename A> common::IfNoLvalue<MaybeExpr, A> AsMaybeExpr(A &&x) { 619 return AsGenericExpr(std::move(x)); 620 } 621 template <typename A> MaybeExpr AsMaybeExpr(std::optional<A> &&x) { 622 if (x) { 623 return AsMaybeExpr(std::move(*x)); 624 } 625 return std::nullopt; 626 } 627 628 // Type kind parameter values for literal constants. 629 int ExpressionAnalyzer::AnalyzeKindParam( 630 const std::optional<parser::KindParam> &kindParam, int defaultKind) { 631 if (!kindParam) { 632 return defaultKind; 633 } 634 std::int64_t kind{common::visit( 635 common::visitors{ 636 [](std::uint64_t k) { return static_cast<std::int64_t>(k); }, 637 [&](const parser::Scalar< 638 parser::Integer<parser::Constant<parser::Name>>> &n) { 639 if (MaybeExpr ie{Analyze(n)}) { 640 return ToInt64(*ie).value_or(defaultKind); 641 } 642 return static_cast<std::int64_t>(defaultKind); 643 }, 644 }, 645 kindParam->u)}; 646 if (kind != static_cast<int>(kind)) { 647 Say("Unsupported type kind value (%jd)"_err_en_US, 648 static_cast<std::intmax_t>(kind)); 649 kind = defaultKind; 650 } 651 return static_cast<int>(kind); 652 } 653 654 // Common handling of parser::IntLiteralConstant, SignedIntLiteralConstant, 655 // and UnsignedLiteralConstant 656 template <typename TYPES, TypeCategory CAT> struct IntTypeVisitor { 657 using Result = MaybeExpr; 658 using Types = TYPES; 659 template <typename T> Result Test() { 660 if (T::kind >= kind) { 661 const char *p{digits.begin()}; 662 using Int = typename T::Scalar; 663 typename Int::ValueWithOverflow num{0, false}; 664 const char *typeName{ 665 CAT == TypeCategory::Integer ? "INTEGER" : "UNSIGNED"}; 666 if (isNegated) { 667 auto unsignedNum{Int::Read(p, 10, false /*unsigned*/)}; 668 num.value = unsignedNum.value.Negate().value; 669 num.overflow = unsignedNum.overflow || 670 (CAT == TypeCategory::Integer && num.value > Int{0}); 671 if (!num.overflow && num.value.Negate().overflow) { 672 analyzer.Warn(LanguageFeature::BigIntLiterals, digits, 673 "negated maximum INTEGER(KIND=%d) literal"_port_en_US, T::kind); 674 } 675 } else { 676 num = Int::Read(p, 10, /*isSigned=*/CAT == TypeCategory::Integer); 677 } 678 if (num.overflow) { 679 if constexpr (CAT == TypeCategory::Unsigned) { 680 analyzer.Warn(common::UsageWarning::UnsignedLiteralTruncation, 681 "Unsigned literal too large for UNSIGNED(KIND=%d); truncated"_warn_en_US, 682 kind); 683 return Expr<SomeType>{ 684 Expr<SomeKind<CAT>>{Expr<T>{Constant<T>{std::move(num.value)}}}}; 685 } 686 } else { 687 if (T::kind > kind) { 688 if (!isDefaultKind || 689 !analyzer.context().IsEnabled(LanguageFeature::BigIntLiterals)) { 690 return std::nullopt; 691 } else { 692 analyzer.Warn(LanguageFeature::BigIntLiterals, digits, 693 "Integer literal is too large for default %s(KIND=%d); " 694 "assuming %s(KIND=%d)"_port_en_US, 695 typeName, kind, typeName, T::kind); 696 } 697 } 698 return Expr<SomeType>{ 699 Expr<SomeKind<CAT>>{Expr<T>{Constant<T>{std::move(num.value)}}}}; 700 } 701 } 702 return std::nullopt; 703 } 704 ExpressionAnalyzer &analyzer; 705 parser::CharBlock digits; 706 std::int64_t kind; 707 bool isDefaultKind; 708 bool isNegated; 709 }; 710 711 template <typename TYPES, TypeCategory CAT, typename PARSED> 712 MaybeExpr ExpressionAnalyzer::IntLiteralConstant( 713 const PARSED &x, bool isNegated) { 714 const auto &kindParam{std::get<std::optional<parser::KindParam>>(x.t)}; 715 bool isDefaultKind{!kindParam}; 716 int kind{AnalyzeKindParam(kindParam, GetDefaultKind(CAT))}; 717 const char *typeName{CAT == TypeCategory::Integer ? "INTEGER" : "UNSIGNED"}; 718 if (CheckIntrinsicKind(CAT, kind)) { 719 auto digits{std::get<parser::CharBlock>(x.t)}; 720 if (MaybeExpr result{common::SearchTypes(IntTypeVisitor<TYPES, CAT>{ 721 *this, digits, kind, isDefaultKind, isNegated})}) { 722 return result; 723 } else if (isDefaultKind) { 724 Say(digits, 725 "Integer literal is too large for any allowable kind of %s"_err_en_US, 726 typeName); 727 } else { 728 Say(digits, "Integer literal is too large for %s(KIND=%d)"_err_en_US, 729 typeName, kind); 730 } 731 } 732 return std::nullopt; 733 } 734 735 MaybeExpr ExpressionAnalyzer::Analyze( 736 const parser::IntLiteralConstant &x, bool isNegated) { 737 auto restorer{ 738 GetContextualMessages().SetLocation(std::get<parser::CharBlock>(x.t))}; 739 return IntLiteralConstant<IntegerTypes, TypeCategory::Integer>(x, isNegated); 740 } 741 742 MaybeExpr ExpressionAnalyzer::Analyze( 743 const parser::SignedIntLiteralConstant &x) { 744 auto restorer{GetContextualMessages().SetLocation(x.source)}; 745 return IntLiteralConstant<IntegerTypes, TypeCategory::Integer>(x); 746 } 747 748 MaybeExpr ExpressionAnalyzer::Analyze( 749 const parser::UnsignedLiteralConstant &x) { 750 parser::CharBlock at{std::get<parser::CharBlock>(x.t)}; 751 auto restorer{GetContextualMessages().SetLocation(at)}; 752 if (!context().IsEnabled(common::LanguageFeature::Unsigned) && 753 !context().AnyFatalError()) { 754 context().Say( 755 at, "-funsigned is required to enable UNSIGNED constants"_err_en_US); 756 } 757 return IntLiteralConstant<UnsignedTypes, TypeCategory::Unsigned>(x); 758 } 759 760 template <typename TYPE> 761 Constant<TYPE> ReadRealLiteral( 762 parser::CharBlock source, FoldingContext &context) { 763 const char *p{source.begin()}; 764 auto valWithFlags{ 765 Scalar<TYPE>::Read(p, context.targetCharacteristics().roundingMode())}; 766 CHECK(p == source.end()); 767 RealFlagWarnings(context, valWithFlags.flags, "conversion of REAL literal"); 768 auto value{valWithFlags.value}; 769 if (context.targetCharacteristics().areSubnormalsFlushedToZero()) { 770 value = value.FlushSubnormalToZero(); 771 } 772 return {value}; 773 } 774 775 struct RealTypeVisitor { 776 using Result = std::optional<Expr<SomeReal>>; 777 using Types = RealTypes; 778 779 RealTypeVisitor(int k, parser::CharBlock lit, FoldingContext &ctx) 780 : kind{k}, literal{lit}, context{ctx} {} 781 782 template <typename T> Result Test() { 783 if (kind == T::kind) { 784 return {AsCategoryExpr(ReadRealLiteral<T>(literal, context))}; 785 } 786 return std::nullopt; 787 } 788 789 int kind; 790 parser::CharBlock literal; 791 FoldingContext &context; 792 }; 793 794 // Reads a real literal constant and encodes it with the right kind. 795 MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) { 796 // Use a local message context around the real literal for better 797 // provenance on any messages. 798 auto restorer{GetContextualMessages().SetLocation(x.real.source)}; 799 // If a kind parameter appears, it defines the kind of the literal and the 800 // letter used in an exponent part must be 'E' (e.g., the 'E' in 801 // "6.02214E+23"). In the absence of an explicit kind parameter, any 802 // exponent letter determines the kind. Otherwise, defaults apply. 803 auto &defaults{context_.defaultKinds()}; 804 int defaultKind{defaults.GetDefaultKind(TypeCategory::Real)}; 805 const char *end{x.real.source.end()}; 806 char expoLetter{' '}; 807 std::optional<int> letterKind; 808 for (const char *p{x.real.source.begin()}; p < end; ++p) { 809 if (parser::IsLetter(*p)) { 810 expoLetter = *p; 811 switch (expoLetter) { 812 case 'e': 813 letterKind = defaults.GetDefaultKind(TypeCategory::Real); 814 break; 815 case 'd': 816 letterKind = defaults.doublePrecisionKind(); 817 break; 818 case 'q': 819 letterKind = defaults.quadPrecisionKind(); 820 break; 821 default: 822 Say("Unknown exponent letter '%c'"_err_en_US, expoLetter); 823 } 824 break; 825 } 826 } 827 if (letterKind) { 828 defaultKind = *letterKind; 829 } 830 // C716 requires 'E' as an exponent. 831 // Extension: allow exponent-letter matching the kind-param. 832 auto kind{AnalyzeKindParam(x.kind, defaultKind)}; 833 if (letterKind && expoLetter != 'e') { 834 if (kind != *letterKind) { 835 Warn(common::LanguageFeature::ExponentMatchingKindParam, 836 "Explicit kind parameter on real constant disagrees with exponent letter '%c'"_warn_en_US, 837 expoLetter); 838 } else if (x.kind) { 839 Warn(common::LanguageFeature::ExponentMatchingKindParam, 840 "Explicit kind parameter together with non-'E' exponent letter is not standard"_port_en_US); 841 } 842 } 843 auto result{common::SearchTypes( 844 RealTypeVisitor{kind, x.real.source, GetFoldingContext()})}; 845 if (!result) { // C717 846 Say("Unsupported REAL(KIND=%d)"_err_en_US, kind); 847 } 848 return AsMaybeExpr(std::move(result)); 849 } 850 851 MaybeExpr ExpressionAnalyzer::Analyze( 852 const parser::SignedRealLiteralConstant &x) { 853 if (auto result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) { 854 auto &realExpr{std::get<Expr<SomeReal>>(result->u)}; 855 if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) { 856 if (sign == parser::Sign::Negative) { 857 return AsGenericExpr(-std::move(realExpr)); 858 } 859 } 860 return result; 861 } 862 return std::nullopt; 863 } 864 865 MaybeExpr ExpressionAnalyzer::Analyze( 866 const parser::SignedComplexLiteralConstant &x) { 867 auto result{Analyze(std::get<parser::ComplexLiteralConstant>(x.t))}; 868 if (!result) { 869 return std::nullopt; 870 } else if (std::get<parser::Sign>(x.t) == parser::Sign::Negative) { 871 return AsGenericExpr(-std::move(std::get<Expr<SomeComplex>>(result->u))); 872 } else { 873 return result; 874 } 875 } 876 877 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexPart &x) { 878 return Analyze(x.u); 879 } 880 881 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexLiteralConstant &z) { 882 return AnalyzeComplex(Analyze(std::get<0>(z.t)), Analyze(std::get<1>(z.t)), 883 "complex literal constant"); 884 } 885 886 // CHARACTER literal processing. 887 MaybeExpr ExpressionAnalyzer::AnalyzeString(std::string &&string, int kind) { 888 if (!CheckIntrinsicKind(TypeCategory::Character, kind)) { 889 return std::nullopt; 890 } 891 switch (kind) { 892 case 1: 893 return AsGenericExpr(Constant<Type<TypeCategory::Character, 1>>{ 894 parser::DecodeString<std::string, parser::Encoding::LATIN_1>( 895 string, true)}); 896 case 2: 897 return AsGenericExpr(Constant<Type<TypeCategory::Character, 2>>{ 898 parser::DecodeString<std::u16string, parser::Encoding::UTF_8>( 899 string, true)}); 900 case 4: 901 return AsGenericExpr(Constant<Type<TypeCategory::Character, 4>>{ 902 parser::DecodeString<std::u32string, parser::Encoding::UTF_8>( 903 string, true)}); 904 default: 905 CRASH_NO_CASE; 906 } 907 } 908 909 MaybeExpr ExpressionAnalyzer::Analyze(const parser::CharLiteralConstant &x) { 910 int kind{ 911 AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t), 1)}; 912 auto value{std::get<std::string>(x.t)}; 913 return AnalyzeString(std::move(value), kind); 914 } 915 916 MaybeExpr ExpressionAnalyzer::Analyze( 917 const parser::HollerithLiteralConstant &x) { 918 int kind{GetDefaultKind(TypeCategory::Character)}; 919 auto result{AnalyzeString(std::string{x.v}, kind)}; 920 if (auto *constant{UnwrapConstantValue<Ascii>(result)}) { 921 constant->set_wasHollerith(true); 922 } 923 return result; 924 } 925 926 // .TRUE. and .FALSE. of various kinds 927 MaybeExpr ExpressionAnalyzer::Analyze(const parser::LogicalLiteralConstant &x) { 928 auto kind{AnalyzeKindParam(std::get<std::optional<parser::KindParam>>(x.t), 929 GetDefaultKind(TypeCategory::Logical))}; 930 bool value{std::get<bool>(x.t)}; 931 auto result{common::SearchTypes( 932 TypeKindVisitor<TypeCategory::Logical, Constant, bool>{ 933 kind, std::move(value)})}; 934 if (!result) { 935 Say("unsupported LOGICAL(KIND=%d)"_err_en_US, kind); // C728 936 } 937 return result; 938 } 939 940 // BOZ typeless literals 941 MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) { 942 const char *p{x.v.c_str()}; 943 std::uint64_t base{16}; 944 switch (*p++) { 945 case 'b': 946 base = 2; 947 break; 948 case 'o': 949 base = 8; 950 break; 951 case 'z': 952 break; 953 case 'x': 954 break; 955 default: 956 CRASH_NO_CASE; 957 } 958 CHECK(*p == '"'); 959 ++p; 960 auto value{BOZLiteralConstant::Read(p, base, false /*unsigned*/)}; 961 if (*p != '"') { 962 Say("Invalid digit ('%c') in BOZ literal '%s'"_err_en_US, *p, 963 x.v); // C7107, C7108 964 return std::nullopt; 965 } 966 if (value.overflow) { 967 Say("BOZ literal '%s' too large"_err_en_US, x.v); 968 return std::nullopt; 969 } 970 return AsGenericExpr(std::move(value.value)); 971 } 972 973 // Names and named constants 974 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) { 975 auto restorer{GetContextualMessages().SetLocation(n.source)}; 976 if (std::optional<int> kind{IsImpliedDo(n.source)}) { 977 return AsMaybeExpr(ConvertToKind<TypeCategory::Integer>( 978 *kind, AsExpr(ImpliedDoIndex{n.source}))); 979 } 980 if (context_.HasError(n.symbol)) { // includes case of no symbol 981 return std::nullopt; 982 } else { 983 const Symbol &ultimate{n.symbol->GetUltimate()}; 984 if (ultimate.has<semantics::TypeParamDetails>()) { 985 // A bare reference to a derived type parameter within a parameterized 986 // derived type definition. 987 auto dyType{DynamicType::From(ultimate)}; 988 if (!dyType) { 989 // When the integer kind of this type parameter is not known now, 990 // it's either an error or because it depends on earlier-declared kind 991 // type parameters. So assume that it's a subscript integer for now 992 // while processing other specification expressions in the PDT 993 // definition; the right kind value will be used later in each of its 994 // instantiations. 995 int kind{SubscriptInteger::kind}; 996 if (const auto *typeSpec{ultimate.GetType()}) { 997 if (const semantics::IntrinsicTypeSpec * 998 intrinType{typeSpec->AsIntrinsic()}) { 999 if (auto k{ToInt64(Fold(semantics::KindExpr{intrinType->kind()}))}; 1000 k && IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) { 1001 kind = *k; 1002 } 1003 } 1004 } 1005 dyType = DynamicType{TypeCategory::Integer, kind}; 1006 } 1007 return Fold(ConvertToType( 1008 *dyType, AsGenericExpr(TypeParamInquiry{std::nullopt, ultimate}))); 1009 } else { 1010 if (n.symbol->attrs().test(semantics::Attr::VOLATILE)) { 1011 if (const semantics::Scope *pure{semantics::FindPureProcedureContaining( 1012 context_.FindScope(n.source))}) { 1013 SayAt(n, 1014 "VOLATILE variable '%s' may not be referenced in pure subprogram '%s'"_err_en_US, 1015 n.source, DEREF(pure->symbol()).name()); 1016 n.symbol->attrs().reset(semantics::Attr::VOLATILE); 1017 } 1018 } 1019 if (!isWholeAssumedSizeArrayOk_ && 1020 semantics::IsAssumedSizeArray( 1021 ResolveAssociations(*n.symbol))) { // C1002, C1014, C1231 1022 AttachDeclaration( 1023 SayAt(n, 1024 "Whole assumed-size array '%s' may not appear here without subscripts"_err_en_US, 1025 n.source), 1026 *n.symbol); 1027 } 1028 return Designate(DataRef{*n.symbol}); 1029 } 1030 } 1031 } 1032 1033 MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) { 1034 auto restorer{GetContextualMessages().SetLocation(n.v.source)}; 1035 if (MaybeExpr value{Analyze(n.v)}) { 1036 Expr<SomeType> folded{Fold(std::move(*value))}; 1037 if (IsConstantExpr(folded)) { 1038 return folded; 1039 } 1040 Say(n.v.source, "must be a constant"_err_en_US); // C718 1041 } 1042 return std::nullopt; 1043 } 1044 1045 MaybeExpr ExpressionAnalyzer::Analyze(const parser::NullInit &n) { 1046 auto restorer{AllowNullPointer()}; 1047 if (MaybeExpr value{Analyze(n.v.value())}) { 1048 // Subtle: when the NullInit is a DataStmtConstant, it might 1049 // be a misparse of a structure constructor without parameters 1050 // or components (e.g., T()). Checking the result to ensure 1051 // that a "=>" data entity initializer actually resolved to 1052 // a null pointer has to be done by the caller. 1053 return Fold(std::move(*value)); 1054 } 1055 return std::nullopt; 1056 } 1057 1058 MaybeExpr ExpressionAnalyzer::Analyze( 1059 const parser::StmtFunctionStmt &stmtFunc) { 1060 inStmtFunctionDefinition_ = true; 1061 return Analyze(std::get<parser::Scalar<parser::Expr>>(stmtFunc.t)); 1062 } 1063 1064 MaybeExpr ExpressionAnalyzer::Analyze(const parser::InitialDataTarget &x) { 1065 return Analyze(x.value()); 1066 } 1067 1068 MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtValue &x) { 1069 if (const auto &repeat{ 1070 std::get<std::optional<parser::DataStmtRepeat>>(x.t)}) { 1071 x.repetitions = -1; 1072 if (MaybeExpr expr{Analyze(repeat->u)}) { 1073 Expr<SomeType> folded{Fold(std::move(*expr))}; 1074 if (auto value{ToInt64(folded)}) { 1075 if (*value >= 0) { // C882 1076 x.repetitions = *value; 1077 } else { 1078 Say(FindSourceLocation(repeat), 1079 "Repeat count (%jd) for data value must not be negative"_err_en_US, 1080 *value); 1081 } 1082 } 1083 } 1084 } 1085 return Analyze(std::get<parser::DataStmtConstant>(x.t)); 1086 } 1087 1088 // Substring references 1089 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::GetSubstringBound( 1090 const std::optional<parser::ScalarIntExpr> &bound) { 1091 if (bound) { 1092 if (MaybeExpr expr{Analyze(*bound)}) { 1093 if (expr->Rank() > 1) { 1094 Say("substring bound expression has rank %d"_err_en_US, expr->Rank()); 1095 } 1096 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) { 1097 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) { 1098 return {std::move(*ssIntExpr)}; 1099 } 1100 return {Expr<SubscriptInteger>{ 1101 Convert<SubscriptInteger, TypeCategory::Integer>{ 1102 std::move(*intExpr)}}}; 1103 } else { 1104 Say("substring bound expression is not INTEGER"_err_en_US); 1105 } 1106 } 1107 } 1108 return std::nullopt; 1109 } 1110 1111 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Substring &ss) { 1112 if (MaybeExpr baseExpr{Analyze(std::get<parser::DataRef>(ss.t))}) { 1113 if (std::optional<DataRef> dataRef{ExtractDataRef(std::move(*baseExpr))}) { 1114 if (MaybeExpr newBaseExpr{Designate(std::move(*dataRef))}) { 1115 if (std::optional<DataRef> checked{ 1116 ExtractDataRef(std::move(*newBaseExpr))}) { 1117 const parser::SubstringRange &range{ 1118 std::get<parser::SubstringRange>(ss.t)}; 1119 std::optional<Expr<SubscriptInteger>> first{ 1120 Fold(GetSubstringBound(std::get<0>(range.t)))}; 1121 std::optional<Expr<SubscriptInteger>> last{ 1122 Fold(GetSubstringBound(std::get<1>(range.t)))}; 1123 const Symbol &symbol{checked->GetLastSymbol()}; 1124 if (std::optional<DynamicType> dynamicType{ 1125 DynamicType::From(symbol)}) { 1126 if (dynamicType->category() == TypeCategory::Character) { 1127 auto lbValue{ToInt64(first)}; 1128 if (!lbValue) { 1129 lbValue = 1; 1130 } 1131 auto ubValue{ToInt64(last)}; 1132 auto len{dynamicType->knownLength()}; 1133 if (!ubValue) { 1134 ubValue = len; 1135 } 1136 if (lbValue && ubValue && *lbValue > *ubValue) { 1137 // valid, substring is empty 1138 } else if (lbValue && *lbValue < 1 && (ubValue || !last)) { 1139 Say("Substring must begin at 1 or later, not %jd"_err_en_US, 1140 static_cast<std::intmax_t>(*lbValue)); 1141 return std::nullopt; 1142 } else if (ubValue && len && *ubValue > *len && 1143 (lbValue || !first)) { 1144 Say("Substring must end at %zd or earlier, not %jd"_err_en_US, 1145 static_cast<std::intmax_t>(*len), 1146 static_cast<std::intmax_t>(*ubValue)); 1147 return std::nullopt; 1148 } 1149 return WrapperHelper<TypeCategory::Character, Designator, 1150 Substring>(dynamicType->kind(), 1151 Substring{std::move(checked.value()), std::move(first), 1152 std::move(last)}); 1153 } 1154 } 1155 Say("substring may apply only to CHARACTER"_err_en_US); 1156 } 1157 } 1158 } 1159 } 1160 return std::nullopt; 1161 } 1162 1163 // CHARACTER literal substrings 1164 MaybeExpr ExpressionAnalyzer::Analyze( 1165 const parser::CharLiteralConstantSubstring &x) { 1166 const parser::SubstringRange &range{std::get<parser::SubstringRange>(x.t)}; 1167 std::optional<Expr<SubscriptInteger>> lower{ 1168 GetSubstringBound(std::get<0>(range.t))}; 1169 std::optional<Expr<SubscriptInteger>> upper{ 1170 GetSubstringBound(std::get<1>(range.t))}; 1171 if (MaybeExpr string{Analyze(std::get<parser::CharLiteralConstant>(x.t))}) { 1172 if (auto *charExpr{std::get_if<Expr<SomeCharacter>>(&string->u)}) { 1173 Expr<SubscriptInteger> length{ 1174 common::visit([](const auto &ckExpr) { return ckExpr.LEN().value(); }, 1175 charExpr->u)}; 1176 if (!lower) { 1177 lower = Expr<SubscriptInteger>{1}; 1178 } 1179 if (!upper) { 1180 upper = Expr<SubscriptInteger>{ 1181 static_cast<std::int64_t>(ToInt64(length).value())}; 1182 } 1183 return common::visit( 1184 [&](auto &&ckExpr) -> MaybeExpr { 1185 using Result = ResultType<decltype(ckExpr)>; 1186 auto *cp{std::get_if<Constant<Result>>(&ckExpr.u)}; 1187 CHECK(DEREF(cp).size() == 1); 1188 StaticDataObject::Pointer staticData{StaticDataObject::Create()}; 1189 staticData->set_alignment(Result::kind) 1190 .set_itemBytes(Result::kind) 1191 .Push(cp->GetScalarValue().value(), 1192 foldingContext_.targetCharacteristics().isBigEndian()); 1193 Substring substring{std::move(staticData), std::move(lower.value()), 1194 std::move(upper.value())}; 1195 return AsGenericExpr( 1196 Expr<Result>{Designator<Result>{std::move(substring)}}); 1197 }, 1198 std::move(charExpr->u)); 1199 } 1200 } 1201 return std::nullopt; 1202 } 1203 1204 // substring%KIND/LEN 1205 MaybeExpr ExpressionAnalyzer::Analyze(const parser::SubstringInquiry &x) { 1206 if (MaybeExpr substring{Analyze(x.v)}) { 1207 CHECK(x.source.size() >= 8); 1208 int nameLen{x.source.end()[-1] == 'n' ? 3 /*LEN*/ : 4 /*KIND*/}; 1209 parser::CharBlock name{ 1210 x.source.end() - nameLen, static_cast<std::size_t>(nameLen)}; 1211 CHECK(name == "len" || name == "kind"); 1212 return MakeFunctionRef( 1213 name, ActualArguments{ActualArgument{std::move(*substring)}}); 1214 } else { 1215 return std::nullopt; 1216 } 1217 } 1218 1219 // Subscripted array references 1220 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::AsSubscript( 1221 MaybeExpr &&expr) { 1222 if (expr) { 1223 if (expr->Rank() > 1) { 1224 Say("Subscript expression has rank %d greater than 1"_err_en_US, 1225 expr->Rank()); 1226 } 1227 if (auto *intExpr{std::get_if<Expr<SomeInteger>>(&expr->u)}) { 1228 if (auto *ssIntExpr{std::get_if<Expr<SubscriptInteger>>(&intExpr->u)}) { 1229 return std::move(*ssIntExpr); 1230 } else { 1231 return Expr<SubscriptInteger>{ 1232 Convert<SubscriptInteger, TypeCategory::Integer>{ 1233 std::move(*intExpr)}}; 1234 } 1235 } else { 1236 Say("Subscript expression is not INTEGER"_err_en_US); 1237 } 1238 } 1239 return std::nullopt; 1240 } 1241 1242 std::optional<Expr<SubscriptInteger>> ExpressionAnalyzer::TripletPart( 1243 const std::optional<parser::Subscript> &s) { 1244 if (s) { 1245 return AsSubscript(Analyze(*s)); 1246 } else { 1247 return std::nullopt; 1248 } 1249 } 1250 1251 std::optional<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscript( 1252 const parser::SectionSubscript &ss) { 1253 return common::visit( 1254 common::visitors{ 1255 [&](const parser::SubscriptTriplet &t) -> std::optional<Subscript> { 1256 const auto &lower{std::get<0>(t.t)}; 1257 const auto &upper{std::get<1>(t.t)}; 1258 const auto &stride{std::get<2>(t.t)}; 1259 auto result{Triplet{ 1260 TripletPart(lower), TripletPart(upper), TripletPart(stride)}}; 1261 if ((lower && !result.lower()) || (upper && !result.upper())) { 1262 return std::nullopt; 1263 } else { 1264 return std::make_optional<Subscript>(result); 1265 } 1266 }, 1267 [&](const auto &s) -> std::optional<Subscript> { 1268 if (auto subscriptExpr{AsSubscript(Analyze(s))}) { 1269 return Subscript{std::move(*subscriptExpr)}; 1270 } else { 1271 return std::nullopt; 1272 } 1273 }, 1274 }, 1275 ss.u); 1276 } 1277 1278 // Empty result means an error occurred 1279 std::vector<Subscript> ExpressionAnalyzer::AnalyzeSectionSubscripts( 1280 const std::list<parser::SectionSubscript> &sss) { 1281 bool error{false}; 1282 std::vector<Subscript> subscripts; 1283 for (const auto &s : sss) { 1284 if (auto subscript{AnalyzeSectionSubscript(s)}) { 1285 subscripts.emplace_back(std::move(*subscript)); 1286 } else { 1287 error = true; 1288 } 1289 } 1290 return !error ? subscripts : std::vector<Subscript>{}; 1291 } 1292 1293 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayElement &ae) { 1294 MaybeExpr baseExpr; 1295 { 1296 auto restorer{AllowWholeAssumedSizeArray()}; 1297 baseExpr = Analyze(ae.base); 1298 } 1299 if (baseExpr) { 1300 if (ae.subscripts.empty()) { 1301 // will be converted to function call later or error reported 1302 } else if (baseExpr->Rank() == 0) { 1303 if (const Symbol *symbol{GetLastSymbol(*baseExpr)}) { 1304 if (!context_.HasError(symbol)) { 1305 if (inDataStmtConstant_) { 1306 // Better error for NULL(X) with a MOLD= argument 1307 Say("'%s' must be an array or structure constructor if used with non-empty parentheses as a DATA statement constant"_err_en_US, 1308 symbol->name()); 1309 } else { 1310 Say("'%s' is not an array"_err_en_US, symbol->name()); 1311 } 1312 context_.SetError(*symbol); 1313 } 1314 } 1315 } else if (std::optional<DataRef> dataRef{ 1316 ExtractDataRef(std::move(*baseExpr))}) { 1317 return ApplySubscripts( 1318 std::move(*dataRef), AnalyzeSectionSubscripts(ae.subscripts)); 1319 } else { 1320 Say("Subscripts may be applied only to an object, component, or array constant"_err_en_US); 1321 } 1322 } 1323 // error was reported: analyze subscripts without reporting more errors 1324 auto restorer{GetContextualMessages().DiscardMessages()}; 1325 AnalyzeSectionSubscripts(ae.subscripts); 1326 return std::nullopt; 1327 } 1328 1329 // Type parameter inquiries apply to data references, but don't depend 1330 // on any trailing (co)subscripts. 1331 static NamedEntity IgnoreAnySubscripts(Designator<SomeDerived> &&designator) { 1332 return common::visit( 1333 common::visitors{ 1334 [](SymbolRef &&symbol) { return NamedEntity{symbol}; }, 1335 [](Component &&component) { 1336 return NamedEntity{std::move(component)}; 1337 }, 1338 [](ArrayRef &&arrayRef) { return std::move(arrayRef.base()); }, 1339 [](CoarrayRef &&coarrayRef) { 1340 return NamedEntity{coarrayRef.GetLastSymbol()}; 1341 }, 1342 }, 1343 std::move(designator.u)); 1344 } 1345 1346 // Components, but not bindings, of parent derived types are explicitly 1347 // represented as such. 1348 std::optional<Component> ExpressionAnalyzer::CreateComponent(DataRef &&base, 1349 const Symbol &component, const semantics::Scope &scope, 1350 bool C919bAlreadyEnforced) { 1351 if (!C919bAlreadyEnforced && IsAllocatableOrPointer(component) && 1352 base.Rank() > 0) { // C919b 1353 Say("An allocatable or pointer component reference must be applied to a scalar base"_err_en_US); 1354 } 1355 if (&component.owner() == &scope || 1356 component.has<semantics::ProcBindingDetails>()) { 1357 return Component{std::move(base), component}; 1358 } 1359 if (const Symbol *typeSymbol{scope.GetSymbol()}) { 1360 if (const Symbol *parentComponent{typeSymbol->GetParentComponent(&scope)}) { 1361 if (const auto *object{ 1362 parentComponent->detailsIf<semantics::ObjectEntityDetails>()}) { 1363 if (const auto *parentType{object->type()}) { 1364 if (const semantics::Scope *parentScope{ 1365 parentType->derivedTypeSpec().scope()}) { 1366 return CreateComponent( 1367 DataRef{Component{std::move(base), *parentComponent}}, 1368 component, *parentScope, C919bAlreadyEnforced); 1369 } 1370 } 1371 } 1372 } 1373 } 1374 return std::nullopt; 1375 } 1376 1377 // Derived type component references and type parameter inquiries 1378 MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) { 1379 Symbol *sym{sc.component.symbol}; 1380 if (context_.HasError(sym)) { 1381 return std::nullopt; 1382 } 1383 const auto *misc{sym->detailsIf<semantics::MiscDetails>()}; 1384 bool isTypeParamInquiry{sym->has<semantics::TypeParamDetails>() || 1385 (misc && 1386 (misc->kind() == semantics::MiscDetails::Kind::KindParamInquiry || 1387 misc->kind() == semantics::MiscDetails::Kind::LenParamInquiry))}; 1388 MaybeExpr base; 1389 if (isTypeParamInquiry) { 1390 auto restorer{AllowWholeAssumedSizeArray()}; 1391 base = Analyze(sc.base); 1392 } else { 1393 base = Analyze(sc.base); 1394 } 1395 if (!base) { 1396 return std::nullopt; 1397 } 1398 const auto &name{sc.component.source}; 1399 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) { 1400 const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())}; 1401 if (isTypeParamInquiry) { 1402 if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) { 1403 if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) { 1404 if (dyType->category() == TypeCategory::Integer) { 1405 auto restorer{GetContextualMessages().SetLocation(name)}; 1406 return Fold(ConvertToType(*dyType, 1407 AsGenericExpr(TypeParamInquiry{ 1408 IgnoreAnySubscripts(std::move(*designator)), *sym}))); 1409 } 1410 } 1411 Say(name, "Type parameter is not INTEGER"_err_en_US); 1412 } else { 1413 Say(name, 1414 "A type parameter inquiry must be applied to a designator"_err_en_US); 1415 } 1416 } else if (!dtSpec || !dtSpec->scope()) { 1417 CHECK(context_.AnyFatalError() || !foldingContext_.messages().empty()); 1418 return std::nullopt; 1419 } else if (std::optional<DataRef> dataRef{ 1420 ExtractDataRef(std::move(*dtExpr))}) { 1421 auto restorer{GetContextualMessages().SetLocation(name)}; 1422 if (auto component{ 1423 CreateComponent(std::move(*dataRef), *sym, *dtSpec->scope())}) { 1424 return Designate(DataRef{std::move(*component)}); 1425 } else { 1426 Say(name, "Component is not in scope of derived TYPE(%s)"_err_en_US, 1427 dtSpec->typeSymbol().name()); 1428 } 1429 } else { 1430 Say(name, 1431 "Base of component reference must be a data reference"_err_en_US); 1432 } 1433 } else if (auto *details{sym->detailsIf<semantics::MiscDetails>()}) { 1434 // special part-ref: %re, %im, %kind, %len 1435 // Type errors on the base of %re/%im/%len are detected and 1436 // reported in name resolution. 1437 using MiscKind = semantics::MiscDetails::Kind; 1438 MiscKind kind{details->kind()}; 1439 if (kind == MiscKind::ComplexPartRe || kind == MiscKind::ComplexPartIm) { 1440 if (auto *zExpr{std::get_if<Expr<SomeComplex>>(&base->u)}) { 1441 if (std::optional<DataRef> dataRef{ExtractDataRef(*zExpr)}) { 1442 // Represent %RE/%IM as a designator 1443 Expr<SomeReal> realExpr{common::visit( 1444 [&](const auto &z) { 1445 using PartType = typename ResultType<decltype(z)>::Part; 1446 auto part{kind == MiscKind::ComplexPartRe 1447 ? ComplexPart::Part::RE 1448 : ComplexPart::Part::IM}; 1449 return AsCategoryExpr(Designator<PartType>{ 1450 ComplexPart{std::move(*dataRef), part}}); 1451 }, 1452 zExpr->u)}; 1453 return AsGenericExpr(std::move(realExpr)); 1454 } 1455 } 1456 } else if (isTypeParamInquiry) { // %kind or %len 1457 ActualArgument arg{std::move(*base)}; 1458 SetArgSourceLocation(arg, name); 1459 return MakeFunctionRef(name, ActualArguments{std::move(arg)}); 1460 } else { 1461 DIE("unexpected MiscDetails::Kind"); 1462 } 1463 } else { 1464 Say(name, "derived type required before component reference"_err_en_US); 1465 } 1466 return std::nullopt; 1467 } 1468 1469 MaybeExpr ExpressionAnalyzer::Analyze(const parser::CoindexedNamedObject &x) { 1470 if (auto maybeDataRef{ExtractDataRef(Analyze(x.base))}) { 1471 DataRef *dataRef{&*maybeDataRef}; 1472 std::vector<Subscript> subscripts; 1473 SymbolVector reversed; 1474 if (auto *aRef{std::get_if<ArrayRef>(&dataRef->u)}) { 1475 subscripts = std::move(aRef->subscript()); 1476 reversed.push_back(aRef->GetLastSymbol()); 1477 if (Component *component{aRef->base().UnwrapComponent()}) { 1478 dataRef = &component->base(); 1479 } else { 1480 dataRef = nullptr; 1481 } 1482 } 1483 if (dataRef) { 1484 while (auto *component{std::get_if<Component>(&dataRef->u)}) { 1485 reversed.push_back(component->GetLastSymbol()); 1486 dataRef = &component->base(); 1487 } 1488 if (auto *baseSym{std::get_if<SymbolRef>(&dataRef->u)}) { 1489 reversed.push_back(*baseSym); 1490 } else { 1491 Say("Base of coindexed named object has subscripts or cosubscripts"_err_en_US); 1492 } 1493 } 1494 std::vector<Expr<SubscriptInteger>> cosubscripts; 1495 bool cosubsOk{true}; 1496 for (const auto &cosub : 1497 std::get<std::list<parser::Cosubscript>>(x.imageSelector.t)) { 1498 MaybeExpr coex{Analyze(cosub)}; 1499 if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(coex)}) { 1500 cosubscripts.push_back( 1501 ConvertToType<SubscriptInteger>(std::move(*intExpr))); 1502 } else { 1503 cosubsOk = false; 1504 } 1505 } 1506 if (cosubsOk && !reversed.empty()) { 1507 int numCosubscripts{static_cast<int>(cosubscripts.size())}; 1508 const Symbol &symbol{reversed.front()}; 1509 if (numCosubscripts != GetCorank(symbol)) { 1510 Say("'%s' has corank %d, but coindexed reference has %d cosubscripts"_err_en_US, 1511 symbol.name(), GetCorank(symbol), numCosubscripts); 1512 } 1513 } 1514 for (const auto &imageSelSpec : 1515 std::get<std::list<parser::ImageSelectorSpec>>(x.imageSelector.t)) { 1516 common::visit( 1517 common::visitors{ 1518 [&](const auto &x) { Analyze(x.v); }, 1519 }, 1520 imageSelSpec.u); 1521 } 1522 // Reverse the chain of symbols so that the base is first and coarray 1523 // ultimate component is last. 1524 if (cosubsOk) { 1525 return Designate( 1526 DataRef{CoarrayRef{SymbolVector{reversed.crbegin(), reversed.crend()}, 1527 std::move(subscripts), std::move(cosubscripts)}}); 1528 } 1529 } 1530 return std::nullopt; 1531 } 1532 1533 int ExpressionAnalyzer::IntegerTypeSpecKind( 1534 const parser::IntegerTypeSpec &spec) { 1535 Expr<SubscriptInteger> value{ 1536 AnalyzeKindSelector(TypeCategory::Integer, spec.v)}; 1537 if (auto kind{ToInt64(value)}) { 1538 return static_cast<int>(*kind); 1539 } 1540 SayAt(spec, "Constant INTEGER kind value required here"_err_en_US); 1541 return GetDefaultKind(TypeCategory::Integer); 1542 } 1543 1544 // Array constructors 1545 1546 // Inverts a collection of generic ArrayConstructorValues<SomeType> that 1547 // all happen to have the same actual type T into one ArrayConstructor<T>. 1548 template <typename T> 1549 ArrayConstructorValues<T> MakeSpecific( 1550 ArrayConstructorValues<SomeType> &&from) { 1551 ArrayConstructorValues<T> to; 1552 for (ArrayConstructorValue<SomeType> &x : from) { 1553 common::visit( 1554 common::visitors{ 1555 [&](common::CopyableIndirection<Expr<SomeType>> &&expr) { 1556 auto *typed{UnwrapExpr<Expr<T>>(expr.value())}; 1557 to.Push(std::move(DEREF(typed))); 1558 }, 1559 [&](ImpliedDo<SomeType> &&impliedDo) { 1560 to.Push(ImpliedDo<T>{impliedDo.name(), 1561 std::move(impliedDo.lower()), std::move(impliedDo.upper()), 1562 std::move(impliedDo.stride()), 1563 MakeSpecific<T>(std::move(impliedDo.values()))}); 1564 }, 1565 }, 1566 std::move(x.u)); 1567 } 1568 return to; 1569 } 1570 1571 class ArrayConstructorContext { 1572 public: 1573 ArrayConstructorContext( 1574 ExpressionAnalyzer &c, std::optional<DynamicTypeWithLength> &&t) 1575 : exprAnalyzer_{c}, type_{std::move(t)} {} 1576 1577 void Add(const parser::AcValue &); 1578 MaybeExpr ToExpr(); 1579 1580 // These interfaces allow *this to be used as a type visitor argument to 1581 // common::SearchTypes() to convert the array constructor to a typed 1582 // expression in ToExpr(). 1583 using Result = MaybeExpr; 1584 using Types = AllTypes; 1585 template <typename T> Result Test() { 1586 if (type_ && type_->category() == T::category) { 1587 if constexpr (T::category == TypeCategory::Derived) { 1588 if (!type_->IsUnlimitedPolymorphic()) { 1589 return AsMaybeExpr(ArrayConstructor<T>{type_->GetDerivedTypeSpec(), 1590 MakeSpecific<T>(std::move(values_))}); 1591 } 1592 } else if (type_->kind() == T::kind) { 1593 ArrayConstructor<T> result{MakeSpecific<T>(std::move(values_))}; 1594 if constexpr (T::category == TypeCategory::Character) { 1595 if (auto len{LengthIfGood()}) { 1596 // The ac-do-variables may be treated as constant expressions, 1597 // if some conditions on ac-implied-do-control hold (10.1.12 (12)). 1598 // At the same time, they may be treated as constant expressions 1599 // only in the context of the ac-implied-do, but setting 1600 // the character length here may result in complete elimination 1601 // of the ac-implied-do. For example: 1602 // character(10) :: c 1603 // ... len([(c(i:i), integer(8)::i = 1,4)]) 1604 // would be evaulated into: 1605 // ... int(max(0_8,i-i+1_8),kind=4) 1606 // with a dangling reference to the ac-do-variable. 1607 // Prevent this by checking for the ac-do-variable references 1608 // in the 'len' expression. 1609 result.set_LEN(std::move(*len)); 1610 } 1611 } 1612 return AsMaybeExpr(std::move(result)); 1613 } 1614 } 1615 return std::nullopt; 1616 } 1617 1618 private: 1619 using ImpliedDoIntType = ResultType<ImpliedDoIndex>; 1620 1621 std::optional<Expr<SubscriptInteger>> LengthIfGood() const { 1622 if (type_) { 1623 auto len{type_->LEN()}; 1624 if (explicitType_ || 1625 (len && IsConstantExpr(*len) && !ContainsAnyImpliedDoIndex(*len))) { 1626 return len; 1627 } 1628 } 1629 return std::nullopt; 1630 } 1631 bool NeedLength() const { 1632 return type_ && type_->category() == TypeCategory::Character && 1633 !LengthIfGood(); 1634 } 1635 void Push(MaybeExpr &&); 1636 void Add(const parser::AcValue::Triplet &); 1637 void Add(const parser::Expr &); 1638 void Add(const parser::AcImpliedDo &); 1639 void UnrollConstantImpliedDo(const parser::AcImpliedDo &, 1640 parser::CharBlock name, std::int64_t lower, std::int64_t upper, 1641 std::int64_t stride); 1642 1643 template <int KIND> 1644 std::optional<Expr<Type<TypeCategory::Integer, KIND>>> ToSpecificInt( 1645 MaybeExpr &&y) { 1646 if (y) { 1647 Expr<SomeInteger> *intExpr{UnwrapExpr<Expr<SomeInteger>>(*y)}; 1648 return Fold(exprAnalyzer_.GetFoldingContext(), 1649 ConvertToType<Type<TypeCategory::Integer, KIND>>( 1650 std::move(DEREF(intExpr)))); 1651 } else { 1652 return std::nullopt; 1653 } 1654 } 1655 1656 template <int KIND, typename A> 1657 std::optional<Expr<Type<TypeCategory::Integer, KIND>>> GetSpecificIntExpr( 1658 const A &x) { 1659 return ToSpecificInt<KIND>(exprAnalyzer_.Analyze(x)); 1660 } 1661 1662 // Nested array constructors all reference the same ExpressionAnalyzer, 1663 // which represents the nest of active implied DO loop indices. 1664 ExpressionAnalyzer &exprAnalyzer_; 1665 std::optional<DynamicTypeWithLength> type_; 1666 bool explicitType_{type_.has_value()}; 1667 std::optional<std::int64_t> constantLength_; 1668 ArrayConstructorValues<SomeType> values_; 1669 std::uint64_t messageDisplayedSet_{0}; 1670 }; 1671 1672 void ArrayConstructorContext::Push(MaybeExpr &&x) { 1673 if (!x) { 1674 return; 1675 } 1676 if (!type_) { 1677 if (auto *boz{std::get_if<BOZLiteralConstant>(&x->u)}) { 1678 // Treat an array constructor of BOZ as if default integer. 1679 exprAnalyzer_.Warn(common::LanguageFeature::BOZAsDefaultInteger, 1680 "BOZ literal in array constructor without explicit type is assumed to be default INTEGER"_port_en_US); 1681 x = AsGenericExpr(ConvertToKind<TypeCategory::Integer>( 1682 exprAnalyzer_.GetDefaultKind(TypeCategory::Integer), 1683 std::move(*boz))); 1684 } 1685 } 1686 std::optional<DynamicType> dyType{x->GetType()}; 1687 if (!dyType) { 1688 if (auto *boz{std::get_if<BOZLiteralConstant>(&x->u)}) { 1689 if (!type_) { 1690 // Treat an array constructor of BOZ as if default integer. 1691 exprAnalyzer_.Warn(common::LanguageFeature::BOZAsDefaultInteger, 1692 "BOZ literal in array constructor without explicit type is assumed to be default INTEGER"_port_en_US); 1693 x = AsGenericExpr(ConvertToKind<TypeCategory::Integer>( 1694 exprAnalyzer_.GetDefaultKind(TypeCategory::Integer), 1695 std::move(*boz))); 1696 dyType = x.value().GetType(); 1697 } else if (auto cast{ConvertToType(*type_, std::move(*x))}) { 1698 x = std::move(cast); 1699 dyType = *type_; 1700 } else { 1701 if (!(messageDisplayedSet_ & 0x80)) { 1702 exprAnalyzer_.Say( 1703 "BOZ literal is not suitable for use in this array constructor"_err_en_US); 1704 messageDisplayedSet_ |= 0x80; 1705 } 1706 return; 1707 } 1708 } else { // procedure name, &c. 1709 if (!(messageDisplayedSet_ & 0x40)) { 1710 exprAnalyzer_.Say( 1711 "Item is not suitable for use in an array constructor"_err_en_US); 1712 messageDisplayedSet_ |= 0x40; 1713 } 1714 return; 1715 } 1716 } else if (dyType->IsUnlimitedPolymorphic()) { 1717 if (!(messageDisplayedSet_ & 8)) { 1718 exprAnalyzer_.Say("Cannot have an unlimited polymorphic value in an " 1719 "array constructor"_err_en_US); // C7113 1720 messageDisplayedSet_ |= 8; 1721 } 1722 return; 1723 } else if (dyType->category() == TypeCategory::Derived && 1724 dyType->GetDerivedTypeSpec().typeSymbol().attrs().test( 1725 semantics::Attr::ABSTRACT)) { // F'2023 C7125 1726 if (!(messageDisplayedSet_ & 0x200)) { 1727 exprAnalyzer_.Say( 1728 "An item whose declared type is ABSTRACT may not appear in an array constructor"_err_en_US); 1729 messageDisplayedSet_ |= 0x200; 1730 } 1731 } 1732 DynamicTypeWithLength xType{dyType.value()}; 1733 if (Expr<SomeCharacter> * charExpr{UnwrapExpr<Expr<SomeCharacter>>(*x)}) { 1734 CHECK(xType.category() == TypeCategory::Character); 1735 xType.length = 1736 common::visit([](const auto &kc) { return kc.LEN(); }, charExpr->u); 1737 } 1738 if (!type_) { 1739 // If there is no explicit type-spec in an array constructor, the type 1740 // of the array is the declared type of all of the elements, which must 1741 // be well-defined and all match. 1742 // TODO: Possible language extension: use the most general type of 1743 // the values as the type of a numeric constructed array, convert all 1744 // of the other values to that type. Alternative: let the first value 1745 // determine the type, and convert the others to that type. 1746 CHECK(!explicitType_); 1747 type_ = std::move(xType); 1748 constantLength_ = ToInt64(type_->length); 1749 values_.Push(std::move(*x)); 1750 } else if (!explicitType_) { 1751 if (type_->IsTkCompatibleWith(xType) && xType.IsTkCompatibleWith(*type_)) { 1752 values_.Push(std::move(*x)); 1753 auto xLen{xType.LEN()}; 1754 if (auto thisLen{ToInt64(xLen)}) { 1755 if (constantLength_) { 1756 if (*thisLen != *constantLength_ && !(messageDisplayedSet_ & 1)) { 1757 exprAnalyzer_.Warn( 1758 common::LanguageFeature::DistinctArrayConstructorLengths, 1759 "Character literal in array constructor without explicit " 1760 "type has different length than earlier elements"_port_en_US); 1761 messageDisplayedSet_ |= 1; 1762 } 1763 if (*thisLen > *constantLength_) { 1764 // Language extension: use the longest literal to determine the 1765 // length of the array constructor's character elements, not the 1766 // first, when there is no explicit type. 1767 *constantLength_ = *thisLen; 1768 type_->length = std::move(xLen); 1769 } 1770 } else { 1771 constantLength_ = *thisLen; 1772 type_->length = std::move(xLen); 1773 } 1774 } else if (xLen && NeedLength()) { 1775 type_->length = std::move(xLen); 1776 } 1777 } else { 1778 if (!(messageDisplayedSet_ & 2)) { 1779 exprAnalyzer_.Say( 1780 "Values in array constructor must have the same declared type " 1781 "when no explicit type appears"_err_en_US); // C7110 1782 messageDisplayedSet_ |= 2; 1783 } 1784 } 1785 } else { 1786 if (auto cast{ConvertToType(*type_, std::move(*x))}) { 1787 values_.Push(std::move(*cast)); 1788 } else if (!(messageDisplayedSet_ & 4)) { 1789 exprAnalyzer_.Say("Value in array constructor of type '%s' could not " 1790 "be converted to the type of the array '%s'"_err_en_US, 1791 x->GetType()->AsFortran(), type_->AsFortran()); // C7111, C7112 1792 messageDisplayedSet_ |= 4; 1793 } 1794 } 1795 } 1796 1797 void ArrayConstructorContext::Add(const parser::AcValue &x) { 1798 common::visit( 1799 common::visitors{ 1800 [&](const parser::AcValue::Triplet &triplet) { Add(triplet); }, 1801 [&](const common::Indirection<parser::Expr> &expr) { 1802 Add(expr.value()); 1803 }, 1804 [&](const common::Indirection<parser::AcImpliedDo> &impliedDo) { 1805 Add(impliedDo.value()); 1806 }, 1807 }, 1808 x.u); 1809 } 1810 1811 // Transforms l:u(:s) into (_,_=l,u(,s)) with an anonymous index '_' 1812 void ArrayConstructorContext::Add(const parser::AcValue::Triplet &triplet) { 1813 MaybeExpr lowerExpr{exprAnalyzer_.Analyze(std::get<0>(triplet.t))}; 1814 MaybeExpr upperExpr{exprAnalyzer_.Analyze(std::get<1>(triplet.t))}; 1815 MaybeExpr strideExpr{exprAnalyzer_.Analyze(std::get<2>(triplet.t))}; 1816 if (lowerExpr && upperExpr) { 1817 auto lowerType{lowerExpr->GetType()}; 1818 auto upperType{upperExpr->GetType()}; 1819 auto strideType{strideExpr ? strideExpr->GetType() : lowerType}; 1820 if (lowerType && upperType && strideType) { 1821 int kind{lowerType->kind()}; 1822 if (upperType->kind() > kind) { 1823 kind = upperType->kind(); 1824 } 1825 if (strideType->kind() > kind) { 1826 kind = strideType->kind(); 1827 } 1828 auto lower{ToSpecificInt<ImpliedDoIntType::kind>(std::move(lowerExpr))}; 1829 auto upper{ToSpecificInt<ImpliedDoIntType::kind>(std::move(upperExpr))}; 1830 if (lower && upper) { 1831 auto stride{ 1832 ToSpecificInt<ImpliedDoIntType::kind>(std::move(strideExpr))}; 1833 if (!stride) { 1834 stride = Expr<ImpliedDoIntType>{1}; 1835 } 1836 DynamicType type{TypeCategory::Integer, kind}; 1837 if (!type_) { 1838 type_ = DynamicTypeWithLength{type}; 1839 } 1840 parser::CharBlock anonymous; 1841 if (auto converted{ConvertToType(type, 1842 AsGenericExpr( 1843 Expr<ImpliedDoIntType>{ImpliedDoIndex{anonymous}}))}) { 1844 auto v{std::move(values_)}; 1845 Push(std::move(converted)); 1846 std::swap(v, values_); 1847 values_.Push(ImpliedDo<SomeType>{anonymous, std::move(*lower), 1848 std::move(*upper), std::move(*stride), std::move(v)}); 1849 } 1850 } 1851 } 1852 } 1853 } 1854 1855 void ArrayConstructorContext::Add(const parser::Expr &expr) { 1856 auto restorer{exprAnalyzer_.GetContextualMessages().SetLocation(expr.source)}; 1857 Push(exprAnalyzer_.Analyze(expr)); 1858 } 1859 1860 void ArrayConstructorContext::Add(const parser::AcImpliedDo &impliedDo) { 1861 const auto &control{std::get<parser::AcImpliedDoControl>(impliedDo.t)}; 1862 const auto &bounds{std::get<parser::AcImpliedDoControl::Bounds>(control.t)}; 1863 exprAnalyzer_.Analyze(bounds.name); 1864 parser::CharBlock name{bounds.name.thing.thing.source}; 1865 int kind{ImpliedDoIntType::kind}; 1866 if (const Symbol * symbol{bounds.name.thing.thing.symbol}) { 1867 if (auto dynamicType{DynamicType::From(symbol)}) { 1868 if (dynamicType->category() == TypeCategory::Integer) { 1869 kind = dynamicType->kind(); 1870 } 1871 } 1872 } 1873 std::optional<Expr<ImpliedDoIntType>> lower{ 1874 GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.lower)}; 1875 std::optional<Expr<ImpliedDoIntType>> upper{ 1876 GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.upper)}; 1877 if (lower && upper) { 1878 std::optional<Expr<ImpliedDoIntType>> stride{ 1879 GetSpecificIntExpr<ImpliedDoIntType::kind>(bounds.step)}; 1880 if (!stride) { 1881 stride = Expr<ImpliedDoIntType>{1}; 1882 } 1883 if (exprAnalyzer_.AddImpliedDo(name, kind)) { 1884 // Check for constant bounds; the loop may require complete unrolling 1885 // of the parse tree if all bounds are constant in order to allow the 1886 // implied DO loop index to qualify as a constant expression. 1887 auto cLower{ToInt64(lower)}; 1888 auto cUpper{ToInt64(upper)}; 1889 auto cStride{ToInt64(stride)}; 1890 if (!(messageDisplayedSet_ & 0x10) && cStride && *cStride == 0) { 1891 exprAnalyzer_.SayAt(bounds.step.value().thing.thing.value().source, 1892 "The stride of an implied DO loop must not be zero"_err_en_US); 1893 messageDisplayedSet_ |= 0x10; 1894 } 1895 bool isConstant{cLower && cUpper && cStride && *cStride != 0}; 1896 bool isNonemptyConstant{isConstant && 1897 ((*cStride > 0 && *cLower <= *cUpper) || 1898 (*cStride < 0 && *cLower >= *cUpper))}; 1899 bool isEmpty{isConstant && !isNonemptyConstant}; 1900 bool unrollConstantLoop{false}; 1901 parser::Messages buffer; 1902 auto saveMessagesDisplayed{messageDisplayedSet_}; 1903 { 1904 auto messageRestorer{ 1905 exprAnalyzer_.GetContextualMessages().SetMessages(buffer)}; 1906 auto v{std::move(values_)}; 1907 for (const auto &value : 1908 std::get<std::list<parser::AcValue>>(impliedDo.t)) { 1909 Add(value); 1910 } 1911 std::swap(v, values_); 1912 if (isNonemptyConstant && buffer.AnyFatalError()) { 1913 unrollConstantLoop = true; 1914 } else { 1915 values_.Push(ImpliedDo<SomeType>{name, std::move(*lower), 1916 std::move(*upper), std::move(*stride), std::move(v)}); 1917 } 1918 } 1919 // F'2023 7.8 p5 1920 if (!(messageDisplayedSet_ & 0x100) && isEmpty && NeedLength()) { 1921 exprAnalyzer_.SayAt(name, 1922 "Array constructor implied DO loop has no iterations and indeterminate character length"_err_en_US); 1923 messageDisplayedSet_ |= 0x100; 1924 } 1925 if (unrollConstantLoop) { 1926 messageDisplayedSet_ = saveMessagesDisplayed; 1927 UnrollConstantImpliedDo(impliedDo, name, *cLower, *cUpper, *cStride); 1928 } else if (auto *messages{ 1929 exprAnalyzer_.GetContextualMessages().messages()}) { 1930 messages->Annex(std::move(buffer)); 1931 } 1932 exprAnalyzer_.RemoveImpliedDo(name); 1933 } else if (!(messageDisplayedSet_ & 0x20)) { 1934 exprAnalyzer_.SayAt(name, 1935 "Implied DO index '%s' is active in a surrounding implied DO loop " 1936 "and may not have the same name"_err_en_US, 1937 name); // C7115 1938 messageDisplayedSet_ |= 0x20; 1939 } 1940 } 1941 } 1942 1943 // Fortran considers an implied DO index of an array constructor to be 1944 // a constant expression if the bounds of the implied DO loop are constant. 1945 // Usually this doesn't matter, but if we emitted spurious messages as a 1946 // result of not using constant values for the index while analyzing the 1947 // items, we need to do it again the "hard" way with multiple iterations over 1948 // the parse tree. 1949 void ArrayConstructorContext::UnrollConstantImpliedDo( 1950 const parser::AcImpliedDo &impliedDo, parser::CharBlock name, 1951 std::int64_t lower, std::int64_t upper, std::int64_t stride) { 1952 auto &foldingContext{exprAnalyzer_.GetFoldingContext()}; 1953 auto restorer{exprAnalyzer_.DoNotUseSavedTypedExprs()}; 1954 for (auto &at{foldingContext.StartImpliedDo(name, lower)}; 1955 (stride > 0 && at <= upper) || (stride < 0 && at >= upper); 1956 at += stride) { 1957 for (const auto &value : 1958 std::get<std::list<parser::AcValue>>(impliedDo.t)) { 1959 Add(value); 1960 } 1961 } 1962 foldingContext.EndImpliedDo(name); 1963 } 1964 1965 MaybeExpr ArrayConstructorContext::ToExpr() { 1966 return common::SearchTypes(std::move(*this)); 1967 } 1968 1969 MaybeExpr ExpressionAnalyzer::Analyze(const parser::ArrayConstructor &array) { 1970 const parser::AcSpec &acSpec{array.v}; 1971 ArrayConstructorContext acContext{ 1972 *this, AnalyzeTypeSpec(acSpec.type, GetFoldingContext())}; 1973 for (const parser::AcValue &value : acSpec.values) { 1974 acContext.Add(value); 1975 } 1976 return acContext.ToExpr(); 1977 } 1978 1979 // Check if implicit conversion of expr to the symbol type is legal (if needed), 1980 // and make it explicit if requested. 1981 static MaybeExpr ImplicitConvertTo(const semantics::Symbol &sym, 1982 Expr<SomeType> &&expr, bool keepConvertImplicit) { 1983 if (!keepConvertImplicit) { 1984 return ConvertToType(sym, std::move(expr)); 1985 } else { 1986 // Test if a convert could be inserted, but do not make it explicit to 1987 // preserve the information that expr is a variable. 1988 if (ConvertToType(sym, common::Clone(expr))) { 1989 return MaybeExpr{std::move(expr)}; 1990 } 1991 } 1992 // Illegal implicit convert. 1993 return std::nullopt; 1994 } 1995 1996 MaybeExpr ExpressionAnalyzer::Analyze( 1997 const parser::StructureConstructor &structure) { 1998 auto &parsedType{std::get<parser::DerivedTypeSpec>(structure.t)}; 1999 parser::Name structureType{std::get<parser::Name>(parsedType.t)}; 2000 parser::CharBlock &typeName{structureType.source}; 2001 if (semantics::Symbol *typeSymbol{structureType.symbol}) { 2002 if (typeSymbol->has<semantics::DerivedTypeDetails>()) { 2003 semantics::DerivedTypeSpec dtSpec{typeName, typeSymbol->GetUltimate()}; 2004 if (!CheckIsValidForwardReference(dtSpec)) { 2005 return std::nullopt; 2006 } 2007 } 2008 } 2009 if (!parsedType.derivedTypeSpec) { 2010 return std::nullopt; 2011 } 2012 const auto &spec{*parsedType.derivedTypeSpec}; 2013 const Symbol &typeSymbol{spec.typeSymbol()}; 2014 if (!spec.scope() || !typeSymbol.has<semantics::DerivedTypeDetails>()) { 2015 return std::nullopt; // error recovery 2016 } 2017 const semantics::Scope &scope{context_.FindScope(typeName)}; 2018 const semantics::Scope *pureContext{FindPureProcedureContaining(scope)}; 2019 const auto &typeDetails{typeSymbol.get<semantics::DerivedTypeDetails>()}; 2020 const Symbol *parentComponent{typeDetails.GetParentComponent(*spec.scope())}; 2021 2022 if (typeSymbol.attrs().test(semantics::Attr::ABSTRACT)) { // C796 2023 AttachDeclaration(Say(typeName, 2024 "ABSTRACT derived type '%s' may not be used in a " 2025 "structure constructor"_err_en_US, 2026 typeName), 2027 typeSymbol); // C7114 2028 } 2029 2030 // This iterator traverses all of the components in the derived type and its 2031 // parents. The symbols for whole parent components appear after their 2032 // own components and before the components of the types that extend them. 2033 // E.g., TYPE :: A; REAL X; END TYPE 2034 // TYPE, EXTENDS(A) :: B; REAL Y; END TYPE 2035 // produces the component list X, A, Y. 2036 // The order is important below because a structure constructor can 2037 // initialize X or A by name, but not both. 2038 auto components{semantics::OrderedComponentIterator{spec}}; 2039 auto nextAnonymous{components.begin()}; 2040 auto afterLastParentComponentIter{components.end()}; 2041 if (parentComponent) { 2042 for (auto iter{components.begin()}; iter != components.end(); ++iter) { 2043 if (iter->test(Symbol::Flag::ParentComp)) { 2044 afterLastParentComponentIter = iter; 2045 ++afterLastParentComponentIter; 2046 } 2047 } 2048 } 2049 2050 std::set<parser::CharBlock> unavailable; 2051 bool anyKeyword{false}; 2052 StructureConstructor result{spec}; 2053 bool checkConflicts{true}; // until we hit one 2054 auto &messages{GetContextualMessages()}; 2055 2056 // NULL() can be a valid component 2057 auto restorer{AllowNullPointer()}; 2058 2059 for (const auto &component : 2060 std::get<std::list<parser::ComponentSpec>>(structure.t)) { 2061 const parser::Expr &expr{ 2062 std::get<parser::ComponentDataSource>(component.t).v.value()}; 2063 parser::CharBlock source{expr.source}; 2064 auto restorer{messages.SetLocation(source)}; 2065 const Symbol *symbol{nullptr}; 2066 MaybeExpr value{Analyze(expr)}; 2067 std::optional<DynamicType> valueType{DynamicType::From(value)}; 2068 if (const auto &kw{std::get<std::optional<parser::Keyword>>(component.t)}) { 2069 anyKeyword = true; 2070 source = kw->v.source; 2071 symbol = kw->v.symbol; 2072 if (!symbol) { 2073 // Skip overridden inaccessible parent components in favor of 2074 // their later overrides. 2075 for (const Symbol &sym : components) { 2076 if (sym.name() == source) { 2077 symbol = &sym; 2078 } 2079 } 2080 } 2081 if (!symbol) { // C7101 2082 Say(source, 2083 "Keyword '%s=' does not name a component of derived type '%s'"_err_en_US, 2084 source, typeName); 2085 } 2086 } else { 2087 if (anyKeyword) { // C7100 2088 Say(source, 2089 "Value in structure constructor lacks a component name"_err_en_US); 2090 checkConflicts = false; // stem cascade 2091 } 2092 // Here's a regrettably common extension of the standard: anonymous 2093 // initialization of parent components, e.g., T(PT(1)) rather than 2094 // T(1) or T(PT=PT(1)). There may be multiple parent components. 2095 if (nextAnonymous == components.begin() && parentComponent && valueType && 2096 context().IsEnabled(LanguageFeature::AnonymousParents)) { 2097 for (auto parent{components.begin()}; 2098 parent != afterLastParentComponentIter; ++parent) { 2099 if (auto parentType{DynamicType::From(*parent)}; parentType && 2100 parent->test(Symbol::Flag::ParentComp) && 2101 valueType->IsEquivalentTo(*parentType)) { 2102 symbol = &*parent; 2103 nextAnonymous = ++parent; 2104 Warn(LanguageFeature::AnonymousParents, source, 2105 "Whole parent component '%s' in structure constructor should not be anonymous"_port_en_US, 2106 symbol->name()); 2107 break; 2108 } 2109 } 2110 } 2111 while (!symbol && nextAnonymous != components.end()) { 2112 const Symbol &next{*nextAnonymous}; 2113 ++nextAnonymous; 2114 if (!next.test(Symbol::Flag::ParentComp)) { 2115 symbol = &next; 2116 } 2117 } 2118 if (!symbol) { 2119 Say(source, "Unexpected value in structure constructor"_err_en_US); 2120 } 2121 } 2122 if (symbol) { 2123 const semantics::Scope &innermost{context_.FindScope(expr.source)}; 2124 if (auto msg{CheckAccessibleSymbol(innermost, *symbol)}) { 2125 Say(expr.source, std::move(*msg)); 2126 } 2127 if (checkConflicts) { 2128 auto componentIter{ 2129 std::find(components.begin(), components.end(), *symbol)}; 2130 if (unavailable.find(symbol->name()) != unavailable.cend()) { 2131 // C797, C798 2132 Say(source, 2133 "Component '%s' conflicts with another component earlier in " 2134 "this structure constructor"_err_en_US, 2135 symbol->name()); 2136 } else if (symbol->test(Symbol::Flag::ParentComp)) { 2137 // Make earlier components unavailable once a whole parent appears. 2138 for (auto it{components.begin()}; it != componentIter; ++it) { 2139 unavailable.insert(it->name()); 2140 } 2141 } else { 2142 // Make whole parent components unavailable after any of their 2143 // constituents appear. 2144 for (auto it{componentIter}; it != components.end(); ++it) { 2145 if (it->test(Symbol::Flag::ParentComp)) { 2146 unavailable.insert(it->name()); 2147 } 2148 } 2149 } 2150 } 2151 unavailable.insert(symbol->name()); 2152 if (value) { 2153 if (symbol->has<semantics::TypeParamDetails>()) { 2154 Say(expr.source, 2155 "Type parameter '%s' may not appear as a component of a structure constructor"_err_en_US, 2156 symbol->name()); 2157 } 2158 if (!(symbol->has<semantics::ProcEntityDetails>() || 2159 symbol->has<semantics::ObjectEntityDetails>())) { 2160 continue; // recovery 2161 } 2162 if (IsPointer(*symbol)) { // C7104, C7105, C1594(4) 2163 semantics::CheckStructConstructorPointerComponent( 2164 context_, *symbol, *value, innermost); 2165 result.Add(*symbol, Fold(std::move(*value))); 2166 continue; 2167 } 2168 if (IsNullPointer(*value)) { 2169 if (IsAllocatable(*symbol)) { 2170 if (IsBareNullPointer(&*value)) { 2171 // NULL() with no arguments allowed by 7.5.10 para 6 for 2172 // ALLOCATABLE. 2173 result.Add(*symbol, Expr<SomeType>{NullPointer{}}); 2174 continue; 2175 } 2176 if (IsNullObjectPointer(*value)) { 2177 AttachDeclaration( 2178 Warn(common::LanguageFeature:: 2179 NullMoldAllocatableComponentValue, 2180 expr.source, 2181 "NULL() with arguments is not standard conforming as the value for allocatable component '%s'"_port_en_US, 2182 symbol->name()), 2183 *symbol); 2184 // proceed to check type & shape 2185 } else { 2186 AttachDeclaration( 2187 Say(expr.source, 2188 "A NULL procedure pointer may not be used as the value for component '%s'"_err_en_US, 2189 symbol->name()), 2190 *symbol); 2191 continue; 2192 } 2193 } else { 2194 AttachDeclaration( 2195 Say(expr.source, 2196 "A NULL pointer may not be used as the value for component '%s'"_err_en_US, 2197 symbol->name()), 2198 *symbol); 2199 continue; 2200 } 2201 } else if (const Symbol * pointer{FindPointerComponent(*symbol)}; 2202 pointer && pureContext) { // C1594(4) 2203 if (const Symbol * 2204 visible{semantics::FindExternallyVisibleObject( 2205 *value, *pureContext)}) { 2206 Say(expr.source, 2207 "The externally visible object '%s' may not be used in a pure procedure as the value for component '%s' which has the pointer component '%s'"_err_en_US, 2208 visible->name(), symbol->name(), pointer->name()); 2209 } 2210 } 2211 // Make implicit conversion explicit to allow folding of the structure 2212 // constructors and help semantic checking, unless the component is 2213 // allocatable, in which case the value could be an unallocated 2214 // allocatable (see Fortran 2018 7.5.10 point 7). The explicit 2215 // convert would cause a segfault. Lowering will deal with 2216 // conditionally converting and preserving the lower bounds in this 2217 // case. 2218 if (MaybeExpr converted{ImplicitConvertTo( 2219 *symbol, std::move(*value), IsAllocatable(*symbol))}) { 2220 if (auto componentShape{GetShape(GetFoldingContext(), *symbol)}) { 2221 if (auto valueShape{GetShape(GetFoldingContext(), *converted)}) { 2222 if (GetRank(*componentShape) == 0 && GetRank(*valueShape) > 0) { 2223 AttachDeclaration( 2224 Say(expr.source, 2225 "Rank-%d array value is not compatible with scalar component '%s'"_err_en_US, 2226 GetRank(*valueShape), symbol->name()), 2227 *symbol); 2228 } else { 2229 auto checked{ 2230 CheckConformance(messages, *componentShape, *valueShape, 2231 CheckConformanceFlags::RightIsExpandableDeferred, 2232 "component", "value")}; 2233 if (checked && *checked && GetRank(*componentShape) > 0 && 2234 GetRank(*valueShape) == 0 && 2235 (IsDeferredShape(*symbol) || 2236 !IsExpandableScalar(*converted, GetFoldingContext(), 2237 *componentShape, true /*admit PURE call*/))) { 2238 AttachDeclaration( 2239 Say(expr.source, 2240 "Scalar value cannot be expanded to shape of array component '%s'"_err_en_US, 2241 symbol->name()), 2242 *symbol); 2243 } 2244 if (checked.value_or(true)) { 2245 result.Add(*symbol, std::move(*converted)); 2246 } 2247 } 2248 } else { 2249 Say(expr.source, "Shape of value cannot be determined"_err_en_US); 2250 } 2251 } else { 2252 AttachDeclaration( 2253 Say(expr.source, 2254 "Shape of component '%s' cannot be determined"_err_en_US, 2255 symbol->name()), 2256 *symbol); 2257 } 2258 } else if (auto symType{DynamicType::From(symbol)}) { 2259 if (IsAllocatable(*symbol) && symType->IsUnlimitedPolymorphic() && 2260 valueType) { 2261 // ok 2262 } else if (valueType) { 2263 AttachDeclaration( 2264 Say(expr.source, 2265 "Value in structure constructor of type '%s' is " 2266 "incompatible with component '%s' of type '%s'"_err_en_US, 2267 valueType->AsFortran(), symbol->name(), 2268 symType->AsFortran()), 2269 *symbol); 2270 } else { 2271 AttachDeclaration( 2272 Say(expr.source, 2273 "Value in structure constructor is incompatible with " 2274 "component '%s' of type %s"_err_en_US, 2275 symbol->name(), symType->AsFortran()), 2276 *symbol); 2277 } 2278 } 2279 } 2280 } 2281 } 2282 2283 // Ensure that unmentioned component objects have default initializers. 2284 for (const Symbol &symbol : components) { 2285 if (!symbol.test(Symbol::Flag::ParentComp) && 2286 unavailable.find(symbol.name()) == unavailable.cend()) { 2287 if (IsAllocatable(symbol)) { 2288 // Set all remaining allocatables to explicit NULL(). 2289 result.Add(symbol, Expr<SomeType>{NullPointer{}}); 2290 } else { 2291 const auto *object{symbol.detailsIf<semantics::ObjectEntityDetails>()}; 2292 if (object && object->init()) { 2293 result.Add(symbol, common::Clone(*object->init())); 2294 } else if (IsPointer(symbol)) { 2295 result.Add(symbol, Expr<SomeType>{NullPointer{}}); 2296 } else if (object) { // C799 2297 AttachDeclaration(Say(typeName, 2298 "Structure constructor lacks a value for " 2299 "component '%s'"_err_en_US, 2300 symbol.name()), 2301 symbol); 2302 } 2303 } 2304 } 2305 } 2306 2307 return AsMaybeExpr(Expr<SomeDerived>{std::move(result)}); 2308 } 2309 2310 static std::optional<parser::CharBlock> GetPassName( 2311 const semantics::Symbol &proc) { 2312 return common::visit( 2313 [](const auto &details) { 2314 if constexpr (std::is_base_of_v<semantics::WithPassArg, 2315 std::decay_t<decltype(details)>>) { 2316 return details.passName(); 2317 } else { 2318 return std::optional<parser::CharBlock>{}; 2319 } 2320 }, 2321 proc.details()); 2322 } 2323 2324 static std::optional<int> GetPassIndex(const Symbol &proc) { 2325 CHECK(!proc.attrs().test(semantics::Attr::NOPASS)); 2326 std::optional<parser::CharBlock> passName{GetPassName(proc)}; 2327 const auto *interface { 2328 semantics::FindInterface(proc) 2329 }; 2330 if (!passName || !interface) { 2331 return 0; // first argument is passed-object 2332 } 2333 const auto &subp{interface->get<semantics::SubprogramDetails>()}; 2334 int index{0}; 2335 for (const auto *arg : subp.dummyArgs()) { 2336 if (arg && arg->name() == passName) { 2337 return index; 2338 } 2339 ++index; 2340 } 2341 return std::nullopt; 2342 } 2343 2344 // Injects an expression into an actual argument list as the "passed object" 2345 // for a type-bound procedure reference that is not NOPASS. Adds an 2346 // argument keyword if possible, but not when the passed object goes 2347 // before a positional argument. 2348 // e.g., obj%tbp(x) -> tbp(obj,x). 2349 static void AddPassArg(ActualArguments &actuals, const Expr<SomeDerived> &expr, 2350 const Symbol &component, bool isPassedObject = true) { 2351 if (component.attrs().test(semantics::Attr::NOPASS)) { 2352 return; 2353 } 2354 std::optional<int> passIndex{GetPassIndex(component)}; 2355 if (!passIndex) { 2356 return; // error recovery 2357 } 2358 auto iter{actuals.begin()}; 2359 int at{0}; 2360 while (iter < actuals.end() && at < *passIndex) { 2361 if (*iter && (*iter)->keyword()) { 2362 iter = actuals.end(); 2363 break; 2364 } 2365 ++iter; 2366 ++at; 2367 } 2368 ActualArgument passed{AsGenericExpr(common::Clone(expr))}; 2369 passed.set_isPassedObject(isPassedObject); 2370 if (iter == actuals.end()) { 2371 if (auto passName{GetPassName(component)}) { 2372 passed.set_keyword(*passName); 2373 } 2374 } 2375 actuals.emplace(iter, std::move(passed)); 2376 } 2377 2378 // Return the compile-time resolution of a procedure binding, if possible. 2379 static const Symbol *GetBindingResolution( 2380 const std::optional<DynamicType> &baseType, const Symbol &component) { 2381 const auto *binding{component.detailsIf<semantics::ProcBindingDetails>()}; 2382 if (!binding) { 2383 return nullptr; 2384 } 2385 if (!component.attrs().test(semantics::Attr::NON_OVERRIDABLE) && 2386 (!baseType || baseType->IsPolymorphic())) { 2387 return nullptr; 2388 } 2389 return &binding->symbol(); 2390 } 2391 2392 auto ExpressionAnalyzer::AnalyzeProcedureComponentRef( 2393 const parser::ProcComponentRef &pcr, ActualArguments &&arguments, 2394 bool isSubroutine) -> std::optional<CalleeAndArguments> { 2395 const parser::StructureComponent &sc{pcr.v.thing}; 2396 if (MaybeExpr base{Analyze(sc.base)}) { 2397 if (const Symbol *sym{sc.component.symbol}) { 2398 if (context_.HasError(sym)) { 2399 return std::nullopt; 2400 } 2401 if (!IsProcedure(*sym)) { 2402 AttachDeclaration( 2403 Say(sc.component.source, "'%s' is not a procedure"_err_en_US, 2404 sc.component.source), 2405 *sym); 2406 return std::nullopt; 2407 } 2408 if (auto *dtExpr{UnwrapExpr<Expr<SomeDerived>>(*base)}) { 2409 if (sym->has<semantics::GenericDetails>()) { 2410 const Symbol &generic{*sym}; 2411 auto dyType{dtExpr->GetType()}; 2412 AdjustActuals adjustment{ 2413 [&](const Symbol &proc, ActualArguments &actuals) { 2414 if (!proc.attrs().test(semantics::Attr::NOPASS)) { 2415 AddPassArg(actuals, std::move(*dtExpr), proc); 2416 } 2417 return true; 2418 }}; 2419 auto pair{ 2420 ResolveGeneric(generic, arguments, adjustment, isSubroutine)}; 2421 sym = pair.first; 2422 if (!sym) { 2423 EmitGenericResolutionError(generic, pair.second, isSubroutine); 2424 return std::nullopt; 2425 } 2426 // re-resolve the name to the specific binding 2427 CHECK(sym->has<semantics::ProcBindingDetails>()); 2428 // Use the most recent override of a binding, respecting 2429 // the rule that inaccessible bindings may not be overridden 2430 // outside their module. Fortran doesn't allow a PUBLIC 2431 // binding to be overridden by a PRIVATE one. 2432 CHECK(dyType && dyType->category() == TypeCategory::Derived && 2433 !dyType->IsUnlimitedPolymorphic()); 2434 if (const Symbol * 2435 latest{DEREF(dyType->GetDerivedTypeSpec().typeSymbol().scope()) 2436 .FindComponent(sym->name())}) { 2437 if (sym->attrs().test(semantics::Attr::PRIVATE)) { 2438 const auto *bindingModule{FindModuleContaining(generic.owner())}; 2439 const Symbol *s{latest}; 2440 while (s && FindModuleContaining(s->owner()) != bindingModule) { 2441 if (const auto *parent{s->owner().GetDerivedTypeParent()}) { 2442 s = parent->FindComponent(sym->name()); 2443 } else { 2444 s = nullptr; 2445 } 2446 } 2447 if (s && !s->attrs().test(semantics::Attr::PRIVATE)) { 2448 // The latest override in the same module as the binding 2449 // is public, so it can be overridden. 2450 } else { 2451 latest = s; 2452 } 2453 } 2454 if (latest) { 2455 sym = latest; 2456 } 2457 } 2458 sc.component.symbol = const_cast<Symbol *>(sym); 2459 } 2460 std::optional<DataRef> dataRef{ExtractDataRef(std::move(*dtExpr))}; 2461 if (dataRef && !CheckDataRef(*dataRef)) { 2462 return std::nullopt; 2463 } 2464 if (dataRef && dataRef->Rank() > 0) { 2465 if (sym->has<semantics::ProcBindingDetails>() && 2466 sym->attrs().test(semantics::Attr::NOPASS)) { 2467 // F'2023 C1529 seems unnecessary and most compilers don't 2468 // enforce it. 2469 AttachDeclaration( 2470 Warn(common::LanguageFeature::NopassScalarBase, 2471 sc.component.source, 2472 "Base of NOPASS type-bound procedure reference should be scalar"_port_en_US), 2473 *sym); 2474 } else if (IsProcedurePointer(*sym)) { // C919 2475 Say(sc.component.source, 2476 "Base of procedure component reference must be scalar"_err_en_US); 2477 } 2478 } 2479 if (const Symbol *resolution{ 2480 GetBindingResolution(dtExpr->GetType(), *sym)}) { 2481 AddPassArg(arguments, std::move(*dtExpr), *sym, false); 2482 return CalleeAndArguments{ 2483 ProcedureDesignator{*resolution}, std::move(arguments)}; 2484 } else if (dataRef.has_value()) { 2485 if (sym->attrs().test(semantics::Attr::NOPASS)) { 2486 const auto *dtSpec{GetDerivedTypeSpec(dtExpr->GetType())}; 2487 if (dtSpec && dtSpec->scope()) { 2488 if (auto component{CreateComponent(std::move(*dataRef), *sym, 2489 *dtSpec->scope(), /*C919bAlreadyEnforced=*/true)}) { 2490 return CalleeAndArguments{ 2491 ProcedureDesignator{std::move(*component)}, 2492 std::move(arguments)}; 2493 } 2494 } 2495 Say(sc.component.source, 2496 "Component is not in scope of base derived type"_err_en_US); 2497 return std::nullopt; 2498 } else { 2499 AddPassArg(arguments, 2500 Expr<SomeDerived>{Designator<SomeDerived>{std::move(*dataRef)}}, 2501 *sym); 2502 return CalleeAndArguments{ 2503 ProcedureDesignator{*sym}, std::move(arguments)}; 2504 } 2505 } 2506 } 2507 Say(sc.component.source, 2508 "Base of procedure component reference is not a derived-type object"_err_en_US); 2509 } 2510 } 2511 CHECK(context_.AnyFatalError()); 2512 return std::nullopt; 2513 } 2514 2515 // Can actual be argument associated with dummy? 2516 static bool CheckCompatibleArgument(bool isElemental, 2517 const ActualArgument &actual, const characteristics::DummyArgument &dummy, 2518 FoldingContext &foldingContext) { 2519 const auto *expr{actual.UnwrapExpr()}; 2520 return common::visit( 2521 common::visitors{ 2522 [&](const characteristics::DummyDataObject &x) { 2523 if (x.attrs.test(characteristics::DummyDataObject::Attr::Pointer) && 2524 IsBareNullPointer(expr)) { 2525 // NULL() without MOLD= is compatible with any dummy data pointer 2526 // but cannot be allowed to lead to ambiguity. 2527 return true; 2528 } else if (!isElemental && actual.Rank() != x.type.Rank() && 2529 !x.type.attrs().test( 2530 characteristics::TypeAndShape::Attr::AssumedRank) && 2531 !x.ignoreTKR.test(common::IgnoreTKR::Rank)) { 2532 return false; 2533 } else if (auto actualType{actual.GetType()}) { 2534 return x.type.type().IsTkCompatibleWith(*actualType, x.ignoreTKR); 2535 } 2536 return false; 2537 }, 2538 [&](const characteristics::DummyProcedure &dummy) { 2539 if ((dummy.attrs.test( 2540 characteristics::DummyProcedure::Attr::Optional) || 2541 dummy.attrs.test( 2542 characteristics::DummyProcedure::Attr::Pointer)) && 2543 IsBareNullPointer(expr)) { 2544 // NULL() is compatible with any dummy pointer 2545 // or optional dummy procedure. 2546 return true; 2547 } 2548 if (!expr || !IsProcedurePointerTarget(*expr)) { 2549 return false; 2550 } 2551 if (auto actualProc{characteristics::Procedure::Characterize( 2552 *expr, foldingContext)}) { 2553 const auto &dummyResult{dummy.procedure.value().functionResult}; 2554 const auto *dummyTypeAndShape{ 2555 dummyResult ? dummyResult->GetTypeAndShape() : nullptr}; 2556 const auto &actualResult{actualProc->functionResult}; 2557 const auto *actualTypeAndShape{ 2558 actualResult ? actualResult->GetTypeAndShape() : nullptr}; 2559 if (dummyTypeAndShape && actualTypeAndShape) { 2560 // Return false when the function results' types are both 2561 // known and not compatible. 2562 return actualTypeAndShape->type().IsTkCompatibleWith( 2563 dummyTypeAndShape->type()); 2564 } 2565 } 2566 return true; 2567 }, 2568 [&](const characteristics::AlternateReturn &) { 2569 return actual.isAlternateReturn(); 2570 }, 2571 }, 2572 dummy.u); 2573 } 2574 2575 // Are the actual arguments compatible with the dummy arguments of procedure? 2576 static bool CheckCompatibleArguments( 2577 const characteristics::Procedure &procedure, const ActualArguments &actuals, 2578 FoldingContext &foldingContext) { 2579 bool isElemental{procedure.IsElemental()}; 2580 const auto &dummies{procedure.dummyArguments}; 2581 CHECK(dummies.size() == actuals.size()); 2582 for (std::size_t i{0}; i < dummies.size(); ++i) { 2583 const characteristics::DummyArgument &dummy{dummies[i]}; 2584 const std::optional<ActualArgument> &actual{actuals[i]}; 2585 if (actual && 2586 !CheckCompatibleArgument(isElemental, *actual, dummy, foldingContext)) { 2587 return false; 2588 } 2589 } 2590 return true; 2591 } 2592 2593 static constexpr int cudaInfMatchingValue{std::numeric_limits<int>::max()}; 2594 2595 // Compute the matching distance as described in section 3.2.3 of the CUDA 2596 // Fortran references. 2597 static int GetMatchingDistance(const common::LanguageFeatureControl &features, 2598 const characteristics::DummyArgument &dummy, 2599 const std::optional<ActualArgument> &actual) { 2600 bool isCudaManaged{features.IsEnabled(common::LanguageFeature::CudaManaged)}; 2601 bool isCudaUnified{features.IsEnabled(common::LanguageFeature::CudaUnified)}; 2602 CHECK(!(isCudaUnified && isCudaManaged) && "expect only one enabled."); 2603 2604 std::optional<common::CUDADataAttr> actualDataAttr, dummyDataAttr; 2605 if (actual) { 2606 if (auto *expr{actual->UnwrapExpr()}) { 2607 const auto *actualLastSymbol{evaluate::GetLastSymbol(*expr)}; 2608 if (actualLastSymbol) { 2609 actualLastSymbol = &semantics::ResolveAssociations(*actualLastSymbol); 2610 if (const auto *actualObject{actualLastSymbol 2611 ? actualLastSymbol 2612 ->detailsIf<semantics::ObjectEntityDetails>() 2613 : nullptr}) { 2614 actualDataAttr = actualObject->cudaDataAttr(); 2615 } 2616 } 2617 } 2618 } 2619 2620 common::visit(common::visitors{ 2621 [&](const characteristics::DummyDataObject &object) { 2622 dummyDataAttr = object.cudaDataAttr; 2623 }, 2624 [&](const auto &) {}, 2625 }, 2626 dummy.u); 2627 2628 if (!dummyDataAttr) { 2629 if (!actualDataAttr) { 2630 if (isCudaUnified || isCudaManaged) { 2631 return 3; 2632 } 2633 return 0; 2634 } else if (*actualDataAttr == common::CUDADataAttr::Device) { 2635 return cudaInfMatchingValue; 2636 } else if (*actualDataAttr == common::CUDADataAttr::Managed || 2637 *actualDataAttr == common::CUDADataAttr::Unified) { 2638 return 3; 2639 } 2640 } else if (*dummyDataAttr == common::CUDADataAttr::Device) { 2641 if (!actualDataAttr) { 2642 if (isCudaUnified || isCudaManaged) { 2643 return 2; 2644 } 2645 return cudaInfMatchingValue; 2646 } else if (*actualDataAttr == common::CUDADataAttr::Device) { 2647 return 0; 2648 } else if (*actualDataAttr == common::CUDADataAttr::Managed || 2649 *actualDataAttr == common::CUDADataAttr::Unified) { 2650 return 2; 2651 } 2652 } else if (*dummyDataAttr == common::CUDADataAttr::Managed) { 2653 if (!actualDataAttr) { 2654 return isCudaUnified ? 1 : isCudaManaged ? 0 : cudaInfMatchingValue; 2655 } 2656 if (*actualDataAttr == common::CUDADataAttr::Device) { 2657 return cudaInfMatchingValue; 2658 } else if (*actualDataAttr == common::CUDADataAttr::Managed) { 2659 return 0; 2660 } else if (*actualDataAttr == common::CUDADataAttr::Unified) { 2661 return 1; 2662 } 2663 } else if (*dummyDataAttr == common::CUDADataAttr::Unified) { 2664 if (!actualDataAttr) { 2665 return isCudaUnified ? 0 : isCudaManaged ? 1 : cudaInfMatchingValue; 2666 } 2667 if (*actualDataAttr == common::CUDADataAttr::Device) { 2668 return cudaInfMatchingValue; 2669 } else if (*actualDataAttr == common::CUDADataAttr::Managed) { 2670 return 1; 2671 } else if (*actualDataAttr == common::CUDADataAttr::Unified) { 2672 return 0; 2673 } 2674 } 2675 return cudaInfMatchingValue; 2676 } 2677 2678 static int ComputeCudaMatchingDistance( 2679 const common::LanguageFeatureControl &features, 2680 const characteristics::Procedure &procedure, 2681 const ActualArguments &actuals) { 2682 const auto &dummies{procedure.dummyArguments}; 2683 CHECK(dummies.size() == actuals.size()); 2684 int distance{0}; 2685 for (std::size_t i{0}; i < dummies.size(); ++i) { 2686 const characteristics::DummyArgument &dummy{dummies[i]}; 2687 const std::optional<ActualArgument> &actual{actuals[i]}; 2688 int d{GetMatchingDistance(features, dummy, actual)}; 2689 if (d == cudaInfMatchingValue) 2690 return d; 2691 distance += d; 2692 } 2693 return distance; 2694 } 2695 2696 // Handles a forward reference to a module function from what must 2697 // be a specification expression. Return false if the symbol is 2698 // an invalid forward reference. 2699 const Symbol *ExpressionAnalyzer::ResolveForward(const Symbol &symbol) { 2700 if (context_.HasError(symbol)) { 2701 return nullptr; 2702 } 2703 if (const auto *details{ 2704 symbol.detailsIf<semantics::SubprogramNameDetails>()}) { 2705 if (details->kind() == semantics::SubprogramKind::Module) { 2706 // If this symbol is still a SubprogramNameDetails, we must be 2707 // checking a specification expression in a sibling module 2708 // procedure. Resolve its names now so that its interface 2709 // is known. 2710 const semantics::Scope &scope{symbol.owner()}; 2711 semantics::ResolveSpecificationParts(context_, symbol); 2712 const Symbol *resolved{nullptr}; 2713 if (auto iter{scope.find(symbol.name())}; iter != scope.cend()) { 2714 resolved = &*iter->second; 2715 } 2716 if (!resolved || resolved->has<semantics::SubprogramNameDetails>()) { 2717 // When the symbol hasn't had its details updated, we must have 2718 // already been in the process of resolving the function's 2719 // specification part; but recursive function calls are not 2720 // allowed in specification parts (10.1.11 para 5). 2721 Say("The module function '%s' may not be referenced recursively in a specification expression"_err_en_US, 2722 symbol.name()); 2723 context_.SetError(symbol); 2724 } 2725 return resolved; 2726 } else if (inStmtFunctionDefinition_) { 2727 semantics::ResolveSpecificationParts(context_, symbol); 2728 CHECK(symbol.has<semantics::SubprogramDetails>()); 2729 } else { // 10.1.11 para 4 2730 Say("The internal function '%s' may not be referenced in a specification expression"_err_en_US, 2731 symbol.name()); 2732 context_.SetError(symbol); 2733 return nullptr; 2734 } 2735 } 2736 return &symbol; 2737 } 2738 2739 // Resolve a call to a generic procedure with given actual arguments. 2740 // adjustActuals is called on procedure bindings to handle pass arg. 2741 std::pair<const Symbol *, bool> ExpressionAnalyzer::ResolveGeneric( 2742 const Symbol &symbol, const ActualArguments &actuals, 2743 const AdjustActuals &adjustActuals, bool isSubroutine, 2744 bool mightBeStructureConstructor) { 2745 const Symbol *elemental{nullptr}; // matching elemental specific proc 2746 const Symbol *nonElemental{nullptr}; // matching non-elemental specific 2747 const Symbol &ultimate{symbol.GetUltimate()}; 2748 int crtMatchingDistance{cudaInfMatchingValue}; 2749 // Check for a match with an explicit INTRINSIC 2750 if (ultimate.attrs().test(semantics::Attr::INTRINSIC)) { 2751 parser::Messages buffer; 2752 auto restorer{foldingContext_.messages().SetMessages(buffer)}; 2753 ActualArguments localActuals{actuals}; 2754 if (context_.intrinsics().Probe( 2755 CallCharacteristics{ultimate.name().ToString(), isSubroutine}, 2756 localActuals, foldingContext_) && 2757 !buffer.AnyFatalError()) { 2758 return {&ultimate, false}; 2759 } 2760 } 2761 if (const auto *details{ultimate.detailsIf<semantics::GenericDetails>()}) { 2762 for (const Symbol &specific0 : details->specificProcs()) { 2763 const Symbol &specific1{BypassGeneric(specific0)}; 2764 if (isSubroutine != !IsFunction(specific1)) { 2765 continue; 2766 } 2767 const Symbol *specific{ResolveForward(specific1)}; 2768 if (!specific) { 2769 continue; 2770 } 2771 if (std::optional<characteristics::Procedure> procedure{ 2772 characteristics::Procedure::Characterize( 2773 ProcedureDesignator{*specific}, context_.foldingContext(), 2774 /*emitError=*/false)}) { 2775 ActualArguments localActuals{actuals}; 2776 if (specific->has<semantics::ProcBindingDetails>()) { 2777 if (!adjustActuals.value()(*specific, localActuals)) { 2778 continue; 2779 } 2780 } 2781 if (semantics::CheckInterfaceForGeneric(*procedure, localActuals, 2782 context_, false /* no integer conversions */) && 2783 CheckCompatibleArguments( 2784 *procedure, localActuals, foldingContext_)) { 2785 if ((procedure->IsElemental() && elemental) || 2786 (!procedure->IsElemental() && nonElemental)) { 2787 int d{ComputeCudaMatchingDistance( 2788 context_.languageFeatures(), *procedure, localActuals)}; 2789 if (d != crtMatchingDistance) { 2790 if (d > crtMatchingDistance) { 2791 continue; 2792 } 2793 // Matching distance is smaller than the previously matched 2794 // specific. Let it go thourgh so the current procedure is picked. 2795 } else { 2796 // 16.9.144(6): a bare NULL() is not allowed as an actual 2797 // argument to a generic procedure if the specific procedure 2798 // cannot be unambiguously distinguished 2799 // Underspecified external procedure actual arguments can 2800 // also lead to ambiguity. 2801 return {nullptr, true /* due to ambiguity */}; 2802 } 2803 } 2804 if (!procedure->IsElemental()) { 2805 // takes priority over elemental match 2806 nonElemental = specific; 2807 } else { 2808 elemental = specific; 2809 } 2810 crtMatchingDistance = ComputeCudaMatchingDistance( 2811 context_.languageFeatures(), *procedure, localActuals); 2812 } 2813 } 2814 } 2815 if (nonElemental) { 2816 return {&AccessSpecific(symbol, *nonElemental), false}; 2817 } else if (elemental) { 2818 return {&AccessSpecific(symbol, *elemental), false}; 2819 } 2820 // Check parent derived type 2821 if (const auto *parentScope{symbol.owner().GetDerivedTypeParent()}) { 2822 if (const Symbol *extended{parentScope->FindComponent(symbol.name())}) { 2823 auto pair{ResolveGeneric( 2824 *extended, actuals, adjustActuals, isSubroutine, false)}; 2825 if (pair.first) { 2826 return pair; 2827 } 2828 } 2829 } 2830 if (mightBeStructureConstructor && details->derivedType()) { 2831 return {details->derivedType(), false}; 2832 } 2833 } 2834 // Check for generic or explicit INTRINSIC of the same name in outer scopes. 2835 // See 15.5.5.2 for details. 2836 if (!symbol.owner().IsGlobal() && !symbol.owner().IsDerivedType()) { 2837 for (const std::string &n : GetAllNames(context_, symbol.name())) { 2838 if (const Symbol *outer{symbol.owner().parent().FindSymbol(n)}) { 2839 auto pair{ResolveGeneric(*outer, actuals, adjustActuals, isSubroutine, 2840 mightBeStructureConstructor)}; 2841 if (pair.first) { 2842 return pair; 2843 } 2844 } 2845 } 2846 } 2847 return {nullptr, false}; 2848 } 2849 2850 const Symbol &ExpressionAnalyzer::AccessSpecific( 2851 const Symbol &originalGeneric, const Symbol &specific) { 2852 if (const auto *hosted{ 2853 originalGeneric.detailsIf<semantics::HostAssocDetails>()}) { 2854 return AccessSpecific(hosted->symbol(), specific); 2855 } else if (const auto *used{ 2856 originalGeneric.detailsIf<semantics::UseDetails>()}) { 2857 const auto &scope{originalGeneric.owner()}; 2858 if (auto iter{scope.find(specific.name())}; iter != scope.end()) { 2859 if (const auto *useDetails{ 2860 iter->second->detailsIf<semantics::UseDetails>()}) { 2861 const Symbol &usedSymbol{useDetails->symbol()}; 2862 const auto *usedGeneric{ 2863 usedSymbol.detailsIf<semantics::GenericDetails>()}; 2864 if (&usedSymbol == &specific || 2865 (usedGeneric && usedGeneric->specific() == &specific)) { 2866 return specific; 2867 } 2868 } 2869 } 2870 // Create a renaming USE of the specific procedure. 2871 auto rename{context_.SaveTempName( 2872 used->symbol().owner().GetName().value().ToString() + "$" + 2873 specific.owner().GetName().value().ToString() + "$" + 2874 specific.name().ToString())}; 2875 return *const_cast<semantics::Scope &>(scope) 2876 .try_emplace(rename, specific.attrs(), 2877 semantics::UseDetails{rename, specific}) 2878 .first->second; 2879 } else { 2880 return specific; 2881 } 2882 } 2883 2884 void ExpressionAnalyzer::EmitGenericResolutionError( 2885 const Symbol &symbol, bool dueToAmbiguity, bool isSubroutine) { 2886 Say(dueToAmbiguity 2887 ? "The actual arguments to the generic procedure '%s' matched multiple specific procedures, perhaps due to use of NULL() without MOLD= or an actual procedure with an implicit interface"_err_en_US 2888 : semantics::IsGenericDefinedOp(symbol) 2889 ? "No specific procedure of generic operator '%s' matches the actual arguments"_err_en_US 2890 : isSubroutine 2891 ? "No specific subroutine of generic '%s' matches the actual arguments"_err_en_US 2892 : "No specific function of generic '%s' matches the actual arguments"_err_en_US, 2893 symbol.name()); 2894 } 2895 2896 auto ExpressionAnalyzer::GetCalleeAndArguments( 2897 const parser::ProcedureDesignator &pd, ActualArguments &&arguments, 2898 bool isSubroutine, bool mightBeStructureConstructor) 2899 -> std::optional<CalleeAndArguments> { 2900 return common::visit(common::visitors{ 2901 [&](const parser::Name &name) { 2902 return GetCalleeAndArguments(name, 2903 std::move(arguments), isSubroutine, 2904 mightBeStructureConstructor); 2905 }, 2906 [&](const parser::ProcComponentRef &pcr) { 2907 return AnalyzeProcedureComponentRef( 2908 pcr, std::move(arguments), isSubroutine); 2909 }, 2910 }, 2911 pd.u); 2912 } 2913 2914 auto ExpressionAnalyzer::GetCalleeAndArguments(const parser::Name &name, 2915 ActualArguments &&arguments, bool isSubroutine, 2916 bool mightBeStructureConstructor) -> std::optional<CalleeAndArguments> { 2917 const Symbol *symbol{name.symbol}; 2918 if (context_.HasError(symbol)) { 2919 return std::nullopt; // also handles null symbol 2920 } 2921 symbol = ResolveForward(*symbol); 2922 if (!symbol) { 2923 return std::nullopt; 2924 } 2925 name.symbol = const_cast<Symbol *>(symbol); 2926 const Symbol &ultimate{symbol->GetUltimate()}; 2927 CheckForBadRecursion(name.source, ultimate); 2928 bool dueToAmbiguity{false}; 2929 bool isGenericInterface{ultimate.has<semantics::GenericDetails>()}; 2930 bool isExplicitIntrinsic{ultimate.attrs().test(semantics::Attr::INTRINSIC)}; 2931 const Symbol *resolution{nullptr}; 2932 if (isGenericInterface || isExplicitIntrinsic) { 2933 ExpressionAnalyzer::AdjustActuals noAdjustment; 2934 auto pair{ResolveGeneric(*symbol, arguments, noAdjustment, isSubroutine, 2935 mightBeStructureConstructor)}; 2936 resolution = pair.first; 2937 dueToAmbiguity = pair.second; 2938 if (resolution) { 2939 if (context_.GetPPCBuiltinsScope() && 2940 resolution->name().ToString().rfind("__ppc_", 0) == 0) { 2941 semantics::CheckPPCIntrinsic( 2942 *symbol, *resolution, arguments, GetFoldingContext()); 2943 } 2944 // re-resolve name to the specific procedure 2945 name.symbol = const_cast<Symbol *>(resolution); 2946 } 2947 } else if (IsProcedure(ultimate) && 2948 ultimate.attrs().test(semantics::Attr::ABSTRACT)) { 2949 Say("Abstract procedure interface '%s' may not be referenced"_err_en_US, 2950 name.source); 2951 } else { 2952 resolution = symbol; 2953 } 2954 if (resolution && context_.targetCharacteristics().isOSWindows()) { 2955 semantics::CheckWindowsIntrinsic(*resolution, GetFoldingContext()); 2956 } 2957 if (!resolution || resolution->attrs().test(semantics::Attr::INTRINSIC)) { 2958 auto name{resolution ? resolution->name() : ultimate.name()}; 2959 if (std::optional<SpecificCall> specificCall{context_.intrinsics().Probe( 2960 CallCharacteristics{name.ToString(), isSubroutine}, arguments, 2961 GetFoldingContext())}) { 2962 CheckBadExplicitType(*specificCall, *symbol); 2963 return CalleeAndArguments{ 2964 ProcedureDesignator{std::move(specificCall->specificIntrinsic)}, 2965 std::move(specificCall->arguments)}; 2966 } else { 2967 if (isGenericInterface) { 2968 EmitGenericResolutionError(*symbol, dueToAmbiguity, isSubroutine); 2969 } 2970 return std::nullopt; 2971 } 2972 } 2973 if (resolution->GetUltimate().has<semantics::DerivedTypeDetails>()) { 2974 if (mightBeStructureConstructor) { 2975 return CalleeAndArguments{ 2976 semantics::SymbolRef{*resolution}, std::move(arguments)}; 2977 } 2978 } else if (IsProcedure(*resolution)) { 2979 return CalleeAndArguments{ 2980 ProcedureDesignator{*resolution}, std::move(arguments)}; 2981 } 2982 if (!context_.HasError(*resolution)) { 2983 AttachDeclaration( 2984 Say(name.source, "'%s' is not a callable procedure"_err_en_US, 2985 name.source), 2986 *resolution); 2987 } 2988 return std::nullopt; 2989 } 2990 2991 // Fortran 2018 expressly states (8.2 p3) that any declared type for a 2992 // generic intrinsic function "has no effect" on the result type of a 2993 // call to that intrinsic. So one can declare "character*8 cos" and 2994 // still get a real result from "cos(1.)". This is a dangerous feature, 2995 // especially since implementations are free to extend their sets of 2996 // intrinsics, and in doing so might clash with a name in a program. 2997 // So we emit a warning in this situation, and perhaps it should be an 2998 // error -- any correctly working program can silence the message by 2999 // simply deleting the pointless type declaration. 3000 void ExpressionAnalyzer::CheckBadExplicitType( 3001 const SpecificCall &call, const Symbol &intrinsic) { 3002 if (intrinsic.GetUltimate().GetType()) { 3003 const auto &procedure{call.specificIntrinsic.characteristics.value()}; 3004 if (const auto &result{procedure.functionResult}) { 3005 if (const auto *typeAndShape{result->GetTypeAndShape()}) { 3006 if (auto declared{ 3007 typeAndShape->Characterize(intrinsic, GetFoldingContext())}) { 3008 if (!declared->type().IsTkCompatibleWith(typeAndShape->type())) { 3009 if (auto *msg{Warn( 3010 common::UsageWarning::IgnoredIntrinsicFunctionType, 3011 "The result type '%s' of the intrinsic function '%s' is not the explicit declared type '%s'"_warn_en_US, 3012 typeAndShape->AsFortran(), intrinsic.name(), 3013 declared->AsFortran())}) { 3014 msg->Attach(intrinsic.name(), 3015 "Ignored declaration of intrinsic function '%s'"_en_US, 3016 intrinsic.name()); 3017 } 3018 } 3019 } 3020 } 3021 } 3022 } 3023 } 3024 3025 void ExpressionAnalyzer::CheckForBadRecursion( 3026 parser::CharBlock callSite, const semantics::Symbol &proc) { 3027 if (const auto *scope{proc.scope()}) { 3028 if (scope->sourceRange().Contains(callSite)) { 3029 parser::Message *msg{nullptr}; 3030 if (proc.attrs().test(semantics::Attr::NON_RECURSIVE)) { // 15.6.2.1(3) 3031 msg = Say("NON_RECURSIVE procedure '%s' cannot call itself"_err_en_US, 3032 callSite); 3033 } else if (IsAssumedLengthCharacter(proc) && IsExternal(proc)) { 3034 // TODO: Also catch assumed PDT type parameters 3035 msg = Say( // 15.6.2.1(3) 3036 "Assumed-length CHARACTER(*) function '%s' cannot call itself"_err_en_US, 3037 callSite); 3038 } else if (FindCUDADeviceContext(scope)) { 3039 msg = Say( 3040 "Device subprogram '%s' cannot call itself"_err_en_US, callSite); 3041 } 3042 AttachDeclaration(msg, proc); 3043 } 3044 } 3045 } 3046 3047 template <typename A> static const Symbol *AssumedTypeDummy(const A &x) { 3048 if (const auto *designator{ 3049 std::get_if<common::Indirection<parser::Designator>>(&x.u)}) { 3050 if (const auto *dataRef{ 3051 std::get_if<parser::DataRef>(&designator->value().u)}) { 3052 if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) { 3053 return AssumedTypeDummy(*name); 3054 } 3055 } 3056 } 3057 return nullptr; 3058 } 3059 template <> 3060 const Symbol *AssumedTypeDummy<parser::Name>(const parser::Name &name) { 3061 if (const Symbol *symbol{name.symbol}) { 3062 if (const auto *type{symbol->GetType()}) { 3063 if (type->category() == semantics::DeclTypeSpec::TypeStar) { 3064 return symbol; 3065 } 3066 } 3067 } 3068 return nullptr; 3069 } 3070 template <typename A> 3071 static const Symbol *AssumedTypePointerOrAllocatableDummy(const A &object) { 3072 // It is illegal for allocatable of pointer objects to be TYPE(*), but at that 3073 // point it is not guaranteed that it has been checked the object has 3074 // POINTER or ALLOCATABLE attribute, so do not assume nullptr can be directly 3075 // returned. 3076 return common::visit( 3077 common::visitors{ 3078 [&](const parser::StructureComponent &x) { 3079 return AssumedTypeDummy(x.component); 3080 }, 3081 [&](const parser::Name &x) { return AssumedTypeDummy(x); }, 3082 }, 3083 object.u); 3084 } 3085 template <> 3086 const Symbol *AssumedTypeDummy<parser::AllocateObject>( 3087 const parser::AllocateObject &x) { 3088 return AssumedTypePointerOrAllocatableDummy(x); 3089 } 3090 template <> 3091 const Symbol *AssumedTypeDummy<parser::PointerObject>( 3092 const parser::PointerObject &x) { 3093 return AssumedTypePointerOrAllocatableDummy(x); 3094 } 3095 3096 bool ExpressionAnalyzer::CheckIsValidForwardReference( 3097 const semantics::DerivedTypeSpec &dtSpec) { 3098 if (dtSpec.IsForwardReferenced()) { 3099 Say("Cannot construct value for derived type '%s' before it is defined"_err_en_US, 3100 dtSpec.name()); 3101 return false; 3102 } 3103 return true; 3104 } 3105 3106 std::optional<Chevrons> ExpressionAnalyzer::AnalyzeChevrons( 3107 const parser::CallStmt &call) { 3108 Chevrons result; 3109 auto checkLaunchArg{[&](const Expr<SomeType> &expr, const char *which) { 3110 if (auto dyType{expr.GetType()}) { 3111 if (dyType->category() == TypeCategory::Integer) { 3112 return true; 3113 } 3114 if (dyType->category() == TypeCategory::Derived && 3115 !dyType->IsPolymorphic() && 3116 IsBuiltinDerivedType(&dyType->GetDerivedTypeSpec(), "dim3")) { 3117 return true; 3118 } 3119 } 3120 Say("Kernel launch %s parameter must be either integer or TYPE(dim3)"_err_en_US, 3121 which); 3122 return false; 3123 }}; 3124 if (const auto &chevrons{call.chevrons}) { 3125 auto &starOrExpr{std::get<0>(chevrons->t)}; 3126 if (starOrExpr.v) { 3127 if (auto expr{Analyze(*starOrExpr.v)}; 3128 expr && checkLaunchArg(*expr, "grid")) { 3129 result.emplace_back(*expr); 3130 } else { 3131 return std::nullopt; 3132 } 3133 } else { 3134 result.emplace_back( 3135 AsGenericExpr(evaluate::Constant<evaluate::CInteger>{-1})); 3136 } 3137 if (auto expr{Analyze(std::get<1>(chevrons->t))}; 3138 expr && checkLaunchArg(*expr, "block")) { 3139 result.emplace_back(*expr); 3140 } else { 3141 return std::nullopt; 3142 } 3143 if (const auto &maybeExpr{std::get<2>(chevrons->t)}) { 3144 if (auto expr{Analyze(*maybeExpr)}) { 3145 result.emplace_back(*expr); 3146 } else { 3147 return std::nullopt; 3148 } 3149 } 3150 if (const auto &maybeExpr{std::get<3>(chevrons->t)}) { 3151 if (auto expr{Analyze(*maybeExpr)}) { 3152 result.emplace_back(*expr); 3153 } else { 3154 return std::nullopt; 3155 } 3156 } 3157 } 3158 return std::move(result); 3159 } 3160 3161 MaybeExpr ExpressionAnalyzer::Analyze(const parser::FunctionReference &funcRef, 3162 std::optional<parser::StructureConstructor> *structureConstructor) { 3163 const parser::Call &call{funcRef.v}; 3164 auto restorer{GetContextualMessages().SetLocation(funcRef.source)}; 3165 ArgumentAnalyzer analyzer{*this, funcRef.source, true /* isProcedureCall */}; 3166 for (const auto &arg : std::get<std::list<parser::ActualArgSpec>>(call.t)) { 3167 analyzer.Analyze(arg, false /* not subroutine call */); 3168 } 3169 if (analyzer.fatalErrors()) { 3170 return std::nullopt; 3171 } 3172 bool mightBeStructureConstructor{structureConstructor != nullptr}; 3173 if (std::optional<CalleeAndArguments> callee{GetCalleeAndArguments( 3174 std::get<parser::ProcedureDesignator>(call.t), analyzer.GetActuals(), 3175 false /* not subroutine */, mightBeStructureConstructor)}) { 3176 if (auto *proc{std::get_if<ProcedureDesignator>(&callee->u)}) { 3177 return MakeFunctionRef( 3178 funcRef.source, std::move(*proc), std::move(callee->arguments)); 3179 } 3180 CHECK(std::holds_alternative<semantics::SymbolRef>(callee->u)); 3181 const Symbol &symbol{*std::get<semantics::SymbolRef>(callee->u)}; 3182 if (mightBeStructureConstructor) { 3183 // Structure constructor misparsed as function reference? 3184 const auto &designator{std::get<parser::ProcedureDesignator>(call.t)}; 3185 if (const auto *name{std::get_if<parser::Name>(&designator.u)}) { 3186 semantics::Scope &scope{context_.FindScope(name->source)}; 3187 semantics::DerivedTypeSpec dtSpec{name->source, symbol.GetUltimate()}; 3188 if (!CheckIsValidForwardReference(dtSpec)) { 3189 return std::nullopt; 3190 } 3191 const semantics::DeclTypeSpec &type{ 3192 semantics::FindOrInstantiateDerivedType(scope, std::move(dtSpec))}; 3193 auto &mutableRef{const_cast<parser::FunctionReference &>(funcRef)}; 3194 *structureConstructor = 3195 mutableRef.ConvertToStructureConstructor(type.derivedTypeSpec()); 3196 return Analyze(structureConstructor->value()); 3197 } 3198 } 3199 if (!context_.HasError(symbol)) { 3200 AttachDeclaration( 3201 Say("'%s' is called like a function but is not a procedure"_err_en_US, 3202 symbol.name()), 3203 symbol); 3204 context_.SetError(symbol); 3205 } 3206 } 3207 return std::nullopt; 3208 } 3209 3210 static bool HasAlternateReturns(const evaluate::ActualArguments &args) { 3211 for (const auto &arg : args) { 3212 if (arg && arg->isAlternateReturn()) { 3213 return true; 3214 } 3215 } 3216 return false; 3217 } 3218 3219 void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) { 3220 const parser::Call &call{callStmt.call}; 3221 auto restorer{GetContextualMessages().SetLocation(callStmt.source)}; 3222 ArgumentAnalyzer analyzer{*this, callStmt.source, true /* isProcedureCall */}; 3223 const auto &actualArgList{std::get<std::list<parser::ActualArgSpec>>(call.t)}; 3224 for (const auto &arg : actualArgList) { 3225 analyzer.Analyze(arg, true /* is subroutine call */); 3226 } 3227 if (auto chevrons{AnalyzeChevrons(callStmt)}; 3228 chevrons && !analyzer.fatalErrors()) { 3229 if (std::optional<CalleeAndArguments> callee{ 3230 GetCalleeAndArguments(std::get<parser::ProcedureDesignator>(call.t), 3231 analyzer.GetActuals(), true /* subroutine */)}) { 3232 ProcedureDesignator *proc{std::get_if<ProcedureDesignator>(&callee->u)}; 3233 CHECK(proc); 3234 bool isKernel{false}; 3235 if (const Symbol * procSym{proc->GetSymbol()}) { 3236 const Symbol &ultimate{procSym->GetUltimate()}; 3237 if (const auto *subpDetails{ 3238 ultimate.detailsIf<semantics::SubprogramDetails>()}) { 3239 if (auto attrs{subpDetails->cudaSubprogramAttrs()}) { 3240 isKernel = *attrs == common::CUDASubprogramAttrs::Global || 3241 *attrs == common::CUDASubprogramAttrs::Grid_Global; 3242 } 3243 } else if (const auto *procDetails{ 3244 ultimate.detailsIf<semantics::ProcEntityDetails>()}) { 3245 isKernel = procDetails->isCUDAKernel(); 3246 } 3247 if (isKernel && chevrons->empty()) { 3248 Say("'%s' is a kernel subroutine and must be called with kernel launch parameters in chevrons"_err_en_US, 3249 procSym->name()); 3250 } 3251 } 3252 if (!isKernel && !chevrons->empty()) { 3253 Say("Kernel launch parameters in chevrons may not be used unless calling a kernel subroutine"_err_en_US); 3254 } 3255 if (CheckCall(callStmt.source, *proc, callee->arguments)) { 3256 callStmt.typedCall.Reset( 3257 new ProcedureRef{std::move(*proc), std::move(callee->arguments), 3258 HasAlternateReturns(callee->arguments)}, 3259 ProcedureRef::Deleter); 3260 DEREF(callStmt.typedCall.get()).set_chevrons(std::move(*chevrons)); 3261 return; 3262 } 3263 } 3264 if (!context_.AnyFatalError()) { 3265 std::string buf; 3266 llvm::raw_string_ostream dump{buf}; 3267 parser::DumpTree(dump, callStmt); 3268 Say("Internal error: Expression analysis failed on CALL statement: %s"_err_en_US, 3269 buf); 3270 } 3271 } 3272 } 3273 3274 const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) { 3275 if (!x.typedAssignment) { 3276 ArgumentAnalyzer analyzer{*this}; 3277 const auto &variable{std::get<parser::Variable>(x.t)}; 3278 analyzer.Analyze(variable); 3279 analyzer.Analyze(std::get<parser::Expr>(x.t)); 3280 std::optional<Assignment> assignment; 3281 if (!analyzer.fatalErrors()) { 3282 auto restorer{GetContextualMessages().SetLocation(variable.GetSource())}; 3283 std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()}; 3284 if (!procRef) { 3285 analyzer.CheckForNullPointer( 3286 "in a non-pointer intrinsic assignment statement"); 3287 analyzer.CheckForAssumedRank("in an assignment statement"); 3288 const Expr<SomeType> &lhs{analyzer.GetExpr(0)}; 3289 if (auto dyType{lhs.GetType()}; 3290 dyType && dyType->IsPolymorphic()) { // 10.2.1.2p1(1) 3291 const Symbol *lastWhole0{UnwrapWholeSymbolOrComponentDataRef(lhs)}; 3292 const Symbol *lastWhole{ 3293 lastWhole0 ? &lastWhole0->GetUltimate() : nullptr}; 3294 if (!lastWhole || !IsAllocatable(*lastWhole)) { 3295 Say("Left-hand side of assignment may not be polymorphic unless assignment is to an entire allocatable"_err_en_US); 3296 } else if (evaluate::IsCoarray(*lastWhole)) { 3297 Say("Left-hand side of assignment may not be polymorphic if it is a coarray"_err_en_US); 3298 } 3299 } 3300 } 3301 assignment.emplace(analyzer.MoveExpr(0), analyzer.MoveExpr(1)); 3302 if (procRef) { 3303 assignment->u = std::move(*procRef); 3304 } 3305 } 3306 x.typedAssignment.Reset(new GenericAssignmentWrapper{std::move(assignment)}, 3307 GenericAssignmentWrapper::Deleter); 3308 } 3309 return common::GetPtrFromOptional(x.typedAssignment->v); 3310 } 3311 3312 const Assignment *ExpressionAnalyzer::Analyze( 3313 const parser::PointerAssignmentStmt &x) { 3314 if (!x.typedAssignment) { 3315 MaybeExpr lhs{Analyze(std::get<parser::DataRef>(x.t))}; 3316 MaybeExpr rhs; 3317 { 3318 auto restorer{AllowNullPointer()}; 3319 rhs = Analyze(std::get<parser::Expr>(x.t)); 3320 } 3321 if (!lhs || !rhs) { 3322 x.typedAssignment.Reset( 3323 new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter); 3324 } else { 3325 Assignment assignment{std::move(*lhs), std::move(*rhs)}; 3326 common::visit( 3327 common::visitors{ 3328 [&](const std::list<parser::BoundsRemapping> &list) { 3329 Assignment::BoundsRemapping bounds; 3330 for (const auto &elem : list) { 3331 auto lower{AsSubscript(Analyze(std::get<0>(elem.t)))}; 3332 auto upper{AsSubscript(Analyze(std::get<1>(elem.t)))}; 3333 if (lower && upper) { 3334 bounds.emplace_back( 3335 Fold(std::move(*lower)), Fold(std::move(*upper))); 3336 } 3337 } 3338 assignment.u = std::move(bounds); 3339 }, 3340 [&](const std::list<parser::BoundsSpec> &list) { 3341 Assignment::BoundsSpec bounds; 3342 for (const auto &bound : list) { 3343 if (auto lower{AsSubscript(Analyze(bound.v))}) { 3344 bounds.emplace_back(Fold(std::move(*lower))); 3345 } 3346 } 3347 assignment.u = std::move(bounds); 3348 }, 3349 }, 3350 std::get<parser::PointerAssignmentStmt::Bounds>(x.t).u); 3351 x.typedAssignment.Reset( 3352 new GenericAssignmentWrapper{std::move(assignment)}, 3353 GenericAssignmentWrapper::Deleter); 3354 } 3355 } 3356 return common::GetPtrFromOptional(x.typedAssignment->v); 3357 } 3358 3359 static bool IsExternalCalledImplicitly( 3360 parser::CharBlock callSite, const Symbol *symbol) { 3361 return symbol && symbol->owner().IsGlobal() && 3362 symbol->has<semantics::SubprogramDetails>() && 3363 (!symbol->scope() /*ENTRY*/ || 3364 !symbol->scope()->sourceRange().Contains(callSite)); 3365 } 3366 3367 std::optional<characteristics::Procedure> ExpressionAnalyzer::CheckCall( 3368 parser::CharBlock callSite, const ProcedureDesignator &proc, 3369 ActualArguments &arguments) { 3370 bool treatExternalAsImplicit{ 3371 IsExternalCalledImplicitly(callSite, proc.GetSymbol())}; 3372 const Symbol *procSymbol{proc.GetSymbol()}; 3373 std::optional<characteristics::Procedure> chars; 3374 if (procSymbol && procSymbol->has<semantics::ProcEntityDetails>() && 3375 procSymbol->owner().IsGlobal()) { 3376 // Unknown global external, implicit interface; assume 3377 // characteristics from the actual arguments, and check 3378 // for consistency with other references. 3379 chars = characteristics::Procedure::FromActuals( 3380 proc, arguments, context_.foldingContext()); 3381 if (chars && procSymbol) { 3382 // Ensure calls over implicit interfaces are consistent 3383 auto name{procSymbol->name()}; 3384 if (auto iter{implicitInterfaces_.find(name)}; 3385 iter != implicitInterfaces_.end()) { 3386 std::string whyNot; 3387 if (!chars->IsCompatibleWith(iter->second.second, 3388 /*ignoreImplicitVsExplicit=*/false, &whyNot)) { 3389 if (auto *msg{Warn( 3390 common::UsageWarning::IncompatibleImplicitInterfaces, 3391 callSite, 3392 "Reference to the procedure '%s' has an implicit interface that is distinct from another reference: %s"_warn_en_US, 3393 name, whyNot)}) { 3394 msg->Attach( 3395 iter->second.first, "previous reference to '%s'"_en_US, name); 3396 } 3397 } 3398 } else { 3399 implicitInterfaces_.insert( 3400 std::make_pair(name, std::make_pair(callSite, *chars))); 3401 } 3402 } 3403 } 3404 if (!chars) { 3405 chars = characteristics::Procedure::Characterize( 3406 proc, context_.foldingContext(), /*emitError=*/true); 3407 } 3408 bool ok{true}; 3409 if (chars) { 3410 std::string whyNot; 3411 if (treatExternalAsImplicit && 3412 !chars->CanBeCalledViaImplicitInterface(&whyNot)) { 3413 if (auto *msg{Say(callSite, 3414 "References to the procedure '%s' require an explicit interface"_err_en_US, 3415 DEREF(procSymbol).name())}; 3416 msg && !whyNot.empty()) { 3417 msg->Attach(callSite, "%s"_because_en_US, whyNot); 3418 } 3419 } 3420 const SpecificIntrinsic *specificIntrinsic{proc.GetSpecificIntrinsic()}; 3421 bool procIsDummy{procSymbol && IsDummy(*procSymbol)}; 3422 if (chars->functionResult && 3423 chars->functionResult->IsAssumedLengthCharacter() && 3424 !specificIntrinsic && !procIsDummy) { 3425 Say(callSite, 3426 "Assumed-length character function must be defined with a length to be called"_err_en_US); 3427 } 3428 ok &= semantics::CheckArguments(*chars, arguments, context_, 3429 context_.FindScope(callSite), treatExternalAsImplicit, 3430 /*ignoreImplicitVsExplicit=*/false, specificIntrinsic); 3431 } 3432 if (procSymbol && !IsPureProcedure(*procSymbol)) { 3433 if (const semantics::Scope * 3434 pure{semantics::FindPureProcedureContaining( 3435 context_.FindScope(callSite))}) { 3436 Say(callSite, 3437 "Procedure '%s' referenced in pure subprogram '%s' must be pure too"_err_en_US, 3438 procSymbol->name(), DEREF(pure->symbol()).name()); 3439 } 3440 } 3441 if (ok && !treatExternalAsImplicit && procSymbol && 3442 !(chars && chars->HasExplicitInterface())) { 3443 if (const Symbol *global{FindGlobal(*procSymbol)}; 3444 global && global != procSymbol && IsProcedure(*global)) { 3445 // Check a known global definition behind a local interface 3446 if (auto globalChars{characteristics::Procedure::Characterize( 3447 *global, context_.foldingContext())}) { 3448 semantics::CheckArguments(*globalChars, arguments, context_, 3449 context_.FindScope(callSite), /*treatExternalAsImplicit=*/true, 3450 /*ignoreImplicitVsExplicit=*/false, 3451 nullptr /*not specific intrinsic*/); 3452 } 3453 } 3454 } 3455 return chars; 3456 } 3457 3458 // Unary operations 3459 3460 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Parentheses &x) { 3461 if (MaybeExpr operand{Analyze(x.v.value())}) { 3462 if (const semantics::Symbol *symbol{GetLastSymbol(*operand)}) { 3463 if (const semantics::Symbol *result{FindFunctionResult(*symbol)}) { 3464 if (semantics::IsProcedurePointer(*result)) { 3465 Say("A function reference that returns a procedure " 3466 "pointer may not be parenthesized"_err_en_US); // C1003 3467 } 3468 } 3469 } 3470 return Parenthesize(std::move(*operand)); 3471 } 3472 return std::nullopt; 3473 } 3474 3475 static MaybeExpr NumericUnaryHelper(ExpressionAnalyzer &context, 3476 NumericOperator opr, const parser::Expr::IntrinsicUnary &x) { 3477 ArgumentAnalyzer analyzer{context}; 3478 analyzer.Analyze(x.v); 3479 if (!analyzer.fatalErrors()) { 3480 if (analyzer.IsIntrinsicNumeric(opr)) { 3481 analyzer.CheckForNullPointer(); 3482 analyzer.CheckForAssumedRank(); 3483 if (opr == NumericOperator::Add) { 3484 return analyzer.MoveExpr(0); 3485 } else { 3486 return Negation(context.GetContextualMessages(), analyzer.MoveExpr(0)); 3487 } 3488 } else { 3489 return analyzer.TryDefinedOp(AsFortran(opr), 3490 "Operand of unary %s must be numeric; have %s"_err_en_US); 3491 } 3492 } 3493 return std::nullopt; 3494 } 3495 3496 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::UnaryPlus &x) { 3497 return NumericUnaryHelper(*this, NumericOperator::Add, x); 3498 } 3499 3500 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Negate &x) { 3501 if (const auto *litConst{ 3502 std::get_if<parser::LiteralConstant>(&x.v.value().u)}) { 3503 if (const auto *intConst{ 3504 std::get_if<parser::IntLiteralConstant>(&litConst->u)}) { 3505 return Analyze(*intConst, true); 3506 } 3507 } 3508 return NumericUnaryHelper(*this, NumericOperator::Subtract, x); 3509 } 3510 3511 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NOT &x) { 3512 ArgumentAnalyzer analyzer{*this}; 3513 analyzer.Analyze(x.v); 3514 if (!analyzer.fatalErrors()) { 3515 if (analyzer.IsIntrinsicLogical()) { 3516 analyzer.CheckForNullPointer(); 3517 analyzer.CheckForAssumedRank(); 3518 return AsGenericExpr( 3519 LogicalNegation(std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u))); 3520 } else { 3521 return analyzer.TryDefinedOp(LogicalOperator::Not, 3522 "Operand of %s must be LOGICAL; have %s"_err_en_US); 3523 } 3524 } 3525 return std::nullopt; 3526 } 3527 3528 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::PercentLoc &x) { 3529 // Represent %LOC() exactly as if it had been a call to the LOC() extension 3530 // intrinsic function. 3531 // Use the actual source for the name of the call for error reporting. 3532 std::optional<ActualArgument> arg; 3533 if (const Symbol *assumedTypeDummy{AssumedTypeDummy(x.v.value())}) { 3534 arg = ActualArgument{ActualArgument::AssumedType{*assumedTypeDummy}}; 3535 } else if (MaybeExpr argExpr{Analyze(x.v.value())}) { 3536 arg = ActualArgument{std::move(*argExpr)}; 3537 } else { 3538 return std::nullopt; 3539 } 3540 parser::CharBlock at{GetContextualMessages().at()}; 3541 CHECK(at.size() >= 4); 3542 parser::CharBlock loc{at.begin() + 1, 3}; 3543 CHECK(loc == "loc"); 3544 return MakeFunctionRef(loc, ActualArguments{std::move(*arg)}); 3545 } 3546 3547 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedUnary &x) { 3548 const auto &name{std::get<parser::DefinedOpName>(x.t).v}; 3549 ArgumentAnalyzer analyzer{*this, name.source}; 3550 analyzer.Analyze(std::get<1>(x.t)); 3551 return analyzer.TryDefinedOp(name.source.ToString().c_str(), 3552 "No operator %s defined for %s"_err_en_US, true); 3553 } 3554 3555 // Binary (dyadic) operations 3556 3557 template <template <typename> class OPR, NumericOperator opr> 3558 MaybeExpr NumericBinaryHelper( 3559 ExpressionAnalyzer &context, const parser::Expr::IntrinsicBinary &x) { 3560 ArgumentAnalyzer analyzer{context}; 3561 analyzer.Analyze(std::get<0>(x.t)); 3562 analyzer.Analyze(std::get<1>(x.t)); 3563 if (!analyzer.fatalErrors()) { 3564 if (analyzer.IsIntrinsicNumeric(opr)) { 3565 analyzer.CheckForNullPointer(); 3566 analyzer.CheckForAssumedRank(); 3567 analyzer.CheckConformance(); 3568 constexpr bool canBeUnsigned{opr != NumericOperator::Power}; 3569 return NumericOperation<OPR, canBeUnsigned>( 3570 context.GetContextualMessages(), analyzer.MoveExpr(0), 3571 analyzer.MoveExpr(1), context.GetDefaultKind(TypeCategory::Real)); 3572 } else { 3573 return analyzer.TryDefinedOp(AsFortran(opr), 3574 "Operands of %s must be numeric; have %s and %s"_err_en_US); 3575 } 3576 } 3577 return std::nullopt; 3578 } 3579 3580 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Power &x) { 3581 return NumericBinaryHelper<Power, NumericOperator::Power>(*this, x); 3582 } 3583 3584 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Multiply &x) { 3585 return NumericBinaryHelper<Multiply, NumericOperator::Multiply>(*this, x); 3586 } 3587 3588 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Divide &x) { 3589 return NumericBinaryHelper<Divide, NumericOperator::Divide>(*this, x); 3590 } 3591 3592 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Add &x) { 3593 return NumericBinaryHelper<Add, NumericOperator::Add>(*this, x); 3594 } 3595 3596 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Subtract &x) { 3597 return NumericBinaryHelper<Subtract, NumericOperator::Subtract>(*this, x); 3598 } 3599 3600 MaybeExpr ExpressionAnalyzer::Analyze( 3601 const parser::Expr::ComplexConstructor &z) { 3602 Warn(common::LanguageFeature::ComplexConstructor, 3603 "nonstandard usage: generalized COMPLEX constructor"_port_en_US); 3604 return AnalyzeComplex(Analyze(std::get<0>(z.t).value()), 3605 Analyze(std::get<1>(z.t).value()), "complex constructor"); 3606 } 3607 3608 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::Concat &x) { 3609 ArgumentAnalyzer analyzer{*this}; 3610 analyzer.Analyze(std::get<0>(x.t)); 3611 analyzer.Analyze(std::get<1>(x.t)); 3612 if (!analyzer.fatalErrors()) { 3613 if (analyzer.IsIntrinsicConcat()) { 3614 analyzer.CheckForNullPointer(); 3615 analyzer.CheckForAssumedRank(); 3616 return common::visit( 3617 [&](auto &&x, auto &&y) -> MaybeExpr { 3618 using T = ResultType<decltype(x)>; 3619 if constexpr (std::is_same_v<T, ResultType<decltype(y)>>) { 3620 return AsGenericExpr(Concat<T::kind>{std::move(x), std::move(y)}); 3621 } else { 3622 DIE("different types for intrinsic concat"); 3623 } 3624 }, 3625 std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(0).u).u), 3626 std::move(std::get<Expr<SomeCharacter>>(analyzer.MoveExpr(1).u).u)); 3627 } else { 3628 return analyzer.TryDefinedOp("//", 3629 "Operands of %s must be CHARACTER with the same kind; have %s and %s"_err_en_US); 3630 } 3631 } 3632 return std::nullopt; 3633 } 3634 3635 // The Name represents a user-defined intrinsic operator. 3636 // If the actuals match one of the specific procedures, return a function ref. 3637 // Otherwise report the error in messages. 3638 MaybeExpr ExpressionAnalyzer::AnalyzeDefinedOp( 3639 const parser::Name &name, ActualArguments &&actuals) { 3640 if (auto callee{GetCalleeAndArguments(name, std::move(actuals))}) { 3641 CHECK(std::holds_alternative<ProcedureDesignator>(callee->u)); 3642 return MakeFunctionRef(name.source, 3643 std::move(std::get<ProcedureDesignator>(callee->u)), 3644 std::move(callee->arguments)); 3645 } else { 3646 return std::nullopt; 3647 } 3648 } 3649 3650 MaybeExpr RelationHelper(ExpressionAnalyzer &context, RelationalOperator opr, 3651 const parser::Expr::IntrinsicBinary &x) { 3652 ArgumentAnalyzer analyzer{context}; 3653 analyzer.Analyze(std::get<0>(x.t)); 3654 analyzer.Analyze(std::get<1>(x.t)); 3655 if (!analyzer.fatalErrors()) { 3656 std::optional<DynamicType> leftType{analyzer.GetType(0)}; 3657 std::optional<DynamicType> rightType{analyzer.GetType(1)}; 3658 analyzer.ConvertBOZ(&leftType, 0, rightType); 3659 analyzer.ConvertBOZ(&rightType, 1, leftType); 3660 if (leftType && rightType && 3661 analyzer.IsIntrinsicRelational(opr, *leftType, *rightType)) { 3662 analyzer.CheckForNullPointer("as a relational operand"); 3663 analyzer.CheckForAssumedRank("as a relational operand"); 3664 if (auto cmp{Relate(context.GetContextualMessages(), opr, 3665 analyzer.MoveExpr(0), analyzer.MoveExpr(1))}) { 3666 return AsMaybeExpr(ConvertToKind<TypeCategory::Logical>( 3667 context.GetDefaultKind(TypeCategory::Logical), 3668 AsExpr(std::move(*cmp)))); 3669 } 3670 } else { 3671 return analyzer.TryDefinedOp(opr, 3672 leftType && leftType->category() == TypeCategory::Logical && 3673 rightType && rightType->category() == TypeCategory::Logical 3674 ? "LOGICAL operands must be compared using .EQV. or .NEQV."_err_en_US 3675 : "Operands of %s must have comparable types; have %s and %s"_err_en_US); 3676 } 3677 } 3678 return std::nullopt; 3679 } 3680 3681 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LT &x) { 3682 return RelationHelper(*this, RelationalOperator::LT, x); 3683 } 3684 3685 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::LE &x) { 3686 return RelationHelper(*this, RelationalOperator::LE, x); 3687 } 3688 3689 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQ &x) { 3690 return RelationHelper(*this, RelationalOperator::EQ, x); 3691 } 3692 3693 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NE &x) { 3694 return RelationHelper(*this, RelationalOperator::NE, x); 3695 } 3696 3697 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GE &x) { 3698 return RelationHelper(*this, RelationalOperator::GE, x); 3699 } 3700 3701 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::GT &x) { 3702 return RelationHelper(*this, RelationalOperator::GT, x); 3703 } 3704 3705 MaybeExpr LogicalBinaryHelper(ExpressionAnalyzer &context, LogicalOperator opr, 3706 const parser::Expr::IntrinsicBinary &x) { 3707 ArgumentAnalyzer analyzer{context}; 3708 analyzer.Analyze(std::get<0>(x.t)); 3709 analyzer.Analyze(std::get<1>(x.t)); 3710 if (!analyzer.fatalErrors()) { 3711 if (analyzer.IsIntrinsicLogical()) { 3712 analyzer.CheckForNullPointer("as a logical operand"); 3713 analyzer.CheckForAssumedRank("as a logical operand"); 3714 return AsGenericExpr(BinaryLogicalOperation(opr, 3715 std::get<Expr<SomeLogical>>(analyzer.MoveExpr(0).u), 3716 std::get<Expr<SomeLogical>>(analyzer.MoveExpr(1).u))); 3717 } else { 3718 return analyzer.TryDefinedOp( 3719 opr, "Operands of %s must be LOGICAL; have %s and %s"_err_en_US); 3720 } 3721 } 3722 return std::nullopt; 3723 } 3724 3725 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::AND &x) { 3726 return LogicalBinaryHelper(*this, LogicalOperator::And, x); 3727 } 3728 3729 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::OR &x) { 3730 return LogicalBinaryHelper(*this, LogicalOperator::Or, x); 3731 } 3732 3733 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::EQV &x) { 3734 return LogicalBinaryHelper(*this, LogicalOperator::Eqv, x); 3735 } 3736 3737 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::NEQV &x) { 3738 return LogicalBinaryHelper(*this, LogicalOperator::Neqv, x); 3739 } 3740 3741 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &x) { 3742 const auto &name{std::get<parser::DefinedOpName>(x.t).v}; 3743 ArgumentAnalyzer analyzer{*this, name.source}; 3744 analyzer.Analyze(std::get<1>(x.t)); 3745 analyzer.Analyze(std::get<2>(x.t)); 3746 return analyzer.TryDefinedOp(name.source.ToString().c_str(), 3747 "No operator %s defined for %s and %s"_err_en_US, true); 3748 } 3749 3750 // Returns true if a parsed function reference should be converted 3751 // into an array element reference. 3752 static bool CheckFuncRefToArrayElement(semantics::SemanticsContext &context, 3753 const parser::FunctionReference &funcRef) { 3754 // Emit message if the function reference fix will end up an array element 3755 // reference with no subscripts, or subscripts on a scalar, because it will 3756 // not be possible to later distinguish in expressions between an empty 3757 // subscript list due to bad subscripts error recovery or because the 3758 // user did not put any. 3759 auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)}; 3760 const auto *name{std::get_if<parser::Name>(&proc.u)}; 3761 if (!name) { 3762 name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component; 3763 } 3764 if (!name->symbol) { 3765 return false; 3766 } else if (name->symbol->Rank() == 0) { 3767 if (const Symbol *function{ 3768 semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)}) { 3769 auto &msg{context.Say(funcRef.source, 3770 function->flags().test(Symbol::Flag::StmtFunction) 3771 ? "Recursive call to statement function '%s' is not allowed"_err_en_US 3772 : "Recursive call to '%s' requires a distinct RESULT in its declaration"_err_en_US, 3773 name->source)}; 3774 AttachDeclaration(&msg, *function); 3775 name->symbol = const_cast<Symbol *>(function); 3776 } 3777 return false; 3778 } else { 3779 if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) { 3780 auto &msg{context.Say(funcRef.source, 3781 "Reference to array '%s' with empty subscript list"_err_en_US, 3782 name->source)}; 3783 if (name->symbol) { 3784 AttachDeclaration(&msg, *name->symbol); 3785 } 3786 } 3787 return true; 3788 } 3789 } 3790 3791 // Converts, if appropriate, an original misparse of ambiguous syntax like 3792 // A(1) as a function reference into an array reference. 3793 // Misparsed structure constructors are detected elsewhere after generic 3794 // function call resolution fails. 3795 template <typename... A> 3796 static void FixMisparsedFunctionReference( 3797 semantics::SemanticsContext &context, const std::variant<A...> &constU) { 3798 // The parse tree is updated in situ when resolving an ambiguous parse. 3799 using uType = std::decay_t<decltype(constU)>; 3800 auto &u{const_cast<uType &>(constU)}; 3801 if (auto *func{ 3802 std::get_if<common::Indirection<parser::FunctionReference>>(&u)}) { 3803 parser::FunctionReference &funcRef{func->value()}; 3804 // Ensure that there are no argument keywords 3805 for (const auto &arg : 3806 std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t)) { 3807 if (std::get<std::optional<parser::Keyword>>(arg.t)) { 3808 return; 3809 } 3810 } 3811 auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)}; 3812 if (Symbol *origSymbol{ 3813 common::visit(common::visitors{ 3814 [&](parser::Name &name) { return name.symbol; }, 3815 [&](parser::ProcComponentRef &pcr) { 3816 return pcr.v.thing.component.symbol; 3817 }, 3818 }, 3819 proc.u)}) { 3820 Symbol &symbol{origSymbol->GetUltimate()}; 3821 if (symbol.has<semantics::ObjectEntityDetails>() || 3822 symbol.has<semantics::AssocEntityDetails>()) { 3823 // Note that expression in AssocEntityDetails cannot be a procedure 3824 // pointer as per C1105 so this cannot be a function reference. 3825 if constexpr (common::HasMember<common::Indirection<parser::Designator>, 3826 uType>) { 3827 if (CheckFuncRefToArrayElement(context, funcRef)) { 3828 u = common::Indirection{funcRef.ConvertToArrayElementRef()}; 3829 } 3830 } else { 3831 DIE("can't fix misparsed function as array reference"); 3832 } 3833 } 3834 } 3835 } 3836 } 3837 3838 // Common handling of parse tree node types that retain the 3839 // representation of the analyzed expression. 3840 template <typename PARSED> 3841 MaybeExpr ExpressionAnalyzer::ExprOrVariable( 3842 const PARSED &x, parser::CharBlock source) { 3843 auto restorer{GetContextualMessages().SetLocation(source)}; 3844 if constexpr (std::is_same_v<PARSED, parser::Expr> || 3845 std::is_same_v<PARSED, parser::Variable>) { 3846 FixMisparsedFunctionReference(context_, x.u); 3847 } 3848 if (AssumedTypeDummy(x)) { // C710 3849 Say("TYPE(*) dummy argument may only be used as an actual argument"_err_en_US); 3850 ResetExpr(x); 3851 return std::nullopt; 3852 } 3853 MaybeExpr result; 3854 if constexpr (common::HasMember<parser::StructureConstructor, 3855 std::decay_t<decltype(x.u)>> && 3856 common::HasMember<common::Indirection<parser::FunctionReference>, 3857 std::decay_t<decltype(x.u)>>) { 3858 if (const auto *funcRef{ 3859 std::get_if<common::Indirection<parser::FunctionReference>>( 3860 &x.u)}) { 3861 // Function references in Exprs might turn out to be misparsed structure 3862 // constructors; we have to try generic procedure resolution 3863 // first to be sure. 3864 std::optional<parser::StructureConstructor> ctor; 3865 result = Analyze(funcRef->value(), &ctor); 3866 if (result && ctor) { 3867 // A misparsed function reference is really a structure 3868 // constructor. Repair the parse tree in situ. 3869 const_cast<PARSED &>(x).u = std::move(*ctor); 3870 } 3871 } else { 3872 result = Analyze(x.u); 3873 } 3874 } else { 3875 result = Analyze(x.u); 3876 } 3877 if (result) { 3878 if constexpr (std::is_same_v<PARSED, parser::Expr>) { 3879 if (!isNullPointerOk_ && IsNullPointer(*result)) { 3880 Say(source, 3881 "NULL() may not be used as an expression in this context"_err_en_US); 3882 } 3883 } 3884 SetExpr(x, Fold(std::move(*result))); 3885 return x.typedExpr->v; 3886 } else { 3887 ResetExpr(x); 3888 if (!context_.AnyFatalError()) { 3889 std::string buf; 3890 llvm::raw_string_ostream dump{buf}; 3891 parser::DumpTree(dump, x); 3892 Say("Internal error: Expression analysis failed on: %s"_err_en_US, buf); 3893 } 3894 return std::nullopt; 3895 } 3896 } 3897 3898 // This is an optional preliminary pass over parser::Expr subtrees. 3899 // Given an expression tree, iteratively traverse it in a bottom-up order 3900 // to analyze all of its subexpressions. A later normal top-down analysis 3901 // will then be able to use the results that will have been saved in the 3902 // parse tree without having to recurse deeply. This technique keeps 3903 // absurdly deep expression parse trees from causing the analyzer to overflow 3904 // its stack. 3905 MaybeExpr ExpressionAnalyzer::IterativelyAnalyzeSubexpressions( 3906 const parser::Expr &top) { 3907 std::vector<const parser::Expr *> queue, finish; 3908 queue.push_back(&top); 3909 do { 3910 const parser::Expr &expr{*queue.back()}; 3911 queue.pop_back(); 3912 if (!expr.typedExpr) { 3913 const parser::Expr::IntrinsicUnary *unary{nullptr}; 3914 const parser::Expr::IntrinsicBinary *binary{nullptr}; 3915 common::visit( 3916 [&unary, &binary](auto &y) { 3917 if constexpr (std::is_convertible_v<decltype(&y), 3918 decltype(unary)>) { 3919 // Don't evaluate a constant operand to Negate 3920 if (!std::holds_alternative<parser::LiteralConstant>( 3921 y.v.value().u)) { 3922 unary = &y; 3923 } 3924 } else if constexpr (std::is_convertible_v<decltype(&y), 3925 decltype(binary)>) { 3926 binary = &y; 3927 } 3928 }, 3929 expr.u); 3930 if (unary) { 3931 queue.push_back(&unary->v.value()); 3932 } else if (binary) { 3933 queue.push_back(&std::get<0>(binary->t).value()); 3934 queue.push_back(&std::get<1>(binary->t).value()); 3935 } 3936 finish.push_back(&expr); 3937 } 3938 } while (!queue.empty()); 3939 // Analyze the collected subexpressions in bottom-up order. 3940 // On an error, bail out and leave partial results in place. 3941 MaybeExpr result; 3942 for (auto riter{finish.rbegin()}; riter != finish.rend(); ++riter) { 3943 const parser::Expr &expr{**riter}; 3944 result = ExprOrVariable(expr, expr.source); 3945 if (!result) { 3946 return result; 3947 } 3948 } 3949 return result; // last value was from analysis of "top" 3950 } 3951 3952 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) { 3953 bool wasIterativelyAnalyzing{iterativelyAnalyzingSubexpressions_}; 3954 MaybeExpr result; 3955 if (useSavedTypedExprs_) { 3956 if (expr.typedExpr) { 3957 return expr.typedExpr->v; 3958 } 3959 if (!wasIterativelyAnalyzing) { 3960 iterativelyAnalyzingSubexpressions_ = true; 3961 result = IterativelyAnalyzeSubexpressions(expr); 3962 } 3963 } 3964 if (!result) { 3965 result = ExprOrVariable(expr, expr.source); 3966 } 3967 iterativelyAnalyzingSubexpressions_ = wasIterativelyAnalyzing; 3968 return result; 3969 } 3970 3971 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) { 3972 if (useSavedTypedExprs_ && variable.typedExpr) { 3973 return variable.typedExpr->v; 3974 } 3975 return ExprOrVariable(variable, variable.GetSource()); 3976 } 3977 3978 MaybeExpr ExpressionAnalyzer::Analyze(const parser::Selector &selector) { 3979 if (const auto *var{std::get_if<parser::Variable>(&selector.u)}) { 3980 if (!useSavedTypedExprs_ || !var->typedExpr) { 3981 parser::CharBlock source{var->GetSource()}; 3982 auto restorer{GetContextualMessages().SetLocation(source)}; 3983 FixMisparsedFunctionReference(context_, var->u); 3984 if (const auto *funcRef{ 3985 std::get_if<common::Indirection<parser::FunctionReference>>( 3986 &var->u)}) { 3987 // A Selector that parsed as a Variable might turn out during analysis 3988 // to actually be a structure constructor. In that case, repair the 3989 // Variable parse tree node into an Expr 3990 std::optional<parser::StructureConstructor> ctor; 3991 if (MaybeExpr result{Analyze(funcRef->value(), &ctor)}) { 3992 if (ctor) { 3993 auto &writable{const_cast<parser::Selector &>(selector)}; 3994 writable.u = parser::Expr{std::move(*ctor)}; 3995 auto &expr{std::get<parser::Expr>(writable.u)}; 3996 expr.source = source; 3997 SetExpr(expr, Fold(std::move(*result))); 3998 return expr.typedExpr->v; 3999 } else { 4000 SetExpr(*var, Fold(std::move(*result))); 4001 return var->typedExpr->v; 4002 } 4003 } else { 4004 ResetExpr(*var); 4005 if (context_.AnyFatalError()) { 4006 return std::nullopt; 4007 } 4008 } 4009 } 4010 } 4011 // Not a Variable -> FunctionReference 4012 auto restorer{AllowWholeAssumedSizeArray()}; 4013 return Analyze(selector.u); 4014 } else { // Expr 4015 return Analyze(selector.u); 4016 } 4017 } 4018 4019 MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) { 4020 auto restorer{common::ScopedSet(inDataStmtConstant_, true)}; 4021 return ExprOrVariable(x, x.source); 4022 } 4023 4024 MaybeExpr ExpressionAnalyzer::Analyze(const parser::AllocateObject &x) { 4025 return ExprOrVariable(x, parser::FindSourceLocation(x)); 4026 } 4027 4028 MaybeExpr ExpressionAnalyzer::Analyze(const parser::PointerObject &x) { 4029 return ExprOrVariable(x, parser::FindSourceLocation(x)); 4030 } 4031 4032 Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector( 4033 TypeCategory category, 4034 const std::optional<parser::KindSelector> &selector) { 4035 int defaultKind{GetDefaultKind(category)}; 4036 if (!selector) { 4037 return Expr<SubscriptInteger>{defaultKind}; 4038 } 4039 return common::visit( 4040 common::visitors{ 4041 [&](const parser::ScalarIntConstantExpr &x) { 4042 if (MaybeExpr kind{Analyze(x)}) { 4043 if (std::optional<std::int64_t> code{ToInt64(*kind)}) { 4044 if (CheckIntrinsicKind(category, *code)) { 4045 return Expr<SubscriptInteger>{*code}; 4046 } 4047 } else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(*kind)}) { 4048 return ConvertToType<SubscriptInteger>(std::move(*intExpr)); 4049 } 4050 } 4051 return Expr<SubscriptInteger>{defaultKind}; 4052 }, 4053 [&](const parser::KindSelector::StarSize &x) { 4054 std::intmax_t size = x.v; 4055 if (!CheckIntrinsicSize(category, size)) { 4056 size = defaultKind; 4057 } else if (category == TypeCategory::Complex) { 4058 size /= 2; 4059 } 4060 return Expr<SubscriptInteger>{size}; 4061 }, 4062 }, 4063 selector->u); 4064 } 4065 4066 int ExpressionAnalyzer::GetDefaultKind(common::TypeCategory category) { 4067 return context_.GetDefaultKind(category); 4068 } 4069 4070 DynamicType ExpressionAnalyzer::GetDefaultKindOfType( 4071 common::TypeCategory category) { 4072 return {category, GetDefaultKind(category)}; 4073 } 4074 4075 bool ExpressionAnalyzer::CheckIntrinsicKind( 4076 TypeCategory category, std::int64_t kind) { 4077 if (foldingContext_.targetCharacteristics().IsTypeEnabled( 4078 category, kind)) { // C712, C714, C715, C727 4079 return true; 4080 } else if (foldingContext_.targetCharacteristics().CanSupportType( 4081 category, kind)) { 4082 Warn(common::UsageWarning::BadTypeForTarget, 4083 "%s(KIND=%jd) is not an enabled type for this target"_warn_en_US, 4084 ToUpperCase(EnumToString(category)), kind); 4085 return true; 4086 } else { 4087 Say("%s(KIND=%jd) is not a supported type"_err_en_US, 4088 ToUpperCase(EnumToString(category)), kind); 4089 return false; 4090 } 4091 } 4092 4093 bool ExpressionAnalyzer::CheckIntrinsicSize( 4094 TypeCategory category, std::int64_t size) { 4095 std::int64_t kind{size}; 4096 if (category == TypeCategory::Complex) { 4097 // COMPLEX*16 == COMPLEX(KIND=8) 4098 if (size % 2 == 0) { 4099 kind = size / 2; 4100 } else { 4101 Say("COMPLEX*%jd is not a supported type"_err_en_US, size); 4102 return false; 4103 } 4104 } 4105 if (foldingContext_.targetCharacteristics().IsTypeEnabled( 4106 category, kind)) { // C712, C714, C715, C727 4107 return true; 4108 } else if (foldingContext_.targetCharacteristics().CanSupportType( 4109 category, kind)) { 4110 Warn(common::UsageWarning::BadTypeForTarget, 4111 "%s*%jd is not an enabled type for this target"_warn_en_US, 4112 ToUpperCase(EnumToString(category)), size); 4113 return true; 4114 } else { 4115 Say("%s*%jd is not a supported type"_err_en_US, 4116 ToUpperCase(EnumToString(category)), size); 4117 return false; 4118 } 4119 } 4120 4121 bool ExpressionAnalyzer::AddImpliedDo(parser::CharBlock name, int kind) { 4122 return impliedDos_.insert(std::make_pair(name, kind)).second; 4123 } 4124 4125 void ExpressionAnalyzer::RemoveImpliedDo(parser::CharBlock name) { 4126 auto iter{impliedDos_.find(name)}; 4127 if (iter != impliedDos_.end()) { 4128 impliedDos_.erase(iter); 4129 } 4130 } 4131 4132 std::optional<int> ExpressionAnalyzer::IsImpliedDo( 4133 parser::CharBlock name) const { 4134 auto iter{impliedDos_.find(name)}; 4135 if (iter != impliedDos_.cend()) { 4136 return {iter->second}; 4137 } else { 4138 return std::nullopt; 4139 } 4140 } 4141 4142 bool ExpressionAnalyzer::EnforceTypeConstraint(parser::CharBlock at, 4143 const MaybeExpr &result, TypeCategory category, bool defaultKind) { 4144 if (result) { 4145 if (auto type{result->GetType()}) { 4146 if (type->category() != category) { // C885 4147 Say(at, "Must have %s type, but is %s"_err_en_US, 4148 ToUpperCase(EnumToString(category)), 4149 ToUpperCase(type->AsFortran())); 4150 return false; 4151 } else if (defaultKind) { 4152 int kind{context_.GetDefaultKind(category)}; 4153 if (type->kind() != kind) { 4154 Say(at, "Must have default kind(%d) of %s type, but is %s"_err_en_US, 4155 kind, ToUpperCase(EnumToString(category)), 4156 ToUpperCase(type->AsFortran())); 4157 return false; 4158 } 4159 } 4160 } else { 4161 Say(at, "Must have %s type, but is typeless"_err_en_US, 4162 ToUpperCase(EnumToString(category))); 4163 return false; 4164 } 4165 } 4166 return true; 4167 } 4168 4169 MaybeExpr ExpressionAnalyzer::MakeFunctionRef(parser::CharBlock callSite, 4170 ProcedureDesignator &&proc, ActualArguments &&arguments) { 4171 if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&proc.u)}) { 4172 if (intrinsic->characteristics.value().attrs.test( 4173 characteristics::Procedure::Attr::NullPointer) && 4174 arguments.empty()) { 4175 return Expr<SomeType>{NullPointer{}}; 4176 } 4177 } 4178 if (const Symbol *symbol{proc.GetSymbol()}) { 4179 if (!ResolveForward(*symbol)) { 4180 return std::nullopt; 4181 } 4182 } 4183 if (auto chars{CheckCall(callSite, proc, arguments)}) { 4184 if (chars->functionResult) { 4185 const auto &result{*chars->functionResult}; 4186 ProcedureRef procRef{std::move(proc), std::move(arguments)}; 4187 if (result.IsProcedurePointer()) { 4188 return Expr<SomeType>{std::move(procRef)}; 4189 } else { 4190 // Not a procedure pointer, so type and shape are known. 4191 return TypedWrapper<FunctionRef, ProcedureRef>( 4192 DEREF(result.GetTypeAndShape()).type(), std::move(procRef)); 4193 } 4194 } else { 4195 Say("Function result characteristics are not known"_err_en_US); 4196 } 4197 } 4198 return std::nullopt; 4199 } 4200 4201 MaybeExpr ExpressionAnalyzer::MakeFunctionRef( 4202 parser::CharBlock intrinsic, ActualArguments &&arguments) { 4203 if (std::optional<SpecificCall> specificCall{ 4204 context_.intrinsics().Probe(CallCharacteristics{intrinsic.ToString()}, 4205 arguments, GetFoldingContext())}) { 4206 return MakeFunctionRef(intrinsic, 4207 ProcedureDesignator{std::move(specificCall->specificIntrinsic)}, 4208 std::move(specificCall->arguments)); 4209 } else { 4210 return std::nullopt; 4211 } 4212 } 4213 4214 MaybeExpr ExpressionAnalyzer::AnalyzeComplex( 4215 MaybeExpr &&re, MaybeExpr &&im, const char *what) { 4216 if (re && re->Rank() > 0) { 4217 Warn(common::LanguageFeature::ComplexConstructor, 4218 "Real part of %s is not scalar"_port_en_US, what); 4219 } 4220 if (im && im->Rank() > 0) { 4221 Warn(common::LanguageFeature::ComplexConstructor, 4222 "Imaginary part of %s is not scalar"_port_en_US, what); 4223 } 4224 if (re && im) { 4225 ConformabilityCheck(GetContextualMessages(), *re, *im); 4226 } 4227 return AsMaybeExpr(ConstructComplex(GetContextualMessages(), std::move(re), 4228 std::move(im), GetDefaultKind(TypeCategory::Real))); 4229 } 4230 4231 std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeVariable( 4232 const parser::Variable &x) { 4233 source_.ExtendToCover(x.GetSource()); 4234 if (MaybeExpr expr{context_.Analyze(x)}) { 4235 if (!IsConstantExpr(*expr)) { 4236 ActualArgument actual{std::move(*expr)}; 4237 SetArgSourceLocation(actual, x.GetSource()); 4238 return actual; 4239 } 4240 const Symbol *symbol{GetLastSymbol(*expr)}; 4241 if (!symbol) { 4242 context_.SayAt(x, "Assignment to constant '%s' is not allowed"_err_en_US, 4243 x.GetSource()); 4244 } else if (IsProcedure(*symbol)) { 4245 if (auto *msg{context_.SayAt(x, 4246 "Assignment to procedure '%s' is not allowed"_err_en_US, 4247 symbol->name())}) { 4248 if (auto *subp{symbol->detailsIf<semantics::SubprogramDetails>()}) { 4249 if (subp->isFunction()) { 4250 const auto &result{subp->result().name()}; 4251 msg->Attach(result, "Function result is '%s'"_en_US, result); 4252 } 4253 } 4254 } 4255 } else { 4256 context_.SayAt( 4257 x, "Assignment to '%s' is not allowed"_err_en_US, symbol->name()); 4258 } 4259 } 4260 fatalErrors_ = true; 4261 return std::nullopt; 4262 } 4263 4264 void ArgumentAnalyzer::Analyze(const parser::Variable &x) { 4265 if (auto actual = AnalyzeVariable(x)) { 4266 actuals_.emplace_back(std::move(actual)); 4267 } 4268 } 4269 4270 void ArgumentAnalyzer::Analyze( 4271 const parser::ActualArgSpec &arg, bool isSubroutine) { 4272 // TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed. 4273 std::optional<ActualArgument> actual; 4274 auto restorer{context_.AllowWholeAssumedSizeArray()}; 4275 common::visit( 4276 common::visitors{ 4277 [&](const common::Indirection<parser::Expr> &x) { 4278 actual = AnalyzeExpr(x.value()); 4279 }, 4280 [&](const parser::AltReturnSpec &label) { 4281 if (!isSubroutine) { 4282 context_.Say( 4283 "alternate return specification may not appear on function reference"_err_en_US); 4284 } 4285 actual = ActualArgument(label.v); 4286 }, 4287 [&](const parser::ActualArg::PercentRef &percentRef) { 4288 actual = AnalyzeExpr(percentRef.v); 4289 if (actual.has_value()) { 4290 actual->set_isPercentRef(); 4291 } 4292 }, 4293 [&](const parser::ActualArg::PercentVal &percentVal) { 4294 actual = AnalyzeExpr(percentVal.v); 4295 if (actual.has_value()) { 4296 actual->set_isPercentVal(); 4297 } 4298 }, 4299 }, 4300 std::get<parser::ActualArg>(arg.t).u); 4301 if (actual) { 4302 if (const auto &argKW{std::get<std::optional<parser::Keyword>>(arg.t)}) { 4303 actual->set_keyword(argKW->v.source); 4304 } 4305 actuals_.emplace_back(std::move(*actual)); 4306 } else { 4307 fatalErrors_ = true; 4308 } 4309 } 4310 4311 bool ArgumentAnalyzer::IsIntrinsicRelational(RelationalOperator opr, 4312 const DynamicType &leftType, const DynamicType &rightType) const { 4313 CHECK(actuals_.size() == 2); 4314 return semantics::IsIntrinsicRelational( 4315 opr, leftType, GetRank(0), rightType, GetRank(1)); 4316 } 4317 4318 bool ArgumentAnalyzer::IsIntrinsicNumeric(NumericOperator opr) const { 4319 std::optional<DynamicType> leftType{GetType(0)}; 4320 if (actuals_.size() == 1) { 4321 if (IsBOZLiteral(0)) { 4322 return opr == NumericOperator::Add; // unary '+' 4323 } else { 4324 return leftType && semantics::IsIntrinsicNumeric(*leftType); 4325 } 4326 } else { 4327 std::optional<DynamicType> rightType{GetType(1)}; 4328 if (IsBOZLiteral(0) && rightType) { // BOZ opr Integer/Unsigned/Real 4329 auto cat1{rightType->category()}; 4330 return cat1 == TypeCategory::Integer || cat1 == TypeCategory::Unsigned || 4331 cat1 == TypeCategory::Real; 4332 } else if (IsBOZLiteral(1) && leftType) { // Integer/Unsigned/Real opr BOZ 4333 auto cat0{leftType->category()}; 4334 return cat0 == TypeCategory::Integer || cat0 == TypeCategory::Unsigned || 4335 cat0 == TypeCategory::Real; 4336 } else { 4337 return leftType && rightType && 4338 semantics::IsIntrinsicNumeric( 4339 *leftType, GetRank(0), *rightType, GetRank(1)); 4340 } 4341 } 4342 } 4343 4344 bool ArgumentAnalyzer::IsIntrinsicLogical() const { 4345 if (std::optional<DynamicType> leftType{GetType(0)}) { 4346 if (actuals_.size() == 1) { 4347 return semantics::IsIntrinsicLogical(*leftType); 4348 } else if (std::optional<DynamicType> rightType{GetType(1)}) { 4349 return semantics::IsIntrinsicLogical( 4350 *leftType, GetRank(0), *rightType, GetRank(1)); 4351 } 4352 } 4353 return false; 4354 } 4355 4356 bool ArgumentAnalyzer::IsIntrinsicConcat() const { 4357 if (std::optional<DynamicType> leftType{GetType(0)}) { 4358 if (std::optional<DynamicType> rightType{GetType(1)}) { 4359 return semantics::IsIntrinsicConcat( 4360 *leftType, GetRank(0), *rightType, GetRank(1)); 4361 } 4362 } 4363 return false; 4364 } 4365 4366 bool ArgumentAnalyzer::CheckConformance() { 4367 if (actuals_.size() == 2) { 4368 const auto *lhs{actuals_.at(0).value().UnwrapExpr()}; 4369 const auto *rhs{actuals_.at(1).value().UnwrapExpr()}; 4370 if (lhs && rhs) { 4371 auto &foldingContext{context_.GetFoldingContext()}; 4372 auto lhShape{GetShape(foldingContext, *lhs)}; 4373 auto rhShape{GetShape(foldingContext, *rhs)}; 4374 if (lhShape && rhShape) { 4375 if (!evaluate::CheckConformance(foldingContext.messages(), *lhShape, 4376 *rhShape, CheckConformanceFlags::EitherScalarExpandable, 4377 "left operand", "right operand") 4378 .value_or(false /*fail when conformance is not known now*/)) { 4379 fatalErrors_ = true; 4380 return false; 4381 } 4382 } 4383 } 4384 } 4385 return true; // no proven problem 4386 } 4387 4388 bool ArgumentAnalyzer::CheckAssignmentConformance() { 4389 if (actuals_.size() == 2 && actuals_[0] && actuals_[1]) { 4390 const auto *lhs{actuals_[0]->UnwrapExpr()}; 4391 const auto *rhs{actuals_[1]->UnwrapExpr()}; 4392 if (lhs && rhs) { 4393 auto &foldingContext{context_.GetFoldingContext()}; 4394 auto lhShape{GetShape(foldingContext, *lhs)}; 4395 auto rhShape{GetShape(foldingContext, *rhs)}; 4396 if (lhShape && rhShape) { 4397 if (!evaluate::CheckConformance(foldingContext.messages(), *lhShape, 4398 *rhShape, CheckConformanceFlags::RightScalarExpandable, 4399 "left-hand side", "right-hand side") 4400 .value_or(true /*ok when conformance is not known now*/)) { 4401 fatalErrors_ = true; 4402 return false; 4403 } 4404 } 4405 } 4406 } 4407 return true; // no proven problem 4408 } 4409 4410 bool ArgumentAnalyzer::CheckForNullPointer(const char *where) { 4411 for (const std::optional<ActualArgument> &arg : actuals_) { 4412 if (arg) { 4413 if (const Expr<SomeType> *expr{arg->UnwrapExpr()}) { 4414 if (IsNullPointer(*expr)) { 4415 context_.Say( 4416 source_, "A NULL() pointer is not allowed %s"_err_en_US, where); 4417 fatalErrors_ = true; 4418 return false; 4419 } 4420 } 4421 } 4422 } 4423 return true; 4424 } 4425 4426 bool ArgumentAnalyzer::CheckForAssumedRank(const char *where) { 4427 for (const std::optional<ActualArgument> &arg : actuals_) { 4428 if (arg && IsAssumedRank(arg->UnwrapExpr())) { 4429 context_.Say(source_, 4430 "An assumed-rank dummy argument is not allowed %s"_err_en_US, where); 4431 fatalErrors_ = true; 4432 return false; 4433 } 4434 } 4435 return true; 4436 } 4437 4438 MaybeExpr ArgumentAnalyzer::TryDefinedOp( 4439 const char *opr, parser::MessageFixedText error, bool isUserOp) { 4440 if (AnyUntypedOrMissingOperand()) { 4441 context_.Say(error, ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1)); 4442 return std::nullopt; 4443 } 4444 MaybeExpr result; 4445 bool anyPossibilities{false}; 4446 std::optional<parser::MessageFormattedText> inaccessible; 4447 std::vector<const Symbol *> hit; 4448 std::string oprNameString{ 4449 isUserOp ? std::string{opr} : "operator("s + opr + ')'}; 4450 parser::CharBlock oprName{oprNameString}; 4451 parser::Messages hitBuffer; 4452 { 4453 parser::Messages buffer; 4454 auto restorer{context_.GetContextualMessages().SetMessages(buffer)}; 4455 const auto &scope{context_.context().FindScope(source_)}; 4456 if (Symbol *symbol{scope.FindSymbol(oprName)}) { 4457 anyPossibilities = true; 4458 parser::Name name{symbol->name(), symbol}; 4459 if (!fatalErrors_) { 4460 result = context_.AnalyzeDefinedOp(name, GetActuals()); 4461 } 4462 if (result) { 4463 inaccessible = CheckAccessibleSymbol(scope, *symbol); 4464 if (inaccessible) { 4465 result.reset(); 4466 } else { 4467 hit.push_back(symbol); 4468 hitBuffer = std::move(buffer); 4469 } 4470 } 4471 } 4472 for (std::size_t passIndex{0}; passIndex < actuals_.size(); ++passIndex) { 4473 buffer.clear(); 4474 const Symbol *generic{nullptr}; 4475 if (const Symbol *binding{ 4476 FindBoundOp(oprName, passIndex, generic, false)}) { 4477 anyPossibilities = true; 4478 if (MaybeExpr thisResult{TryBoundOp(*binding, passIndex)}) { 4479 if (auto thisInaccessible{ 4480 CheckAccessibleSymbol(scope, DEREF(generic))}) { 4481 inaccessible = thisInaccessible; 4482 } else { 4483 result = std::move(thisResult); 4484 hit.push_back(binding); 4485 hitBuffer = std::move(buffer); 4486 } 4487 } 4488 } 4489 } 4490 } 4491 if (result) { 4492 if (hit.size() > 1) { 4493 if (auto *msg{context_.Say( 4494 "%zd matching accessible generic interfaces for %s were found"_err_en_US, 4495 hit.size(), ToUpperCase(opr))}) { 4496 for (const Symbol *symbol : hit) { 4497 AttachDeclaration(*msg, *symbol); 4498 } 4499 } 4500 } 4501 if (auto *msgs{context_.GetContextualMessages().messages()}) { 4502 msgs->Annex(std::move(hitBuffer)); 4503 } 4504 } else if (inaccessible) { 4505 context_.Say(source_, std::move(*inaccessible)); 4506 } else if (anyPossibilities) { 4507 SayNoMatch(ToUpperCase(oprNameString), false); 4508 } else if (actuals_.size() == 2 && !AreConformable()) { 4509 context_.Say( 4510 "Operands of %s are not conformable; have rank %d and rank %d"_err_en_US, 4511 ToUpperCase(opr), actuals_[0]->Rank(), actuals_[1]->Rank()); 4512 } else if (CheckForNullPointer() && CheckForAssumedRank()) { 4513 context_.Say(error, ToUpperCase(opr), TypeAsFortran(0), TypeAsFortran(1)); 4514 } 4515 return result; 4516 } 4517 4518 MaybeExpr ArgumentAnalyzer::TryDefinedOp( 4519 const std::vector<const char *> &oprs, parser::MessageFixedText error) { 4520 if (oprs.size() == 1) { 4521 return TryDefinedOp(oprs[0], error); 4522 } 4523 MaybeExpr result; 4524 std::vector<const char *> hit; 4525 parser::Messages hitBuffer; 4526 { 4527 for (std::size_t i{0}; i < oprs.size(); ++i) { 4528 parser::Messages buffer; 4529 auto restorer{context_.GetContextualMessages().SetMessages(buffer)}; 4530 if (MaybeExpr thisResult{TryDefinedOp(oprs[i], error)}) { 4531 result = std::move(thisResult); 4532 hit.push_back(oprs[i]); 4533 hitBuffer = std::move(buffer); 4534 } 4535 } 4536 } 4537 if (hit.empty()) { // for the error 4538 result = TryDefinedOp(oprs[0], error); 4539 } else if (hit.size() > 1) { 4540 context_.Say( 4541 "Matching accessible definitions were found with %zd variant spellings of the generic operator ('%s', '%s')"_err_en_US, 4542 hit.size(), ToUpperCase(hit[0]), ToUpperCase(hit[1])); 4543 } else { // one hit; preserve errors 4544 context_.context().messages().Annex(std::move(hitBuffer)); 4545 } 4546 return result; 4547 } 4548 4549 MaybeExpr ArgumentAnalyzer::TryBoundOp(const Symbol &symbol, int passIndex) { 4550 ActualArguments localActuals{actuals_}; 4551 const Symbol *proc{GetBindingResolution(GetType(passIndex), symbol)}; 4552 if (!proc) { 4553 proc = &symbol; 4554 localActuals.at(passIndex).value().set_isPassedObject(); 4555 } 4556 CheckConformance(); 4557 return context_.MakeFunctionRef( 4558 source_, ProcedureDesignator{*proc}, std::move(localActuals)); 4559 } 4560 4561 std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() { 4562 using semantics::Tristate; 4563 const Expr<SomeType> &lhs{GetExpr(0)}; 4564 const Expr<SomeType> &rhs{GetExpr(1)}; 4565 std::optional<DynamicType> lhsType{lhs.GetType()}; 4566 std::optional<DynamicType> rhsType{rhs.GetType()}; 4567 int lhsRank{lhs.Rank()}; 4568 int rhsRank{rhs.Rank()}; 4569 Tristate isDefined{ 4570 semantics::IsDefinedAssignment(lhsType, lhsRank, rhsType, rhsRank)}; 4571 if (isDefined == Tristate::No) { 4572 // Make implicit conversion explicit, unless it is an assignment to a whole 4573 // allocatable (the explicit conversion would prevent the propagation of the 4574 // right hand side if it is a variable). Lowering will deal with the 4575 // conversion in this case. 4576 if (lhsType) { 4577 if (rhsType) { 4578 if (!IsAllocatableDesignator(lhs) || context_.inWhereBody()) { 4579 AddAssignmentConversion(*lhsType, *rhsType); 4580 } 4581 } else { 4582 if (lhsType->category() == TypeCategory::Integer || 4583 lhsType->category() == TypeCategory::Unsigned || 4584 lhsType->category() == TypeCategory::Real) { 4585 ConvertBOZ(nullptr, 1, lhsType); 4586 } 4587 if (IsBOZLiteral(1)) { 4588 context_.Say( 4589 "Right-hand side of this assignment may not be BOZ"_err_en_US); 4590 fatalErrors_ = true; 4591 } 4592 } 4593 } 4594 if (!fatalErrors_) { 4595 CheckAssignmentConformance(); 4596 } 4597 return std::nullopt; // user-defined assignment not allowed for these args 4598 } 4599 auto restorer{context_.GetContextualMessages().SetLocation(source_)}; 4600 if (std::optional<ProcedureRef> procRef{GetDefinedAssignmentProc()}) { 4601 if (context_.inWhereBody() && !procRef->proc().IsElemental()) { // C1032 4602 context_.Say( 4603 "Defined assignment in WHERE must be elemental, but '%s' is not"_err_en_US, 4604 DEREF(procRef->proc().GetSymbol()).name()); 4605 } 4606 context_.CheckCall(source_, procRef->proc(), procRef->arguments()); 4607 return std::move(*procRef); 4608 } 4609 if (isDefined == Tristate::Yes) { 4610 if (!lhsType || !rhsType || (lhsRank != rhsRank && rhsRank != 0) || 4611 !OkLogicalIntegerAssignment(lhsType->category(), rhsType->category())) { 4612 SayNoMatch("ASSIGNMENT(=)", true); 4613 } 4614 } else if (!fatalErrors_) { 4615 CheckAssignmentConformance(); 4616 } 4617 return std::nullopt; 4618 } 4619 4620 bool ArgumentAnalyzer::OkLogicalIntegerAssignment( 4621 TypeCategory lhs, TypeCategory rhs) { 4622 if (!context_.context().languageFeatures().IsEnabled( 4623 common::LanguageFeature::LogicalIntegerAssignment)) { 4624 return false; 4625 } 4626 std::optional<parser::MessageFixedText> msg; 4627 if (lhs == TypeCategory::Integer && rhs == TypeCategory::Logical) { 4628 // allow assignment to LOGICAL from INTEGER as a legacy extension 4629 msg = "assignment of LOGICAL to INTEGER"_port_en_US; 4630 } else if (lhs == TypeCategory::Logical && rhs == TypeCategory::Integer) { 4631 // ... and assignment to LOGICAL from INTEGER 4632 msg = "assignment of INTEGER to LOGICAL"_port_en_US; 4633 } else { 4634 return false; 4635 } 4636 context_.Warn( 4637 common::LanguageFeature::LogicalIntegerAssignment, std::move(*msg)); 4638 return true; 4639 } 4640 4641 std::optional<ProcedureRef> ArgumentAnalyzer::GetDefinedAssignmentProc() { 4642 const Symbol *proc{nullptr}; 4643 std::optional<int> passedObjectIndex; 4644 std::string oprNameString{"assignment(=)"}; 4645 parser::CharBlock oprName{oprNameString}; 4646 const auto &scope{context_.context().FindScope(source_)}; 4647 // If multiple resolutions were possible, they will have been already 4648 // diagnosed. 4649 { 4650 auto restorer{context_.GetContextualMessages().DiscardMessages()}; 4651 if (const Symbol *symbol{scope.FindSymbol(oprName)}) { 4652 ExpressionAnalyzer::AdjustActuals noAdjustment; 4653 proc = 4654 context_.ResolveGeneric(*symbol, actuals_, noAdjustment, true).first; 4655 } 4656 for (std::size_t i{0}; !proc && i < actuals_.size(); ++i) { 4657 const Symbol *generic{nullptr}; 4658 if (const Symbol *binding{FindBoundOp(oprName, i, generic, true)}) { 4659 if (CheckAccessibleSymbol(scope, DEREF(generic))) { 4660 // ignore inaccessible type-bound ASSIGNMENT(=) generic 4661 } else if (const Symbol * 4662 resolution{GetBindingResolution(GetType(i), *binding)}) { 4663 proc = resolution; 4664 } else { 4665 proc = binding; 4666 passedObjectIndex = i; 4667 } 4668 } 4669 } 4670 } 4671 if (!proc) { 4672 return std::nullopt; 4673 } 4674 ActualArguments actualsCopy{actuals_}; 4675 // Ensure that the RHS argument is not passed as a variable unless 4676 // the dummy argument has the VALUE attribute. 4677 if (evaluate::IsVariable(actualsCopy.at(1).value().UnwrapExpr())) { 4678 auto chars{evaluate::characteristics::Procedure::Characterize( 4679 *proc, context_.GetFoldingContext())}; 4680 const auto *rhsDummy{chars && chars->dummyArguments.size() == 2 4681 ? std::get_if<evaluate::characteristics::DummyDataObject>( 4682 &chars->dummyArguments.at(1).u) 4683 : nullptr}; 4684 if (!rhsDummy || 4685 !rhsDummy->attrs.test( 4686 evaluate::characteristics::DummyDataObject::Attr::Value)) { 4687 actualsCopy.at(1).value().Parenthesize(); 4688 } 4689 } 4690 if (passedObjectIndex) { 4691 actualsCopy[*passedObjectIndex]->set_isPassedObject(); 4692 } 4693 return ProcedureRef{ProcedureDesignator{*proc}, std::move(actualsCopy)}; 4694 } 4695 4696 void ArgumentAnalyzer::Dump(llvm::raw_ostream &os) { 4697 os << "source_: " << source_.ToString() << " fatalErrors_ = " << fatalErrors_ 4698 << '\n'; 4699 for (const auto &actual : actuals_) { 4700 if (!actual.has_value()) { 4701 os << "- error\n"; 4702 } else if (const Symbol *symbol{actual->GetAssumedTypeDummy()}) { 4703 os << "- assumed type: " << symbol->name().ToString() << '\n'; 4704 } else if (const Expr<SomeType> *expr{actual->UnwrapExpr()}) { 4705 expr->AsFortran(os << "- expr: ") << '\n'; 4706 } else { 4707 DIE("bad ActualArgument"); 4708 } 4709 } 4710 } 4711 4712 std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr( 4713 const parser::Expr &expr) { 4714 source_.ExtendToCover(expr.source); 4715 if (const Symbol *assumedTypeDummy{AssumedTypeDummy(expr)}) { 4716 ResetExpr(expr); 4717 if (isProcedureCall_) { 4718 ActualArgument arg{ActualArgument::AssumedType{*assumedTypeDummy}}; 4719 SetArgSourceLocation(arg, expr.source); 4720 return std::move(arg); 4721 } 4722 context_.SayAt(expr.source, 4723 "TYPE(*) dummy argument may only be used as an actual argument"_err_en_US); 4724 } else if (MaybeExpr argExpr{AnalyzeExprOrWholeAssumedSizeArray(expr)}) { 4725 if (isProcedureCall_ || !IsProcedureDesignator(*argExpr)) { 4726 ActualArgument arg{std::move(*argExpr)}; 4727 SetArgSourceLocation(arg, expr.source); 4728 return std::move(arg); 4729 } 4730 context_.SayAt(expr.source, 4731 IsFunctionDesignator(*argExpr) 4732 ? "Function call must have argument list"_err_en_US 4733 : "Subroutine name is not allowed here"_err_en_US); 4734 } 4735 return std::nullopt; 4736 } 4737 4738 MaybeExpr ArgumentAnalyzer::AnalyzeExprOrWholeAssumedSizeArray( 4739 const parser::Expr &expr) { 4740 // If an expression's parse tree is a whole assumed-size array: 4741 // Expr -> Designator -> DataRef -> Name 4742 // treat it as a special case for argument passing and bypass 4743 // the C1002/C1014 constraint checking in expression semantics. 4744 if (const auto *name{parser::Unwrap<parser::Name>(expr)}) { 4745 if (name->symbol && semantics::IsAssumedSizeArray(*name->symbol)) { 4746 auto restorer{context_.AllowWholeAssumedSizeArray()}; 4747 return context_.Analyze(expr); 4748 } 4749 } 4750 auto restorer{context_.AllowNullPointer()}; 4751 return context_.Analyze(expr); 4752 } 4753 4754 bool ArgumentAnalyzer::AreConformable() const { 4755 CHECK(actuals_.size() == 2); 4756 return actuals_[0] && actuals_[1] && 4757 evaluate::AreConformable(*actuals_[0], *actuals_[1]); 4758 } 4759 4760 // Look for a type-bound operator in the type of arg number passIndex. 4761 const Symbol *ArgumentAnalyzer::FindBoundOp(parser::CharBlock oprName, 4762 int passIndex, const Symbol *&generic, bool isSubroutine) { 4763 const auto *type{GetDerivedTypeSpec(GetType(passIndex))}; 4764 const semantics::Scope *scope{type ? type->scope() : nullptr}; 4765 if (scope) { 4766 // Use the original type definition's scope, since PDT 4767 // instantiations don't have redundant copies of bindings or 4768 // generics. 4769 scope = DEREF(scope->derivedTypeSpec()).typeSymbol().scope(); 4770 } 4771 generic = scope ? scope->FindComponent(oprName) : nullptr; 4772 if (generic) { 4773 ExpressionAnalyzer::AdjustActuals adjustment{ 4774 [&](const Symbol &proc, ActualArguments &) { 4775 return passIndex == GetPassIndex(proc).value_or(-1); 4776 }}; 4777 auto pair{ 4778 context_.ResolveGeneric(*generic, actuals_, adjustment, isSubroutine)}; 4779 if (const Symbol *binding{pair.first}) { 4780 CHECK(binding->has<semantics::ProcBindingDetails>()); 4781 // Use the most recent override of the binding, if any 4782 return scope->FindComponent(binding->name()); 4783 } else { 4784 context_.EmitGenericResolutionError(*generic, pair.second, isSubroutine); 4785 } 4786 } 4787 return nullptr; 4788 } 4789 4790 // If there is an implicit conversion between intrinsic types, make it explicit 4791 void ArgumentAnalyzer::AddAssignmentConversion( 4792 const DynamicType &lhsType, const DynamicType &rhsType) { 4793 if (lhsType.category() == rhsType.category() && 4794 (lhsType.category() == TypeCategory::Derived || 4795 lhsType.kind() == rhsType.kind())) { 4796 // no conversion necessary 4797 } else if (auto rhsExpr{evaluate::Fold(context_.GetFoldingContext(), 4798 evaluate::ConvertToType(lhsType, MoveExpr(1)))}) { 4799 std::optional<parser::CharBlock> source; 4800 if (actuals_[1]) { 4801 source = actuals_[1]->sourceLocation(); 4802 } 4803 actuals_[1] = ActualArgument{*rhsExpr}; 4804 SetArgSourceLocation(actuals_[1], source); 4805 } else { 4806 actuals_[1] = std::nullopt; 4807 } 4808 } 4809 4810 std::optional<DynamicType> ArgumentAnalyzer::GetType(std::size_t i) const { 4811 return i < actuals_.size() ? actuals_[i].value().GetType() : std::nullopt; 4812 } 4813 int ArgumentAnalyzer::GetRank(std::size_t i) const { 4814 return i < actuals_.size() ? actuals_[i].value().Rank() : 0; 4815 } 4816 4817 // If the argument at index i is a BOZ literal, convert its type to match the 4818 // otherType. If it's REAL, convert to REAL; if it's UNSIGNED, convert to 4819 // UNSIGNED; otherwise, convert to INTEGER. 4820 // Note that IBM supports comparing BOZ literals to CHARACTER operands. That 4821 // is not currently supported. 4822 void ArgumentAnalyzer::ConvertBOZ(std::optional<DynamicType> *thisType, 4823 std::size_t i, std::optional<DynamicType> otherType) { 4824 if (IsBOZLiteral(i)) { 4825 Expr<SomeType> &&argExpr{MoveExpr(i)}; 4826 auto *boz{std::get_if<BOZLiteralConstant>(&argExpr.u)}; 4827 if (otherType && otherType->category() == TypeCategory::Real) { 4828 int kind{context_.context().GetDefaultKind(TypeCategory::Real)}; 4829 MaybeExpr realExpr{ 4830 ConvertToKind<TypeCategory::Real>(kind, std::move(*boz))}; 4831 actuals_[i] = std::move(realExpr.value()); 4832 if (thisType) { 4833 thisType->emplace(TypeCategory::Real, kind); 4834 } 4835 } else if (otherType && otherType->category() == TypeCategory::Unsigned) { 4836 int kind{context_.context().GetDefaultKind(TypeCategory::Unsigned)}; 4837 MaybeExpr unsignedExpr{ 4838 ConvertToKind<TypeCategory::Unsigned>(kind, std::move(*boz))}; 4839 actuals_[i] = std::move(unsignedExpr.value()); 4840 if (thisType) { 4841 thisType->emplace(TypeCategory::Unsigned, kind); 4842 } 4843 } else { 4844 int kind{context_.context().GetDefaultKind(TypeCategory::Integer)}; 4845 MaybeExpr intExpr{ 4846 ConvertToKind<TypeCategory::Integer>(kind, std::move(*boz))}; 4847 actuals_[i] = std::move(*intExpr); 4848 if (thisType) { 4849 thisType->emplace(TypeCategory::Integer, kind); 4850 } 4851 } 4852 } 4853 } 4854 4855 // Report error resolving opr when there is a user-defined one available 4856 void ArgumentAnalyzer::SayNoMatch(const std::string &opr, bool isAssignment) { 4857 std::string type0{TypeAsFortran(0)}; 4858 auto rank0{actuals_[0]->Rank()}; 4859 if (actuals_.size() == 1) { 4860 if (rank0 > 0) { 4861 context_.Say("No intrinsic or user-defined %s matches " 4862 "rank %d array of %s"_err_en_US, 4863 opr, rank0, type0); 4864 } else { 4865 context_.Say("No intrinsic or user-defined %s matches " 4866 "operand type %s"_err_en_US, 4867 opr, type0); 4868 } 4869 } else { 4870 std::string type1{TypeAsFortran(1)}; 4871 auto rank1{actuals_[1]->Rank()}; 4872 if (rank0 > 0 && rank1 > 0 && rank0 != rank1) { 4873 context_.Say("No intrinsic or user-defined %s matches " 4874 "rank %d array of %s and rank %d array of %s"_err_en_US, 4875 opr, rank0, type0, rank1, type1); 4876 } else if (isAssignment && rank0 != rank1) { 4877 if (rank0 == 0) { 4878 context_.Say("No intrinsic or user-defined %s matches " 4879 "scalar %s and rank %d array of %s"_err_en_US, 4880 opr, type0, rank1, type1); 4881 } else { 4882 context_.Say("No intrinsic or user-defined %s matches " 4883 "rank %d array of %s and scalar %s"_err_en_US, 4884 opr, rank0, type0, type1); 4885 } 4886 } else { 4887 context_.Say("No intrinsic or user-defined %s matches " 4888 "operand types %s and %s"_err_en_US, 4889 opr, type0, type1); 4890 } 4891 } 4892 } 4893 4894 std::string ArgumentAnalyzer::TypeAsFortran(std::size_t i) { 4895 if (i >= actuals_.size() || !actuals_[i]) { 4896 return "missing argument"; 4897 } else if (std::optional<DynamicType> type{GetType(i)}) { 4898 return type->IsAssumedType() ? "TYPE(*)"s 4899 : type->IsUnlimitedPolymorphic() ? "CLASS(*)"s 4900 : type->IsPolymorphic() ? type->AsFortran() 4901 : type->category() == TypeCategory::Derived 4902 ? "TYPE("s + type->AsFortran() + ')' 4903 : type->category() == TypeCategory::Character 4904 ? "CHARACTER(KIND="s + std::to_string(type->kind()) + ')' 4905 : ToUpperCase(type->AsFortran()); 4906 } else { 4907 return "untyped"; 4908 } 4909 } 4910 4911 bool ArgumentAnalyzer::AnyUntypedOrMissingOperand() { 4912 for (const auto &actual : actuals_) { 4913 if (!actual || 4914 (!actual->GetType() && !IsBareNullPointer(actual->UnwrapExpr()))) { 4915 return true; 4916 } 4917 } 4918 return false; 4919 } 4920 } // namespace Fortran::evaluate 4921 4922 namespace Fortran::semantics { 4923 evaluate::Expr<evaluate::SubscriptInteger> AnalyzeKindSelector( 4924 SemanticsContext &context, common::TypeCategory category, 4925 const std::optional<parser::KindSelector> &selector) { 4926 evaluate::ExpressionAnalyzer analyzer{context}; 4927 CHECK(context.location().has_value()); 4928 auto restorer{ 4929 analyzer.GetContextualMessages().SetLocation(*context.location())}; 4930 return analyzer.AnalyzeKindSelector(category, selector); 4931 } 4932 4933 ExprChecker::ExprChecker(SemanticsContext &context) : context_{context} {} 4934 4935 bool ExprChecker::Pre(const parser::DataStmtObject &obj) { 4936 exprAnalyzer_.set_inDataStmtObject(true); 4937 return true; 4938 } 4939 4940 void ExprChecker::Post(const parser::DataStmtObject &obj) { 4941 exprAnalyzer_.set_inDataStmtObject(false); 4942 } 4943 4944 bool ExprChecker::Pre(const parser::DataImpliedDo &ido) { 4945 parser::Walk(std::get<parser::DataImpliedDo::Bounds>(ido.t), *this); 4946 const auto &bounds{std::get<parser::DataImpliedDo::Bounds>(ido.t)}; 4947 auto name{bounds.name.thing.thing}; 4948 int kind{evaluate::ResultType<evaluate::ImpliedDoIndex>::kind}; 4949 if (const auto dynamicType{evaluate::DynamicType::From(*name.symbol)}) { 4950 if (dynamicType->category() == TypeCategory::Integer) { 4951 kind = dynamicType->kind(); 4952 } 4953 } 4954 exprAnalyzer_.AddImpliedDo(name.source, kind); 4955 parser::Walk(std::get<std::list<parser::DataIDoObject>>(ido.t), *this); 4956 exprAnalyzer_.RemoveImpliedDo(name.source); 4957 return false; 4958 } 4959 4960 bool ExprChecker::Walk(const parser::Program &program) { 4961 parser::Walk(program, *this); 4962 return !context_.AnyFatalError(); 4963 } 4964 } // namespace Fortran::semantics 4965