1 //===-- lib/Evaluate/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/Evaluate/type.h"
10 #include "flang/Common/idioms.h"
11 #include "flang/Evaluate/expression.h"
12 #include "flang/Evaluate/fold.h"
13 #include "flang/Evaluate/target.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 "flang/Semantics/type.h"
19 #include <algorithm>
20 #include <optional>
21 #include <string>
22
23 // IsDescriptor() predicate: true when a symbol is implemented
24 // at runtime with a descriptor.
25 namespace Fortran::semantics {
26
IsDescriptor(const DeclTypeSpec * type)27 static bool IsDescriptor(const DeclTypeSpec *type) {
28 if (type) {
29 if (auto dynamicType{evaluate::DynamicType::From(*type)}) {
30 return dynamicType->RequiresDescriptor();
31 }
32 }
33 return false;
34 }
35
IsDescriptor(const ObjectEntityDetails & details)36 static bool IsDescriptor(const ObjectEntityDetails &details) {
37 if (IsDescriptor(details.type())) {
38 return true;
39 }
40 for (const ShapeSpec &shapeSpec : details.shape()) {
41 const auto &lb{shapeSpec.lbound().GetExplicit()};
42 const auto &ub{shapeSpec.ubound().GetExplicit()};
43 if (!lb || !ub || !IsConstantExpr(*lb) || !IsConstantExpr(*ub)) {
44 return true;
45 }
46 }
47 return false;
48 }
49
IsDescriptor(const ProcEntityDetails & details)50 static bool IsDescriptor(const ProcEntityDetails &details) {
51 // A procedure pointer or dummy procedure must be & is a descriptor if
52 // and only if it requires a static link.
53 // TODO: refine this placeholder
54 return details.HasExplicitInterface();
55 }
56
IsDescriptor(const Symbol & symbol)57 bool IsDescriptor(const Symbol &symbol) {
58 return common::visit(
59 common::visitors{
60 [&](const ObjectEntityDetails &d) {
61 return IsAllocatableOrPointer(symbol) || IsDescriptor(d);
62 },
63 [&](const ProcEntityDetails &d) {
64 return (symbol.attrs().test(Attr::POINTER) ||
65 symbol.attrs().test(Attr::EXTERNAL)) &&
66 IsDescriptor(d);
67 },
68 [&](const EntityDetails &d) { return IsDescriptor(d.type()); },
69 [](const AssocEntityDetails &d) {
70 if (const auto &expr{d.expr()}) {
71 if (expr->Rank() > 0) {
72 return true;
73 }
74 if (const auto dynamicType{expr->GetType()}) {
75 if (dynamicType->RequiresDescriptor()) {
76 return true;
77 }
78 }
79 }
80 return false;
81 },
82 [](const SubprogramDetails &d) {
83 return d.isFunction() && IsDescriptor(d.result());
84 },
85 [](const UseDetails &d) { return IsDescriptor(d.symbol()); },
86 [](const HostAssocDetails &d) { return IsDescriptor(d.symbol()); },
87 [](const auto &) { return false; },
88 },
89 symbol.details());
90 }
91 } // namespace Fortran::semantics
92
93 namespace Fortran::evaluate {
94
DynamicType(int k,const semantics::ParamValue & pv)95 DynamicType::DynamicType(int k, const semantics::ParamValue &pv)
96 : category_{TypeCategory::Character}, kind_{k} {
97 CHECK(IsValidKindOfIntrinsicType(category_, kind_));
98 if (auto n{ToInt64(pv.GetExplicit())}) {
99 knownLength_ = *n;
100 } else {
101 charLengthParamValue_ = &pv;
102 }
103 }
104
PointeeComparison(const A * x,const A * y)105 template <typename A> inline bool PointeeComparison(const A *x, const A *y) {
106 return x == y || (x && y && *x == *y);
107 }
108
operator ==(const DynamicType & that) const109 bool DynamicType::operator==(const DynamicType &that) const {
110 return category_ == that.category_ && kind_ == that.kind_ &&
111 PointeeComparison(charLengthParamValue_, that.charLengthParamValue_) &&
112 knownLength().has_value() == that.knownLength().has_value() &&
113 (!knownLength() || *knownLength() == *that.knownLength()) &&
114 PointeeComparison(derived_, that.derived_);
115 }
116
GetCharLength() const117 std::optional<Expr<SubscriptInteger>> DynamicType::GetCharLength() const {
118 if (category_ == TypeCategory::Character) {
119 if (knownLength()) {
120 return AsExpr(Constant<SubscriptInteger>(*knownLength()));
121 } else if (charLengthParamValue_) {
122 if (auto length{charLengthParamValue_->GetExplicit()}) {
123 return ConvertToType<SubscriptInteger>(std::move(*length));
124 }
125 }
126 }
127 return std::nullopt;
128 }
129
GetAlignment(const TargetCharacteristics & targetCharacteristics) const130 std::size_t DynamicType::GetAlignment(
131 const TargetCharacteristics &targetCharacteristics) const {
132 if (category_ == TypeCategory::Derived) {
133 if (derived_ && derived_->scope()) {
134 return derived_->scope()->alignment().value_or(1);
135 }
136 } else {
137 return targetCharacteristics.GetAlignment(category_, kind_);
138 }
139 return 1; // needs to be after switch to dodge a bogus gcc warning
140 }
141
MeasureSizeInBytes(FoldingContext & context,bool aligned) const142 std::optional<Expr<SubscriptInteger>> DynamicType::MeasureSizeInBytes(
143 FoldingContext &context, bool aligned) const {
144 switch (category_) {
145 case TypeCategory::Integer:
146 case TypeCategory::Real:
147 case TypeCategory::Complex:
148 case TypeCategory::Logical:
149 return Expr<SubscriptInteger>{
150 context.targetCharacteristics().GetByteSize(category_, kind_)};
151 case TypeCategory::Character:
152 if (auto len{GetCharLength()}) {
153 return Fold(context,
154 Expr<SubscriptInteger>{
155 context.targetCharacteristics().GetByteSize(category_, kind_)} *
156 std::move(*len));
157 }
158 break;
159 case TypeCategory::Derived:
160 if (derived_ && derived_->scope()) {
161 auto size{derived_->scope()->size()};
162 auto align{aligned ? derived_->scope()->alignment().value_or(0) : 0};
163 auto alignedSize{align > 0 ? ((size + align - 1) / align) * align : size};
164 return Expr<SubscriptInteger>{
165 static_cast<ConstantSubscript>(alignedSize)};
166 }
167 break;
168 }
169 return std::nullopt;
170 }
171
IsAssumedLengthCharacter() const172 bool DynamicType::IsAssumedLengthCharacter() const {
173 return category_ == TypeCategory::Character && charLengthParamValue_ &&
174 charLengthParamValue_->isAssumed();
175 }
176
IsNonConstantLengthCharacter() const177 bool DynamicType::IsNonConstantLengthCharacter() const {
178 if (category_ != TypeCategory::Character) {
179 return false;
180 } else if (knownLength()) {
181 return false;
182 } else if (!charLengthParamValue_) {
183 return true;
184 } else if (const auto &expr{charLengthParamValue_->GetExplicit()}) {
185 return !IsConstantExpr(*expr);
186 } else {
187 return true;
188 }
189 }
190
IsTypelessIntrinsicArgument() const191 bool DynamicType::IsTypelessIntrinsicArgument() const {
192 return category_ == TypeCategory::Integer && kind_ == TypelessKind;
193 }
194
GetDerivedTypeSpec(const std::optional<DynamicType> & type)195 const semantics::DerivedTypeSpec *GetDerivedTypeSpec(
196 const std::optional<DynamicType> &type) {
197 return type ? GetDerivedTypeSpec(*type) : nullptr;
198 }
199
GetDerivedTypeSpec(const DynamicType & type)200 const semantics::DerivedTypeSpec *GetDerivedTypeSpec(const DynamicType &type) {
201 if (type.category() == TypeCategory::Derived &&
202 !type.IsUnlimitedPolymorphic()) {
203 return &type.GetDerivedTypeSpec();
204 } else {
205 return nullptr;
206 }
207 }
208
FindParentComponent(const semantics::DerivedTypeSpec & derived)209 static const semantics::Symbol *FindParentComponent(
210 const semantics::DerivedTypeSpec &derived) {
211 const semantics::Symbol &typeSymbol{derived.typeSymbol()};
212 if (const semantics::Scope * scope{typeSymbol.scope()}) {
213 const auto &dtDetails{typeSymbol.get<semantics::DerivedTypeDetails>()};
214 if (auto extends{dtDetails.GetParentComponentName()}) {
215 if (auto iter{scope->find(*extends)}; iter != scope->cend()) {
216 if (const Symbol & symbol{*iter->second};
217 symbol.test(Symbol::Flag::ParentComp)) {
218 return &symbol;
219 }
220 }
221 }
222 }
223 return nullptr;
224 }
225
GetParentTypeSpec(const semantics::DerivedTypeSpec & derived)226 const semantics::DerivedTypeSpec *GetParentTypeSpec(
227 const semantics::DerivedTypeSpec &derived) {
228 if (const semantics::Symbol * parent{FindParentComponent(derived)}) {
229 return &parent->get<semantics::ObjectEntityDetails>()
230 .type()
231 ->derivedTypeSpec();
232 } else {
233 return nullptr;
234 }
235 }
236
237 // Compares two derived type representations to see whether they both
238 // represent the "same type" in the sense of section 7.5.2.4.
239 using SetOfDerivedTypePairs =
240 std::set<std::pair<const semantics::DerivedTypeSpec *,
241 const semantics::DerivedTypeSpec *>>;
242
243 static bool AreSameComponent(const semantics::Symbol &,
244 const semantics::Symbol &, SetOfDerivedTypePairs &inProgress);
245
AreSameDerivedType(const semantics::DerivedTypeSpec & x,const semantics::DerivedTypeSpec & y,SetOfDerivedTypePairs & inProgress)246 static bool AreSameDerivedType(const semantics::DerivedTypeSpec &x,
247 const semantics::DerivedTypeSpec &y, SetOfDerivedTypePairs &inProgress) {
248 const auto &xSymbol{x.typeSymbol()};
249 const auto &ySymbol{y.typeSymbol()};
250 if (&x == &y || xSymbol == ySymbol) {
251 return true;
252 }
253 auto thisQuery{std::make_pair(&x, &y)};
254 if (inProgress.find(thisQuery) != inProgress.end()) {
255 return true; // recursive use of types in components
256 }
257 inProgress.insert(thisQuery);
258 const auto &xDetails{xSymbol.get<semantics::DerivedTypeDetails>()};
259 const auto &yDetails{ySymbol.get<semantics::DerivedTypeDetails>()};
260 if (xSymbol.name() != ySymbol.name()) {
261 return false;
262 }
263 if (!(xDetails.sequence() && yDetails.sequence()) &&
264 !(xSymbol.attrs().test(semantics::Attr::BIND_C) &&
265 ySymbol.attrs().test(semantics::Attr::BIND_C))) {
266 // PGI does not enforce this requirement; all other Fortran
267 // processors do with a hard error when violations are caught.
268 return false;
269 }
270 // Compare the component lists in their orders of declaration.
271 auto xEnd{xDetails.componentNames().cend()};
272 auto yComponentName{yDetails.componentNames().cbegin()};
273 auto yEnd{yDetails.componentNames().cend()};
274 for (auto xComponentName{xDetails.componentNames().cbegin()};
275 xComponentName != xEnd; ++xComponentName, ++yComponentName) {
276 if (yComponentName == yEnd || *xComponentName != *yComponentName ||
277 !xSymbol.scope() || !ySymbol.scope()) {
278 return false;
279 }
280 const auto xLookup{xSymbol.scope()->find(*xComponentName)};
281 const auto yLookup{ySymbol.scope()->find(*yComponentName)};
282 if (xLookup == xSymbol.scope()->end() ||
283 yLookup == ySymbol.scope()->end() ||
284 !AreSameComponent(*xLookup->second, *yLookup->second, inProgress)) {
285 return false;
286 }
287 }
288 return yComponentName == yEnd;
289 }
290
AreSameComponent(const semantics::Symbol & x,const semantics::Symbol & y,SetOfDerivedTypePairs &)291 static bool AreSameComponent(const semantics::Symbol &x,
292 const semantics::Symbol &y,
293 SetOfDerivedTypePairs & /* inProgress - not yet used */) {
294 if (x.attrs() != y.attrs()) {
295 return false;
296 }
297 if (x.attrs().test(semantics::Attr::PRIVATE)) {
298 return false;
299 }
300 // TODO: compare types, parameters, bounds, &c.
301 return x.has<semantics::ObjectEntityDetails>() ==
302 y.has<semantics::ObjectEntityDetails>();
303 }
304
AreCompatibleDerivedTypes(const semantics::DerivedTypeSpec * x,const semantics::DerivedTypeSpec * y,bool isPolymorphic)305 static bool AreCompatibleDerivedTypes(const semantics::DerivedTypeSpec *x,
306 const semantics::DerivedTypeSpec *y, bool isPolymorphic) {
307 if (!x || !y) {
308 return false;
309 } else {
310 SetOfDerivedTypePairs inProgress;
311 if (AreSameDerivedType(*x, *y, inProgress)) {
312 return true;
313 } else {
314 return isPolymorphic &&
315 AreCompatibleDerivedTypes(x, GetParentTypeSpec(*y), true);
316 }
317 }
318 }
319
AreCompatibleTypes(const DynamicType & x,const DynamicType & y,bool ignoreTypeParameterValues)320 static bool AreCompatibleTypes(const DynamicType &x, const DynamicType &y,
321 bool ignoreTypeParameterValues) {
322 if (x.IsUnlimitedPolymorphic()) {
323 return true;
324 } else if (y.IsUnlimitedPolymorphic()) {
325 return false;
326 } else if (x.category() != y.category()) {
327 return false;
328 } else if (x.category() != TypeCategory::Derived) {
329 return x.kind() == y.kind();
330 } else {
331 const auto *xdt{GetDerivedTypeSpec(x)};
332 const auto *ydt{GetDerivedTypeSpec(y)};
333 return AreCompatibleDerivedTypes(xdt, ydt, x.IsPolymorphic()) &&
334 (ignoreTypeParameterValues ||
335 (xdt && ydt && AreTypeParamCompatible(*xdt, *ydt)));
336 }
337 }
338
339 // See 7.3.2.3 (5) & 15.5.2.4
IsTkCompatibleWith(const DynamicType & that) const340 bool DynamicType::IsTkCompatibleWith(const DynamicType &that) const {
341 return AreCompatibleTypes(*this, that, false);
342 }
343
344 // 16.9.165
SameTypeAs(const DynamicType & that) const345 std::optional<bool> DynamicType::SameTypeAs(const DynamicType &that) const {
346 bool x{AreCompatibleTypes(*this, that, true)};
347 bool y{AreCompatibleTypes(that, *this, true)};
348 if (x == y) {
349 return x;
350 } else {
351 // If either is unlimited polymorphic, the result is unknown.
352 return std::nullopt;
353 }
354 }
355
356 // 16.9.76
ExtendsTypeOf(const DynamicType & that) const357 std::optional<bool> DynamicType::ExtendsTypeOf(const DynamicType &that) const {
358 if (IsUnlimitedPolymorphic() || that.IsUnlimitedPolymorphic()) {
359 return std::nullopt; // unknown
360 } else if (!AreCompatibleDerivedTypes(evaluate::GetDerivedTypeSpec(that),
361 evaluate::GetDerivedTypeSpec(*this), true)) {
362 return false;
363 } else if (that.IsPolymorphic()) {
364 return std::nullopt; // unknown
365 } else {
366 return true;
367 }
368 }
369
From(const semantics::DeclTypeSpec & type)370 std::optional<DynamicType> DynamicType::From(
371 const semantics::DeclTypeSpec &type) {
372 if (const auto *intrinsic{type.AsIntrinsic()}) {
373 if (auto kind{ToInt64(intrinsic->kind())}) {
374 TypeCategory category{intrinsic->category()};
375 if (IsValidKindOfIntrinsicType(category, *kind)) {
376 if (category == TypeCategory::Character) {
377 const auto &charType{type.characterTypeSpec()};
378 return DynamicType{static_cast<int>(*kind), charType.length()};
379 } else {
380 return DynamicType{category, static_cast<int>(*kind)};
381 }
382 }
383 }
384 } else if (const auto *derived{type.AsDerived()}) {
385 return DynamicType{
386 *derived, type.category() == semantics::DeclTypeSpec::ClassDerived};
387 } else if (type.category() == semantics::DeclTypeSpec::ClassStar) {
388 return DynamicType::UnlimitedPolymorphic();
389 } else if (type.category() == semantics::DeclTypeSpec::TypeStar) {
390 return DynamicType::AssumedType();
391 } else {
392 common::die("DynamicType::From(DeclTypeSpec): failed");
393 }
394 return std::nullopt;
395 }
396
From(const semantics::Symbol & symbol)397 std::optional<DynamicType> DynamicType::From(const semantics::Symbol &symbol) {
398 return From(symbol.GetType()); // Symbol -> DeclTypeSpec -> DynamicType
399 }
400
ResultTypeForMultiply(const DynamicType & that) const401 DynamicType DynamicType::ResultTypeForMultiply(const DynamicType &that) const {
402 switch (category_) {
403 case TypeCategory::Integer:
404 switch (that.category_) {
405 case TypeCategory::Integer:
406 return DynamicType{TypeCategory::Integer, std::max(kind_, that.kind_)};
407 case TypeCategory::Real:
408 case TypeCategory::Complex:
409 return that;
410 default:
411 CRASH_NO_CASE;
412 }
413 break;
414 case TypeCategory::Real:
415 switch (that.category_) {
416 case TypeCategory::Integer:
417 return *this;
418 case TypeCategory::Real:
419 return DynamicType{TypeCategory::Real, std::max(kind_, that.kind_)};
420 case TypeCategory::Complex:
421 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)};
422 default:
423 CRASH_NO_CASE;
424 }
425 break;
426 case TypeCategory::Complex:
427 switch (that.category_) {
428 case TypeCategory::Integer:
429 return *this;
430 case TypeCategory::Real:
431 case TypeCategory::Complex:
432 return DynamicType{TypeCategory::Complex, std::max(kind_, that.kind_)};
433 default:
434 CRASH_NO_CASE;
435 }
436 break;
437 case TypeCategory::Logical:
438 switch (that.category_) {
439 case TypeCategory::Logical:
440 return DynamicType{TypeCategory::Logical, std::max(kind_, that.kind_)};
441 default:
442 CRASH_NO_CASE;
443 }
444 break;
445 default:
446 CRASH_NO_CASE;
447 }
448 return *this;
449 }
450
RequiresDescriptor() const451 bool DynamicType::RequiresDescriptor() const {
452 return IsPolymorphic() || IsNonConstantLengthCharacter() ||
453 (derived_ && CountNonConstantLenParameters(*derived_) > 0);
454 }
455
HasDeferredTypeParameter() const456 bool DynamicType::HasDeferredTypeParameter() const {
457 if (derived_) {
458 for (const auto &pair : derived_->parameters()) {
459 if (pair.second.isDeferred()) {
460 return true;
461 }
462 }
463 }
464 return charLengthParamValue_ && charLengthParamValue_->isDeferred();
465 }
466
operator ==(const SomeKind<TypeCategory::Derived> & that) const467 bool SomeKind<TypeCategory::Derived>::operator==(
468 const SomeKind<TypeCategory::Derived> &that) const {
469 return PointeeComparison(derivedTypeSpec_, that.derivedTypeSpec_);
470 }
471
SelectedCharKind(const std::string & s,int defaultKind)472 int SelectedCharKind(const std::string &s, int defaultKind) { // 16.9.168
473 auto lower{parser::ToLowerCaseLetters(s)};
474 auto n{lower.size()};
475 while (n > 0 && lower[0] == ' ') {
476 lower.erase(0, 1);
477 --n;
478 }
479 while (n > 0 && lower[n - 1] == ' ') {
480 lower.erase(--n, 1);
481 }
482 if (lower == "ascii") {
483 return 1;
484 } else if (lower == "ucs-2") {
485 return 2;
486 } else if (lower == "iso_10646" || lower == "ucs-4") {
487 return 4;
488 } else if (lower == "default") {
489 return defaultKind;
490 } else {
491 return -1;
492 }
493 }
494
ComparisonType(const DynamicType & t1,const DynamicType & t2)495 std::optional<DynamicType> ComparisonType(
496 const DynamicType &t1, const DynamicType &t2) {
497 switch (t1.category()) {
498 case TypeCategory::Integer:
499 switch (t2.category()) {
500 case TypeCategory::Integer:
501 return DynamicType{TypeCategory::Integer, std::max(t1.kind(), t2.kind())};
502 case TypeCategory::Real:
503 case TypeCategory::Complex:
504 return t2;
505 default:
506 return std::nullopt;
507 }
508 case TypeCategory::Real:
509 switch (t2.category()) {
510 case TypeCategory::Integer:
511 return t1;
512 case TypeCategory::Real:
513 case TypeCategory::Complex:
514 return DynamicType{t2.category(), std::max(t1.kind(), t2.kind())};
515 default:
516 return std::nullopt;
517 }
518 case TypeCategory::Complex:
519 switch (t2.category()) {
520 case TypeCategory::Integer:
521 return t1;
522 case TypeCategory::Real:
523 case TypeCategory::Complex:
524 return DynamicType{TypeCategory::Complex, std::max(t1.kind(), t2.kind())};
525 default:
526 return std::nullopt;
527 }
528 case TypeCategory::Character:
529 switch (t2.category()) {
530 case TypeCategory::Character:
531 return DynamicType{
532 TypeCategory::Character, std::max(t1.kind(), t2.kind())};
533 default:
534 return std::nullopt;
535 }
536 case TypeCategory::Logical:
537 switch (t2.category()) {
538 case TypeCategory::Logical:
539 return DynamicType{TypeCategory::Logical, LogicalResult::kind};
540 default:
541 return std::nullopt;
542 }
543 default:
544 return std::nullopt;
545 }
546 }
547
548 } // namespace Fortran::evaluate
549