diff --git a/flang/include/flang/Evaluate/tools.h b/flang/include/flang/Evaluate/tools.h --- a/flang/include/flang/Evaluate/tools.h +++ b/flang/include/flang/Evaluate/tools.h @@ -115,14 +115,19 @@ } } +inline Expr AsGenericExpr(Expr &&x) { return std::move(x); } + +// These overloads wrap DataRefs and simple whole variables up into +// generic expressions if they have a known type. +std::optional> AsGenericExpr(DataRef &&); +std::optional> AsGenericExpr(const Symbol &); + template common::IfNoLvalue::category>>, A> AsCategoryExpr( A &&x) { return Expr::category>>{AsExpr(std::move(x))}; } -inline Expr AsGenericExpr(Expr &&x) { return std::move(x); } - Expr Parenthesize(Expr &&); Expr GetComplexPart( diff --git a/flang/lib/Evaluate/fold-designator.cpp b/flang/lib/Evaluate/fold-designator.cpp --- a/flang/lib/Evaluate/fold-designator.cpp +++ b/flang/lib/Evaluate/fold-designator.cpp @@ -312,12 +312,12 @@ if (std::optional dataRef{ OffsetToDataRef(context, NamedEntity{baseSymbol}, offset, size)}) { const Symbol &symbol{dataRef->GetLastSymbol()}; - if (auto type{DynamicType::From(symbol)}) { - if (std::optional> result{ - TypedWrapper(*type, std::move(*dataRef))}) { - if (IsAllocatableOrPointer(symbol)) { - } else if (auto elementBytes{ - ToInt64(type->MeasureSizeInBytes(context, true))}) { + if (std::optional> result{ + AsGenericExpr(std::move(*dataRef))}) { + if (IsAllocatableOrPointer(symbol)) { + } else if (auto type{DynamicType::From(symbol)}) { + if (auto elementBytes{ + ToInt64(type->MeasureSizeInBytes(context, true))}) { if (auto *zExpr{std::get_if>(&result->u)}) { if (size * 2 > static_cast(*elementBytes)) { return result; @@ -351,9 +351,9 @@ } } } - if (offset == 0) { - return result; - } + } + if (offset == 0) { + return result; } } } diff --git a/flang/lib/Evaluate/tools.cpp b/flang/lib/Evaluate/tools.cpp --- a/flang/lib/Evaluate/tools.cpp +++ b/flang/lib/Evaluate/tools.cpp @@ -19,6 +19,18 @@ namespace Fortran::evaluate { +std::optional> AsGenericExpr(DataRef &&ref) { + const Symbol &symbol{ref.GetLastSymbol()}; + if (auto dyType{DynamicType::From(symbol)}) { + return TypedWrapper(*dyType, std::move(ref)); + } + return std::nullopt; +} + +std::optional> AsGenericExpr(const Symbol &symbol) { + return AsGenericExpr(DataRef{symbol}); +} + Expr Parenthesize(Expr &&expr) { return std::visit( [&](auto &&x) { 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 @@ -538,13 +538,10 @@ !scopeIsUninstantiatedPDT_) { if (const auto *object{symbol.detailsIf()}) { if (object->init()) { // C764, C765; C808 - if (auto dyType{evaluate::DynamicType::From(symbol)}) { - if (auto designator{evaluate::TypedWrapper( - *dyType, evaluate::DataRef{symbol})}) { - auto restorer{messages_.SetLocation(symbol.name())}; - context_.set_location(symbol.name()); - CheckInitialTarget(foldingContext_, *designator, *object->init()); - } + if (auto designator{evaluate::AsGenericExpr(symbol)}) { + auto restorer{messages_.SetLocation(symbol.name())}; + context_.set_location(symbol.name()); + CheckInitialTarget(foldingContext_, *designator, *object->init()); } } } else if (const auto *proc{symbol.detailsIf()}) { diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -195,12 +195,11 @@ } else { Say("'%s' is not a specific intrinsic procedure"_err_en_US, symbol.name()); - return std::nullopt; } - } else if (auto dyType{DynamicType::From(symbol)}) { - return TypedWrapper(*dyType, std::move(ref)); + return std::nullopt; + } else { + return AsGenericExpr(std::move(ref)); } - return std::nullopt; } // Some subscript semantic checks must be deferred until all of the