1 //===-- runtime/terminate.cpp ---------------------------------------------===//
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 #include "terminator.h"
10 #include <cstdio>
11 #include <cstdlib>
12 
13 namespace Fortran::runtime {
14 
Crash(const char * message,...) const15 [[noreturn]] void Terminator::Crash(const char *message, ...) const {
16   va_list ap;
17   va_start(ap, message);
18   CrashArgs(message, ap);
19   va_end(ap);
20 }
21 
22 static void (*crashHandler)(const char *, int, const char *, va_list &){
23     nullptr};
24 
RegisterCrashHandler(void (* handler)(const char *,int,const char *,va_list &))25 void Terminator::RegisterCrashHandler(
26     void (*handler)(const char *, int, const char *, va_list &)) {
27   crashHandler = handler;
28 }
29 
CrashArgs(const char * message,va_list & ap) const30 [[noreturn]] void Terminator::CrashArgs(
31     const char *message, va_list &ap) const {
32   if (crashHandler) {
33     crashHandler(sourceFileName_, sourceLine_, message, ap);
34   }
35   std::fputs("\nfatal Fortran runtime error", stderr);
36   if (sourceFileName_) {
37     std::fprintf(stderr, "(%s", sourceFileName_);
38     if (sourceLine_) {
39       std::fprintf(stderr, ":%d", sourceLine_);
40     }
41     fputc(')', stderr);
42   }
43   std::fputs(": ", stderr);
44   std::vfprintf(stderr, message, ap);
45   fputc('\n', stderr);
46   va_end(ap);
47   io::FlushOutputOnCrash(*this);
48   NotifyOtherImagesOfErrorTermination();
49   std::abort();
50 }
51 
CheckFailed(const char * predicate,const char * file,int line) const52 [[noreturn]] void Terminator::CheckFailed(
53     const char *predicate, const char *file, int line) const {
54   Crash("Internal error: RUNTIME_CHECK(%s) failed at %s(%d)", predicate, file,
55       line);
56 }
57 
CheckFailed(const char * predicate) const58 [[noreturn]] void Terminator::CheckFailed(const char *predicate) const {
59   Crash("Internal error: RUNTIME_CHECK(%s) failed at %s(%d)", predicate,
60       sourceFileName_, sourceLine_);
61 }
62 
63 // TODO: These will be defined in the coarray runtime library
NotifyOtherImagesOfNormalEnd()64 void NotifyOtherImagesOfNormalEnd() {}
NotifyOtherImagesOfFailImageStatement()65 void NotifyOtherImagesOfFailImageStatement() {}
NotifyOtherImagesOfErrorTermination()66 void NotifyOtherImagesOfErrorTermination() {}
67 } // namespace Fortran::runtime
68