xref: /llvm-project/llvm/utils/not/not.cpp (revision 53a656d9a4032b842ad0c59489353e17daa54531)
1 //===- not.cpp - The 'not' testing tool -----------------------------------===//
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 // Usage:
9 //   not cmd
10 //     Will return true if cmd doesn't crash and returns false.
11 //   not --crash cmd
12 //     Will return true if cmd crashes (e.g. for testing crash reporting).
13 
14 #include "llvm/Support/Process.h"
15 #include "llvm/Support/Program.h"
16 #include "llvm/Support/WithColor.h"
17 #include "llvm/Support/raw_ostream.h"
18 
19 #ifdef _WIN32
20 #include <windows.h>
21 #endif
22 
23 using namespace llvm;
24 
main(int argc,const char ** argv)25 int main(int argc, const char **argv) {
26   bool ExpectCrash = false;
27 
28   ++argv;
29   --argc;
30 
31   if (argc > 0 && StringRef(argv[0]) == "--crash") {
32     ++argv;
33     --argc;
34     ExpectCrash = true;
35 
36     // Crash is expected, so disable crash report and symbolization to reduce
37     // output and avoid potentially slow symbolization.
38 #ifdef _WIN32
39     SetEnvironmentVariableA("LLVM_DISABLE_CRASH_REPORT", "1");
40     SetEnvironmentVariableA("LLVM_DISABLE_SYMBOLIZATION", "1");
41 #else
42     setenv("LLVM_DISABLE_CRASH_REPORT", "1", 0);
43     setenv("LLVM_DISABLE_SYMBOLIZATION", "1", 0);
44 #endif
45     // Try to disable coredumps for expected crashes as well since this can
46     // noticeably slow down running the test suite.
47     sys::Process::PreventCoreFiles();
48   }
49 
50   if (argc == 0)
51     return 1;
52 
53   auto Program = sys::findProgramByName(argv[0]);
54   if (!Program) {
55     WithColor::error() << "unable to find `" << argv[0]
56                        << "' in PATH: " << Program.getError().message() << "\n";
57     return 1;
58   }
59 
60   std::vector<StringRef> Argv;
61   Argv.reserve(argc);
62   for (int i = 0; i < argc; ++i)
63     Argv.push_back(argv[i]);
64   std::string ErrMsg;
65   int Result =
66       sys::ExecuteAndWait(*Program, Argv, std::nullopt, {}, 0, 0, &ErrMsg);
67 #ifdef _WIN32
68   // Handle abort() in msvcrt -- It has exit code as 3.  abort(), aka
69   // unreachable, should be recognized as a crash.  However, some binaries use
70   // exit code 3 on non-crash failure paths, so only do this if we expect a
71   // crash.
72   if (ExpectCrash && Result == 3)
73     Result = -3;
74 #endif
75   if (Result < 0) {
76     WithColor::error() << ErrMsg << "\n";
77     if (ExpectCrash)
78       return 0;
79     return 1;
80   }
81 
82   if (ExpectCrash)
83     return 1;
84 
85   return Result == 0;
86 }
87