diff --git a/flang/runtime/terminator.h b/flang/runtime/terminator.h --- a/flang/runtime/terminator.h +++ b/flang/runtime/terminator.h @@ -34,7 +34,8 @@ const char *predicate, const char *file, int line) const; // For test harnessing - overrides CrashArgs(). - static void RegisterCrashHandler(void (*)(const char *, va_list &)); + static void RegisterCrashHandler(void (*)(const char *sourceFile, + int sourceLine, const char *message, va_list &ap)); private: const char *sourceFileName_{nullptr}; diff --git a/flang/runtime/terminator.cpp b/flang/runtime/terminator.cpp --- a/flang/runtime/terminator.cpp +++ b/flang/runtime/terminator.cpp @@ -18,17 +18,18 @@ CrashArgs(message, ap); } -static void (*crashHandler)(const char *, va_list &){nullptr}; +static void (*crashHandler)(const char *, int, const char *, va_list &){ + nullptr}; void Terminator::RegisterCrashHandler( - void (*handler)(const char *, va_list &)) { + void (*handler)(const char *, int, const char *, va_list &)) { crashHandler = handler; } [[noreturn]] void Terminator::CrashArgs( const char *message, va_list &ap) const { if (crashHandler) { - crashHandler(message, ap); + crashHandler(sourceFileName_, sourceLine_, message, ap); } std::fputs("\nfatal Fortran runtime error", stderr); if (sourceFileName_) { 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 @@ -41,6 +41,18 @@ LLVMSupport ) +add_executable(external-io + external-io.cpp +) + +target_link_libraries(external-io + RuntimeTesting + FortranRuntime + LLVMSupport +) + +add_test(NAME ExternalIO COMMAND external-io) + add_executable(list-input-test list-input.cpp ) diff --git a/flang/unittests/Runtime/external-hello.cpp b/flang/unittests/Runtime/external-hello.cpp --- a/flang/unittests/Runtime/external-hello.cpp +++ b/flang/unittests/Runtime/external-hello.cpp @@ -5,9 +5,8 @@ using namespace Fortran::runtime::io; -int main(int argc, const char *argv[], const char *envp[]) { - RTNAME(ProgramStart)(argc, argv, envp); - auto *io{IONAME(BeginExternalListOutput)()}; +void output1() { + auto io{IONAME(BeginExternalListOutput)()}; const char str[]{"Hello, world!"}; IONAME(OutputAscii)(io, str, std::strlen(str)); IONAME(OutputInteger64)(io, 678); @@ -21,6 +20,31 @@ IONAME(OutputLogical)(io, false); IONAME(OutputLogical)(io, true); IONAME(EndIoStatement)(io); +} + +void input1() { + auto io{IONAME(BeginExternalListOutput)()}; + const char prompt[]{"Enter an integer value:"}; + IONAME(OutputAscii)(io, prompt, std::strlen(prompt)); + IONAME(EndIoStatement)(io); + + io = IONAME(BeginExternalListInput)(); + std::int64_t n{-666}; + IONAME(InputInteger)(io, n); + IONAME(EndIoStatement)(io); + + io = IONAME(BeginExternalListOutput)(); + const char str[]{"Result:"}; + IONAME(OutputAscii)(io, str, std::strlen(str)); + IONAME(OutputInteger64)(io, n); + IONAME(EndIoStatement)(io); +} + +int main(int argc, const char *argv[], const char *envp[]) { + RTNAME(ProgramStart)(argc, argv, envp); + output1(); + input1(); + RTNAME(PauseStatement)(); RTNAME(ProgramEndStatement)(); return 0; } diff --git a/flang/unittests/Runtime/testing.h b/flang/unittests/Runtime/testing.h --- a/flang/unittests/Runtime/testing.h +++ b/flang/unittests/Runtime/testing.h @@ -12,6 +12,7 @@ llvm::raw_ostream &Fail(); int EndTests(); +// Defines a CHARACTER object with padding when needed void SetCharacter(char *, std::size_t, const char *); #endif // FORTRAN_TEST_RUNTIME_TESTING_H_ diff --git a/flang/unittests/Runtime/testing.cpp b/flang/unittests/Runtime/testing.cpp --- a/flang/unittests/Runtime/testing.cpp +++ b/flang/unittests/Runtime/testing.cpp @@ -9,10 +9,13 @@ static int failures{0}; // Override the Fortran runtime's Crash() for testing purposes -[[noreturn]] static void CatchCrash(const char *message, va_list &ap) { +[[noreturn]] static void CatchCrash( + const char *sourceFile, int sourceLine, const char *message, va_list &ap) { char buffer[1000]; std::vsnprintf(buffer, sizeof buffer, message, ap); va_end(ap); + llvm::errs() << (sourceFile ? sourceFile : "unknown source file") << '(' + << sourceLine << "): CRASH: " << buffer << '\n'; throw std::string{buffer}; }