Skip to content

Commit 069aee0

Browse files
authored
[flang] Rework F'2023 constraint C1167 checking (#83888)
The code that verifies that the type in a TYPE IS or CLASS IS clause is a match or an extension of the type of the SELECT TYPE selector needs rework to avoid emitting a bogus error for a test. Fixes #83612.
1 parent d35f2c4 commit 069aee0

File tree

4 files changed

+70
-36
lines changed

4 files changed

+70
-36
lines changed

flang/include/flang/Semantics/type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ class DerivedTypeSpec {
306306
}
307307
// For TYPE IS & CLASS IS: kind type parameters must be
308308
// explicit and equal, len type parameters are ignored.
309-
bool Match(const DerivedTypeSpec &) const;
309+
bool MatchesOrExtends(const DerivedTypeSpec &) const;
310310
std::string AsFortran() const;
311311
std::string VectorTypeAsFortran() const;
312312

flang/lib/Semantics/check-select-type.cpp

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,31 +120,25 @@ class TypeCaseValues {
120120
bool PassesDerivedTypeChecks(const semantics::DerivedTypeSpec &derived,
121121
parser::CharBlock sourceLoc) const {
122122
for (const auto &pair : derived.parameters()) {
123-
if (pair.second.isLen() && !pair.second.isAssumed()) { // C1160
123+
if (pair.second.isLen() && !pair.second.isAssumed()) { // F'2023 C1165
124124
context_.Say(sourceLoc,
125-
"The type specification statement must have "
126-
"LEN type parameter as assumed"_err_en_US);
125+
"The type specification statement must have LEN type parameter as assumed"_err_en_US);
127126
return false;
128127
}
129128
}
130-
if (!IsExtensibleType(&derived)) { // C1161
129+
if (!IsExtensibleType(&derived)) { // F'2023 C1166
131130
context_.Say(sourceLoc,
132-
"The type specification statement must not specify "
133-
"a type with a SEQUENCE attribute or a BIND attribute"_err_en_US);
131+
"The type specification statement must not specify a type with a SEQUENCE attribute or a BIND attribute"_err_en_US);
134132
return false;
135133
}
136-
if (!selectorType_.IsUnlimitedPolymorphic()) { // C1162
137-
if (const semantics::Scope * guardScope{derived.typeSymbol().scope()}) {
138-
if (const auto *selDerivedTypeSpec{
139-
evaluate::GetDerivedTypeSpec(selectorType_)}) {
140-
if (!derived.Match(*selDerivedTypeSpec) &&
141-
!guardScope->FindComponent(selDerivedTypeSpec->name())) {
142-
context_.Say(sourceLoc,
143-
"Type specification '%s' must be an extension"
144-
" of TYPE '%s'"_err_en_US,
145-
derived.AsFortran(), selDerivedTypeSpec->AsFortran());
146-
return false;
147-
}
134+
if (!selectorType_.IsUnlimitedPolymorphic()) { // F'2023 C1167
135+
if (const auto *selDerivedTypeSpec{
136+
evaluate::GetDerivedTypeSpec(selectorType_)}) {
137+
if (!derived.MatchesOrExtends(*selDerivedTypeSpec)) {
138+
context_.Say(sourceLoc,
139+
"Type specification '%s' must be an extension of TYPE '%s'"_err_en_US,
140+
derived.AsFortran(), selDerivedTypeSpec->AsFortran());
141+
return false;
148142
}
149143
}
150144
}

flang/lib/Semantics/type.cpp

Lines changed: 26 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -231,27 +231,36 @@ ParamValue *DerivedTypeSpec::FindParameter(SourceName target) {
231231
const_cast<const DerivedTypeSpec *>(this)->FindParameter(target));
232232
}
233233

234-
bool DerivedTypeSpec::Match(const DerivedTypeSpec &that) const {
235-
if (&typeSymbol_ != &that.typeSymbol_) {
236-
return false;
237-
}
238-
for (const auto &pair : parameters_) {
239-
const Symbol *tpSym{scope_ ? scope_->FindSymbol(pair.first) : nullptr};
240-
const auto *tpDetails{
241-
tpSym ? tpSym->detailsIf<TypeParamDetails>() : nullptr};
242-
if (!tpDetails) {
243-
return false;
244-
}
245-
if (tpDetails->attr() != common::TypeParamAttr::Kind) {
246-
continue;
234+
static bool MatchKindParams(const Symbol &typeSymbol,
235+
const DerivedTypeSpec &thisSpec, const DerivedTypeSpec &thatSpec) {
236+
for (auto ref : typeSymbol.get<DerivedTypeDetails>().paramDecls()) {
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+
}
247243
}
248-
const ParamValue &value{pair.second};
249-
auto iter{that.parameters_.find(pair.first)};
250-
if (iter == that.parameters_.end() || iter->second != value) {
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 {
251260
return false;
252261
}
253262
}
254-
return true;
263+
return MatchKindParams(*typeSymbol, *this, that);
255264
}
256265

257266
class InstantiateHelper {

flang/test/Semantics/selecttype04.f90

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
! Check F'2023 C1167
3+
module m
4+
type :: base(kindparam, lenparam)
5+
integer, kind :: kindparam
6+
integer, len :: lenparam
7+
end type
8+
type, extends(base) :: ext1
9+
contains
10+
procedure :: tbp
11+
end type
12+
type, extends(ext1) :: ext2
13+
end type
14+
contains
15+
function tbp(x)
16+
class(ext1(123,*)), target :: x
17+
class(ext1(123,:)), pointer :: tbp
18+
tbp => x
19+
end
20+
subroutine test
21+
type(ext1(123,456)), target :: var
22+
select type (sel => var%tbp())
23+
type is (ext1(123,*)) ! ok
24+
type is (ext2(123,*)) ! ok
25+
!ERROR: Type specification 'ext1(kindparam=234_4,lenparam=*)' must be an extension of TYPE 'ext1(kindparam=123_4,lenparam=:)'
26+
type is (ext1(234,*))
27+
!ERROR: Type specification 'ext2(kindparam=234_4,lenparam=*)' must be an extension of TYPE 'ext1(kindparam=123_4,lenparam=:)'
28+
type is (ext2(234,*))
29+
end select
30+
end
31+
end

0 commit comments

Comments
 (0)