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