forked from OSchip/llvm-project
[flang] Merge with current master, address early review comments.
Original-commit: flang-compiler/f18@d1f981ddb4 Reviewed-on: https://github.com/flang-compiler/f18/pull/183 Tree-same-pre-rewrite: false
This commit is contained in:
parent
a73eebdbca
commit
55763194f1
|
@ -78,8 +78,9 @@ struct OverMembersHelper<T, std::tuple<Ts...>> {
|
|||
using type = T<Ts...>;
|
||||
};
|
||||
|
||||
template<template<typename...> class T, typename TorV>
|
||||
using OverMembers = typename OverMembersHelper<T, std::decay_t<TorV>>::type;
|
||||
template<template<typename...> class T, typename TUPLEorVARIANT>
|
||||
using OverMembers =
|
||||
typename OverMembersHelper<T, std::decay_t<TUPLEorVARIANT>>::type;
|
||||
|
||||
// SearchMembers<PREDICATE> scans the types that constitute the alternatives
|
||||
// of a std::variant instantiation or elements of a std::tuple.
|
||||
|
@ -92,31 +93,14 @@ template<template<typename> class PREDICATE> struct SearchMembersHelper {
|
|||
};
|
||||
};
|
||||
|
||||
template<template<typename> class PREDICATE, typename TorV>
|
||||
template<template<typename> class PREDICATE, typename TUPLEorVARIANT>
|
||||
constexpr int SearchMembers{
|
||||
OverMembers<SearchMembersHelper<PREDICATE>::template Scanner,
|
||||
TorV>::value()};
|
||||
TUPLEorVARIANT>::value()};
|
||||
|
||||
template<typename A, typename TorV>
|
||||
template<typename A, typename TUPLEorVARIANT>
|
||||
constexpr bool HasMember{
|
||||
SearchMembers<MatchType<A>::template Match, TorV> >= 0};
|
||||
|
||||
// const A * -> std::optional<A>
|
||||
template<typename A> std::optional<A> GetIfNonNull(const A *p) {
|
||||
if (p) {
|
||||
return {*p};
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// const std::variant<..., A, ...> -> std::optional<A>
|
||||
// i.e., when a variant holds a value of a particular type, return a copy
|
||||
// of that value in a std::optional<>. The type A must be a valid
|
||||
// alternative for the variant.
|
||||
template<typename A, typename VARIANT>
|
||||
std::optional<A> GetIf(const VARIANT &u) {
|
||||
return GetIfNonNull(std::get_if<A>(&u));
|
||||
}
|
||||
SearchMembers<MatchType<A>::template Match, TUPLEorVARIANT> >= 0};
|
||||
|
||||
// std::optional<std::optional<A>> -> std::optional<A>
|
||||
template<typename A>
|
||||
|
@ -209,9 +193,10 @@ template<template<typename> class F, template<typename...> class PACKAGE,
|
|||
struct MapTemplateHelper<F, PACKAGE, std::variant<Ts...>> {
|
||||
using type = PACKAGE<F<Ts>...>;
|
||||
};
|
||||
template<template<typename> class F, typename TorV,
|
||||
template<template<typename> class F, typename TUPLEorVARIANT,
|
||||
template<typename...> class PACKAGE = std::variant>
|
||||
using MapTemplate = typename MapTemplateHelper<F, PACKAGE, TorV>::type;
|
||||
using MapTemplate =
|
||||
typename MapTemplateHelper<F, PACKAGE, TUPLEorVARIANT>::type;
|
||||
|
||||
// std::tuple<std::optional<>...> -> std::optional<std::tuple<...>>
|
||||
// i.e., inverts a tuple of optional values into an optional tuple that has
|
||||
|
|
|
@ -503,13 +503,13 @@ template<typename RESULT>
|
|||
auto ExpressionBase<RESULT>::ScalarValue() const
|
||||
-> std::optional<Scalar<Result>> {
|
||||
if constexpr (Result::isSpecificType) {
|
||||
if (auto c{common::GetIf<Constant<Result>>(derived().u)}) {
|
||||
if (auto *c{std::get_if<Constant<Result>>(&derived().u)}) {
|
||||
return {c->value};
|
||||
}
|
||||
// TODO: every specifically-typed Expr should support Parentheses
|
||||
if constexpr (common::HasMember<Parentheses<Result>,
|
||||
decltype(derived().u)>) {
|
||||
if (auto p{common::GetIf<Parentheses<Result>>(derived().u)}) {
|
||||
if (auto *p{std::get_if<Parentheses<Result>>(&derived().u)}) {
|
||||
return p->left().ScalarValue();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ Expr<TO> ConvertToType(Expr<SomeKind<FROMCAT>> &&x) {
|
|||
}
|
||||
} else {
|
||||
// Same type category
|
||||
if (auto already{common::GetIf<Expr<TO>>(x.u)}) {
|
||||
if (auto *already{std::get_if<Expr<TO>>(&x.u)}) {
|
||||
return std::move(*already);
|
||||
}
|
||||
if constexpr (TO::category == TypeCategory::Complex) {
|
||||
|
|
|
@ -210,7 +210,7 @@ template<typename TYPES> struct SomeScalar {
|
|||
SomeScalar(std::enable_if_t<!std::is_reference_v<A>, A> &&x)
|
||||
: u{std::move(x)} {}
|
||||
|
||||
auto ToInt64() const {
|
||||
std::optional<std::int64_t> ToInt64() const {
|
||||
return std::visit(
|
||||
[](const auto &x) -> std::optional<std::int64_t> {
|
||||
if constexpr (TypeOf<decltype(x)>::category ==
|
||||
|
@ -222,7 +222,7 @@ template<typename TYPES> struct SomeScalar {
|
|||
u);
|
||||
}
|
||||
|
||||
auto ToString() const {
|
||||
std::optional<std::string> ToString() const {
|
||||
return std::visit(
|
||||
[](const auto &x) -> std::optional<std::string> {
|
||||
if constexpr (std::is_same_v<std::string,
|
||||
|
@ -234,7 +234,7 @@ template<typename TYPES> struct SomeScalar {
|
|||
u);
|
||||
}
|
||||
|
||||
auto IsTrue() const {
|
||||
std::optional<bool> IsTrue() const {
|
||||
return std::visit(
|
||||
[](const auto &x) -> std::optional<bool> {
|
||||
if constexpr (TypeOf<decltype(x)>::category ==
|
||||
|
@ -246,10 +246,6 @@ template<typename TYPES> struct SomeScalar {
|
|||
u);
|
||||
}
|
||||
|
||||
template<typename T> auto GetIf() const {
|
||||
return common::GetIf<Scalar<T>>(u);
|
||||
}
|
||||
|
||||
common::MapTemplate<Scalar, Types> u;
|
||||
};
|
||||
|
||||
|
|
|
@ -323,9 +323,11 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
|
|||
|
||||
MaybeExpr ExprAnalyzer::Analyze(const parser::SignedRealLiteralConstant &x) {
|
||||
if (MaybeExpr result{Analyze(std::get<parser::RealLiteralConstant>(x.t))}) {
|
||||
auto *realExpr{std::get_if<Expr<SomeReal>>(&result->u)};
|
||||
CHECK(realExpr != nullptr);
|
||||
if (auto sign{std::get<std::optional<parser::Sign>>(x.t)}) {
|
||||
if (sign == parser::Sign::Negative) {
|
||||
return {AsGenericExpr(-*common::GetIf<Expr<SomeReal>>(result->u))};
|
||||
return {AsGenericExpr(-std::move(*realExpr))};
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -397,66 +399,42 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
|
|||
return {AsGenericExpr(value.value)};
|
||||
}
|
||||
|
||||
template<typename TYPE, TypeCategory CATEGORY>
|
||||
MaybeExpr DataRefIfType(
|
||||
const semantics::Symbol &symbol, int defaultKind, DataRef &&dataRef) {
|
||||
template<TypeCategory CATEGORY>
|
||||
MaybeExpr TypedDataRefHelper(int kind, DataRef &&dataRef) {
|
||||
return common::SearchDynamicTypes(
|
||||
TypeKindVisitor<CATEGORY, DataReference, DataRef>{
|
||||
kind, std::move(dataRef)});
|
||||
}
|
||||
|
||||
static MaybeExpr TypedDataRef(
|
||||
const semantics::Symbol &symbol, DataRef &&dataRef) {
|
||||
if (auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
||||
if (details->type().has_value()) {
|
||||
if (details->type()->category() ==
|
||||
semantics::DeclTypeSpec::Category::Intrinsic) {
|
||||
std::uint64_t kindParam{
|
||||
details->type()->intrinsicTypeSpec().kind().value().value()};
|
||||
int kind = static_cast<int>(kindParam);
|
||||
if (static_cast<std::uint64_t>(kind) == kindParam) {
|
||||
// TODO: Inspection of semantics::IntrinsicTypeSpec requires the use
|
||||
// of forbidden RTTI via dynamic_cast<>. See whether
|
||||
// semantics::IntrinsicTypeSpec can be augmented with query
|
||||
// interfaces instead.
|
||||
if (dynamic_cast<const TYPE *>(
|
||||
&details->type()->intrinsicTypeSpec()) != nullptr) {
|
||||
if (kind == 0) { // TODO: resolve default kinds in semantics
|
||||
kind = defaultKind;
|
||||
}
|
||||
if (MaybeExpr result{common::SearchDynamicTypes(
|
||||
TypeKindVisitor<CATEGORY, DataReference, DataRef>{
|
||||
kind, std::move(dataRef)})}) {
|
||||
return result;
|
||||
TypeCategory category{details->type()->intrinsicTypeSpec().category()};
|
||||
int kind{details->type()->intrinsicTypeSpec().kind()};
|
||||
switch (category) {
|
||||
case TypeCategory::Integer:
|
||||
return TypedDataRefHelper<TypeCategory::Integer>(
|
||||
kind, std::move(dataRef));
|
||||
case TypeCategory::Real:
|
||||
return TypedDataRefHelper<TypeCategory::Real>(
|
||||
kind, std::move(dataRef));
|
||||
case TypeCategory::Complex:
|
||||
return TypedDataRefHelper<TypeCategory::Complex>(
|
||||
kind, std::move(dataRef));
|
||||
case TypeCategory::Character:
|
||||
return TypedDataRefHelper<TypeCategory::Character>(
|
||||
kind, std::move(dataRef));
|
||||
case TypeCategory::Logical:
|
||||
return TypedDataRefHelper<TypeCategory::Logical>(
|
||||
kind, std::move(dataRef));
|
||||
default: CRASH_NO_CASE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
static MaybeExpr TypedDataRef(const semantics::Symbol &symbol,
|
||||
const semantics::IntrinsicTypeDefaultKinds &defaults, DataRef &&dataRef) {
|
||||
if (MaybeExpr result{
|
||||
DataRefIfType<semantics::IntegerTypeSpec, TypeCategory::Integer>(
|
||||
symbol, defaults.defaultIntegerKind, std::move(dataRef))}) {
|
||||
return result;
|
||||
}
|
||||
if (MaybeExpr result{
|
||||
DataRefIfType<semantics::RealTypeSpec, TypeCategory::Real>(
|
||||
symbol, defaults.defaultRealKind, std::move(dataRef))}) {
|
||||
return result;
|
||||
}
|
||||
if (MaybeExpr result{
|
||||
DataRefIfType<semantics::ComplexTypeSpec, TypeCategory::Complex>(
|
||||
symbol, defaults.defaultRealKind, std::move(dataRef))}) {
|
||||
return result;
|
||||
}
|
||||
if (MaybeExpr result{
|
||||
DataRefIfType<semantics::CharacterTypeSpec, TypeCategory::Character>(
|
||||
symbol, defaults.defaultCharacterKind, std::move(dataRef))}) {
|
||||
return result;
|
||||
}
|
||||
if (MaybeExpr result{
|
||||
DataRefIfType<semantics::LogicalTypeSpec, TypeCategory::Logical>(
|
||||
symbol, defaults.defaultLogicalKind, std::move(dataRef))}) {
|
||||
return result;
|
||||
}
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
@ -471,8 +449,7 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::Name &n) {
|
|||
"TODO: PARAMETER references not yet implemented"_err_en_US);
|
||||
// TODO: enumerators, do they have the PARAMETER attribute?
|
||||
} else {
|
||||
if (MaybeExpr result{
|
||||
TypedDataRef(*n.symbol, defaults, DataRef{*n.symbol})}) {
|
||||
if (MaybeExpr result{TypedDataRef(*n.symbol, DataRef{*n.symbol})}) {
|
||||
return result;
|
||||
}
|
||||
context.messages.Say("'%s' is not of a supported type and kind"_err_en_US,
|
||||
|
@ -562,8 +539,7 @@ MaybeExpr ExprAnalyzer::Analyze(const parser::ArrayElement &ae) {
|
|||
name->ToString().data());
|
||||
} else {
|
||||
ArrayRef arrayRef{*name->symbol, std::move(subscripts)};
|
||||
return TypedDataRef(
|
||||
*name->symbol, defaults, DataRef{std::move(arrayRef)});
|
||||
return TypedDataRef(*name->symbol, DataRef{std::move(arrayRef)});
|
||||
}
|
||||
} else if (const auto *component{
|
||||
std::get_if<common::Indirection<parser::StructureComponent>>(
|
||||
|
|
Loading…
Reference in New Issue