diff --git a/flang/include/flang/Semantics/type.h b/flang/include/flang/Semantics/type.h --- a/flang/include/flang/Semantics/type.h +++ b/flang/include/flang/Semantics/type.h @@ -293,7 +293,6 @@ return nullptr; } } - bool MightBeAssignmentCompatibleWith(const DerivedTypeSpec &) const; bool operator==(const DerivedTypeSpec &that) const { return RawEquals(that) && parameters_ == that.parameters_; } diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp --- a/flang/lib/Semantics/tools.cpp +++ b/flang/lib/Semantics/tools.cpp @@ -88,16 +88,13 @@ } } -static bool MightHaveCompatibleDerivedtypes( +// 7.5.2.4 "same derived type" test -- rely on IsTkCompatibleWith() and its +// infrastructure to detect and handle comparisons on distinct (but "same") +// sequence/bind(C) derived types +static bool MightBeSameDerivedType( const std::optional &lhsType, const std::optional &rhsType) { - const DerivedTypeSpec *lhsDerived{evaluate::GetDerivedTypeSpec(lhsType)}; - const DerivedTypeSpec *rhsDerived{evaluate::GetDerivedTypeSpec(rhsType)}; - if (!lhsDerived || !rhsDerived) { - return false; - } - return *lhsDerived == *rhsDerived || - lhsDerived->MightBeAssignmentCompatibleWith(*rhsDerived); + return lhsType && rhsType && rhsType->IsTkCompatibleWith(*lhsType); } Tristate IsDefinedAssignment( @@ -113,7 +110,7 @@ } else if (lhsCat != TypeCategory::Derived) { return ToTristate(lhsCat != rhsCat && (!IsNumericTypeCategory(lhsCat) || !IsNumericTypeCategory(rhsCat))); - } else if (MightHaveCompatibleDerivedtypes(lhsType, rhsType)) { + } else if (MightBeSameDerivedType(lhsType, rhsType)) { return Tristate::Maybe; // TYPE(t) = TYPE(t) can be defined or intrinsic } else { return Tristate::Yes; diff --git a/flang/lib/Semantics/type.cpp b/flang/lib/Semantics/type.cpp --- a/flang/lib/Semantics/type.cpp +++ b/flang/lib/Semantics/type.cpp @@ -199,17 +199,6 @@ const_cast(this)->FindParameter(target)); } -// Objects of derived types might be assignment compatible if they are equal -// with respect to everything other than their instantiated type parameters -// and their constant instantiated type parameters have the same values. -bool DerivedTypeSpec::MightBeAssignmentCompatibleWith( - const DerivedTypeSpec &that) const { - if (!RawEquals(that)) { - return false; - } - return AreTypeParamCompatible(*this, that); -} - class InstantiateHelper { public: InstantiateHelper(Scope &scope) : scope_{scope} {} diff --git a/flang/test/Semantics/assign08.f90 b/flang/test/Semantics/assign08.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/assign08.f90 @@ -0,0 +1,48 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 +! "Same type" checking for intrinsic assignment +module m1 + type :: nonSeqType + integer :: n1 + end type + type :: seqType + sequence + integer :: n2 + end type + type, bind(c) :: bindCType + integer :: n3 + end type +end module + +program test + use m1, modNonSeqType => nonSeqType, modSeqType => seqType, modBindCType => bindCType + type :: nonSeqType + integer :: n1 + end type + type :: seqType + sequence + integer :: n2 + end type + type, bind(c) :: bindCType + integer :: n3 + end type + type(modNonSeqType) :: mns1, mns2 + type(modSeqType) :: ms1, ms2 + type(modBindCType) :: mb1, mb2 + type(nonSeqType) :: ns1, ns2 + type(seqType) :: s1, s2 + type(bindCType) :: b1, b2 + ! These are trivially ok + mns1 = mns2 + ms1 = ms2 + mb1 = mb2 + ns1 = ns2 + s1 = s2 + b1 = b2 + ! These are ok per 7.5.2.4 + ms1 = s1 + mb1 = b1 + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types TYPE(modnonseqtype) and TYPE(nonseqtype) + mns1 = ns1 + !ERROR: No intrinsic or user-defined ASSIGNMENT(=) matches operand types TYPE(nonseqtype) and TYPE(modnonseqtype) + ns1 = mns1 +end