diff --git a/flang/runtime/stop.cpp b/flang/runtime/stop.cpp --- a/flang/runtime/stop.cpp +++ b/flang/runtime/stop.cpp @@ -71,11 +71,19 @@ 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 --- a/flang/unittests/Runtime/CMakeLists.txt +++ b/flang/unittests/Runtime/CMakeLists.txt @@ -14,6 +14,7 @@ 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 --- 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 @@ 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 --- /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)(), ""); }