From 7796d81ae8204289c6ea07f19e538cf287d3213f Mon Sep 17 00:00:00 2001 From: Jean Perier Date: Thu, 18 Nov 2021 18:06:19 +0100 Subject: [PATCH] [flang] Skip `Fortran STOP:` before message when NO_STOP_MESSAGE is set 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 | 14 ++++- flang/unittests/Runtime/CMakeLists.txt | 1 + flang/unittests/Runtime/RuntimeCrashTest.cpp | 19 ------- flang/unittests/Runtime/Stop.cpp | 85 ++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 22 deletions(-) create mode 100644 flang/unittests/Runtime/Stop.cpp diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp index 765c401..c7dbe7e 100644 --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -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(length), code); + if (Fortran::runtime::executionEnvironment.noStopMessage && !isErrorStop) { + std::fprintf(stderr, "%.*s\n", static_cast(length), code); + } else { + std::fprintf(stderr, "Fortran %s: %.*s\n", + isErrorStop ? "ERROR STOP" : "STOP", static_cast(length), code); + } DescribeIEEESignaledExceptions(); } - std::exit(EXIT_FAILURE); + if (isErrorStop) { + std::exit(EXIT_FAILURE); + } else { + std::exit(EXIT_SUCCESS); + } } static bool StartPause() { diff --git a/flang/unittests/Runtime/CMakeLists.txt b/flang/unittests/Runtime/CMakeLists.txt index 33f1bd0..1067348 100644 --- a/flang/unittests/Runtime/CMakeLists.txt +++ b/flang/unittests/Runtime/CMakeLists.txt @@ -14,6 +14,7 @@ add_flang_unittest(FlangRuntimeTests Random.cpp Reduction.cpp RuntimeCrashTest.cpp + Stop.cpp Time.cpp Transformational.cpp ) diff --git a/flang/unittests/Runtime/RuntimeCrashTest.cpp b/flang/unittests/Runtime/RuntimeCrashTest.cpp index c6f4358..8dd7aba 100644 --- a/flang/unittests/Runtime/RuntimeCrashTest.cpp +++ b/flang/unittests/Runtime/RuntimeCrashTest.cpp @@ -13,7 +13,6 @@ #include "CrashHandlerFixture.h" #include "../../runtime/terminator.h" #include "flang/Runtime/io-api.h" -#include "flang/Runtime/stop.h" #include 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 index 0000000..4160a1d --- /dev/null +++ b/flang/unittests/Runtime/Stop.cpp @@ -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 +#include + +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("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("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)(), ""); } -- 2.7.4