[flang] Improvements to name resolution in data statements
authorTim Keith <tkeith@nvidia.com>
Thu, 7 Feb 2019 01:18:02 +0000 (17:18 -0800)
committerTim Keith <tkeith@nvidia.com>
Thu, 7 Feb 2019 01:18:02 +0000 (17:18 -0800)
Handle variables in data statements differently from implied dos:
If a variable is first mentioned in a data statement, it is implicitly
declared in the current scope (and subsequent type declarations only
confirm the type).
In the implied do case, the only variables that can be implicitly
declared are the iteration variables. They must be created in the new
ImpliedDos scope. There must be one such scope for each data-stmt-object
because the variable name can be reused.

Resolve references to named constants, e.g. in complex-literal-constant
and data-stmt-value. This requires changing the handling of
named-constant-def as that is a definition, not a reference.

Original-commit: flang-compiler/f18@9952b56af090b307f03202c128f242866d76d1a2
Reviewed-on: https://github.com/flang-compiler/f18/pull/277
Tree-same-pre-rewrite: false

flang/lib/semantics/resolve-names.cc
flang/test/semantics/resolve40.f90
flang/test/semantics/symbol09.f90

index b75f7f2..f7d79c3 100644 (file)
@@ -623,7 +623,8 @@ public:
   bool Pre(const parser::BindStmt &) { return BeginAttrs(); }
   void Post(const parser::BindStmt &) { EndAttrs(); }
   bool Pre(const parser::BindEntity &);
-  void Post(const parser::NamedConstantDef &);
+  bool Pre(const parser::NamedConstantDef &);
+  bool Pre(const parser::NamedConstant &);
   bool Pre(const parser::AsynchronousStmt &);
   bool Pre(const parser::ContiguousStmt &);
   bool Pre(const parser::ExternalStmt &);
@@ -787,8 +788,7 @@ public:
   bool Pre(const parser::AcSpec &);
   bool Pre(const parser::AcImpliedDo &);
   bool Pre(const parser::DataImpliedDo &);
-  bool Pre(const parser::DataStmtSet &);
-  void Post(const parser::DataStmtSet &);
+  bool Pre(const parser::DataStmtObject &);
   bool Pre(const parser::DoConstruct &);
   void Post(const parser::DoConstruct &);
   void Post(const parser::ConcurrentControl &);
@@ -2406,17 +2406,28 @@ bool DeclarationVisitor::Pre(const parser::BindEntity &x) {
   }
   return false;
 }
-void DeclarationVisitor::Post(const parser::NamedConstantDef &x) {
+bool DeclarationVisitor::Pre(const parser::NamedConstantDef &x) {
   auto &name{std::get<parser::NamedConstant>(x.t).v};
   auto &symbol{HandleAttributeStmt(Attr::PARAMETER, name)};
   if (!ConvertToObjectEntity(symbol)) {
     SayWithDecl(
         name, symbol, "PARAMETER attribute not allowed on '%s'"_err_en_US);
-    return;
+    return false;
   }
   const auto &expr{std::get<parser::ConstantExpr>(x.t)};
+  Walk(expr);
   symbol.get<ObjectEntityDetails>().set_init(EvaluateExpr(expr));
   ApplyImplicitRules(symbol);
+  return false;
+}
+bool DeclarationVisitor::Pre(const parser::NamedConstant &x) {
+  const parser::Name &name{x.v};
+  if (!FindSymbol(name)) {
+    Say(name, "Named constant '%s' not found"_err_en_US);
+  } else {
+    CheckUseError(name);
+  }
+  return false;
 }
 bool DeclarationVisitor::Pre(const parser::AsynchronousStmt &x) {
   return HandleAttributeStmt(Attr::ASYNCHRONOUS, x.v);
@@ -3328,11 +3339,19 @@ bool ConstructVisitor::Pre(const parser::DataImpliedDo &x) {
   return false;
 }
 
-bool ConstructVisitor::Pre(const parser::DataStmtSet &) {
-  PushScope(Scope::Kind::ImpliedDos, nullptr);
-  return true;
+bool ConstructVisitor::Pre(const parser::DataStmtObject &x) {
+  std::visit(
+      common::visitors{
+          [&](const common::Indirection<parser::Variable> &y) { Walk(*y); },
+          [&](const parser::DataImpliedDo &y) {
+            PushScope(Scope::Kind::ImpliedDos, nullptr);
+            Walk(y);
+            PopScope();
+          },
+      },
+      x.u);
+  return false;
 }
-void ConstructVisitor::Post(const parser::DataStmtSet &) { PopScope(); }
 
 bool ConstructVisitor::Pre(const parser::DoConstruct &x) {
   if (x.IsDoConcurrent()) {
index 806eac8..b141804 100644 (file)
@@ -74,3 +74,15 @@ subroutine s7
   !ERROR: EXTERNAL attribute not allowed on 'x'
   external x
 end
+
+subroutine s8
+  data x/1.0/
+  !ERROR: The type of 'x' has already been implicitly declared
+  integer x
+end
+
+subroutine s9
+  real :: x(4)
+  !ERROR: 'i' is already declared in this scoping unit
+  data ((x(i,i),i=1,2),i=1,2)/4*0.0/
+end
index d27c35a..8cd293d 100644 (file)
@@ -128,3 +128,28 @@ subroutine s6
   a(i) = j+1
  end do
 end subroutine
+
+!DEF: /s7 Subprogram
+subroutine s7
+ !DEF: /s7/one PARAMETER ObjectEntity REAL(4)
+ real, parameter :: one = 1.0
+ !DEF: /s7/z ObjectEntity COMPLEX(4)
+ !REF: /s7/one
+ complex :: z = (one, -one)
+end subroutine
+
+!DEF: /s8 Subprogram
+subroutine s8
+ !DEF: /s8/one PARAMETER ObjectEntity REAL(4)
+ real, parameter :: one = 1.0
+ !DEF: /s8/y ObjectEntity REAL(4)
+ !DEF: /s8/z ObjectEntity REAL(4)
+ real y(10), z(10)
+ !REF: /s8/y
+ !DEF: /s8/ImpliedDos1/i (implicit) ObjectEntity INTEGER(4)
+ !REF: /s8/z
+ !DEF: /s8/ImpliedDos2/i (implicit) ObjectEntity INTEGER(4)
+ !DEF: /s8/x (implicit) ObjectEntity REAL(4)
+ !REF: /s8/one
+ data (y(i),i=1,10),(z(i),i=1,10),x/21*one/
+end subroutine