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 "flang/Evaluate/fold.h" 11 #include "flang/Parser/characters.h" 12 #include "flang/Semantics/scope.h" 13 #include "flang/Semantics/symbol.h" 14 #include "flang/Semantics/tools.h" 15 #include "llvm/Support/raw_ostream.h" 16 17 namespace Fortran::semantics { 18 19 DerivedTypeSpec::DerivedTypeSpec(SourceName name, const Symbol &typeSymbol) 20 : name_{name}, typeSymbol_{typeSymbol} { 21 CHECK(typeSymbol.has<DerivedTypeDetails>()); 22 } 23 DerivedTypeSpec::DerivedTypeSpec(const DerivedTypeSpec &that) = default; 24 DerivedTypeSpec::DerivedTypeSpec(DerivedTypeSpec &&that) = default; 25 26 void DerivedTypeSpec::set_scope(const Scope &scope) { 27 CHECK(!scope_); 28 ReplaceScope(scope); 29 } 30 void DerivedTypeSpec::ReplaceScope(const Scope &scope) { 31 CHECK(scope.IsDerivedType()); 32 scope_ = &scope; 33 } 34 35 void DerivedTypeSpec::AddRawParamValue( 36 const std::optional<parser::Keyword> &keyword, ParamValue &&value) { 37 CHECK(parameters_.empty()); 38 rawParameters_.emplace_back(keyword ? &*keyword : nullptr, std::move(value)); 39 } 40 41 void DerivedTypeSpec::CookParameters(evaluate::FoldingContext &foldingContext) { 42 if (cooked_) { 43 return; 44 } 45 cooked_ = true; 46 auto &messages{foldingContext.messages()}; 47 if (IsForwardReferenced()) { 48 messages.Say(typeSymbol_.name(), 49 "Derived type '%s' was used but never defined"_err_en_US, 50 typeSymbol_.name()); 51 return; 52 } 53 54 // Parameters of the most deeply nested "base class" come first when the 55 // derived type is an extension. 56 auto parameterNames{OrderParameterNames(typeSymbol_)}; 57 auto parameterDecls{OrderParameterDeclarations(typeSymbol_)}; 58 auto nextNameIter{parameterNames.begin()}; 59 RawParameters raw{std::move(rawParameters_)}; 60 for (auto &[maybeKeyword, value] : raw) { 61 SourceName name; 62 common::TypeParamAttr attr{common::TypeParamAttr::Kind}; 63 if (maybeKeyword) { 64 name = maybeKeyword->v.source; 65 auto it{std::find_if(parameterDecls.begin(), parameterDecls.end(), 66 [&](const Symbol &symbol) { return symbol.name() == name; })}; 67 if (it == parameterDecls.end()) { 68 messages.Say(name, 69 "'%s' is not the name of a parameter for derived type '%s'"_err_en_US, 70 name, typeSymbol_.name()); 71 } else { 72 // Resolve the keyword's symbol 73 maybeKeyword->v.symbol = const_cast<Symbol *>(&it->get()); 74 attr = it->get().get<TypeParamDetails>().attr(); 75 } 76 } else if (nextNameIter != parameterNames.end()) { 77 name = *nextNameIter++; 78 auto it{std::find_if(parameterDecls.begin(), parameterDecls.end(), 79 [&](const Symbol &symbol) { return symbol.name() == name; })}; 80 CHECK(it != parameterDecls.end()); 81 attr = it->get().get<TypeParamDetails>().attr(); 82 } else { 83 messages.Say(name_, 84 "Too many type parameters given for derived type '%s'"_err_en_US, 85 typeSymbol_.name()); 86 break; 87 } 88 if (FindParameter(name)) { 89 messages.Say(name_, 90 "Multiple values given for type parameter '%s'"_err_en_US, name); 91 } else { 92 value.set_attr(attr); 93 AddParamValue(name, std::move(value)); 94 } 95 } 96 } 97 98 void DerivedTypeSpec::EvaluateParameters( 99 evaluate::FoldingContext &foldingContext) { 100 CookParameters(foldingContext); 101 if (evaluated_) { 102 return; 103 } 104 evaluated_ = true; 105 auto &messages{foldingContext.messages()}; 106 107 // Fold the explicit type parameter value expressions first. Do not 108 // fold them within the scope of the derived type being instantiated; 109 // these expressions cannot use its type parameters. Convert the values 110 // of the expressions to the declared types of the type parameters. 111 auto parameterDecls{OrderParameterDeclarations(typeSymbol_)}; 112 for (const Symbol &symbol : parameterDecls) { 113 const SourceName &name{symbol.name()}; 114 if (ParamValue * paramValue{FindParameter(name)}) { 115 if (const MaybeIntExpr & expr{paramValue->GetExplicit()}) { 116 if (auto converted{evaluate::ConvertToType(symbol, SomeExpr{*expr})}) { 117 SomeExpr folded{ 118 evaluate::Fold(foldingContext, std::move(*converted))}; 119 if (auto *intExpr{std::get_if<SomeIntExpr>(&folded.u)}) { 120 paramValue->SetExplicit(std::move(*intExpr)); 121 continue; 122 } 123 } 124 evaluate::SayWithDeclaration(messages, symbol, 125 "Value of type parameter '%s' (%s) is not convertible to its type"_err_en_US, 126 name, expr->AsFortran()); 127 } 128 } 129 } 130 131 // Default initialization expressions for the derived type's parameters 132 // may reference other parameters so long as the declaration precedes the 133 // use in the expression (10.1.12). This is not necessarily the same 134 // order as "type parameter order" (7.5.3.2). 135 // Type parameter default value expressions are folded in declaration order 136 // within the scope of the derived type so that the values of earlier type 137 // parameters are available for use in the default initialization 138 // expressions of later parameters. 139 auto restorer{foldingContext.WithPDTInstance(*this)}; 140 for (const Symbol &symbol : parameterDecls) { 141 const SourceName &name{symbol.name()}; 142 if (!FindParameter(name)) { 143 const TypeParamDetails &details{symbol.get<TypeParamDetails>()}; 144 if (details.init()) { 145 auto expr{ 146 evaluate::Fold(foldingContext, common::Clone(details.init()))}; 147 AddParamValue(name, ParamValue{std::move(*expr), details.attr()}); 148 } else { 149 messages.Say(name_, 150 "Type parameter '%s' lacks a value and has no default"_err_en_US, 151 name); 152 } 153 } 154 } 155 } 156 157 void DerivedTypeSpec::AddParamValue(SourceName name, ParamValue &&value) { 158 CHECK(cooked_); 159 auto pair{parameters_.insert(std::make_pair(name, std::move(value)))}; 160 CHECK(pair.second); // name was not already present 161 } 162 163 bool DerivedTypeSpec::MightBeParameterized() const { 164 return !cooked_ || !parameters_.empty(); 165 } 166 167 bool DerivedTypeSpec::IsForwardReferenced() const { 168 return typeSymbol_.get<DerivedTypeDetails>().isForwardReferenced(); 169 } 170 171 bool DerivedTypeSpec::HasDefaultInitialization() const { 172 for (const Scope *scope{scope_}; scope; 173 scope = scope->GetDerivedTypeParent()) { 174 for (const auto &pair : *scope) { 175 const Symbol &symbol{*pair.second}; 176 if (IsAllocatable(symbol) || IsInitialized(symbol)) { 177 return true; 178 } 179 } 180 } 181 return false; 182 } 183 184 ParamValue *DerivedTypeSpec::FindParameter(SourceName target) { 185 return const_cast<ParamValue *>( 186 const_cast<const DerivedTypeSpec *>(this)->FindParameter(target)); 187 } 188 189 void DerivedTypeSpec::Instantiate( 190 Scope &containingScope, SemanticsContext &context) { 191 if (instantiated_) { 192 return; 193 } 194 instantiated_ = true; 195 auto &foldingContext{context.foldingContext()}; 196 if (IsForwardReferenced()) { 197 foldingContext.messages().Say(typeSymbol_.name(), 198 "The derived type '%s' was forward-referenced but not defined"_err_en_US, 199 typeSymbol_.name()); 200 return; 201 } 202 CookParameters(foldingContext); 203 EvaluateParameters(foldingContext); 204 const Scope &typeScope{DEREF(typeSymbol_.scope())}; 205 if (!MightBeParameterized()) { 206 scope_ = &typeScope; 207 for (const auto &pair : typeScope) { 208 const Symbol &symbol{*pair.second}; 209 if (const DeclTypeSpec * type{symbol.GetType()}) { 210 if (const DerivedTypeSpec * derived{type->AsDerived()}) { 211 if (!(derived->IsForwardReferenced() && 212 IsAllocatableOrPointer(symbol))) { 213 auto &instantiatable{*const_cast<DerivedTypeSpec *>(derived)}; 214 instantiatable.Instantiate(containingScope, context); 215 } 216 } 217 } 218 } 219 return; 220 } 221 Scope &newScope{containingScope.MakeScope(Scope::Kind::DerivedType)}; 222 newScope.set_derivedTypeSpec(*this); 223 ReplaceScope(newScope); 224 for (const Symbol &symbol : OrderParameterDeclarations(typeSymbol_)) { 225 const SourceName &name{symbol.name()}; 226 if (typeScope.find(symbol.name()) != typeScope.end()) { 227 // This type parameter belongs to the derived type itself, not to 228 // one of its ancestors. Put the type parameter expression value 229 // into the new scope as the initialization value for the parameter. 230 if (ParamValue * paramValue{FindParameter(name)}) { 231 const TypeParamDetails &details{symbol.get<TypeParamDetails>()}; 232 paramValue->set_attr(details.attr()); 233 if (MaybeIntExpr expr{paramValue->GetExplicit()}) { 234 // Ensure that any kind type parameters with values are 235 // constant by now. 236 if (details.attr() == common::TypeParamAttr::Kind) { 237 // Any errors in rank and type will have already elicited 238 // messages, so don't pile on by complaining further here. 239 if (auto maybeDynamicType{expr->GetType()}) { 240 if (expr->Rank() == 0 && 241 maybeDynamicType->category() == TypeCategory::Integer) { 242 if (!evaluate::ToInt64(*expr)) { 243 if (auto *msg{foldingContext.messages().Say( 244 "Value of kind type parameter '%s' (%s) is not " 245 "a scalar INTEGER constant"_err_en_US, 246 name, expr->AsFortran())}) { 247 msg->Attach(name, "declared here"_en_US); 248 } 249 } 250 } 251 } 252 } 253 TypeParamDetails instanceDetails{details.attr()}; 254 if (const DeclTypeSpec * type{details.type()}) { 255 instanceDetails.set_type(*type); 256 } 257 instanceDetails.set_init(std::move(*expr)); 258 newScope.try_emplace(name, std::move(instanceDetails)); 259 } 260 } 261 } 262 } 263 // Instantiate every non-parameter symbol from the original derived 264 // type's scope into the new instance. 265 auto restorer{foldingContext.WithPDTInstance(*this)}; 266 newScope.AddSourceRange(typeScope.sourceRange()); 267 for (const auto &pair : typeScope) { 268 const Symbol &symbol{*pair.second}; 269 symbol.InstantiateComponent(newScope, context); 270 } 271 } 272 273 std::string DerivedTypeSpec::AsFortran() const { 274 std::string buf; 275 llvm::raw_string_ostream ss{buf}; 276 ss << name_; 277 if (!rawParameters_.empty()) { 278 CHECK(parameters_.empty()); 279 ss << '('; 280 bool first = true; 281 for (const auto &[maybeKeyword, value] : rawParameters_) { 282 if (first) { 283 first = false; 284 } else { 285 ss << ','; 286 } 287 if (maybeKeyword) { 288 ss << maybeKeyword->v.source.ToString() << '='; 289 } 290 ss << value.AsFortran(); 291 } 292 ss << ')'; 293 } else if (!parameters_.empty()) { 294 ss << '('; 295 bool first = true; 296 for (const auto &[name, value] : parameters_) { 297 if (first) { 298 first = false; 299 } else { 300 ss << ','; 301 } 302 ss << name.ToString() << '=' << value.AsFortran(); 303 } 304 ss << ')'; 305 } 306 return ss.str(); 307 } 308 309 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DerivedTypeSpec &x) { 310 return o << x.AsFortran(); 311 } 312 313 Bound::Bound(int bound) : expr_{bound} {} 314 315 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const Bound &x) { 316 if (x.isAssumed()) { 317 o << '*'; 318 } else if (x.isDeferred()) { 319 o << ':'; 320 } else if (x.expr_) { 321 x.expr_->AsFortran(o); 322 } else { 323 o << "<no-expr>"; 324 } 325 return o; 326 } 327 328 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const ShapeSpec &x) { 329 if (x.lb_.isAssumed()) { 330 CHECK(x.ub_.isAssumed()); 331 o << ".."; 332 } else { 333 if (!x.lb_.isDeferred()) { 334 o << x.lb_; 335 } 336 o << ':'; 337 if (!x.ub_.isDeferred()) { 338 o << x.ub_; 339 } 340 } 341 return o; 342 } 343 344 bool ArraySpec::IsExplicitShape() const { 345 return CheckAll([](const ShapeSpec &x) { return x.ubound().isExplicit(); }); 346 } 347 bool ArraySpec::IsAssumedShape() const { 348 return CheckAll([](const ShapeSpec &x) { return x.ubound().isDeferred(); }); 349 } 350 bool ArraySpec::IsDeferredShape() const { 351 return CheckAll([](const ShapeSpec &x) { 352 return x.lbound().isDeferred() && x.ubound().isDeferred(); 353 }); 354 } 355 bool ArraySpec::IsImpliedShape() const { 356 return !IsAssumedRank() && 357 CheckAll([](const ShapeSpec &x) { return x.ubound().isAssumed(); }); 358 } 359 bool ArraySpec::IsAssumedSize() const { 360 return !empty() && !IsAssumedRank() && back().ubound().isAssumed() && 361 std::all_of(begin(), end() - 1, 362 [](const ShapeSpec &x) { return x.ubound().isExplicit(); }); 363 } 364 bool ArraySpec::IsAssumedRank() const { 365 return Rank() == 1 && front().lbound().isAssumed(); 366 } 367 368 llvm::raw_ostream &operator<<( 369 llvm::raw_ostream &os, const ArraySpec &arraySpec) { 370 char sep{'('}; 371 for (auto &shape : arraySpec) { 372 os << sep << shape; 373 sep = ','; 374 } 375 if (sep == ',') { 376 os << ')'; 377 } 378 return os; 379 } 380 381 ParamValue::ParamValue(MaybeIntExpr &&expr, common::TypeParamAttr attr) 382 : attr_{attr}, expr_{std::move(expr)} {} 383 ParamValue::ParamValue(SomeIntExpr &&expr, common::TypeParamAttr attr) 384 : attr_{attr}, expr_{std::move(expr)} {} 385 ParamValue::ParamValue( 386 common::ConstantSubscript value, common::TypeParamAttr attr) 387 : ParamValue(SomeIntExpr{evaluate::Expr<evaluate::SubscriptInteger>{value}}, 388 attr) {} 389 390 void ParamValue::SetExplicit(SomeIntExpr &&x) { 391 category_ = Category::Explicit; 392 expr_ = std::move(x); 393 } 394 395 std::string ParamValue::AsFortran() const { 396 switch (category_) { 397 SWITCH_COVERS_ALL_CASES 398 case Category::Assumed: 399 return "*"; 400 case Category::Deferred: 401 return ":"; 402 case Category::Explicit: 403 if (expr_) { 404 std::string buf; 405 llvm::raw_string_ostream ss{buf}; 406 expr_->AsFortran(ss); 407 return ss.str(); 408 } else { 409 return ""; 410 } 411 } 412 } 413 414 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const ParamValue &x) { 415 return o << x.AsFortran(); 416 } 417 418 IntrinsicTypeSpec::IntrinsicTypeSpec(TypeCategory category, KindExpr &&kind) 419 : category_{category}, kind_{std::move(kind)} { 420 CHECK(category != TypeCategory::Derived); 421 } 422 423 static std::string KindAsFortran(const KindExpr &kind) { 424 std::string buf; 425 llvm::raw_string_ostream ss{buf}; 426 if (auto k{evaluate::ToInt64(kind)}) { 427 ss << *k; // emit unsuffixed kind code 428 } else { 429 kind.AsFortran(ss); 430 } 431 return ss.str(); 432 } 433 434 std::string IntrinsicTypeSpec::AsFortran() const { 435 return parser::ToUpperCaseLetters(common::EnumToString(category_)) + '(' + 436 KindAsFortran(kind_) + ')'; 437 } 438 439 llvm::raw_ostream &operator<<( 440 llvm::raw_ostream &os, const IntrinsicTypeSpec &x) { 441 return os << x.AsFortran(); 442 } 443 444 std::string CharacterTypeSpec::AsFortran() const { 445 return "CHARACTER(" + length_.AsFortran() + ',' + KindAsFortran(kind()) + ')'; 446 } 447 448 llvm::raw_ostream &operator<<( 449 llvm::raw_ostream &os, const CharacterTypeSpec &x) { 450 return os << x.AsFortran(); 451 } 452 453 DeclTypeSpec::DeclTypeSpec(NumericTypeSpec &&typeSpec) 454 : category_{Numeric}, typeSpec_{std::move(typeSpec)} {} 455 DeclTypeSpec::DeclTypeSpec(LogicalTypeSpec &&typeSpec) 456 : category_{Logical}, typeSpec_{std::move(typeSpec)} {} 457 DeclTypeSpec::DeclTypeSpec(const CharacterTypeSpec &typeSpec) 458 : category_{Character}, typeSpec_{typeSpec} {} 459 DeclTypeSpec::DeclTypeSpec(CharacterTypeSpec &&typeSpec) 460 : category_{Character}, typeSpec_{std::move(typeSpec)} {} 461 DeclTypeSpec::DeclTypeSpec(Category category, const DerivedTypeSpec &typeSpec) 462 : category_{category}, typeSpec_{typeSpec} { 463 CHECK(category == TypeDerived || category == ClassDerived); 464 } 465 DeclTypeSpec::DeclTypeSpec(Category category, DerivedTypeSpec &&typeSpec) 466 : category_{category}, typeSpec_{std::move(typeSpec)} { 467 CHECK(category == TypeDerived || category == ClassDerived); 468 } 469 DeclTypeSpec::DeclTypeSpec(Category category) : category_{category} { 470 CHECK(category == TypeStar || category == ClassStar); 471 } 472 bool DeclTypeSpec::IsNumeric(TypeCategory tc) const { 473 return category_ == Numeric && numericTypeSpec().category() == tc; 474 } 475 bool DeclTypeSpec::IsSequenceType() const { 476 if (const DerivedTypeSpec * derivedType{AsDerived()}) { 477 const auto *typeDetails{ 478 derivedType->typeSymbol().detailsIf<DerivedTypeDetails>()}; 479 return typeDetails && typeDetails->sequence(); 480 } 481 return false; 482 } 483 IntrinsicTypeSpec *DeclTypeSpec::AsIntrinsic() { 484 return const_cast<IntrinsicTypeSpec *>( 485 const_cast<const DeclTypeSpec *>(this)->AsIntrinsic()); 486 } 487 const NumericTypeSpec &DeclTypeSpec::numericTypeSpec() const { 488 CHECK(category_ == Numeric); 489 return std::get<NumericTypeSpec>(typeSpec_); 490 } 491 const LogicalTypeSpec &DeclTypeSpec::logicalTypeSpec() const { 492 CHECK(category_ == Logical); 493 return std::get<LogicalTypeSpec>(typeSpec_); 494 } 495 bool DeclTypeSpec::operator==(const DeclTypeSpec &that) const { 496 return category_ == that.category_ && typeSpec_ == that.typeSpec_; 497 } 498 499 std::string DeclTypeSpec::AsFortran() const { 500 switch (category_) { 501 SWITCH_COVERS_ALL_CASES 502 case Numeric: 503 return numericTypeSpec().AsFortran(); 504 case Logical: 505 return logicalTypeSpec().AsFortran(); 506 case Character: 507 return characterTypeSpec().AsFortran(); 508 case TypeDerived: 509 return "TYPE(" + derivedTypeSpec().AsFortran() + ')'; 510 case ClassDerived: 511 return "CLASS(" + derivedTypeSpec().AsFortran() + ')'; 512 case TypeStar: 513 return "TYPE(*)"; 514 case ClassStar: 515 return "CLASS(*)"; 516 } 517 } 518 519 llvm::raw_ostream &operator<<(llvm::raw_ostream &o, const DeclTypeSpec &x) { 520 return o << x.AsFortran(); 521 } 522 523 void ProcInterface::set_symbol(const Symbol &symbol) { 524 CHECK(!type_); 525 symbol_ = &symbol; 526 } 527 void ProcInterface::set_type(const DeclTypeSpec &type) { 528 CHECK(!symbol_); 529 type_ = &type; 530 } 531 } // namespace Fortran::semantics 532