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