[flang] Remove the IF specific context classes; in these cases they
authorSteve Scalpone <sscalpone@nvidia.com>
Wed, 27 Mar 2019 01:03:33 +0000 (18:03 -0700)
committerSteve Scalpone <sscalpone@nvidia.com>
Wed, 27 Mar 2019 01:03:33 +0000 (18:03 -0700)
added no value. Change several error messages to better say
what is expected.  Adjust tests for new messages.  Reformat
with llvm7 clang-format.

Original-commit: flang-compiler/f18@706b506e26ac675ac443c5b616abda5c4cbd0523
Reviewed-on: https://github.com/flang-compiler/f18/pull/356
Tree-same-pre-rewrite: false

14 files changed:
flang/lib/semantics/check-arithmeticif.cc
flang/lib/semantics/check-arithmeticif.h
flang/lib/semantics/check-do-concurrent.cc
flang/lib/semantics/check-do-concurrent.h
flang/lib/semantics/check-if-construct.cc
flang/lib/semantics/check-if-construct.h
flang/lib/semantics/check-if-stmt.cc
flang/lib/semantics/check-if-stmt.h
flang/lib/semantics/semantics.cc
flang/lib/semantics/semantics.h
flang/lib/semantics/tools.cc
flang/test/semantics/if_arith04.f90
flang/test/semantics/if_construct01.f90
flang/test/semantics/if_stmt02.f90

index 9a647b0..d4fa2d1 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "attr.h"
 #include "check-arithmeticif.h"
+#include "attr.h"
 #include "scope.h"
 #include "semantics.h"
 #include "symbol.h"
 
 namespace Fortran::semantics {
 
-class ArithmeticIfStmtContext {
-public:
-  ArithmeticIfStmtContext(SemanticsContext &context)
-    : messages_{context.messages()} {}
-
-  bool operator==(const ArithmeticIfStmtContext &x) const { return this == &x; }
-  bool operator!=(const ArithmeticIfStmtContext &x) const { return this != &x; }
-
-  // Arithmetic IF statements have been removed from Fortran 2018.
-  // The constraints and requirements here refer to the 2008 spec.
-  void Check(const parser::ArithmeticIfStmt &arithmeticIfStmt) {
-    // R853 Check for a scalar-numeric-expr
-    // C849 that shall not be of type complex.
-    auto &expr{std::get<parser::Expr>(arithmeticIfStmt.t)};
-    if (expr.typedExpr->v.Rank() > 0) {
-      messages_.Say(expr.source,
-          "ARITHMETIC IF statement must have a scalar numeric expression"_err_en_US);
-    } else if (ExprHasTypeCategory(
-                   *expr.typedExpr, common::TypeCategory::Complex)) {
-      messages_.Say(expr.source,
-          "ARITHMETIC IF statement must not have a COMPLEX expression"_err_en_US);
-    } else if (!IsNumericExpr(*expr.typedExpr)) {
-      messages_.Say(expr.source,
-          "ARITHMETIC IF statement must have a numeric expression"_err_en_US);
-    }
-    // The labels have already been checked in resolve-labels.
-    // TODO: Really?  Check that they are really branch target
-    // statements and in the same inclusive scope.
-  }
-
-private:
-  bool IsNumericExpr(const evaluate::GenericExprWrapper &expr) {
-    auto dynamicType{expr.v.GetType()};
-    return dynamicType.has_value() &&
-        common::IsNumericTypeCategory(dynamicType->category);
-  }
-  parser::Messages &messages_;
-  parser::CharBlock currentStatementSourcePosition_;
-};
-
-}  // namespace Fortran::semantics
-
-namespace Fortran::semantics {
+bool IsNumericExpr(const evaluate::GenericExprWrapper &expr) {
+  auto dynamicType{expr.v.GetType()};
+  return dynamicType.has_value() &&
+      common::IsNumericTypeCategory(dynamicType->category);
+}
 
 ArithmeticIfStmtChecker::ArithmeticIfStmtChecker(SemanticsContext &context)
-  : context_{new ArithmeticIfStmtContext{context}} {}
+  : context_(context) {}
 
 ArithmeticIfStmtChecker::~ArithmeticIfStmtChecker() = default;
 
-void ArithmeticIfStmtChecker::Leave(const parser::ArithmeticIfStmt &x) {
-  context_.value().Check(x);
+void ArithmeticIfStmtChecker::Leave(
+    const parser::ArithmeticIfStmt &arithmeticIfStmt) {
+  // Arithmetic IF statements have been removed from Fortran 2018.
+  // The constraints and requirements here refer to the 2008 spec.
+  // R853 Check for a scalar-numeric-expr
+  // C849 that shall not be of type complex.
+  auto &expr{std::get<parser::Expr>(arithmeticIfStmt.t)};
+  if (expr.typedExpr->v.Rank() > 0) {
+    context_.messages().Say(expr.source,
+        "ARITHMETIC IF expression must be a scalar expression"_err_en_US);
+  } else if (ExprHasTypeCategory(
+                 *expr.typedExpr, common::TypeCategory::Complex)) {
+    context_.messages().Say(expr.source,
+        "ARITHMETIC IF expression must not be a COMPLEX expression"_err_en_US);
+  } else if (!IsNumericExpr(*expr.typedExpr)) {
+    context_.messages().Say(expr.source,
+        "ARITHMETIC IF expression must be a numeric expression"_err_en_US);
+  }
+  // The labels have already been checked in resolve-labels.
+  // TODO: Really?  Check that they are really branch target
+  // statements and in the same inclusive scope.
 }
 
 }  // namespace Fortran::semantics
-
-template class Fortran::common::Indirection<
-    Fortran::semantics::ArithmeticIfStmtContext>;
index d4ee7e3..0d8aade 100644 (file)
 #define FORTRAN_SEMANTICS_CHECK_ARITHMETICIF_STMT_H_
 
 #include "semantics.h"
-#include "../common/indirection.h"
 
 namespace Fortran::parser {
 struct ArithmeticIfStmt;
 }
-namespace Fortran::semantics {
-class ArithmeticIfStmtContext;
-}
-extern template class Fortran::common::Indirection<
-    Fortran::semantics::ArithmeticIfStmtContext>;
 
 namespace Fortran::semantics {
 class ArithmeticIfStmtChecker : public virtual BaseChecker {
@@ -35,7 +29,7 @@ public:
   void Leave(const parser::ArithmeticIfStmt &);
 
 private:
-  common::Indirection<ArithmeticIfStmtContext> context_;
+  SemanticsContext &context_;
 };
 }
 #endif  // FORTRAN_SEMANTICS_CHECK_ARITHMETICIF_STMT_H_
index 0b20d9a..a4fd2e1 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "attr.h"
 #include "check-do-concurrent.h"
+#include "attr.h"
 #include "scope.h"
 #include "semantics.h"
 #include "symbol.h"
@@ -599,10 +599,6 @@ private:
   parser::CharBlock currentStatementSourcePosition_;
 };
 
