╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ zig_clang_driver.cpp ─────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭ find file ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╮ ╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │ │ │http│ ssh │ │ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─╯ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
373 if (!UseNewCC1Process) { 374 TheDriver.CC1Main = ExecuteCC1WithContext; 375 // Ensure the CC1Command actually catches cc1 crashes 376 llvm::CrashRecoveryContext::Enable(); 377 } 378 379 std::unique_ptr<Compilation> C(TheDriver.BuildCompilation(Args)); 380 381 Driver::ReproLevel ReproLevel = Driver::ReproLevel::OnCrash; 382 if (Arg *A = C->getArgs().getLastArg(options::OPT_gen_reproducer_eq)) { 383 auto Level = 384 llvm::StringSwitch<std::optional<Driver::ReproLevel>>(A->getValue()) 385 .Case("off", Driver::ReproLevel::Off) 386 .Case("crash", Driver::ReproLevel::OnCrash) 387 .Case("error", Driver::ReproLevel::OnError) 388 .Case("always", Driver::ReproLevel::Always) 389 .Default(std::nullopt); 390 if (!Level) { 391 llvm::errs() << "Unknown value for " << A->getSpelling() << ": '" 392 << A->getValue() << "'\n"; 393 return 1; 394 } 395 ReproLevel = *Level; 396 } 397 if (!!::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) 398 ReproLevel = Driver::ReproLevel::Always; 399 400 int Res = 1; 401 bool IsCrash = false; 402 Driver::CommandStatus CommandStatus = Driver::CommandStatus::Ok; 403 // Pretend the first command failed if ReproStatus is Always. 404 const Command *FailingCommand = nullptr; 405 if (!C->getJobs().empty()) 406 FailingCommand = &*C->getJobs().begin(); 407 if (C && !C->containsError()) { 408 SmallVector<std::pair<int, const Command *>, 4> FailingCommands; 409 Res = TheDriver.ExecuteCompilation(*C, FailingCommands); 410 411 for (const auto &P : FailingCommands) { 412 int CommandRes = P.first; 413 FailingCommand = P.second; 414 if (!Res) 415 Res = CommandRes; 416 417 // If result status is < 0, then the driver command signalled an error. 418 // If result status is 70, then the driver command reported a fatal error. 419 // On Windows, abort will return an exit code of 3. In these cases, 420 // generate additional diagnostic information if possible. 421 IsCrash = CommandRes < 0 || CommandRes == 70; 422 #ifdef _WIN32 423 IsCrash |= CommandRes == 3; 424 #endif 425 #if LLVM_ON_UNIX 426 // When running in integrated-cc1 mode, the CrashRecoveryContext returns 427 // the same codes as if the program crashed. See section "Exit Status for 428 // Commands": 429 // https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xcu_chap02.html 430 IsCrash |= CommandRes > 128; 431 #endif 432 CommandStatus = 433 IsCrash ? Driver::CommandStatus::Crash : Driver::CommandStatus::Error; 434 if (IsCrash) 435 break; 436 } 437 } 438 439 // Print the bug report message that would be printed if we did actually 440 // crash, but only if we're crashing due to FORCE_CLANG_DIAGNOSTICS_CRASH. 441 if (::getenv("FORCE_CLANG_DIAGNOSTICS_CRASH")) 442 llvm::dbgs() << llvm::getBugReportMsg(); 443 if (FailingCommand != nullptr && 444 TheDriver.maybeGenerateCompilationDiagnostics(CommandStatus, ReproLevel, 445 *C, *FailingCommand)) 446 Res = 1; 447 448 Diags.getClient()->finish(); 449 450 if (!UseNewCC1Process && IsCrash) { 451 // When crashing in -fintegrated-cc1 mode, bury the timer pointers, because 452 // the internal linked list might point to already released stack frames. 453 llvm::BuryPointer(llvm::TimerGroup::acquireTimerGlobals()); 454 } else { 455 // If any timers were active but haven't been destroyed yet, print their 456 // results now. This happens in -disable-free mode. 457 llvm::TimerGroup::printAll(llvm::errs()); 458 llvm::TimerGroup::clearAll(); 459 } 460 461 #ifdef _WIN32 462 // Exit status should not be negative on Win32, unless abnormal termination. 463 // Once abnormal termination was caught, negative status should not be 464 // propagated. 465 if (Res < 0) 466 Res = 1; 467 #endif 468 469 // If we have multiple failing commands, we return the result of the first 470 // failing command. 471 return Res; 472 } 473 474 extern "C" int ZigClang_main(int, char **); 475 int ZigClang_main(int argc, char **argv) { 476 return clang_main(argc, argv, {argv[0], nullptr, false}); 477 } 478