1//===-- runtime/terminator.h ------------------------------------*- C++ -*-===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9// Termination of the image
10
11#ifndef FORTRAN_RUNTIME_TERMINATOR_H_
12#define FORTRAN_RUNTIME_TERMINATOR_H_
13
14#include "flang/Runtime/api-attrs.h"
15#include <cstdarg>
16#include <cstdio>
17#include <cstdlib>
18
19namespace Fortran::runtime {
20
21// A mixin class for statement-specific image error termination
22// for errors detected in the runtime library
23class Terminator {
24public:
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} {}
30
31 RT_API_ATTRS const char *sourceFileName() const { return sourceFileName_; }
32 RT_API_ATTRS int sourceLine() const { return sourceLine_; }
33
34 RT_API_ATTRS void SetLocation(
35 const char *sourceFileName = nullptr, int sourceLine = 0) {
36 sourceFileName_ = sourceFileName;
37 sourceLine_ = sourceLine;
38 }
39
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"
50#endif
51
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_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...);
62#endif
63 CrashHeader();
64 PrintCrashArgs(message, args...);
65 CrashFooter();
66 }
67
68 template <typename... Args>
69 RT_API_ATTRS void PrintCrashArgs(const char *message, Args... args) const {
70#if RT_DEVICE_COMPILATION
71 std::printf(message, args...);
72#else
73 std::fprintf(stderr, format: message, args...);
74#endif
75 }
76
77#if defined(__clang__)
78#pragma clang diagnostic pop
79#elif defined(__GNUC__)
80#pragma GCC diagnostic pop
81#endif
82
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;
88#endif
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;
92
93 // For test harnessing - overrides CrashArgs().
94 static void RegisterCrashHandler(void (*)(const char *sourceFile,
95 int sourceLine, const char *message, va_list &ap));
96
97private:
98 const char *sourceFileName_{nullptr};
99 int sourceLine_{0};
100};
101
102// RUNTIME_CHECK() guarantees evaluation of its predicate.
103#define RUNTIME_CHECK(terminator, pred) \
104 if (pred) \
105 ; \
106 else \
107 (terminator).CheckFailed(#pred, __FILE__, __LINE__)
108
109#define INTERNAL_CHECK(pred) \
110 if (pred) \
111 ; \
112 else \
113 Terminator{__FILE__, __LINE__}.CheckFailed(#pred)
114
115RT_API_ATTRS void NotifyOtherImagesOfNormalEnd();
116RT_API_ATTRS void NotifyOtherImagesOfFailImageStatement();
117RT_API_ATTRS void NotifyOtherImagesOfErrorTermination();
118} // namespace Fortran::runtime
119
120namespace Fortran::runtime::io {
121RT_API_ATTRS void FlushOutputOnCrash(const Terminator &);
122}
123
124#endif // FORTRAN_RUNTIME_TERMINATOR_H_
125

source code of flang/runtime/terminator.h