From 934b27a9daf6cff8cb32d6e49eaf6ff8f69c7727 Mon Sep 17 00:00:00 2001 From: peter klausler Date: Fri, 30 Oct 2020 13:28:10 -0700 Subject: [PATCH] [flang] Fix actual argument character length and length error reporting Ensure that character length is properly calculated for actual arguments to intrinsics, and that source provenance information is available when expression analysis calls folding in cases where the length is invalid. Differential revision: https://reviews.llvm.org/D90636 --- flang/include/flang/Semantics/expression.h | 3 ++- flang/lib/Evaluate/characteristics.cpp | 11 +++------- flang/lib/Semantics/expression.cpp | 35 +++++++++++++++--------------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/flang/include/flang/Semantics/expression.h b/flang/include/flang/Semantics/expression.h index 4862e98..f49408e 100644 --- a/flang/include/flang/Semantics/expression.h +++ b/flang/include/flang/Semantics/expression.h @@ -326,7 +326,8 @@ private: // Analysis subroutines int AnalyzeKindParam( const std::optional &, int defaultKind); - template MaybeExpr ExprOrVariable(const PARSED &); + template + MaybeExpr ExprOrVariable(const PARSED &, parser::CharBlock source); template MaybeExpr IntLiteralConstant(const PARSED &); MaybeExpr AnalyzeString(std::string &&, int kind); std::optional> AsSubscript(MaybeExpr &&); diff --git a/flang/lib/Evaluate/characteristics.cpp b/flang/lib/Evaluate/characteristics.cpp index 3ebcfbc..e4e904c 100644 --- a/flang/lib/Evaluate/characteristics.cpp +++ b/flang/lib/Evaluate/characteristics.cpp @@ -405,14 +405,9 @@ std::optional DummyArgument::FromActual( } }, [&](const auto &) { - if (auto type{expr.GetType()}) { - if (auto shape{GetShape(context, expr)}) { - return std::make_optional(std::move(name), - DummyDataObject{TypeAndShape{*type, std::move(*shape)}}); - } else { - return std::make_optional( - std::move(name), DummyDataObject{TypeAndShape{*type}}); - } + if (auto type{TypeAndShape::Characterize(expr, context)}) { + return std::make_optional( + std::move(name), DummyDataObject{std::move(*type)}); } else { return std::optional{}; } diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp index 8ffa547..98f0c36 100644 --- a/flang/lib/Semantics/expression.cpp +++ b/flang/lib/Semantics/expression.cpp @@ -98,7 +98,8 @@ static std::optional AnalyzeTypeSpec( class ArgumentAnalyzer { public: explicit ArgumentAnalyzer(ExpressionAnalyzer &context) - : context_{context}, isProcedureCall_{false} {} + : context_{context}, source_{context.GetContextualMessages().at()}, + isProcedureCall_{false} {} ArgumentAnalyzer(ExpressionAnalyzer &context, parser::CharBlock source, bool isProcedureCall = false) : context_{context}, source_{source}, isProcedureCall_{isProcedureCall} {} @@ -656,6 +657,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) { // Names and named constants MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) { + auto restorer{GetContextualMessages().SetLocation(n.source)}; if (std::optional kind{IsImpliedDo(n.source)}) { return AsMaybeExpr(ConvertToKind( *kind, AsExpr(ImpliedDoIndex{n.source}))); @@ -696,6 +698,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) { } MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) { + auto restorer{GetContextualMessages().SetLocation(n.v.source)}; if (MaybeExpr value{Analyze(n.v)}) { Expr folded{Fold(std::move(*value))}; if (IsConstantExpr(folded)) { @@ -967,11 +970,8 @@ static std::optional CreateComponent( // Derived type component references and type parameter inquiries MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) { MaybeExpr base{Analyze(sc.base)}; - if (!base) { - return std::nullopt; - } Symbol *sym{sc.component.symbol}; - if (context_.HasError(sym)) { + if (!base || !sym || context_.HasError(sym)) { return std::nullopt; } const auto &name{sc.component.source}; @@ -981,6 +981,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) { if (auto *designator{UnwrapExpr>(*dtExpr)}) { if (std::optional dyType{DynamicType::From(*sym)}) { if (dyType->category() == TypeCategory::Integer) { + auto restorer{GetContextualMessages().SetLocation(name)}; return Fold(ConvertToType(*dyType, AsGenericExpr(TypeParamInquiry{ IgnoreAnySubscripts(std::move(*designator)), *sym}))); @@ -2155,8 +2156,7 @@ const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) { new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter); } else { std::optional procRef{analyzer.TryDefinedAssignment()}; - Assignment assignment{ - Fold(analyzer.MoveExpr(0)), Fold(analyzer.MoveExpr(1))}; + Assignment assignment{analyzer.MoveExpr(0), analyzer.MoveExpr(1)}; if (procRef) { assignment.u = std::move(*procRef); } @@ -2601,18 +2601,20 @@ static void FixMisparsedFunctionReference( // Common handling of parse tree node types that retain the // representation of the analyzed expression. template -MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) { +MaybeExpr ExpressionAnalyzer::ExprOrVariable( + const PARSED &x, parser::CharBlock source) { if (useSavedTypedExprs_ && x.typedExpr) { return x.typedExpr->v; } + auto restorer{GetContextualMessages().SetLocation(source)}; if constexpr (std::is_same_v || std::is_same_v) { FixMisparsedFunctionReference(context_, x.u); } if (AssumedTypeDummy(x)) { // C710 Say("TYPE(*) dummy argument may only be used as an actual argument"_err_en_US); - } else if (MaybeExpr result{evaluate::Fold(foldingContext_, Analyze(x.u))}) { - SetExpr(x, std::move(*result)); + } else if (MaybeExpr result{Analyze(x.u)}) { + SetExpr(x, Fold(std::move(*result))); return x.typedExpr->v; } ResetExpr(x); @@ -2628,17 +2630,17 @@ MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) { MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) { auto restorer{GetContextualMessages().SetLocation(expr.source)}; - return ExprOrVariable(expr); + return ExprOrVariable(expr, expr.source); } MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) { auto restorer{GetContextualMessages().SetLocation(variable.GetSource())}; - return ExprOrVariable(variable); + return ExprOrVariable(variable, variable.GetSource()); } MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) { auto restorer{GetContextualMessages().SetLocation(x.source)}; - return ExprOrVariable(x); + return ExprOrVariable(x, x.source); } Expr ExpressionAnalyzer::AnalyzeKindSelector( @@ -2652,12 +2654,11 @@ Expr ExpressionAnalyzer::AnalyzeKindSelector( common::visitors{ [&](const parser::ScalarIntConstantExpr &x) { if (MaybeExpr kind{Analyze(x)}) { - Expr folded{Fold(std::move(*kind))}; - if (std::optional code{ToInt64(folded)}) { + if (std::optional code{ToInt64(*kind)}) { if (CheckIntrinsicKind(category, *code)) { return Expr{*code}; } - } else if (auto *intExpr{UnwrapExpr>(folded)}) { + } else if (auto *intExpr{UnwrapExpr>(*kind)}) { return ConvertToType(std::move(*intExpr)); } } @@ -3110,7 +3111,7 @@ std::optional ArgumentAnalyzer::AnalyzeExpr( "TYPE(*) dummy argument may only be used as an actual argument"_err_en_US); } else if (MaybeExpr argExpr{AnalyzeExprOrWholeAssumedSizeArray(expr)}) { if (isProcedureCall_ || !IsProcedure(*argExpr)) { - return ActualArgument{context_.Fold(std::move(*argExpr))}; + return ActualArgument{std::move(*argExpr)}; } context_.SayAt(expr.source, IsFunction(*argExpr) ? "Function call must have argument list"_err_en_US -- 2.7.4