Index: clang/lib/Lex/Pragma.cpp =================================================================== --- clang/lib/Lex/Pragma.cpp +++ clang/lib/Lex/Pragma.cpp @@ -42,6 +42,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Timer.h" #include #include #include @@ -1038,6 +1039,8 @@ if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) llvm_unreachable("This is an assertion!"); } else if (II->isStr("crash")) { + llvm::Timer T("crash", "pragma crash"); + llvm::TimeRegion R(&T); if (!PP.getPreprocessorOpts().DisablePragmaDebugCrash) LLVM_BUILTIN_TRAP; } else if (II->isStr("parser_crash")) { Index: clang/tools/driver/driver.cpp =================================================================== --- clang/tools/driver/driver.cpp +++ clang/tools/driver/driver.cpp @@ -30,6 +30,7 @@ #include "llvm/Option/ArgList.h" #include "llvm/Option/OptTable.h" #include "llvm/Option/Option.h" +#include "llvm/Support/BuryPointer.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/CrashRecoveryContext.h" #include "llvm/Support/ErrorHandling.h" @@ -491,6 +492,7 @@ std::unique_ptr C(TheDriver.BuildCompilation(argv)); int Res = 1; + bool IsCrash = false; if (C && !C->containsError()) { SmallVector, 4> FailingCommands; Res = TheDriver.ExecuteCompilation(*C, FailingCommands); @@ -517,11 +519,11 @@ // If result status is 70, then the driver command reported a fatal error. // On Windows, abort will return an exit code of 3. In these cases, // generate additional diagnostic information if possible. - bool DiagnoseCrash = CommandRes < 0 || CommandRes == 70; + IsCrash = CommandRes < 0 || CommandRes == 70; #ifdef _WIN32 - DiagnoseCrash |= CommandRes == 3; + IsCrash |= CommandRes == 3; #endif - if (DiagnoseCrash) { + if (IsCrash) { TheDriver.generateCompilationDiagnostics(*C, *FailingCommand); break; } @@ -530,10 +532,16 @@ Diags.getClient()->finish(); - // If any timers were active but haven't been destroyed yet, print their - // results now. This happens in -disable-free mode. - llvm::TimerGroup::printAll(llvm::errs()); - llvm::TimerGroup::clearAll(); + if (!UseNewCC1Process && IsCrash) { + // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because + // the internal linked list might point to already released stack frames. + llvm::BuryPointer(llvm::TimerGroup::aquireDefaultGroup()); + } else { + // If any timers were active but haven't been destroyed yet, print their + // results now. This happens in -disable-free mode. + llvm::TimerGroup::printAll(llvm::errs()); + llvm::TimerGroup::clearAll(); + } #ifdef _WIN32 // Exit status should not be negative on Win32, unless abnormal termination. Index: llvm/include/llvm/Support/ManagedStatic.h =================================================================== --- llvm/include/llvm/Support/ManagedStatic.h +++ llvm/include/llvm/Support/ManagedStatic.h @@ -102,6 +102,12 @@ } const C *operator->() const { return &**this; } + + // Extract the instance, leaving the ManagedStatic uninitialized. The + // user is then responsible for the lifetime of the returned instance. + C *claim() { + return static_cast(Ptr.exchange(nullptr)); + } }; /// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. Index: llvm/include/llvm/Support/Timer.h =================================================================== --- llvm/include/llvm/Support/Timer.h +++ llvm/include/llvm/Support/Timer.h @@ -230,6 +230,11 @@ /// used by the Statistic code to influence the construction and destruction /// order of the global timer lists. static void ConstructTimerLists(); + + /// This makes the default group unmanaged, and lets the user manage the + /// group's lifetime. + static std::unique_ptr aquireDefaultGroup(); + private: friend class Timer; friend void PrintStatisticsJSON(raw_ostream &OS); Index: llvm/lib/Support/Timer.cpp =================================================================== --- llvm/lib/Support/Timer.cpp +++ llvm/lib/Support/Timer.cpp @@ -442,3 +442,7 @@ void TimerGroup::ConstructTimerLists() { (void)*NamedGroupedTimers; } + +std::unique_ptr TimerGroup::aquireDefaultGroup() { + return std::unique_ptr(DefaultTimerGroup.claim()); +}