1 //===-- lib/Semantics/type.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/type.h" 10 #include "check-declarations.h" 11 #include "compute-offsets.h" 12 #include "flang/Evaluate/fold.h" 13 #include "flang/Evaluate/tools.h" 14 #include "flang/Evaluate/type.h" 15 #include "flang/Parser/characters.h" 16 #include "flang/Parser/parse-tree-visitor.h" 17 #include "flang/Semantics/scope.h" 18 #include "flang/Semantics/symbol.h" 19 #include "flang/Semantics/tools.h" 20 #include "llvm/Support/raw_ostream.h" 21 22 namespace Fortran::semantics { 23 24 DerivedTypeSpec::DerivedTypeSpec(SourceName name, const Symbol &typeSymbol) 25 : name_{name}, originalTypeSymbol_{typeSymbol}, 26 typeSymbol_{typeSymbol.GetUltimate()} { 27 CHECK(typeSymbol_.has<DerivedTypeDetails>()); 28 } 29 DerivedTypeSpec::DerivedTypeSpec(const DerivedTypeSpec &that) = default; 30 DerivedTypeSpec::DerivedTypeSpec(DerivedTypeSpec &&that) = default; 31 32 void DerivedTypeSpec::set_scope(const Scope &scope) { 33 CHECK(!scope_); 34 ReplaceScope(scope); 35 } 36 void DerivedTypeSpec::ReplaceScope(const Scope &scope) { 37 CHECK(scope.IsDerivedType()); 38 scope_ = &scope; 39 } 40 41 const Scope *DerivedTypeSpec::GetScope() const { 42 return scope_ ? scope_ : typeSymbol_.scope(); 43 } 44 45 void DerivedTypeSpec::AddRawParamValue( 46 const parser::Keyword *keyword, ParamValue &&value) { 47 CHECK(parameters_.empty()); 48 rawParameters_.emplace_back(keyword, std::move(value)); 49 } 50 51 void DerivedTypeSpec::CookParameters(evaluate::FoldingContext &foldingContext) { 52 if (cooked_) { 53 return; 54 } 55 cooked_ = true; 56 auto &messages{foldingContext.messages()}; 57 if (IsForwardReferenced()) { 58 messages.Say(typeSymbol_.name(), 59 "Derived type '%s' was used but never defined"_err_en_US, 60 typeSymbol_.name()); 61 return; 62 } 63 64 // Parameters of the most deeply nested "base class" come first when the 65 // derived type is an extension. 66 auto parameterNames{OrderParameterNames(typeSymbol_)}; 67 auto nextNameIter{parameterNames.begin()}; 68 RawParameters raw{std::move(rawParameters_)}; 69 for (auto &[maybeKeyword, value] : raw) { 70 SourceName name; 71 common::TypeParamAttr attr{common::TypeParamAttr::Kind}; 72 if (maybeKeyword) { 73 name = maybeKeyword->v.source; 74 auto it{std::find_if(parameterNames.begin(), parameterNames.end(), 75 [&](const Symbol &symbol) { return symbol.name() == name; })}; 76 if (it == parameterNames.end()) { 77 messages.Say(name, 78 "'%s' is not the name of a parameter for derived type '%s'"_err_en_US, 79 name, typeSymbol_.name()); 80 } else { 81 // Resolve the keyword's symbol 82 maybeKeyword->v.symbol = const_cast<Symbol *>(&it->get()); 83 if (const auto *tpd{it->get().detailsIf<TypeParamDetails>()}) { 84 attr = tpd->attr().value_or(attr); 85 } 86 } 87 } else if (nextNameIter != parameterNames.end()) { 88 name = nextNameIter->get().name(); 89 if (const auto *tpd{nextNameIter->get().detailsIf<TypeParamDetails>()}) { 90 attr = tpd->attr().value_or(attr); 91 } 92 ++nextNameIter; 93 } else { 94 messages.Say(name_, 95 "Too many type parameters given for derived type '%s'"_err_en_US, 96 typeSymbol_.name()); 97 break; 98 } 99 if (FindParameter(name)) { 100 messages.Say(name_, 101 "Multiple values given for type parameter '%s'"_err_en_US, name); 102 } else { 103 value.set_attr(attr); 104 AddParamValue(name, std::move(value)); 105 } 106 } 107 } 108 109 void DerivedTypeSpec::EvaluateParameters(SemanticsContext &context) { 110 evaluate::FoldingContext &foldingContext{context.foldingContext()}; 111 CookParameters(foldingContext); 112 if (evaluated_) { 113 return; 114 } 115 evaluated_ = true; 116 auto &messages{foldingContext.messages()}; 117 for (const Symbol &symbol : OrderParameterDeclarations(typeSymbol_)) { 118 SourceName name{symbol.name()}; 119 int parameterKind{evaluate::TypeParamInquiry::Result::kind}; 120 // Compute the integer kind value of the type parameter, 121 // which may depend on the values of earlier ones. 122 if (const auto *typeSpec{symbol.GetType()}) { 123 if (const IntrinsicTypeSpec * intrinType{typeSpec->AsIntrinsic()}; 124 intrinType && intrinType->category() == TypeCategory::Integer) { 125 auto restorer{foldingContext.WithPDTInstance(*this)}; 126 auto folded{Fold(foldingContext, KindExpr{intrinType->kind()})}; 127 if (auto k{evaluate::ToInt64(folded)}; k && 128 evaluate::IsValidKindOfIntrinsicType(TypeCategory::Integer, *k)) { 129 parameterKind = static_cast<int>(*k); 130 } else { 131 messages.Say( 132 "Type of type parameter '%s' (%s) is not a valid kind of INTEGER"_err_en_US, 133 name, intrinType->kind().AsFortran()); 134 } 135 } 136 } 137 bool ok{ 138 symbol.get<TypeParamDetails>().attr() == common::TypeParamAttr::Len}; 139 if (ParamValue * paramValue{FindParameter(name)}) { 140 // Explicit type parameter value expressions are not folded within 141 // the scope of the derived type being instantiated, as the expressions 142 // themselves are not in that scope and cannot reference its type 143 // parameters. 144 if (const MaybeIntExpr & expr{paramValue->GetExplicit()}) { 145 evaluate::DynamicType dyType{TypeCategory::Integer, parameterKind}; 146 if (auto converted{evaluate::ConvertToType(dyType, SomeExpr{*expr})}) { 147 SomeExpr folded{ 148 evaluate::Fold(foldingContext, std::move(*converted))}; 149 if (auto *intExpr{std::get_if<SomeIntExpr>(&folded.u)}) { 150 ok = ok || evaluate::IsActuallyConstant(*intExpr); 151 paramValue->SetExplicit(std::move(*intExpr)); 152 } 153 } else if (!context.HasError(symbol)) { 154 evaluate::SayWithDeclaration(messages, symbol, 155 "Value of type parameter '%s' (%s) is not convertible to its type (%s)"_err_en_US, 156 name, expr->AsFortran(), dyType.AsFortran()); 157 } 158 } 159 } else { 160 // Default type parameter value expressions are folded within 161 // the scope of the derived type being instantiated. 162 const TypeParamDetails &details{symbol.get<TypeParamDetails>()}; 163 if (details.init() && details.attr()) { 164 evaluate::DynamicType dyType{TypeCategory::Integer, parameterKind}; 165 if (auto converted{ 166 evaluate::ConvertToType(dyType, SomeExpr{*details.init()})}) { 167 auto restorer{foldingContext.WithPDTInstance(*this)}; 168 SomeExpr folded{ 169 evaluate::Fold(foldingContext, std::move(*converted))}; 170 ok = ok || evaluate::IsActuallyConstant(folded); 171 AddParamValue(name, 172 ParamValue{std::move(std::get<SomeIntExpr>(folded.u)), 173 details.attr().value()}); 174 } else { 175 if (!context.HasError(symbol)) { 176 evaluate::SayWithDeclaration(messages, symbol, 177 "Default value of type parameter '%s' (%s) is not convertible to its type (%s)"_err_en_US, 178 name, details.init()->AsFortran(), dyType.AsFortran()); 179 } 180 } 181 } else if (!context.HasError(symbol)) { 182 messages.Say(name_, 183 "Type parameter '%s' lacks a value and has no default"_err_en_US, 184 name); 185 } 186 } 187 if (!ok && !context.HasError(symbol)) { 188 messages.Say( 189 "Value of KIND type parameter '%s' must be constant"_err_en_US, name); 190 } 191 } 192 } 193 194 void DerivedTypeSpec::AddParamValue(SourceName name, ParamValue &&value) { 195 CHECK(cooked_); 196 auto pair{parameters_.insert(std::make_pair(name, std::move(value)))}; 197 CHECK(pair.second); // name was not already present 198 } 199 200 bool DerivedTypeSpec::MightBeParameterized() const { 201 return !cooked_ || !parameters_.empty(); 202 } 203 204 bool DerivedTypeSpec::IsForwardReferenced() const { 205 return typeSymbol_.get<DerivedTypeDetails>().isForwardReferenced(); 206 } 207 208 bool DerivedTypeSpec::HasDefaultInitialization( 209 bool ignoreAllocatable, bool ignorePointer) const { 210 DirectComponentIterator components{*this}; 211 return bool{std::find_if( 212 components.begin(), components.end(), [&](const Symbol &component) { 213 return IsInitialized(component, /*ignoreDataStatements=*/true, 214 ignoreAllocatable, ignorePointer); 215 })}; 216 } 217 218 bool DerivedTypeSpec::HasDestruction() const { 219 if (!FinalsForDerivedTypeInstantiation(*this).empty()) { 220 return true; 221 } 222 DirectComponentIterator components{*this}; 223 return bool{std::find_if( 224 components.begin(), components.end(), [&](const Symbol &component) { 225 return IsDestructible(component, &typeSymbol()); 226 })}; 227 } 228 229 ParamValue *DerivedTypeSpec::FindParameter(SourceName target) { 230 return const_cast<ParamValue *>( 231 const_cast<const DerivedTypeSpec *>(this)->FindParameter(target)); 232 } 233 234 static bool MatchKindParams(const Symbol &typeSymbol, 235 const DerivedTypeSpec &thisSpec, const DerivedTypeSpec &thatSpec) { 236 for (auto ref : typeSymbol.get<DerivedTypeDetails>().paramNameOrder()) { 237 if (ref->get<TypeParamDetails>().attr() == common::TypeParamAttr::Kind) { 238 const auto *thisValue{thisSpec.FindParameter(ref->name())}; 239 const auto *thatValue{thatSpec.FindParameter(ref->name())}; 240 if (!thisValue || !thatValue || *thisValue != *thatValue) { 241 return false; 242 } 243 } 244 } 245 if (const DerivedTypeSpec * 246 parent{typeSymbol.GetParentTypeSpec(typeSymbol.scope())}) { 247 return MatchKindParams(parent->typeSymbol(), thisSpec, thatSpec); 248 } else { 249 return true; 250 } 251 } 252 253 bool DerivedTypeSpec::MatchesOrExtends(const DerivedTypeSpec &that) const { 254 const Symbol *typeSymbol{&typeSymbol_}; 255 while (typeSymbol != &that.typeSymbol_) { 256 if (const DerivedTypeSpec * 257 parent{typeSymbol->GetParentTypeSpec(typeSymbol->scope())}) { 258 typeSymbol = &parent->typeSymbol_; 259 } else { 260 return false; 261 } 262 } 263 return MatchKindParams(*typeSymbol, *this, that); 264 } 265 266 class InstantiateHelper { 267 public: 268 InstantiateHelper(Scope &scope) : scope_{scope} {} 269 // Instantiate components from fromScope into scope_ 270 void InstantiateComponents(const Scope &); 271 272 private: 273 SemanticsContext &context() const { return scope_.context(); } 274 evaluate::FoldingContext &foldingContext() { 275 return context().foldingContext(); 276 } 277 template <typename A> A Fold(A &&expr) { 278 return evaluate::Fold(foldingContext(), std::move(expr)); 279 } 280 void InstantiateComponent(const Symbol &); 281 const DeclTypeSpec *InstantiateType(const Symbol &); 282 const DeclTypeSpec &InstantiateIntrinsicType( 283 SourceName, const DeclTypeSpec &); 284 DerivedTypeSpec CreateDerivedTypeSpec(const DerivedTypeSpec &, bool); 285 286 Scope &scope_; 287 }; 288 289 static int PlumbPDTInstantiationDepth(const Scope *scope) { 290 int depth{0}; 291 while (scope->IsParameterizedDerivedTypeInstantiation()) { 292 ++depth; 293 scope = &scope->parent(); 294 } 295 return depth; 296 } 297 298 // Completes component derived type instantiation and initializer folding 299 // for a non-parameterized derived type Scope. 300 static void InstantiateNonPDTScope(Scope &typeScope, Scope &containingScope) { 301 auto &context{containingScope.context()}; 302 auto &foldingContext{context.foldingContext()}; 303 for (auto &pair : typeScope) { 304 Symbol &symbol{*pair.second}; 305 if (DeclTypeSpec * type{symbol.GetType()}) { 306 if (DerivedTypeSpec * derived{type->AsDerived()}) { 307 if (!(derived->IsForwardReferenced() && 308 IsAllocatableOrPointer(symbol))) { 309 derived->Instantiate(containingScope); 310 } 311 } 312 } 313 if (!IsPointer(symbol)) { 314 if (auto *object{symbol.detailsIf<ObjectEntityDetails>()}) { 315 if (MaybeExpr & init{object->init()}) { 316 auto restorer{foldingContext.messages().SetLocation(symbol.name())}; 317 init = evaluate::NonPointerInitializationExpr( 318 symbol, std::move(*init), foldingContext); 319 } 320 } 321 } 322 } 323 ComputeOffsets(context, typeScope); 324 } 325 326 void DerivedTypeSpec::Instantiate(Scope &containingScope) { 327 if (instantiated_) { 328 return; 329 } 330 instantiated_ = true; 331 auto &context{containingScope.context()}; 332 auto &foldingContext{context.foldingContext()}; 333 if (IsForwardReferenced()) { 334 foldingContext.messages().Say(typeSymbol_.name(), 335 "The derived type '%s' was forward-referenced but not defined"_err_en_US, 336 typeSymbol_.name()); 337 context.SetError(typeSymbol_); 338 return; 339 } 340 EvaluateParameters(context); 341 const Scope &typeScope{DEREF(typeSymbol_.scope())}; 342 if (!MightBeParameterized()) { 343 scope_ = &typeScope; 344 if (!typeScope.derivedTypeSpec() || *this != *typeScope.derivedTypeSpec()) { 345 Scope &mutableTypeScope{const_cast<Scope &>(typeScope)}; 346 mutableTypeScope.set_derivedTypeSpec(*this); 347 InstantiateNonPDTScope(mutableTypeScope, containingScope); 348 } 349 return; 350 } 351 // New PDT instantiation. Create a new scope and populate it 352 // with components that have been specialized for this set of 353 // parameters. 354 Scope &newScope{containingScope.MakeScope(Scope::Kind::DerivedType)}; 355 newScope.set_derivedTypeSpec(*this); 356 ReplaceScope(newScope); 357 auto restorer{foldingContext.WithPDTInstance(*this)}; 358 std::string desc{typeSymbol_.name().ToString()}; 359 char sep{'('}; 360 for (const Symbol &symbol : OrderParameterDeclarations(typeSymbol_)) { 361 const SourceName &name{symbol.name()}; 362 if (typeScope.find(symbol.name()) != typeScope.end()) { 363 // This type parameter belongs to the derived type itself, not to 364 // one of its ancestors. Put the type parameter expression value, 365 // when there is one, into the new scope as the initialization value 366 // for the parameter. And when there is no explicit value, add an 367 // uninitialized type parameter to forestall use of any default. 368 if (ParamValue * paramValue{FindParameter(name)}) { 369 const TypeParamDetails &details{symbol.get<TypeParamDetails>()}; 370 TypeParamDetails instanceDetails{}; 371 if (details.attr()) { 372 paramValue->set_attr(*details.attr()); 373 instanceDetails.set_attr(*details.attr()); 374 } 375 desc += sep; 376 desc += name.ToString(); 377 desc += '='; 378 sep = ','; 379 if (MaybeIntExpr expr{paramValue->GetExplicit()}) { 380 desc += expr->AsFortran(); 381 instanceDetails.set_init( 382 std::move(DEREF(evaluate::UnwrapExpr<SomeIntExpr>(*expr)))); 383 if (auto dyType{expr->GetType()}) { 384 instanceDetails.set_type(newScope.MakeNumericType( 385 TypeCategory::Integer, KindExpr{dyType->kind()})); 386 } 387 } 388 if (!instanceDetails.type()) { 389 if (const DeclTypeSpec * type{details.type()}) { 390 instanceDetails.set_type(*type); 391 } 392 } 393 if (!instanceDetails.init()) { 394 desc += '*'; 395 } 396 newScope.try_emplace(name, std::move(instanceDetails)); 397 } 398 } 399 } 400 parser::Message *contextMessage{nullptr}; 401 if (sep != '(') { 402 desc += ')'; 403 contextMessage = new parser::Message{foldingContext.messages().at(), 404 "instantiation of parameterized derived type '%s'"_en_US, desc}; 405 if (auto outer{containingScope.instantiationContext()}) { 406 contextMessage->SetContext(outer.get()); 407 } 408 newScope.set_instantiationContext(contextMessage); 409 } 410 // Instantiate nearly every non-parameter symbol from the original derived 411 // type's scope into the new instance. 412 auto restorer2{foldingContext.messages().SetContext(contextMessage)}; 413 if (PlumbPDTInstantiationDepth(&containingScope) > 100) { 414 foldingContext.messages().Say( 415 "Too many recursive parameterized derived type instantiations"_err_en_US); 416 } else { 417 InstantiateHelper{newScope}.InstantiateComponents(typeScope); 418 } 419 } 420 421 void InstantiateHelper::InstantiateComponents(const Scope &fromScope) { 422 // Instantiate symbols in declaration order; this ensures that 423 // parent components and type parameters of ancestor types exist 424 // by the time that they're needed. 425 for (SymbolRef ref : fromScope.GetSymbols()) { 426 InstantiateComponent(*ref); 427 } 428 ComputeOffsets(context(), scope_); 429 } 430 431 // Walks a parsed expression to prepare it for (re)analysis; 432 // clears out the typedExpr analysis results and re-resolves 433 // symbol table pointers of type parameters. 434 class ComponentInitResetHelper { 435 public: 436 explicit ComponentInitResetHelper(Scope &scope) : scope_{scope} {} 437 438 template <typename A> bool Pre(const A &) { return true; } 439 440 template <typename A> void Post(const A &x) { 441 if constexpr (parser::HasTypedExpr<A>()) { 442 x.typedExpr.Reset(); 443 } 444 } 445 446 void Post(const parser::Name &name) { 447 if (name.symbol && name.symbol->has<TypeParamDetails>()) { 448 name.symbol = scope_.FindComponent(name.source); 449 } 450 } 451 452 private: 453 Scope &scope_; 454 }; 455 456 void InstantiateHelper::InstantiateComponent(const Symbol &oldSymbol) { 457 auto pair{scope_.try_emplace( 458 oldSymbol.name(), oldSymbol.attrs(), common::Clone(oldSymbol.details()))}; 459 Symbol &newSymbol{*pair.first->second}; 460 if (!pair.second) { 461 // Symbol was already present in the scope, which can only happen 462 // in the case of type parameters. 463 CHECK(oldSymbol.has<TypeParamDetails>()); 464 return; 465 } 466 newSymbol.flags() = oldSymbol.flags(); 467 if (auto *details{newSymbol.detailsIf<ObjectEntityDetails>()}) { 468 if (const DeclTypeSpec * newType{InstantiateType(newSymbol)}) { 469 details->ReplaceType(*newType); 470 } 471 for (ShapeSpec &dim : details->shape()) { 472 if (dim.lbound().isExplicit()) { 473 dim.lbound().SetExplicit(Fold(std::move(dim.lbound().GetExplicit()))); 474 } 475 if (dim.ubound().isExplicit()) { 476 dim.ubound().SetExplicit(Fold(std::move(dim.ubound().GetExplicit()))); 477 } 478 } 479 for (ShapeSpec &dim : details->coshape()) { 480 if (dim.lbound().isExplicit()) { 481 dim.lbound().SetExplicit(Fold(std::move(dim.lbound().GetExplicit()))); 482 } 483 if (dim.ubound().isExplicit()) { 484 dim.ubound().SetExplicit(Fold(std::move(dim.ubound().GetExplicit()))); 485 } 486 } 487 if (const auto *parsedExpr{details->unanalyzedPDTComponentInit()}) { 488 // Analyze the parsed expression in this PDT instantiation context. 489 ComponentInitResetHelper resetter{scope_}; 490 parser::Walk(*parsedExpr, resetter); 491 auto restorer{foldingContext().messages().SetLocation(newSymbol.name())}; 492 details->set_init(evaluate::Fold( 493 foldingContext(), AnalyzeExpr(context(), *parsedExpr))); 494 details->set_unanalyzedPDTComponentInit(nullptr); 495 // Remove analysis results to prevent unparsing or other use of 496 // instantiation-specific expressions. 497 parser::Walk(*parsedExpr, resetter); 498 } 499 if (MaybeExpr & init{details->init()}) { 500 // Non-pointer components with default initializers are 501 // processed now so that those default initializers can be used 502 // in PARAMETER structure constructors. 503 auto restorer{foldingContext().messages().SetLocation(newSymbol.name())}; 504 init = IsPointer(newSymbol) 505 ? Fold(std::move(*init)) 506 : evaluate::NonPointerInitializationExpr( 507 newSymbol, std::move(*init), foldingContext()); 508 } 509 } else if (auto *procDetails{newSymbol.detailsIf<ProcEntityDetails>()}) { 510 // We have a procedure pointer. Instantiate its return type 511 if (const DeclTypeSpec * returnType{InstantiateType(newSymbol)}) { 512 if (!procDetails->procInterface()) { 513 procDetails->ReplaceType(*returnType); 514 } 515 } 516 } 517 } 518 519 const DeclTypeSpec *InstantiateHelper::InstantiateType(const Symbol &symbol) { 520 const DeclTypeSpec *type{symbol.GetType()}; 521 if (!type) { 522 return nullptr; // error has occurred 523 } else if (const DerivedTypeSpec * spec{type->AsDerived()}) { 524 return &FindOrInstantiateDerivedType(scope_, 525 CreateDerivedTypeSpec(*spec, symbol.test(Symbol::Flag::ParentComp)), 526 type->category()); 527 } else if (type->AsIntrinsic()) { 528 return &InstantiateIntrinsicType(symbol.name(), *type); 529 } else if (type->category() == DeclTypeSpec::ClassStar) { 530 return type; 531 } else { 532 common::die("InstantiateType: %s", type->AsFortran().c_str()); 533 } 534 } 535 536 /// Fold explicit length parameters of character components when the explicit 537 /// expression is a constant expression (if it only depends on KIND parameters). 538 /// Do not fold `character(len=pdt_length)`, even if the length parameter is 539 /// constant in the pdt instantiation, in order to avoid losing the information 540 /// that the character component is automatic (and must be a descriptor). 541 static ParamValue FoldCharacterLength(evaluate::FoldingContext &foldingContext, 542 const CharacterTypeSpec &characterSpec) { 543 if (const auto &len{characterSpec.length().GetExplicit()}) { 544 if (evaluate::IsConstantExpr(*len)) { 545 return ParamValue{evaluate::Fold(foldingContext, common::Clone(*len)), 546 common::TypeParamAttr::Len}; 547 } 548 } 549 return characterSpec.length(); 550 } 551 552 // Apply type parameter values to an intrinsic type spec. 553 const DeclTypeSpec &InstantiateHelper::InstantiateIntrinsicType( 554 SourceName symbolName, const DeclTypeSpec &spec) { 555 const IntrinsicTypeSpec &intrinsic{DEREF(spec.AsIntrinsic())}; 556 if (spec.category() != DeclTypeSpec::Character && 557 evaluate::IsActuallyConstant(intrinsic.kind())) { 558 return spec; // KIND is already a known constant 559 } 560 // The expression was not originally constant, but now it must be so 561 // in the context of a parameterized derived type instantiation. 562 KindExpr copy{Fold(common::Clone(intrinsic.kind()))}; 563 int kind{context().GetDefaultKind(intrinsic.category())}; 564 if (auto value{evaluate::ToInt64(copy)}) { 565 if (foldingContext().targetCharacteristics().IsTypeEnabled( 566 intrinsic.category(), *value)) { 567 kind = *value; 568 } else { 569 foldingContext().messages().Say(symbolName, 570 "KIND parameter value (%jd) of intrinsic type %s " 571 "did not resolve to a supported value"_err_en_US, 572 *value, 573 parser::ToUpperCaseLetters(EnumToString(intrinsic.category()))); 574 } 575 } 576 switch (spec.category()) { 577 case DeclTypeSpec::Numeric: 578 return scope_.MakeNumericType(intrinsic.category(), KindExpr{kind}); 579 case DeclTypeSpec::Logical: 580 return scope_.MakeLogicalType(KindExpr{kind}); 581 case DeclTypeSpec::Character: 582 return scope_.MakeCharacterType( 583 FoldCharacterLength(foldingContext(), spec.characterTypeSpec()), 584 KindExpr{kind}); 585 default: 586 CRASH_NO_CASE; 587 } 588 } 589 590 DerivedTypeSpec InstantiateHelper::CreateDerivedTypeSpec( 591 const DerivedTypeSpec &spec, bool isParentComp) { 592 DerivedTypeSpec result{spec}; 593 result.CookParameters(foldingContext()); // enables AddParamValue() 594 if (isParentComp) { 595 // Forward any explicit type parameter values from the 596 // derived type spec under instantiation that define type parameters 597 // of the parent component to the derived type spec of the 598 // parent component. 599 const DerivedTypeSpec &instanceSpec{DEREF(foldingContext().pdtInstance())}; 600 for (const auto &[name, value] : instanceSpec.parameters()) { 601 if (scope_.find(name) == scope_.end()) { 602 result.AddParamValue(name, ParamValue{value}); 603 } 604 } 605 } 606 return result; 607 } 608 609 std::string DerivedTypeSpec::VectorTypeAsFortran() const { 610 std::string buf; 611 llvm::raw_string_ostream ss{buf}; 612 613 switch (category()) { 614 SWITCH_COVERS_ALL_CASES 615 case (Fortran::semantics::DerivedTypeSpec::Category::IntrinsicVector): { 616 int64_t vecElemKind; 617 int64_t vecElemCategory; 618 619 for (const auto &pair : parameters()) { 620 if (pair.first == "element_category") { 621 vecElemCategory = 622 Fortran::evaluate::ToInt64(pair.second.GetExplicit()).value_or(-1); 623 } else if (pair.first == "element_kind") { 624 vecElemKind = 625 Fortran::evaluate::ToInt64(pair.second.GetExplicit()).value_or(0); 626 } 627 } 628 629 assert((vecElemCategory >= 0 && 630 static_cast<size_t>(vecElemCategory) < 631 Fortran::common::VectorElementCategory_enumSize) && 632 "Vector element type is not specified"); 633 assert(vecElemKind && "Vector element kind is not specified"); 634 635 ss << "vector("; 636 switch (static_cast<common::VectorElementCategory>(vecElemCategory)) { 637 SWITCH_COVERS_ALL_CASES 638 case common::VectorElementCategory::Integer: 639 ss << "integer(" << vecElemKind << ")"; 640 break; 641 case common::VectorElementCategory::Unsigned: 642 ss << "unsigned(" << vecElemKind << ")"; 643 break; 644 case common::VectorElementCategory::Real: 645 ss << "real(" << vecElemKind << ")"; 646 break; 647 } 648 ss << ")"; 649 break; 650 } 651 case (Fortran::semantics::DerivedTypeSpec::Category::PairVector): 652 ss << "__vector_pair"; 653 break; 654 case (Fortran::semantics::DerivedTypeSpec::Category::QuadVector): 655 ss << "__vector_quad"; 656 break; 657 case (Fortran::semantics::DerivedTypeSpec::Category::DerivedType): 658 Fortran::common::die("Vector element type not implemented"); 659 } 660 return buf; 661 } 662 663 std::string DerivedTypeSpec::AsFortran() const { 664 std::string buf; 665 llvm::raw_string_ostream ss{buf}; 666 ss << originalTypeSymbol_.name(); 667 if (!rawParameters_.empty()) { 668 CHECK(parameters_.empty()); 669 ss << '('; 670 bool first = true; 671 for (const auto &[maybeKeyword, value] : rawParameters_) { 672 if (first) { 673 first = false; 674 } else { 675 ss << ','; 676 } 677 if (maybeKeyword) { 678 ss << maybeKeyword->v.source.ToString() << '='; 679 } 680 ss << value.AsFortran(); 681 } 682 ss << ')'; 683 } else if (!parameters_.empty()) { 684 ss << '('; 685 bool first = true; 686 for (const auto &[name, value] : parameters_) { 687 if (first) { 688 first = false; 689 } else { 690 ss << ','; 691 } 692 ss << name.ToString() << '=' << value.AsFortran(); 693 } 694 ss << ')'; 695 } 696 return buf; 697 } 698 699 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DerivedTypeSpec &x) { 700 return o << x.AsFortran(); 701 } 702 703 Bound::Bound(common::ConstantSubscript bound) : expr_{bound} {} 704 705 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const Bound &x) { 706 if (x.isStar()) { 707 o << '*'; 708 } else if (x.isColon()) { 709 o << ':'; 710 } else if (x.expr_) { 711 x.expr_->AsFortran(o); 712 } else { 713 o << "<no-expr>"; 714 } 715 return o; 716 } 717 718 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const ShapeSpec &x) { 719 if (x.lb_.isStar()) { 720 CHECK(x.ub_.isStar()); 721 o << ".."; 722 } else { 723 if (!x.lb_.isColon()) { 724 o << x.lb_; 725 } 726 o << ':'; 727 if (!x.ub_.isColon()) { 728 o << x.ub_; 729 } 730 } 731 return o; 732 } 733 734 llvm::raw_ostream &operator<<( 735 llvm::raw_ostream &os, const ArraySpec &arraySpec) { 736 char sep{'('}; 737 for (auto &shape : arraySpec) { 738 os << sep << shape; 739 sep = ','; 740 } 741 if (sep == ',') { 742 os << ')'; 743 } 744 return os; 745 } 746 747 ParamValue::ParamValue(MaybeIntExpr &&expr, common::TypeParamAttr attr) 748 : attr_{attr}, expr_{std::move(expr)} {} 749 ParamValue::ParamValue(SomeIntExpr &&expr, common::TypeParamAttr attr) 750 : attr_{attr}, expr_{std::move(expr)} {} 751 ParamValue::ParamValue( 752 common::ConstantSubscript value, common::TypeParamAttr attr) 753 : ParamValue(SomeIntExpr{evaluate::Expr<evaluate::SubscriptInteger>{value}}, 754 attr) {} 755 756 void ParamValue::SetExplicit(SomeIntExpr &&x) { 757 category_ = Category::Explicit; 758 expr_ = std::move(x); 759 } 760 761 std::string ParamValue::AsFortran() const { 762 switch (category_) { 763 SWITCH_COVERS_ALL_CASES 764 case Category::Assumed: 765 return "*"; 766 case Category::Deferred: 767 return ":"; 768 case Category::Explicit: 769 if (expr_) { 770 std::string buf; 771 llvm::raw_string_ostream ss{buf}; 772 expr_->AsFortran(ss); 773 return buf; 774 } else { 775 return ""; 776 } 777 } 778 } 779 780 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const ParamValue &x) { 781 return o << x.AsFortran(); 782 } 783 784 IntrinsicTypeSpec::IntrinsicTypeSpec(TypeCategory category, KindExpr &&kind) 785 : category_{category}, kind_{std::move(kind)} { 786 CHECK(category != TypeCategory::Derived); 787 } 788 789 static std::string KindAsFortran(const KindExpr &kind) { 790 std::string buf; 791 llvm::raw_string_ostream ss{buf}; 792 if (auto k{evaluate::ToInt64(kind)}) { 793 ss << *k; // emit unsuffixed kind code 794 } else { 795 kind.AsFortran(ss); 796 } 797 return buf; 798 } 799 800 std::string IntrinsicTypeSpec::AsFortran() const { 801 return parser::ToUpperCaseLetters(common::EnumToString(category_)) + '(' + 802 KindAsFortran(kind_) + ')'; 803 } 804 805 llvm::raw_ostream &operator<<( 806 llvm::raw_ostream &os, const IntrinsicTypeSpec &x) { 807 return os << x.AsFortran(); 808 } 809 810 std::string CharacterTypeSpec::AsFortran() const { 811 return "CHARACTER(" + length_.AsFortran() + ',' + KindAsFortran(kind()) + ')'; 812 } 813 814 llvm::raw_ostream &operator<<( 815 llvm::raw_ostream &os, const CharacterTypeSpec &x) { 816 return os << x.AsFortran(); 817 } 818 819 DeclTypeSpec::DeclTypeSpec(NumericTypeSpec &&typeSpec) 820 : category_{Numeric}, typeSpec_{std::move(typeSpec)} {} 821 DeclTypeSpec::DeclTypeSpec(LogicalTypeSpec &&typeSpec) 822 : category_{Logical}, typeSpec_{std::move(typeSpec)} {} 823 DeclTypeSpec::DeclTypeSpec(const CharacterTypeSpec &typeSpec) 824 : category_{Character}, typeSpec_{typeSpec} {} 825 DeclTypeSpec::DeclTypeSpec(CharacterTypeSpec &&typeSpec) 826 : category_{Character}, typeSpec_{std::move(typeSpec)} {} 827 DeclTypeSpec::DeclTypeSpec(Category category, const DerivedTypeSpec &typeSpec) 828 : category_{category}, typeSpec_{typeSpec} { 829 CHECK(category == TypeDerived || category == ClassDerived); 830 } 831 DeclTypeSpec::DeclTypeSpec(Category category, DerivedTypeSpec &&typeSpec) 832 : category_{category}, typeSpec_{std::move(typeSpec)} { 833 CHECK(category == TypeDerived || category == ClassDerived); 834 } 835 DeclTypeSpec::DeclTypeSpec(Category category) : category_{category} { 836 CHECK(category == TypeStar || category == ClassStar); 837 } 838 bool DeclTypeSpec::IsNumeric(TypeCategory tc) const { 839 return category_ == Numeric && numericTypeSpec().category() == tc; 840 } 841 bool DeclTypeSpec::IsSequenceType() const { 842 if (const DerivedTypeSpec * derivedType{AsDerived()}) { 843 const auto *typeDetails{ 844 derivedType->typeSymbol().detailsIf<DerivedTypeDetails>()}; 845 return typeDetails && typeDetails->sequence(); 846 } 847 return false; 848 } 849 850 const NumericTypeSpec &DeclTypeSpec::numericTypeSpec() const { 851 CHECK(category_ == Numeric); 852 return std::get<NumericTypeSpec>(typeSpec_); 853 } 854 const LogicalTypeSpec &DeclTypeSpec::logicalTypeSpec() const { 855 CHECK(category_ == Logical); 856 return std::get<LogicalTypeSpec>(typeSpec_); 857 } 858 bool DeclTypeSpec::operator==(const DeclTypeSpec &that) const { 859 return category_ == that.category_ && typeSpec_ == that.typeSpec_; 860 } 861 862 std::string DeclTypeSpec::AsFortran() const { 863 switch (category_) { 864 SWITCH_COVERS_ALL_CASES 865 case Numeric: 866 return numericTypeSpec().AsFortran(); 867 case Logical: 868 return logicalTypeSpec().AsFortran(); 869 case Character: 870 return characterTypeSpec().AsFortran(); 871 case TypeDerived: 872 if (derivedTypeSpec() 873 .typeSymbol() 874 .get<DerivedTypeDetails>() 875 .isDECStructure()) { 876 return "RECORD" + derivedTypeSpec().typeSymbol().name().ToString(); 877 } else if (derivedTypeSpec().IsVectorType()) { 878 return derivedTypeSpec().VectorTypeAsFortran(); 879 } else { 880 return "TYPE(" + derivedTypeSpec().AsFortran() + ')'; 881 } 882 case ClassDerived: 883 return "CLASS(" + derivedTypeSpec().AsFortran() + ')'; 884 case TypeStar: 885 return "TYPE(*)"; 886 case ClassStar: 887 return "CLASS(*)"; 888 } 889 } 890 891 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DeclTypeSpec &x) { 892 return o << x.AsFortran(); 893 } 894 895 } // namespace Fortran::semantics 896