1 //===-- runtime/terminator.h ------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Termination of the image
11 #ifndef FORTRAN_RUNTIME_TERMINATOR_H_
12 #define FORTRAN_RUNTIME_TERMINATOR_H_
14 #include "flang/Common/api-attrs.h"
19 namespace Fortran::runtime
{
21 // A mixin class for statement-specific image error termination
22 // for errors detected in the runtime library
25 RT_API_ATTRS
Terminator() {}
26 Terminator(const Terminator
&) = default;
27 explicit RT_API_ATTRS
Terminator(
28 const char *sourceFileName
, int sourceLine
= 0)
29 : sourceFileName_
{sourceFileName
}, sourceLine_
{sourceLine
} {}
31 RT_API_ATTRS
const char *sourceFileName() const { return sourceFileName_
; }
32 RT_API_ATTRS
int sourceLine() const { return sourceLine_
; }
34 RT_API_ATTRS
void SetLocation(
35 const char *sourceFileName
= nullptr, int sourceLine
= 0) {
36 sourceFileName_
= sourceFileName
;
37 sourceLine_
= sourceLine
;
40 // Silence compiler warnings about the format string being
41 // non-literal. A more precise control would be
42 // __attribute__((format_arg(2))), but it requires the function
43 // to return 'char *', which does not work well with noreturn.
44 #if defined(__clang__)
45 #pragma clang diagnostic push
46 #pragma clang diagnostic ignored "-Wformat-security"
47 #elif defined(__GNUC__)
48 #pragma GCC diagnostic push
49 #pragma GCC diagnostic ignored "-Wformat-security"
52 // Device offload compilers do not normally support varargs and va_list,
53 // so use C++ variadic templates to forward the crash arguments
54 // to regular printf for the device compilation.
55 // Try to keep the inline implementations as small as possible.
56 template <typename
... Args
>
57 [[noreturn
]] RT_DEVICE_NOINLINE RT_API_ATTRS
const char *Crash(
58 const char *message
, Args
... args
) const {
59 #if !defined(RT_DEVICE_COMPILATION)
60 // Invoke handler set up by the test harness.
61 InvokeCrashHandler(message
, args
...);
64 PrintCrashArgs(message
, args
...);
68 template <typename
... Args
>
69 RT_API_ATTRS
void PrintCrashArgs(const char *message
, Args
... args
) const {
70 #if defined(RT_DEVICE_COMPILATION)
71 std::printf(message
, args
...);
73 std::fprintf(stderr
, message
, args
...);
77 #if defined(__clang__)
78 #pragma clang diagnostic pop
79 #elif defined(__GNUC__)
80 #pragma GCC diagnostic pop
83 RT_API_ATTRS
void CrashHeader() const;
84 [[noreturn
]] RT_API_ATTRS
void CrashFooter() const;
85 #if !defined(RT_DEVICE_COMPILATION)
86 void InvokeCrashHandler(const char *message
, ...) const;
87 [[noreturn
]] void CrashArgs(const char *message
, va_list &) const;
89 [[noreturn
]] RT_API_ATTRS
void CheckFailed(
90 const char *predicate
, const char *file
, int line
) const;
91 [[noreturn
]] RT_API_ATTRS
void CheckFailed(const char *predicate
) const;
93 // For test harnessing - overrides CrashArgs().
94 static void RegisterCrashHandler(void (*)(const char *sourceFile
,
95 int sourceLine
, const char *message
, va_list &ap
));
98 const char *sourceFileName_
{nullptr};
102 // RUNTIME_CHECK() guarantees evaluation of its predicate.
103 #define RUNTIME_CHECK(terminator, pred) \
107 (terminator).CheckFailed(#pred, __FILE__, __LINE__)
109 #define INTERNAL_CHECK(pred) \
113 Terminator{__FILE__, __LINE__}.CheckFailed(#pred)
115 RT_API_ATTRS
void NotifyOtherImagesOfNormalEnd();
116 RT_API_ATTRS
void NotifyOtherImagesOfFailImageStatement();
117 RT_API_ATTRS
void NotifyOtherImagesOfErrorTermination();
118 } // namespace Fortran::runtime
120 namespace Fortran::runtime::io
{
121 RT_API_ATTRS
void FlushOutputOnCrash(const Terminator
&);
124 #endif // FORTRAN_RUNTIME_TERMINATOR_H_