[flang] Skip `Fortran STOP:` before message when NO_STOP_MESSAGE is set
authorJean Perier <jperier@nvidia.com>
Thu, 18 Nov 2021 17:06:19 +0000 (18:06 +0100)
committerJean Perier <jperier@nvidia.com>
Thu, 18 Nov 2021 17:08:06 +0000 (18:08 +0100)
In 'STOP bye bye', do not print 'Fortran STOP:` before 'bye bye' when
NO_STOP_MESSAGE environment variable is set at runtime.

Also only exit with code 1 in StopStatementText if this is an ERROR STOP.
This matches other compiler behaviors.

Move STOP related unit tests in their own test file and add new tests to
cover this change.

Differential Revision: https://reviews.llvm.org/D114152

flang/runtime/stop.cpp
flang/unittests/Runtime/CMakeLists.txt
flang/unittests/Runtime/RuntimeCrashTest.cpp
flang/unittests/Runtime/Stop.cpp [new file with mode: 0644]

index 765c401..c7dbe7e 100644 (file)
@@ -71,11 +71,19 @@ static void CloseAllExternalUnits(const char *why) {
     const char *code, std::size_t length, bool isErrorStop, bool quiet) {
   CloseAllExternalUnits("STOP statement");
   if (!quiet) {
-    std::fprintf(stderr, "Fortran %s: %.*s\n",
-        isErrorStop ? "ERROR STOP" : "STOP", static_cast<int>(length), code);
+    if (Fortran::runtime::executionEnvironment.noStopMessage && !isErrorStop) {
+      std::fprintf(stderr, "%.*s\n", static_cast<int>(length), code);
+    } else {
+      std::fprintf(stderr, "Fortran %s: %.*s\n",
+          isErrorStop ? "ERROR STOP" : "STOP", static_cast<int>(length), code);
+    }
     DescribeIEEESignaledExceptions();
   }
-  std::exit(EXIT_FAILURE);
+  if (isErrorStop) {
+    std::exit(EXIT_FAILURE);
+  } else {
+    std::exit(EXIT_SUCCESS);
+  }
 }
 
 static bool StartPause() {
index 33f1bd0..1067348 100644 (file)
@@ -14,6 +14,7 @@ add_flang_unittest(FlangRuntimeTests
   Random.cpp
   Reduction.cpp
   RuntimeCrashTest.cpp
+  Stop.cpp
   Time.cpp
   Transformational.cpp
 )
index c6f4358..8dd7aba 100644 (file)
@@ -13,7 +13,6 @@
 #include "CrashHandlerFixture.h"
 #include "../../runtime/terminator.h"
 #include "flang/Runtime/io-api.h"
-#include "flang/Runtime/stop.h"
 #include <gtest/gtest.h>
 
 using namespace Fortran::runtime;
@@ -156,21 +155,3 @@ TEST(TestIOCrash, OverwriteBufferIntegerTest) {
   ASSERT_DEATH(IONAME(OutputInteger64)(cookie, 0xdeadbeef),
       "Internal write overran available records");
 }
-
-TEST(TestIOCrash, StopTest) {
-  EXPECT_EXIT(RTNAME(StopStatement)(), testing::ExitedWithCode(EXIT_SUCCESS),
-      "Fortran STOP");
-}
-
-TEST(TestIOCrash, FailImageTest) {
-  EXPECT_EXIT(
-      RTNAME(FailImageStatement)(), testing::ExitedWithCode(EXIT_FAILURE), "");
-}
-
-TEST(TestIOCrash, ExitTest) {
-  EXPECT_EXIT(RTNAME(Exit)(), testing::ExitedWithCode(EXIT_SUCCESS), "");
-  EXPECT_EXIT(
-      RTNAME(Exit)(EXIT_FAILURE), testing::ExitedWithCode(EXIT_FAILURE), "");
-}
-
-TEST(TestIOCrash, AbortTest) { EXPECT_DEATH(RTNAME(Abort)(), ""); }
diff --git a/flang/unittests/Runtime/Stop.cpp b/flang/unittests/Runtime/Stop.cpp
new file mode 100644 (file)
index 0000000..4160a1d
--- /dev/null
@@ -0,0 +1,85 @@
+//===-- flang/unittests/Runtime/Stop.cpp ----------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+/// Test runtime API for STOP statement and runtime API to kill the program.
+//
+//===----------------------------------------------------------------------===//
+#include "flang/Runtime/stop.h"
+#include "CrashHandlerFixture.h"
+#include "../../runtime/environment.h"
+#include <cstdlib>
+#include <gtest/gtest.h>
+
+using namespace Fortran::runtime;
+
+struct TestProgramEnd : CrashHandlerFixture {};
+
+TEST(TestProgramEnd, StopTest) {
+  EXPECT_EXIT(RTNAME(StopStatement)(), testing::ExitedWithCode(EXIT_SUCCESS),
+      "Fortran STOP");
+}
+
+TEST(TestProgramEnd, StopTestNoStopMessage) {
+  putenv(const_cast<char *>("NO_STOP_MESSAGE=1"));
+  Fortran::runtime::executionEnvironment.Configure(0, nullptr, nullptr);
+  EXPECT_EXIT(
+      RTNAME(StopStatement)(), testing::ExitedWithCode(EXIT_SUCCESS), "");
+}
+
+TEST(TestProgramEnd, StopMessageTest) {
+  static const char *message{"bye bye"};
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/false, /*quiet=*/false),
+      testing::ExitedWithCode(EXIT_SUCCESS), "Fortran STOP: bye bye");
+
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/false, /*quiet=*/true),
+      testing::ExitedWithCode(EXIT_SUCCESS), "");
+
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/true, /*quiet=*/false),
+      testing::ExitedWithCode(EXIT_FAILURE), "Fortran ERROR STOP: bye bye");
+
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/true, /*quiet=*/true),
+      testing::ExitedWithCode(EXIT_FAILURE), "");
+}
+
+TEST(TestProgramEnd, NoStopMessageTest) {
+  putenv(const_cast<char *>("NO_STOP_MESSAGE=1"));
+  Fortran::runtime::executionEnvironment.Configure(0, nullptr, nullptr);
+  static const char *message{"bye bye"};
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/false, /*quiet=*/false),
+      testing::ExitedWithCode(EXIT_SUCCESS), "bye bye");
+
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/false, /*quiet=*/true),
+      testing::ExitedWithCode(EXIT_SUCCESS), "");
+
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/true, /*quiet=*/false),
+      testing::ExitedWithCode(EXIT_FAILURE), "Fortran ERROR STOP: bye bye");
+
+  EXPECT_EXIT(RTNAME(StopStatementText)(message, std::strlen(message),
+                  /*isErrorStop=*/true, /*quiet=*/true),
+      testing::ExitedWithCode(EXIT_FAILURE), "");
+}
+
+TEST(TestProgramEnd, FailImageTest) {
+  EXPECT_EXIT(
+      RTNAME(FailImageStatement)(), testing::ExitedWithCode(EXIT_FAILURE), "");
+}
+
+TEST(TestProgramEnd, ExitTest) {
+  EXPECT_EXIT(RTNAME(Exit)(), testing::ExitedWithCode(EXIT_SUCCESS), "");
+  EXPECT_EXIT(
+      RTNAME(Exit)(EXIT_FAILURE), testing::ExitedWithCode(EXIT_FAILURE), "");
+}
+
+TEST(TestProgramEnd, AbortTest) { EXPECT_DEATH(RTNAME(Abort)(), ""); }