[flang] Expression analysis on DataStmtConstant

Data statements contains expressions but they are not wrapped in one of
the kinds of parse tree nodes that are analyzed, like `parser::Expr`.
So potential errors were not discovered.

Change `ExprChecker` to handle `DataStmtConstant` and analyze any
expressions that are contained in it. Note that the analyzed form of
the expression is not yet saved in the parse tree.

Original-commit: flang-compiler/f18@8bdaf0a521
Reviewed-on: https://github.com/flang-compiler/f18/pull/1044
This commit is contained in:
Tim Keith 2020-03-02 07:59:29 -08:00
parent 015075840d
commit 2a00c617d6
4 changed files with 66 additions and 3 deletions

View File

@ -230,6 +230,10 @@ public:
return Analyze<parser::DataRef>(dr);
}
MaybeExpr Analyze(const parser::StructureComponent &);
MaybeExpr Analyze(const parser::SignedIntLiteralConstant &);
MaybeExpr Analyze(const parser::SignedRealLiteralConstant &);
MaybeExpr Analyze(const parser::SignedComplexLiteralConstant &);
MaybeExpr Analyze(const parser::StructureConstructor &);
void Analyze(const parser::CallStmt &);
const Assignment *Analyze(const parser::AssignmentStmt &);
@ -240,9 +244,7 @@ protected:
private:
MaybeExpr Analyze(const parser::IntLiteralConstant &);
MaybeExpr Analyze(const parser::SignedIntLiteralConstant &);
MaybeExpr Analyze(const parser::RealLiteralConstant &);
MaybeExpr Analyze(const parser::SignedRealLiteralConstant &);
MaybeExpr Analyze(const parser::ComplexPart &);
MaybeExpr Analyze(const parser::ComplexLiteralConstant &);
MaybeExpr Analyze(const parser::LogicalLiteralConstant &);
@ -255,7 +257,6 @@ private:
MaybeExpr Analyze(const parser::CoindexedNamedObject &);
MaybeExpr Analyze(const parser::CharLiteralConstantSubstring &);
MaybeExpr Analyze(const parser::ArrayConstructor &);
MaybeExpr Analyze(const parser::StructureConstructor &);
MaybeExpr Analyze(const parser::FunctionReference &,
std::optional<parser::StructureConstructor> * = nullptr);
MaybeExpr Analyze(const parser::Expr::Parentheses &);
@ -448,6 +449,7 @@ public:
AnalyzePointerAssignmentStmt(context_, x);
return false;
}
bool Pre(const parser::DataStmtConstant &);
template<typename A> bool Pre(const parser::Scalar<A> &x) {
AnalyzeExpr(context_, x);

View File

@ -454,11 +454,14 @@ MaybeExpr ExpressionAnalyzer::IntLiteralConstant(const PARSED &x) {
}
MaybeExpr ExpressionAnalyzer::Analyze(const parser::IntLiteralConstant &x) {
auto restorer{
GetContextualMessages().SetLocation(std::get<parser::CharBlock>(x.t))};
return IntLiteralConstant(x);
}
MaybeExpr ExpressionAnalyzer::Analyze(
const parser::SignedIntLiteralConstant &x) {
auto restorer{GetContextualMessages().SetLocation(x.source)};
return IntLiteralConstant(x);
}
@ -553,6 +556,18 @@ MaybeExpr ExpressionAnalyzer::Analyze(
return std::nullopt;
}
MaybeExpr ExpressionAnalyzer::Analyze(
const parser::SignedComplexLiteralConstant &x) {
auto result{Analyze(std::get<parser::ComplexLiteralConstant>(x.t))};
if (!result) {
return std::nullopt;
} else if (std::get<parser::Sign>(x.t) == parser::Sign::Negative) {
return AsGenericExpr(-std::move(std::get<Expr<SomeComplex>>(result->u)));
} else {
return result;
}
}
MaybeExpr ExpressionAnalyzer::Analyze(const parser::ComplexPart &x) {
return Analyze(x.u);
}
@ -2949,4 +2964,18 @@ bool ExprChecker::Walk(const parser::Program &program) {
parser::Walk(program, *this);
return !context_.AnyFatalError();
}
bool ExprChecker::Pre(const parser::DataStmtConstant &x) {
std::visit(
common::visitors{
[&](const parser::NullInit &) {},
[&](const parser::InitialDataTarget &y) {
AnalyzeExpr(context_, y.value());
},
[&](const auto &y) { AnalyzeExpr(context_, y); },
},
x.u);
return false;
}
}

View File

@ -213,6 +213,7 @@ set(ERROR_TESTS
block-data01.f90
complex01.f90
data01.f90
data02.f90
namelist01.f90
)

View File

@ -0,0 +1,31 @@
! Check that expressions are analyzed in data statements
subroutine s1
type :: t
character(1) :: c
end type
type(t) :: x
!ERROR: Value in structure constructor of type INTEGER(4) is incompatible with component 'c' of type CHARACTER(KIND=1,LEN=1_4)
data x /t(1)/
end
subroutine s2
real :: x1, x2
integer :: i1, i2
!ERROR: Unsupported REAL(KIND=99)
data x1 /1.0_99/
!ERROR: Unsupported REAL(KIND=99)
data x2 /-1.0_99/
!ERROR: INTEGER(KIND=99) is not a supported type
data i1 /1_99/
!ERROR: INTEGER(KIND=99) is not a supported type
data i2 /-1_99/
end
subroutine s3
complex :: z1, z2
!ERROR: Unsupported REAL(KIND=99)
data z1 /(1.0, 2.0_99)/
!ERROR: Unsupported REAL(KIND=99)
data z2 /-(1.0, 2.0_99)/
end