From 4cbfd93a591a2e861bb69dfe896a7cff41931c05 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Tue, 25 Aug 2020 09:40:20 -0700 Subject: [PATCH] [flang] Make `TypeParamInquiry` monomorphic Change the expression representation TypeParamInquiry from being a class that's templatized on the integer KIND of its result into a monomorphic representation that results in a SubscriptInteger that can then be converted. This is a minor simplification, but it's worth doing because it is believed to also be a work-around for bugs in the MSVC compiler with overload resolution that affect the expression traversal framework. Differential Revision: https://reviews.llvm.org/D86551 --- flang/include/flang/Evaluate/expression.h | 7 ++-- flang/include/flang/Evaluate/shape.h | 4 +-- flang/include/flang/Evaluate/traverse.h | 2 +- flang/include/flang/Evaluate/variable.h | 9 ++--- flang/lib/Evaluate/check-expression.cpp | 9 ++--- flang/lib/Evaluate/fold-implementation.h | 5 ++- flang/lib/Evaluate/fold-integer.cpp | 15 ++++----- flang/lib/Evaluate/formatting.cpp | 4 +-- flang/lib/Evaluate/variable.cpp | 4 +-- flang/lib/Lower/ConvertType.cpp | 10 +++--- flang/lib/Semantics/expression.cpp | 41 +++-------------------- flang/test/Semantics/kinds03.f90 | 8 ++--- flang/test/Semantics/modfile17.f90 | 16 ++++----- flang/test/Semantics/modfile22.f90 | 4 +-- flang/test/Semantics/modfile33.f90 | 2 +- flang/test/Semantics/symbol17.f90 | 4 +-- 16 files changed, 49 insertions(+), 95 deletions(-) diff --git a/flang/include/flang/Evaluate/expression.h b/flang/include/flang/Evaluate/expression.h index fffd4645cc9f..09847ec95407 100644 --- a/flang/include/flang/Evaluate/expression.h +++ b/flang/include/flang/Evaluate/expression.h @@ -516,15 +516,18 @@ private: Power, Extremum>; using Indices = std::conditional_t, std::tuple<>>; + using TypeParamInquiries = + std::conditional_t, std::tuple<>>; using DescriptorInquiries = std::conditional_t, std::tuple<>>; using Others = std::tuple, ArrayConstructor, - TypeParamInquiry, Designator, FunctionRef>; + Designator, FunctionRef>; public: common::TupleToVariant> + TypeParamInquiries, DescriptorInquiries, Others>> u; }; diff --git a/flang/include/flang/Evaluate/shape.h b/flang/include/flang/Evaluate/shape.h index d8a1a6f8daff..08fb70efb564 100644 --- a/flang/include/flang/Evaluate/shape.h +++ b/flang/include/flang/Evaluate/shape.h @@ -93,9 +93,7 @@ public: Result operator()(const ImpliedDoIndex &) const { return Scalar(); } Result operator()(const DescriptorInquiry &) const { return Scalar(); } - template Result operator()(const TypeParamInquiry &) const { - return Scalar(); - } + Result operator()(const TypeParamInquiry &) const { return Scalar(); } Result operator()(const BOZLiteralConstant &) const { return Scalar(); } Result operator()(const StaticDataObject::Pointer &) const { return Scalar(); diff --git a/flang/include/flang/Evaluate/traverse.h b/flang/include/flang/Evaluate/traverse.h index a81f511d9dfa..9238e58a1fb3 100644 --- a/flang/include/flang/Evaluate/traverse.h +++ b/flang/include/flang/Evaluate/traverse.h @@ -120,7 +120,7 @@ public: return visitor_(x.GetFirstSymbol()); } } - template Result operator()(const TypeParamInquiry &x) const { + Result operator()(const TypeParamInquiry &x) const { return visitor_(x.base()); } Result operator()(const Triplet &x) const { diff --git a/flang/include/flang/Evaluate/variable.h b/flang/include/flang/Evaluate/variable.h index fd4f92b7f0ed..6265bed61f53 100644 --- a/flang/include/flang/Evaluate/variable.h +++ b/flang/include/flang/Evaluate/variable.h @@ -128,9 +128,9 @@ private: // KIND(x), which is then folded to a constant value. // "Bare" type parameter references within a derived type definition do // not have base objects. -template class TypeParamInquiry { +class TypeParamInquiry { public: - using Result = Type; + using Result = SubscriptInteger; CLASS_BOILERPLATE(TypeParamInquiry) TypeParamInquiry(NamedEntity &&x, const Symbol ¶m) : base_{std::move(x)}, parameter_{param} {} @@ -150,9 +150,6 @@ private: SymbolRef parameter_; }; -EXPAND_FOR_EACH_INTEGER_KIND( - TEMPLATE_INSTANTIATION, extern template class TypeParamInquiry, ) - // R921 subscript-triplet class Triplet { public: @@ -422,8 +419,6 @@ private: }; #define INSTANTIATE_VARIABLE_TEMPLATES \ - EXPAND_FOR_EACH_INTEGER_KIND( \ - TEMPLATE_INSTANTIATION, template class TypeParamInquiry, ) \ FOR_EACH_SPECIFIC_TYPE(template class Designator, ) } // namespace Fortran::evaluate #endif // FORTRAN_EVALUATE_VARIABLE_H_ diff --git a/flang/lib/Evaluate/check-expression.cpp b/flang/lib/Evaluate/check-expression.cpp index a7cc094033d0..09c14179d256 100644 --- a/flang/lib/Evaluate/check-expression.cpp +++ b/flang/lib/Evaluate/check-expression.cpp @@ -29,7 +29,7 @@ public: IsConstantExprHelper() : Base{*this} {} using Base::operator(); - template bool operator()(const TypeParamInquiry &inq) const { + bool operator()(const TypeParamInquiry &inq) const { return IsKindTypeParameter(inq.parameter()); } bool operator()(const semantics::Symbol &symbol) const { @@ -155,9 +155,7 @@ public: return true; } bool operator()(const StaticDataObject &) const { return false; } - template bool operator()(const TypeParamInquiry &) const { - return false; - } + bool operator()(const TypeParamInquiry &) const { return false; } bool operator()(const Triplet &x) const { return IsConstantExpr(x.lower()) && IsConstantExpr(x.upper()) && IsConstantExpr(x.stride()); @@ -310,8 +308,7 @@ public: return std::nullopt; } - template - Result operator()(const TypeParamInquiry &inq) const { + Result operator()(const TypeParamInquiry &inq) const { if (scope_.IsDerivedType() && !IsConstantExpr(inq) && inq.parameter().owner() != scope_) { // C750, C754 return "non-constant reference to a type parameter inquiry not " diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index ebe826fcbc12..e01c7de72f8d 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -115,9 +115,8 @@ Expr FoldOperation(FoldingContext &context, Designator &&designator) { return Folder{context}.Folding(std::move(designator)); } -template -Expr> FoldOperation( - FoldingContext &, TypeParamInquiry &&); +Expr FoldOperation( + FoldingContext &, TypeParamInquiry &&); Expr FoldOperation( FoldingContext &context, ImpliedDoIndex &&); template diff --git a/flang/lib/Evaluate/fold-integer.cpp b/flang/lib/Evaluate/fold-integer.cpp index 9b96a479df59..c48148900bbd 100644 --- a/flang/lib/Evaluate/fold-integer.cpp +++ b/flang/lib/Evaluate/fold-integer.cpp @@ -600,10 +600,8 @@ Expr> FoldIntrinsicFunction( } // Substitute a bare type parameter reference with its value if it has one now -template -Expr> FoldOperation( - FoldingContext &context, TypeParamInquiry &&inquiry) { - using IntKIND = Type; +Expr FoldOperation( + FoldingContext &context, TypeParamInquiry &&inquiry) { if (!inquiry.base()) { // A "bare" type parameter: replace with its value, if that's now known. if (const auto *pdt{context.pdtInstance()}) { @@ -617,21 +615,20 @@ Expr> FoldOperation( IsConstantExpr(*details->init()))) { Expr expr{*details->init()}; return Fold(context, - Expr{ - Convert(std::move(expr))}); + ConvertToType(std::move(expr))); } } } if (const auto *value{pdt->FindParameter(inquiry.parameter().name())}) { if (value->isExplicit()) { return Fold(context, - Expr{Convert( - Expr{value->GetExplicit().value()})}); + AsExpr(ConvertToType( + Expr{value->GetExplicit().value()}))); } } } } - return Expr{std::move(inquiry)}; + return AsExpr(std::move(inquiry)); } std::optional ToInt64(const Expr &expr) { diff --git a/flang/lib/Evaluate/formatting.cpp b/flang/lib/Evaluate/formatting.cpp index c2cbe4521d45..bed7fc4efee7 100644 --- a/flang/lib/Evaluate/formatting.cpp +++ b/flang/lib/Evaluate/formatting.cpp @@ -606,9 +606,7 @@ llvm::raw_ostream &BaseObject::AsFortran(llvm::raw_ostream &o) const { return EmitVar(o, u); } -template -llvm::raw_ostream &TypeParamInquiry::AsFortran( - llvm::raw_ostream &o) const { +llvm::raw_ostream &TypeParamInquiry::AsFortran(llvm::raw_ostream &o) const { if (base_) { return base_->AsFortran(o) << '%'; } diff --git a/flang/lib/Evaluate/variable.cpp b/flang/lib/Evaluate/variable.cpp index cfde6ffb6fd1..d87c71688f1a 100644 --- a/flang/lib/Evaluate/variable.cpp +++ b/flang/lib/Evaluate/variable.cpp @@ -635,9 +635,7 @@ bool NamedEntity::operator==(const NamedEntity &that) const { return !that.IsSymbol() && GetComponent() == that.GetComponent(); } } -template -bool TypeParamInquiry::operator==( - const TypeParamInquiry &that) const { +bool TypeParamInquiry::operator==(const TypeParamInquiry &that) const { return &*parameter_ == &*that.parameter_ && base_ == that.base_; } bool Triplet::operator==(const Triplet &that) const { diff --git a/flang/lib/Lower/ConvertType.cpp b/flang/lib/Lower/ConvertType.cpp index 276df03d6288..c01c6bc64595 100644 --- a/flang/lib/Lower/ConvertType.cpp +++ b/flang/lib/Lower/ConvertType.cpp @@ -262,13 +262,13 @@ private: //===--------------------------------------------------------------------===// mlir::Type gen(const Fortran::evaluate::ImpliedDoIndex &) { - return genFIRType( - context, defaultKind()); + return genFIRType( + context, Fortran::evaluate::ImpliedDoIndex::Result::kind); } - template - mlir::Type gen(const Fortran::evaluate::TypeParamInquiry &) { - return genFIRType(context); + mlir::Type gen(const Fortran::evaluate::TypeParamInquiry &) { + return genFIRType( + context, Fortran::evaluate::TypeParamInquiry::Result::kind); } template diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 21f6bdfe94b8..ec4dae2d3279 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -643,38 +643,6 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) { return AsGenericExpr(std::move(value.value)); } -// For use with SearchTypes to create a TypeParamInquiry with the -// right integer kind. -struct TypeParamInquiryVisitor { - using Result = std::optional>; - using Types = IntegerTypes; - TypeParamInquiryVisitor(int k, NamedEntity &&b, const Symbol ¶m) - : kind{k}, base{std::move(b)}, parameter{param} {} - TypeParamInquiryVisitor(int k, const Symbol ¶m) - : kind{k}, parameter{param} {} - template Result Test() { - if (kind == T::kind) { - return Expr{ - Expr{TypeParamInquiry{std::move(base), parameter}}}; - } - return std::nullopt; - } - int kind; - std::optional base; - const Symbol ¶meter; -}; - -static std::optional> MakeBareTypeParamInquiry( - const Symbol *symbol) { - if (std::optional dyType{DynamicType::From(symbol)}) { - if (dyType->category() == TypeCategory::Integer) { - return common::SearchTypes( - TypeParamInquiryVisitor{dyType->kind(), *symbol}); - } - } - return std::nullopt; -} - // Names and named constants MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) { if (std::optional kind{IsImpliedDo(n.source)}) { @@ -690,7 +658,8 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) { if (ultimate.has()) { // A bare reference to a derived type parameter (within a parameterized // derived type definition) - return AsMaybeExpr(MakeBareTypeParamInquiry(&ultimate)); + return Fold(ConvertToType( + ultimate, AsGenericExpr(TypeParamInquiry{std::nullopt, ultimate}))); } else { if (n.symbol->attrs().test(semantics::Attr::VOLATILE)) { if (const semantics::Scope * @@ -989,9 +958,9 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) { if (auto *designator{UnwrapExpr>(*dtExpr)}) { if (std::optional dyType{DynamicType::From(*sym)}) { if (dyType->category() == TypeCategory::Integer) { - return AsMaybeExpr( - common::SearchTypes(TypeParamInquiryVisitor{dyType->kind(), - IgnoreAnySubscripts(std::move(*designator)), *sym})); + return Fold(ConvertToType(*dyType, + AsGenericExpr(TypeParamInquiry{ + IgnoreAnySubscripts(std::move(*designator)), *sym}))); } } Say(name, "Type parameter is not INTEGER"_err_en_US); diff --git a/flang/test/Semantics/kinds03.f90 b/flang/test/Semantics/kinds03.f90 index 424a79903693..00e6c1fd9c56 100644 --- a/flang/test/Semantics/kinds03.f90 +++ b/flang/test/Semantics/kinds03.f90 @@ -5,7 +5,7 @@ !REF: /MainProgram1/ipdt/k integer, kind :: k !REF: /MainProgram1/ipdt/k - !DEF: /MainProgram1/ipdt/x ObjectEntity INTEGER(int(k,kind=8)) + !DEF: /MainProgram1/ipdt/x ObjectEntity INTEGER(int(int(k,kind=4),kind=8)) integer(kind=k) :: x end type ipdt !DEF: /MainProgram1/rpdt DerivedType @@ -14,7 +14,7 @@ !REF: /MainProgram1/rpdt/k integer, kind :: k !REF: /MainProgram1/rpdt/k - !DEF: /MainProgram1/rpdt/x ObjectEntity REAL(int(k,kind=8)) + !DEF: /MainProgram1/rpdt/x ObjectEntity REAL(int(int(k,kind=4),kind=8)) real(kind=k) :: x end type rpdt !DEF: /MainProgram1/zpdt DerivedType @@ -23,7 +23,7 @@ !REF: /MainProgram1/zpdt/k integer, kind :: k !REF: /MainProgram1/zpdt/k - !DEF: /MainProgram1/zpdt/x ObjectEntity COMPLEX(int(k,kind=8)) + !DEF: /MainProgram1/zpdt/x ObjectEntity COMPLEX(int(int(k,kind=4),kind=8)) complex(kind=k) :: x end type zpdt !DEF: /MainProgram1/lpdt DerivedType @@ -32,7 +32,7 @@ !REF: /MainProgram1/lpdt/k integer, kind :: k !REF: /MainProgram1/lpdt/k - !DEF: /MainProgram1/lpdt/x ObjectEntity LOGICAL(int(k,kind=8)) + !DEF: /MainProgram1/lpdt/x ObjectEntity LOGICAL(int(int(k,kind=4),kind=8)) logical(kind=k) :: x end type lpdt !REF: /MainProgram1/ipdt diff --git a/flang/test/Semantics/modfile17.f90 b/flang/test/Semantics/modfile17.f90 index 921d2f2b6008..414043c02d3a 100644 --- a/flang/test/Semantics/modfile17.f90 +++ b/flang/test/Semantics/modfile17.f90 @@ -91,21 +91,21 @@ end module !integer(2),kind::k2 !integer(4),kind::k4 !integer(8),kind::k8 -!integer(int(k1,kind=8))::j1 -!integer(int(k2,kind=8))::j2 -!integer(int(k4,kind=8))::j4 +!integer(int(int(k1,kind=1),kind=8))::j1 +!integer(int(int(k2,kind=2),kind=8))::j2 +!integer(int(int(k4,kind=4),kind=8))::j4 !integer(k8)::j8 !end type !type::defaulted(n1,n2,n4,n8) !integer(1),kind::n1=1_1 -!integer(2),kind::n2=int(int(n1,kind=4)*2_4,kind=2) -!integer(4),kind::n4=2_4*int(n2,kind=4) -!integer(8),kind::n8=int(12_4-n4,kind=8) -!type(capture(k1=n1,k2=n2,k4=n4,k8=n8))::cap +!integer(2),kind::n2=int(int(int(n1,kind=1),kind=4)*2_4,kind=2) +!integer(4),kind::n4=2_4*int(int(n2,kind=2),kind=4) +!integer(8),kind::n8=int(12_4-int(n4,kind=4),kind=8) +!type(capture(k1=int(n1,kind=1),k2=int(n2,kind=2),k4=int(n4,kind=4),k8=n8))::cap !end type !type,extends(defaulted)::extension(k5) !integer(4),kind::k5=4_4 -!integer(int(k5,kind=8))::j5 +!integer(int(int(k5,kind=4),kind=8))::j5 !end type !type(capture(k1=1_1,k2=1_2,k4=1_4,k8=1_8))::x1111 !integer(1)::res01_1 diff --git a/flang/test/Semantics/modfile22.f90 b/flang/test/Semantics/modfile22.f90 index f03621523e06..bef096bcec15 100644 --- a/flang/test/Semantics/modfile22.f90 +++ b/flang/test/Semantics/modfile22.f90 @@ -15,8 +15,8 @@ end module m !module m !type::t(k) !integer(4),kind::k=1_4 -!character(1_4,int(k,kind=8))::a -!character(3_4,int(k,kind=8))::b +!character(1_4,int(int(k,kind=4),kind=8))::a +!character(3_4,int(int(k,kind=4),kind=8))::b !end type !type(t(k=1_4)),parameter::p=t(k=1_4)(a="x",b="xx ") !character(2_4,1),parameter::c2(1_8:3_8)=[CHARACTER(KIND=1,LEN=2)::"x ","xx","xx"] diff --git a/flang/test/Semantics/modfile33.f90 b/flang/test/Semantics/modfile33.f90 index 861c2132bc57..93845fabf307 100644 --- a/flang/test/Semantics/modfile33.f90 +++ b/flang/test/Semantics/modfile33.f90 @@ -608,7 +608,7 @@ end !module m7 ! type :: t(k) ! integer(4), kind :: k -! real(int(k, kind=8)) :: a +! real(int(int(k,kind=4),kind=8))::a ! end type ! interface operator(+) ! procedure :: f1 diff --git a/flang/test/Semantics/symbol17.f90 b/flang/test/Semantics/symbol17.f90 index 1994cf9977da..f453e2e6772b 100644 --- a/flang/test/Semantics/symbol17.f90 +++ b/flang/test/Semantics/symbol17.f90 @@ -80,7 +80,7 @@ type(fwdpdt(kind(0))) function f2(n) !REF: /f2/fwdpdt/k integer, kind :: k !REF: /f2/fwdpdt/k - !DEF: /f2/fwdpdt/n ObjectEntity INTEGER(int(k,kind=8)) + !DEF: /f2/fwdpdt/n ObjectEntity INTEGER(int(int(k,kind=4),kind=8)) integer(kind=k) :: n end type !DEF: /f2/f2 ObjectEntity TYPE(fwdpdt(k=4_4)) @@ -100,7 +100,7 @@ subroutine s2 (q1) !REF: /s2/fwdpdt/k integer, kind :: k !REF: /s2/fwdpdt/k - !DEF: /s2/fwdpdt/n ObjectEntity INTEGER(int(k,kind=8)) + !DEF: /s2/fwdpdt/n ObjectEntity INTEGER(int(int(k,kind=4),kind=8)) integer(kind=k) :: n end type !REF: /s2/q1