[libc++][Android] Allow testing libc++ with clang-r536225 (#116149)
[llvm-project.git] / flang / runtime / terminator.h
blob609f059d6e09219be03718be225a31df0230c28d
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 //===----------------------------------------------------------------------===//
9 // Termination of the image
11 #ifndef FORTRAN_RUNTIME_TERMINATOR_H_
12 #define FORTRAN_RUNTIME_TERMINATOR_H_
14 #include "flang/Common/api-attrs.h"
15 #include <cstdarg>
16 #include <cstdio>
17 #include <cstdlib>
19 namespace Fortran::runtime {
21 // A mixin class for statement-specific image error termination
22 // for errors detected in the runtime library
23 class Terminator {
24 public:
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"
50 #endif
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...);
62 #endif
63 CrashHeader();
64 PrintCrashArgs(message, args...);
65 CrashFooter();
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...);
72 #else
73 std::fprintf(stderr, message, args...);
74 #endif
77 #if defined(__clang__)
78 #pragma clang diagnostic pop
79 #elif defined(__GNUC__)
80 #pragma GCC diagnostic pop
81 #endif
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;
93 // For test harnessing - overrides CrashArgs().
94 static void RegisterCrashHandler(void (*)(const char *sourceFile,
95 int sourceLine, const char *message, va_list &ap));
97 private:
98 const char *sourceFileName_{nullptr};
99 int sourceLine_{0};
102 // RUNTIME_CHECK() guarantees evaluation of its predicate.
103 #define RUNTIME_CHECK(terminator, pred) \
104 if (pred) \
106 else \
107 (terminator).CheckFailed(#pred, __FILE__, __LINE__)
109 #define INTERNAL_CHECK(pred) \
110 if (pred) \
112 else \
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_