[flang] Expression analysis on DataStmtConstant
authorTim Keith <tkeith@nvidia.com>
Mon, 2 Mar 2020 15:59:29 +0000 (07:59 -0800)
committerTim Keith <tkeith@nvidia.com>
Mon, 2 Mar 2020 15:59:29 +0000 (07:59 -0800)
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@8bdaf0a521f6630ec2c369b2c41484eff4803d6e
Reviewed-on: https://github.com/flang-compiler/f18/pull/1044

flang/include/flang/Semantics/expression.h
flang/lib/Semantics/expression.cpp
flang/test/Semantics/CMakeLists.txt
flang/test/Semantics/data02.f90 [new file with mode: 0644]

index 7282a96..bf04275 100644 (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);
index a09b1ac..09af89f 100644 (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;
+}
+
 }
index e6b6ad8..7144ff9 100644 (file)
@@ -213,6 +213,7 @@ set(ERROR_TESTS
   block-data01.f90
   complex01.f90
   data01.f90
+  data02.f90
   namelist01.f90
 )
 
diff --git a/flang/test/Semantics/data02.f90 b/flang/test/Semantics/data02.f90
new file mode 100644 (file)
index 0000000..4cd5936
--- /dev/null
@@ -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