-}  // namespace Fortran::semantics
-
-namespace Fortran::semantics {
-
 DoConcurrentChecker::DoConcurrentChecker(SemanticsContext &context)
   : context_{new DoConcurrentContext{context}} {}
 
index dee1a4f..517da49 100644 (file)
@@ -37,6 +37,5 @@ public:
 private:
   common::Indirection<DoConcurrentContext> context_;
 };
-
 }
 #endif  // FORTRAN_SEMANTICS_CHECK_DO_CONCURRENT_H_
index 7f17b6e..7b4c4a6 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "attr.h"
 #include "check-if-construct.h"
+#include "attr.h"
 #include "scope.h"
 #include "semantics.h"
 #include "symbol.h"
 
 namespace Fortran::semantics {
 
-class IfConstructContext {
-public:
-  IfConstructContext(SemanticsContext &context)
-    : messages_{context.messages()} {}
-
-  bool operator==(const IfConstructContext &x) const { return this == &x; }
-  bool operator!=(const IfConstructContext &x) const { return this != &x; }
-
-  void Check(const parser::IfConstruct &ifConstruct) {
-    auto &ifThenStmt{
-        std::get<parser::Statement<parser::IfThenStmt>>(ifConstruct.t)
-            .statement};
-    auto &ifThenExpr{
-        std::get<parser::ScalarLogicalExpr>(ifThenStmt.t).thing.thing.value()};
-    CheckScalarLogicalExpr(ifThenExpr, messages_);
-    for (const auto &elseIfBlock :
-        std::get<std::list<parser::IfConstruct::ElseIfBlock>>(ifConstruct.t)) {
-      auto &elseIfStmt{
-          std::get<parser::Statement<parser::ElseIfStmt>>(elseIfBlock.t)
-              .statement};
-      auto &elseIfExpr{std::get<parser::ScalarLogicalExpr>(elseIfStmt.t)
-                           .thing.thing.value()};
-      CheckScalarLogicalExpr(elseIfExpr, messages_);
-    }
-    // The (optional) ELSE does not have an expression to check; ignore it.
-  }
-
-private:
-  parser::Messages &messages_;
-  parser::CharBlock currentStatementSourcePosition_;
-};
-
-}  // namespace Fortran::semantics
-
-namespace Fortran::semantics {
-
 IfConstructChecker::IfConstructChecker(SemanticsContext &context)
-  : context_{new IfConstructContext{context}} {}
+  : context_{context} {}
 
 IfConstructChecker::~IfConstructChecker() = default;
 
-void IfConstructChecker::Leave(const parser::IfConstruct &x) {
-  context_.value().Check(x);
+void IfConstructChecker::Leave(const parser::IfConstruct &ifConstruct) {
+  auto &ifThenStmt{
+      std::get<parser::Statement<parser::IfThenStmt>>(ifConstruct.t).statement};
+  auto &ifThenExpr{
+      std::get<parser::ScalarLogicalExpr>(ifThenStmt.t).thing.thing.value()};
+  // R1135 - IF scalar logical expr
+  CheckScalarLogicalExpr(ifThenExpr, context_.messages());
+  for (const auto &elseIfBlock :
+      std::get<std::list<parser::IfConstruct::ElseIfBlock>>(ifConstruct.t)) {
+    auto &elseIfStmt{
+        std::get<parser::Statement<parser::ElseIfStmt>>(elseIfBlock.t)
+            .statement};
+    auto &elseIfExpr{
+        std::get<parser::ScalarLogicalExpr>(elseIfStmt.t).thing.thing.value()};
+    // R1136 - ELSE IF scalar logical expr
+    CheckScalarLogicalExpr(elseIfExpr, context_.messages());
+  }
+  // R1137 The (optional) ELSE does not have an expression to check; ignore it.
 }
 
 }  // namespace Fortran::semantics
-
-template class Fortran::common::Indirection<
-    Fortran::semantics::IfConstructContext>;
index 2f33833..14b95e3 100644 (file)
 #define FORTRAN_SEMANTICS_CHECK_IF_CONSTRUCT_H_
 
 #include "semantics.h"
-#include "../common/indirection.h"
 
 namespace Fortran::parser {
 struct IfConstruct;
 }
-namespace Fortran::semantics {
-class IfConstructContext;
-}
-extern template class Fortran::common::Indirection<
-    Fortran::semantics::IfConstructContext>;
 
 namespace Fortran::semantics {
 class IfConstructChecker : public virtual BaseChecker {
@@ -35,7 +29,7 @@ public:
   void Leave(const parser::IfConstruct &);
 
 private:
-  common::Indirection<IfConstructContext> context_;
+  SemanticsContext &context_;
 };
 }
 #endif  // FORTRAN_SEMANTICS_CHECK_IF_CONSTRUCT_H_
index df452c4..1d2ce01 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "attr.h"
 #include "check-if-stmt.h"
+#include "attr.h"
 #include "scope.h"
 #include "semantics.h"
 #include "symbol.h"
 #include "../parser/parse-tree.h"
 
 namespace Fortran::semantics {
-
-class IfStmtContext {
-public:
-  IfStmtContext(SemanticsContext &context) : messages_{context.messages()} {}
-
-  bool operator==(const IfStmtContext &x) const { return this == &x; }
-  bool operator!=(const IfStmtContext &x) const { return this != &x; }
-
-  // TODO: remove after fixing the issues that gives rise to the warning
-  template<class T> void suppress_unused_variable_warning(const T &) {}
-
-  void Check(const parser::IfStmt &ifStmt) {
-    // R1139 Check for a scalar logical expression
-    auto &expr{
-        std::get<parser::ScalarLogicalExpr>(ifStmt.t).thing.thing.value()};
-    CheckScalarLogicalExpr(expr, messages_);
-    // C1143 Check that the action stmt is not an if stmt
-    auto &actionStmt{std::get<parser::ActionStmt>(ifStmt.t)};
-    if (auto *actionIfStmt{
-            std::get_if<common::Indirection<parser::IfStmt>>(&actionStmt.u)}) {
-      // TODO: get the source position from the action stmt
-      suppress_unused_variable_warning(actionIfStmt);
-      messages_.Say(expr.source,
-          "IF statement is not allowed"_err_en_US);
-    }
-  }
-
-private:
-  parser::Messages &messages_;
-  parser::CharBlock currentStatementSourcePosition_;
-};
-
-}  // namespace Fortran::semantics
-
-namespace Fortran::semantics {
-
-IfStmtChecker::IfStmtChecker(SemanticsContext &context)
-  : context_{new IfStmtContext{context}} {}
+IfStmtChecker::IfStmtChecker(SemanticsContext &context) : context_{context} {}
 
 IfStmtChecker::~IfStmtChecker() = default;
 
-void IfStmtChecker::Leave(const parser::IfStmt &x) {
-  context_.value().Check(x);
+template<class T> void suppress_unused_variable_warning(const T &) {}
+
+void IfStmtChecker::Leave(const parser::IfStmt &ifStmt) {
+  // R1139 Check for a scalar logical expression
+  auto &expr{std::get<parser::ScalarLogicalExpr>(ifStmt.t).thing.thing.value()};
+  CheckScalarLogicalExpr(expr, context_.messages());
+  // C1143 Check that the action stmt is not an if stmt
+  auto &actionStmt{std::get<parser::ActionStmt>(ifStmt.t)};
+  if (auto *actionIfStmt{
+          std::get_if<common::Indirection<parser::IfStmt>>(&actionStmt.u)}) {
+    // TODO: get the source position from the action stmt
+    suppress_unused_variable_warning(actionIfStmt);
+    context_.messages().Say(
+        expr.source, "IF statement is not allowed in IF statement"_err_en_US);
+  }
 }
 
 }  // namespace Fortran::semantics
-
-template class Fortran::common::Indirection<Fortran::semantics::IfStmtContext>;
index 054e3ed..4722bca 100644 (file)
 #define FORTRAN_SEMANTICS_CHECK_IF_STMT_H_
 
 #include "semantics.h"
-#include "../common/indirection.h"
 
 namespace Fortran::parser {
 struct IfStmt;
 }
-namespace Fortran::semantics {
-class IfStmtContext;
-}
 extern template class Fortran::common::Indirection<
-    Fortran::semantics::IfStmtContext>;
+    Fortran::semantics::SemanticsContext>;
 
 namespace Fortran::semantics {
 class IfStmtChecker : public virtual BaseChecker {
@@ -35,7 +31,7 @@ public:
   void Leave(const parser::IfStmt &);
 
 private:
-  common::Indirection<IfStmtContext> context_;
+  SemanticsContext &context_;
 };
 }
 #endif  // FORTRAN_SEMANTICS_CHECK_IF_STMT_H_
index 1ee8fb7..803d698 100644 (file)
@@ -12,6 +12,7 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#include "semantics.h"
 #include "assignment.h"
 #include "canonicalize-do.h"
 #include "check-arithmeticif.h"
@@ -24,7 +25,6 @@
 #include "resolve-names.h"
 #include "rewrite-parse-tree.h"
 #include "scope.h"
-#include "semantics.h"
 #include "symbol.h"
 #include "../common/default-kinds.h"
 #include "../parser/parse-tree-visitor.h"
index 14b4b26..1cf7342 100644 (file)
@@ -18,8 +18,8 @@
 #include "scope.h"
 #include "../evaluate/common.h"
 #include "../evaluate/intrinsics.h"
-#include "../parser/message.h"
 #include "../parser/features.h"
+#include "../parser/message.h"
 #include <iosfwd>
 #include <string>
 #include <vector>
@@ -130,6 +130,5 @@ struct BaseChecker {
   template<typename N> void Enter(const N &) {}
   template<typename N> void Leave(const N &) {}
 };
-
 }
 #endif
index 0e4db9c..a466d20 100644 (file)
@@ -12,8 +12,8 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "scope.h"
 #include "tools.h"
+#include "scope.h"
 #include "../evaluate/variable.h"
 #include <algorithm>
 #include <set>
@@ -240,7 +240,6 @@ void CheckScalarLogicalExpr(
   if (expr.typedExpr == nullptr) {
     return;
   }
-  // TODO: Whence IsArray()?
   if (expr.typedExpr->v.Rank() > 0) {
     messages.Say(expr.source, "Expected a scalar LOGICAL expression"_err_en_US);
   } else if (!ExprHasTypeCategory(
index 37d8a64..7a9b410 100644 (file)
@@ -24,19 +24,19 @@ if ( I ) 100, 200, 300
 200 CONTINUE
 300 CONTINUE
 
-!ERROR: ARITHMETIC IF statement must not have a COMPLEX expression
+!ERROR: ARITHMETIC IF expression must not be a COMPLEX expression
 if ( Z ) 101, 201, 301
 101 CONTINUE
 201 CONTINUE
 301 CONTINUE
 
-!ERROR: ARITHMETIC IF statement must have a numeric expression
+!ERROR: ARITHMETIC IF expression must be a numeric expression
 if ( L ) 102, 202, 302
 102 CONTINUE
 202 CONTINUE
 302 CONTINUE
 
-!ERROR: ARITHMETIC IF statement must have a scalar numeric expression
+!ERROR: ARITHMETIC IF expression must be a scalar expression
 if ( B ) 103, 203, 303
 103 CONTINUE
 203 CONTINUE
index a67a6c1..175c258 100644 (file)
@@ -12,7 +12,7 @@
 ! See the License for the specific language governing permissions and
 ! limitations under the License.
 
-! Simple check that if iconstructs are ok.
+! Simple check that if constructs are ok.
 
 if (a < b) then
   a = 1
index 6e70f89..1445825 100644 (file)
@@ -12,6 +12,6 @@
 ! See the License for the specific language governing permissions and
 ! limitations under the License.
 
-!ERROR: IF statement is not allowed
+!ERROR: IF statement is not allowed in IF statement
 IF (A > 0.0) IF (B < 0.0) A = LOG (A)
 END