Skip to content

Commit 934b27a

Browse files
committed
[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
1 parent 6816078 commit 934b27a

File tree

3 files changed

+23
-26
lines changed

3 files changed

+23
-26
lines changed

flang/include/flang/Semantics/expression.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,8 @@ class ExpressionAnalyzer {
326326
// Analysis subroutines
327327
int AnalyzeKindParam(
328328
const std::optional<parser::KindParam> &, int defaultKind);
329-
template <typename PARSED> MaybeExpr ExprOrVariable(const PARSED &);
329+
template <typename PARSED>
330+
MaybeExpr ExprOrVariable(const PARSED &, parser::CharBlock source);
330331
template <typename PARSED> MaybeExpr IntLiteralConstant(const PARSED &);
331332
MaybeExpr AnalyzeString(std::string &&, int kind);
332333
std::optional<Expr<SubscriptInteger>> AsSubscript(MaybeExpr &&);

flang/lib/Evaluate/characteristics.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -405,14 +405,9 @@ std::optional<DummyArgument> DummyArgument::FromActual(
405405
}
406406
},
407407
[&](const auto &) {
408-
if (auto type{expr.GetType()}) {
409-
if (auto shape{GetShape(context, expr)}) {
410-
return std::make_optional<DummyArgument>(std::move(name),
411-
DummyDataObject{TypeAndShape{*type, std::move(*shape)}});
412-
} else {
413-
return std::make_optional<DummyArgument>(
414-
std::move(name), DummyDataObject{TypeAndShape{*type}});
415-
}
408+
if (auto type{TypeAndShape::Characterize(expr, context)}) {
409+
return std::make_optional<DummyArgument>(
410+
std::move(name), DummyDataObject{std::move(*type)});
416411
} else {
417412
return std::optional<DummyArgument>{};
418413
}

flang/lib/Semantics/expression.cpp

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ static std::optional<DynamicTypeWithLength> AnalyzeTypeSpec(
9898
class ArgumentAnalyzer {
9999
public:
100100
explicit ArgumentAnalyzer(ExpressionAnalyzer &context)
101-
: context_{context}, isProcedureCall_{false} {}
101+
: context_{context}, source_{context.GetContextualMessages().at()},
102+
isProcedureCall_{false} {}
102103
ArgumentAnalyzer(ExpressionAnalyzer &context, parser::CharBlock source,
103104
bool isProcedureCall = false)
104105
: context_{context}, source_{source}, isProcedureCall_{isProcedureCall} {}
@@ -656,6 +657,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::BOZLiteralConstant &x) {
656657

657658
// Names and named constants
658659
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
660+
auto restorer{GetContextualMessages().SetLocation(n.source)};
659661
if (std::optional<int> kind{IsImpliedDo(n.source)}) {
660662
return AsMaybeExpr(ConvertToKind<TypeCategory::Integer>(
661663
*kind, AsExpr(ImpliedDoIndex{n.source})));
@@ -696,6 +698,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Name &n) {
696698
}
697699

698700
MaybeExpr ExpressionAnalyzer::Analyze(const parser::NamedConstant &n) {
701+
auto restorer{GetContextualMessages().SetLocation(n.v.source)};
699702
if (MaybeExpr value{Analyze(n.v)}) {
700703
Expr<SomeType> folded{Fold(std::move(*value))};
701704
if (IsConstantExpr(folded)) {
@@ -967,11 +970,8 @@ static std::optional<Component> CreateComponent(
967970
// Derived type component references and type parameter inquiries
968971
MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
969972
MaybeExpr base{Analyze(sc.base)};
970-
if (!base) {
971-
return std::nullopt;
972-
}
973973
Symbol *sym{sc.component.symbol};
974-
if (context_.HasError(sym)) {
974+
if (!base || !sym || context_.HasError(sym)) {
975975
return std::nullopt;
976976
}
977977
const auto &name{sc.component.source};
@@ -981,6 +981,7 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::StructureComponent &sc) {
981981
if (auto *designator{UnwrapExpr<Designator<SomeDerived>>(*dtExpr)}) {
982982
if (std::optional<DynamicType> dyType{DynamicType::From(*sym)}) {
983983
if (dyType->category() == TypeCategory::Integer) {
984+
auto restorer{GetContextualMessages().SetLocation(name)};
984985
return Fold(ConvertToType(*dyType,
985986
AsGenericExpr(TypeParamInquiry{
986987
IgnoreAnySubscripts(std::move(*designator)), *sym})));
@@ -2155,8 +2156,7 @@ const Assignment *ExpressionAnalyzer::Analyze(const parser::AssignmentStmt &x) {
21552156
new GenericAssignmentWrapper{}, GenericAssignmentWrapper::Deleter);
21562157
} else {
21572158
std::optional<ProcedureRef> procRef{analyzer.TryDefinedAssignment()};
2158-
Assignment assignment{
2159-
Fold(analyzer.MoveExpr(0)), Fold(analyzer.MoveExpr(1))};
2159+
Assignment assignment{analyzer.MoveExpr(0), analyzer.MoveExpr(1)};
21602160
if (procRef) {
21612161
assignment.u = std::move(*procRef);
21622162
}
@@ -2601,18 +2601,20 @@ static void FixMisparsedFunctionReference(
26012601
// Common handling of parse tree node types that retain the
26022602
// representation of the analyzed expression.
26032603
template <typename PARSED>
2604-
MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) {
2604+
MaybeExpr ExpressionAnalyzer::ExprOrVariable(
2605+
const PARSED &x, parser::CharBlock source) {
26052606
if (useSavedTypedExprs_ && x.typedExpr) {
26062607
return x.typedExpr->v;
26072608
}
2609+
auto restorer{GetContextualMessages().SetLocation(source)};
26082610
if constexpr (std::is_same_v<PARSED, parser::Expr> ||
26092611
std::is_same_v<PARSED, parser::Variable>) {
26102612
FixMisparsedFunctionReference(context_, x.u);
26112613
}
26122614
if (AssumedTypeDummy(x)) { // C710
26132615
Say("TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
2614-
} else if (MaybeExpr result{evaluate::Fold(foldingContext_, Analyze(x.u))}) {
2615-
SetExpr(x, std::move(*result));
2616+
} else if (MaybeExpr result{Analyze(x.u)}) {
2617+
SetExpr(x, Fold(std::move(*result)));
26162618
return x.typedExpr->v;
26172619
}
26182620
ResetExpr(x);
@@ -2628,17 +2630,17 @@ MaybeExpr ExpressionAnalyzer::ExprOrVariable(const PARSED &x) {
26282630

26292631
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr &expr) {
26302632
auto restorer{GetContextualMessages().SetLocation(expr.source)};
2631-
return ExprOrVariable(expr);
2633+
return ExprOrVariable(expr, expr.source);
26322634
}
26332635

26342636
MaybeExpr ExpressionAnalyzer::Analyze(const parser::Variable &variable) {
26352637
auto restorer{GetContextualMessages().SetLocation(variable.GetSource())};
2636-
return ExprOrVariable(variable);
2638+
return ExprOrVariable(variable, variable.GetSource());
26372639
}
26382640

26392641
MaybeExpr ExpressionAnalyzer::Analyze(const parser::DataStmtConstant &x) {
26402642
auto restorer{GetContextualMessages().SetLocation(x.source)};
2641-
return ExprOrVariable(x);
2643+
return ExprOrVariable(x, x.source);
26422644
}
26432645

26442646
Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
@@ -2652,12 +2654,11 @@ Expr<SubscriptInteger> ExpressionAnalyzer::AnalyzeKindSelector(
26522654
common::visitors{
26532655
[&](const parser::ScalarIntConstantExpr &x) {
26542656
if (MaybeExpr kind{Analyze(x)}) {
2655-
Expr<SomeType> folded{Fold(std::move(*kind))};
2656-
if (std::optional<std::int64_t> code{ToInt64(folded)}) {
2657+
if (std::optional<std::int64_t> code{ToInt64(*kind)}) {
26572658
if (CheckIntrinsicKind(category, *code)) {
26582659
return Expr<SubscriptInteger>{*code};
26592660
}
2660-
} else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(folded)}) {
2661+
} else if (auto *intExpr{UnwrapExpr<Expr<SomeInteger>>(*kind)}) {
26612662
return ConvertToType<SubscriptInteger>(std::move(*intExpr));
26622663
}
26632664
}
@@ -3110,7 +3111,7 @@ std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr(
31103111
"TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
31113112
} else if (MaybeExpr argExpr{AnalyzeExprOrWholeAssumedSizeArray(expr)}) {
31123113
if (isProcedureCall_ || !IsProcedure(*argExpr)) {
3113-
return ActualArgument{context_.Fold(std::move(*argExpr))};
3114+
return ActualArgument{std::move(*argExpr)};
31143115
}
31153116
context_.SayAt(expr.source,
31163117
IsFunction(*argExpr) ? "Function call must have argument list"_err_en_US

0 commit comments

Comments
 (0)