diff --git a/flang/include/flang/Evaluate/type.h b/flang/include/flang/Evaluate/type.h --- a/flang/include/flang/Evaluate/type.h +++ b/flang/include/flang/Evaluate/type.h @@ -142,6 +142,11 @@ return charLengthParamValue_; } constexpr std::optional knownLength() const { +#if !__clang__ && __GNUC__ == 7 + if (knownLength_ < 0) { + return std::nullopt; + } +#endif return knownLength_; } std::optional> GetCharLength() const; @@ -217,7 +222,12 @@ TypeCategory category_{TypeCategory::Derived}; // overridable default int kind_{0}; const semantics::ParamValue *charLengthParamValue_{nullptr}; +#if !__clang__ && __GNUC__ == 7 + // GCC 7's optional<> lacks a constexpr operator= + std::int64_t knownLength_{-1}; +#else std::optional knownLength_; +#endif const semantics::DerivedTypeSpec *derived_{nullptr}; // TYPE(T), CLASS(T) }; diff --git a/flang/lib/Evaluate/formatting.cpp b/flang/lib/Evaluate/formatting.cpp --- a/flang/lib/Evaluate/formatting.cpp +++ b/flang/lib/Evaluate/formatting.cpp @@ -475,10 +475,10 @@ if (derived_) { CHECK(category_ == TypeCategory::Derived); return DerivedTypeSpecAsFortran(*derived_); - } else if (charLengthParamValue_ || knownLength_) { + } else if (charLengthParamValue_ || knownLength()) { std::string result{"CHARACTER(KIND="s + std::to_string(kind_) + ",LEN="}; - if (knownLength_) { - result += std::to_string(*knownLength_) + "_8"; + if (knownLength()) { + result += std::to_string(*knownLength()) + "_8"; } else if (charLengthParamValue_->isAssumed()) { result += '*'; } else if (charLengthParamValue_->isDeferred()) { diff --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp --- a/flang/lib/Evaluate/type.cpp +++ b/flang/lib/Evaluate/type.cpp @@ -109,15 +109,15 @@ bool DynamicType::operator==(const DynamicType &that) const { return category_ == that.category_ && kind_ == that.kind_ && PointeeComparison(charLengthParamValue_, that.charLengthParamValue_) && - knownLength_.has_value() == that.knownLength_.has_value() && - (!knownLength_ || *knownLength_ == *that.knownLength_) && + knownLength().has_value() == that.knownLength().has_value() && + (!knownLength() || *knownLength() == *that.knownLength()) && PointeeComparison(derived_, that.derived_); } std::optional> DynamicType::GetCharLength() const { if (category_ == TypeCategory::Character) { - if (knownLength_) { - return AsExpr(Constant(*knownLength_)); + if (knownLength()) { + return AsExpr(Constant(*knownLength())); } else if (charLengthParamValue_) { if (auto length{charLengthParamValue_->GetExplicit()}) { return ConvertToType(std::move(*length)); @@ -194,7 +194,7 @@ bool DynamicType::IsNonConstantLengthCharacter() const { if (category_ != TypeCategory::Character) { return false; - } else if (knownLength_) { + } else if (knownLength()) { return false; } else if (!charLengthParamValue_) { return true; diff --git a/flang/lib/Semantics/check-declarations.cpp b/flang/lib/Semantics/check-declarations.cpp --- a/flang/lib/Semantics/check-declarations.cpp +++ b/flang/lib/Semantics/check-declarations.cpp @@ -2209,15 +2209,14 @@ for (const auto &[name, info] : nameToInfo_) { auto count{info.size()}; for (std::size_t i1{0}; i1 < count - 1; ++i1) { - const auto &[kind1, symbol1, proc1] = info[i1]; + const auto &[kind, symbol, proc]{info[i1]}; for (std::size_t i2{i1 + 1}; i2 < count; ++i2) { - const auto &[kind2, symbol2, proc2] = info[i2]; - auto distinguishable{kind1.IsName() + auto distinguishable{kind.IsName() ? evaluate::characteristics::Distinguishable : evaluate::characteristics::DistinguishableOpOrAssign}; - if (!distinguishable(proc1, proc2)) { - SayNotDistinguishable( - GetTopLevelUnitContaining(scope), name, kind1, symbol1, symbol2); + if (!distinguishable(proc, info[i2].procedure)) { + SayNotDistinguishable(GetTopLevelUnitContaining(scope), name, kind, + symbol, info[i2].symbol); } } }