GCC Code Coverage Report


Directory: ../
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 88.0% 235 / 3 / 270
Functions: 82.1% 23 / 0 / 28
Branches: 48.5% 320 / 8 / 668

src/driver/Driver.cpp
Line Branch Exec Source
1 // Copyright (c) 2021-2026 ChilliBits. All rights reserved.
2
3 #include "Driver.h"
4
5 #include <exception/CliError.h>
6 #include <util/CommonUtil.h>
7 #include <util/CompilerWarning.h>
8 #include <util/SystemUtil.h>
9
10 #include <llvm/Support/CommandLine.h>
11 #include <llvm/TargetParser/Host.h>
12 #include <llvm/TargetParser/Triple.h>
13
14 namespace spice::compiler {
15
16
3/6
✓ Branch 4 → 5 taken 469 times.
✗ Branch 4 → 51 not taken.
✓ Branch 7 → 8 taken 469 times.
✗ Branch 7 → 45 not taken.
✓ Branch 8 → 9 taken 469 times.
✗ Branch 8 → 43 not taken.
1876 Driver::Driver(CliOptions &foreignCliOptions, bool dryRun) : cliOptions(foreignCliOptions), performDryRun(dryRun) {
17 // Allow positional args
18 469 app.positionals_at_end();
19 469 app.allow_extras(false);
20
2/4
✓ Branch 15 → 16 taken 469 times.
✗ Branch 15 → 57 not taken.
✓ Branch 17 → 18 taken 469 times.
✗ Branch 17 → 55 not taken.
469 app.footer("(c) Marc Auberer 2021-" + std::to_string(CommonUtil::getCurrentYear()));
21
22 // Add version flag
23
4/8
✓ Branch 23 → 24 taken 469 times.
✗ Branch 23 → 70 not taken.
✓ Branch 24 → 25 taken 469 times.
✗ Branch 24 → 67 not taken.
✓ Branch 27 → 28 taken 469 times.
✗ Branch 27 → 61 not taken.
✓ Branch 28 → 29 taken 469 times.
✗ Branch 28 → 59 not taken.
1876 app.set_version_flag("--version,-v", CommonUtil::buildVersionInfo());
24
25 // Create sub-commands
26
1/2
✓ Branch 34 → 35 taken 469 times.
✗ Branch 34 → 74 not taken.
469 addBuildSubcommand();
27
1/2
✓ Branch 35 → 36 taken 469 times.
✗ Branch 35 → 74 not taken.
469 addRunSubcommand();
28
1/2
✓ Branch 36 → 37 taken 469 times.
✗ Branch 36 → 74 not taken.
469 addTestSubcommand();
29
1/2
✓ Branch 37 → 38 taken 469 times.
✗ Branch 37 → 74 not taken.
469 addInstallSubcommand();
30
1/2
✓ Branch 38 → 39 taken 469 times.
✗ Branch 38 → 74 not taken.
469 addUninstallSubcommand();
31
32 469 app.final_callback([&] {
33 // Print help text for the root command if no sub-command was given
34
2/4
✓ Branch 2 → 3 taken 465 times.
✗ Branch 2 → 124 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 15 taken 465 times.
465 if (app.get_subcommands().empty()) {
35 std::cout << app.help();
36 return;
37 }
38
39
4/4
✓ Branch 15 → 16 taken 464 times.
✓ Branch 15 → 17 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✓ Branch 16 → 52 taken 463 times.
465 if (shouldInstall || shouldUninstall) {
40 // Prepare the installation path
41
1/2
✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 152 not taken.
2 std::filesystem::path installPath = SystemUtil::getSpiceBinDir();
42
2/4
✓ Branch 18 → 19 taken 2 times.
✗ Branch 18 → 136 not taken.
✓ Branch 19 → 20 taken 2 times.
✗ Branch 19 → 134 not taken.
2 installPath /= cliOptions.mainSourceFile.stem();
43
1/2
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 2 times.
2 if (!performDryRun)
44 create_directories(installPath);
45
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 2 times.
2 assert(cliOptions.outputContainer == OutputContainer::EXECUTABLE);
46
3/6
✓ Branch 25 → 26 taken 2 times.
✗ Branch 25 → 139 not taken.
✓ Branch 26 → 27 taken 2 times.
✗ Branch 26 → 139 not taken.
✓ Branch 27 → 28 taken 2 times.
✗ Branch 27 → 137 not taken.
2 installPath.replace_extension(SystemUtil::getOutputFileExtension(cliOptions, OutputContainer::EXECUTABLE));
47
48 // If the binary should be installed, set the output path to the Spice bin directory
49
2/2
✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 31 taken 1 time.
2 if (shouldInstall)
50
1/2
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 150 not taken.
1 cliOptions.outputPath = installPath;
51
52 // If the binary should be uninstalled, check if the executable exists and uninstall it
53
3/4
✓ Branch 31 → 32 taken 1 time.
✓ Branch 31 → 50 taken 1 time.
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 50 taken 1 time.
2 if (shouldUninstall && !performDryRun) {
54 if (exists(installPath) && std::filesystem::remove(installPath))
55 std::cout << "Successfully uninstalled.\n";
56 else
57 CompilerWarning(UNINSTALL_FAILED, "The executable was not found at the expected location").print();
58 }
59 2 }
60
61 // Abort here if we do not need to compile
62
2/2
✓ Branch 52 → 53 taken 1 time.
✓ Branch 52 → 54 taken 464 times.
465 if (!shouldCompile)
63 1 return;
64
65 // Set output path and dir
66
2/2
✓ Branch 54 → 55 taken 4 times.
✓ Branch 54 → 82 taken 460 times.
464 if (shouldExecute) {
67 4 cliOptions.execute = true;
68 const uint64_t millis =
69
1/2
✓ Branch 57 → 58 taken 4 times.
✗ Branch 57 → 153 not taken.
4 duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
70
8/16
✓ Branch 59 → 60 taken 4 times.
✗ Branch 59 → 175 not taken.
✓ Branch 60 → 61 taken 4 times.
✗ Branch 60 → 173 not taken.
✓ Branch 61 → 62 taken 4 times.
✗ Branch 61 → 169 not taken.
✓ Branch 62 → 63 taken 4 times.
✗ Branch 62 → 165 not taken.
✓ Branch 63 → 64 taken 4 times.
✗ Branch 63 → 162 not taken.
✓ Branch 64 → 65 taken 4 times.
✗ Branch 64 → 160 not taken.
✓ Branch 65 → 66 taken 4 times.
✗ Branch 65 → 158 not taken.
✓ Branch 66 → 67 taken 4 times.
✗ Branch 66 → 156 not taken.
4 cliOptions.outputDir = std::filesystem::temp_directory_path() / "spice" / "output" / std::to_string(millis);
71
2/4
✓ Branch 76 → 77 taken 4 times.
✗ Branch 76 → 180 not taken.
✓ Branch 77 → 78 taken 4 times.
✗ Branch 77 → 178 not taken.
4 cliOptions.outputPath = cliOptions.outputDir / cliOptions.mainSourceFile.filename();
72
2/2
✓ Branch 83 → 84 taken 1 time.
✓ Branch 83 → 99 taken 459 times.
460 } else if (!cliOptions.outputPath.empty()) {
73
1/2
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 93 taken 1 time.
1 if (is_directory(cliOptions.outputPath)) {
74 cliOptions.outputDir = cliOptions.outputPath;
75 cliOptions.outputPath = cliOptions.outputDir / cliOptions.mainSourceFile.filename();
76
1/2
✓ Branch 94 → 95 taken 1 time.
✗ Branch 94 → 106 not taken.
1 } else if (cliOptions.outputPath.has_parent_path()) {
77
1/2
✓ Branch 95 → 96 taken 1 time.
✗ Branch 95 → 186 not taken.
1 cliOptions.outputDir = cliOptions.outputPath.parent_path();
78 }
79 } else {
80 459 cliOptions.outputDir = "./";
81
2/4
✓ Branch 100 → 101 taken 459 times.
✗ Branch 100 → 189 not taken.
✓ Branch 101 → 102 taken 459 times.
✗ Branch 101 → 187 not taken.
459 cliOptions.outputPath = cliOptions.outputDir / cliOptions.mainSourceFile.filename();
82 }
83
84 // Set output file extension
85
3/6
✓ Branch 106 → 107 taken 464 times.
✗ Branch 106 → 193 not taken.
✓ Branch 107 → 108 taken 464 times.
✗ Branch 107 → 193 not taken.
✓ Branch 108 → 109 taken 464 times.
✗ Branch 108 → 191 not taken.
464 cliOptions.outputPath.replace_extension(SystemUtil::getOutputFileExtension(cliOptions, cliOptions.outputContainer));
86
87 // Set cache dir
88
5/10
✓ Branch 110 → 111 taken 464 times.
✗ Branch 110 → 206 not taken.
✓ Branch 111 → 112 taken 464 times.
✗ Branch 111 → 202 not taken.
✓ Branch 112 → 113 taken 464 times.
✗ Branch 112 → 199 not taken.
✓ Branch 113 → 114 taken 464 times.
✗ Branch 113 → 197 not taken.
✓ Branch 114 → 115 taken 464 times.
✗ Branch 114 → 195 not taken.
464 cliOptions.cacheDir = std::filesystem::temp_directory_path() / "spice" / "cache";
89
90 // Create directories in case they not exist yet
91 464 create_directories(cliOptions.cacheDir);
92 464 create_directories(cliOptions.outputDir);
93 });
94 469 }
95
96 /**
97 * Start the parsing process
98 *
99 * @param argc Argument count
100 * @param argv Argument vector
101 * @return Return code
102 */
103 469 int Driver::parse(int argc, const char *argv[]) {
104 try {
105
2/2
✓ Branch 2 → 3 taken 465 times.
✓ Branch 2 → 5 taken 1 time.
469 app.parse(argc, argv);
106 465 return EXIT_SUCCESS;
107
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 1 time.
1 } catch (const CLI::ParseError &parseError) {
108
1/2
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 11 not taken.
1 return app.exit(parseError);
109 1 }
110 }
111
112 /**
113 * Initialize the cli options based on the input of the user
114 */
115 466 void Driver::enrich() const {
116 // Make path of given main source file canonical and relative
117
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 9 taken 466 times.
466 if (!performDryRun)
118 cliOptions.mainSourceFile = relative(cliOptions.mainSourceFile);
119
120 // Propagate llvm args to llvm
121
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 31 taken 466 times.
466 if (!cliOptions.llvmArgs.empty()) {
122 const std::vector<std::string> result = CommonUtil::split("llvm " + cliOptions.llvmArgs);
123 std::vector<const char *> resultCStr;
124 resultCStr.reserve(result.size());
125 for (const std::string &str : result)
126 resultCStr.push_back(str.c_str());
127 llvm::cl::ParseCommandLineOptions(static_cast<int>(result.size()), resultCStr.data());
128 }
129
130 // Propagate target information
131
3/6
✓ Branch 31 → 32 taken 466 times.
✗ Branch 31 → 123 not taken.
✓ Branch 33 → 34 taken 466 times.
✗ Branch 33 → 121 not taken.
✓ Branch 34 → 35 taken 466 times.
✗ Branch 34 → 119 not taken.
466 const llvm::Triple defaultTriple(llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()));
132
2/2
✓ Branch 38 → 39 taken 461 times.
✓ Branch 38 → 57 taken 5 times.
466 if (cliOptions.targetTriple.empty()) {
133
2/4
✓ Branch 39 → 40 taken 461 times.
✗ Branch 39 → 160 not taken.
✓ Branch 40 → 41 taken 461 times.
✗ Branch 40 → 49 not taken.
461 if (cliOptions.targetArch == TARGET_UNKNOWN) { // We have nothing -> obtain native triplet
134
1/2
✓ Branch 41 → 42 taken 461 times.
✗ Branch 41 → 160 not taken.
461 cliOptions.targetTriple = defaultTriple;
135
2/4
✓ Branch 42 → 43 taken 461 times.
✗ Branch 42 → 126 not taken.
✓ Branch 43 → 44 taken 461 times.
✗ Branch 43 → 126 not taken.
461 cliOptions.targetArch = defaultTriple.getArchName();
136
2/4
✓ Branch 44 → 45 taken 461 times.
✗ Branch 44 → 127 not taken.
✓ Branch 45 → 46 taken 461 times.
✗ Branch 45 → 127 not taken.
461 cliOptions.targetVendor = defaultTriple.getVendorName();
137
2/4
✓ Branch 46 → 47 taken 461 times.
✗ Branch 46 → 128 not taken.
✓ Branch 47 → 48 taken 461 times.
✗ Branch 47 → 128 not taken.
461 cliOptions.targetOs = defaultTriple.getOSName();
138 461 cliOptions.isNativeTarget = true;
139 } else { // We have arch, vendor and os -> obtain triplet
140 cliOptions.targetTriple = llvm::Triple(cliOptions.targetArch, cliOptions.targetVendor, cliOptions.targetOs);
141 cliOptions.isNativeTarget = cliOptions.targetTriple == defaultTriple;
142 }
143 } else { // Obtain arch, vendor and os by the triplet
144
2/4
✓ Branch 57 → 58 taken 5 times.
✗ Branch 57 → 135 not taken.
✓ Branch 58 → 59 taken 5 times.
✗ Branch 58 → 133 not taken.
5 const llvm::Triple triple(cliOptions.targetTriple.normalize());
145
2/4
✓ Branch 60 → 61 taken 5 times.
✗ Branch 60 → 136 not taken.
✓ Branch 61 → 62 taken 5 times.
✗ Branch 61 → 136 not taken.
5 cliOptions.targetArch = triple.getArchName();
146
2/4
✓ Branch 62 → 63 taken 5 times.
✗ Branch 62 → 137 not taken.
✓ Branch 63 → 64 taken 5 times.
✗ Branch 63 → 137 not taken.
5 cliOptions.targetVendor = triple.getVendorName();
147
2/4
✓ Branch 64 → 65 taken 5 times.
✗ Branch 64 → 138 not taken.
✓ Branch 65 → 66 taken 5 times.
✗ Branch 65 → 138 not taken.
5 cliOptions.targetOs = triple.getOSName();
148 5 cliOptions.isNativeTarget = triple == defaultTriple;
149 5 }
150
151 // Always preserve IR value names when dumping IR
152
2/2
✓ Branch 69 → 70 taken 1 time.
✓ Branch 69 → 71 taken 465 times.
466 if (cliOptions.dump.dumpIR)
153 1 cliOptions.namesForIRValues = true;
154
155 // Enable test mode when test mode was selected
156
2/2
✓ Branch 71 → 72 taken 2 times.
✓ Branch 71 → 73 taken 464 times.
466 if (cliOptions.buildMode == BuildMode::TEST) {
157 2 cliOptions.noEntryFct = true;
158 2 cliOptions.generateTestMain = true;
159 }
160
161 466 const Sanitizer sanitizer = cliOptions.instrumentation.sanitizer;
162 // Memory sanitizer is only supported on Linux
163
4/6
✓ Branch 74 → 75 taken 3 times.
✓ Branch 74 → 77 taken 463 times.
✗ Branch 75 → 76 not taken.
✓ Branch 75 → 77 taken 3 times.
✗ Branch 78 → 79 not taken.
✓ Branch 78 → 87 taken 466 times.
466 if (!cliOptions.targetTriple.isOSLinux() && sanitizer == Sanitizer::MEMORY)
164 throw CliError(FEATURE_NOT_SUPPORTED_FOR_TARGET, "Memory sanitizer is only supported for Linux targets");
165 // Some sanitizers need lifetime markers to work properly
166
4/4
✓ Branch 87 → 88 taken 463 times.
✓ Branch 87 → 89 taken 3 times.
✓ Branch 88 → 89 taken 3 times.
✓ Branch 88 → 90 taken 460 times.
466 if (sanitizer == Sanitizer::ADDRESS || sanitizer == Sanitizer::MEMORY)
167 6 cliOptions.useLifetimeMarkers = true;
168 // Type sanitizer needs TBAA metadata to work properly
169
2/2
✓ Branch 90 → 91 taken 2 times.
✓ Branch 90 → 92 taken 464 times.
466 if (sanitizer == Sanitizer::TYPE)
170 2 cliOptions.useTBAAMetadata = true;
171
172 // Prevent incompatible option combinations
173
3/4
✓ Branch 92 → 93 taken 1 time.
✓ Branch 92 → 102 taken 465 times.
✓ Branch 93 → 94 taken 1 time.
✗ Branch 93 → 102 not taken.
466 if (cliOptions.staticLinking && cliOptions.outputContainer == OutputContainer::SHARED_LIBRARY)
174
2/4
✓ Branch 97 → 98 taken 1 time.
✗ Branch 97 → 154 not taken.
✓ Branch 98 → 99 taken 1 time.
✗ Branch 98 → 151 not taken.
3 throw CliError(INCOMPATIBLE_OPTIONS, "Cannot link statically if compiling shared library");
175 466 }
176
177 /**
178 * Executes the built executable
179 */
180 void Driver::runBinary() const {
181 // Print status message
182 if (cliOptions.printDebugOutput)
183 std::cout << "Running executable ...\n\n";
184
185 // Run executable
186 std::filesystem::path executablePath = cliOptions.outputPath;
187 executablePath.make_preferred();
188 const int exitCode = std::system(executablePath.string().c_str()) / 256;
189 if (exitCode != 0)
190 throw CliError(NON_ZERO_EXIT_CODE, "Your Spice executable exited with non-zero exit code " + std::to_string(exitCode));
191 }
192
193 /**
194 * Add build subcommand to cli interface
195 */
196 469 void Driver::addBuildSubcommand() {
197 // Create sub-command itself
198
3/6
✓ Branch 4 → 5 taken 469 times.
✗ Branch 4 → 160 not taken.
✓ Branch 7 → 8 taken 469 times.
✗ Branch 7 → 154 not taken.
✓ Branch 8 → 9 taken 469 times.
✗ Branch 8 → 152 not taken.
1876 CLI::App *subCmd = app.add_subcommand("build", "Builds your Spice program and emits an executable");
199
2/4
✓ Branch 15 → 16 taken 469 times.
✗ Branch 15 → 166 not taken.
✓ Branch 16 → 17 taken 469 times.
✗ Branch 16 → 164 not taken.
938 subCmd->alias("b");
200 469 subCmd->allow_non_standard_option_names();
201 469 subCmd->configurable();
202 469 subCmd->callback([&] {
203 459 shouldCompile = true; // Requires the source file to be compiled
204 459 });
205
206
1/2
✓ Branch 24 → 25 taken 469 times.
✗ Branch 24 → 308 not taken.
469 addCompileSubcommandOptions(subCmd);
207
1/2
✓ Branch 25 → 26 taken 469 times.
✗ Branch 25 → 308 not taken.
469 addInstrumentationOptions(subCmd);
208
209 7 const auto outputContainerCallback = [&](const CLI::results_t &results) {
210
1/2
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 29 not taken.
7 std::string inputString = results.front();
211
1/2
✓ Branch 5 → 6 taken 7 times.
✗ Branch 5 → 27 not taken.
7 std::ranges::transform(inputString, inputString.begin(), tolower);
212
213
3/4
✓ Branch 6 → 7 taken 7 times.
✗ Branch 6 → 27 not taken.
✓ Branch 7 → 8 taken 2 times.
✓ Branch 7 → 9 taken 5 times.
7 if (inputString == OUTPUT_CONTAINER_EXECUTABLE)
214 2 cliOptions.outputContainer = OutputContainer::EXECUTABLE;
215
3/4
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 27 not taken.
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 4 times.
5 else if (inputString == OUTPUT_CONTAINER_OBJECT_FILE)
216 1 cliOptions.outputContainer = OutputContainer::OBJECT_FILE;
217
3/4
✓ Branch 12 → 13 taken 4 times.
✗ Branch 12 → 27 not taken.
✓ Branch 13 → 14 taken 1 time.
✓ Branch 13 → 15 taken 3 times.
4 else if (inputString == OUTPUT_CONTAINER_STATIC_LIBRARY)
218 1 cliOptions.outputContainer = OutputContainer::STATIC_LIBRARY;
219
3/4
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 27 not taken.
✓ Branch 16 → 17 taken 2 times.
✓ Branch 16 → 18 taken 1 time.
3 else if (inputString == OUTPUT_CONTAINER_SHARED_LIBRARY)
220 2 cliOptions.outputContainer = OutputContainer::SHARED_LIBRARY;
221 else
222
1/2
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 24 not taken.
1 throw CliError(INVALID_OUTPUT_CONTAINER, inputString);
223
224 6 return true;
225 7 };
226
227 // --output-container
228
3/6
✓ Branch 29 → 30 taken 469 times.
✗ Branch 29 → 181 not taken.
✓ Branch 33 → 34 taken 469 times.
✗ Branch 33 → 172 not taken.
✓ Branch 34 → 35 taken 469 times.
✗ Branch 34 → 170 not taken.
2345 subCmd->add_option("--output-container", outputContainerCallback,
229 "Format of the compilation output container: exec (default), obj, lib, dylib)");
230 // --target-triple
231
3/6
✓ Branch 43 → 44 taken 469 times.
✗ Branch 43 → 196 not taken.
✓ Branch 46 → 47 taken 469 times.
✗ Branch 46 → 190 not taken.
✓ Branch 47 → 48 taken 469 times.
✗ Branch 47 → 188 not taken.
1876 subCmd->add_option<llvm::Triple>("--target,--target-triple,-t", cliOptions.targetTriple,
232 "Target triple for the emitted executable (for cross-compiling)");
233 // --target-arch
234
3/6
✓ Branch 54 → 55 taken 469 times.
✗ Branch 54 → 208 not taken.
✓ Branch 57 → 58 taken 469 times.
✗ Branch 57 → 202 not taken.
✓ Branch 58 → 59 taken 469 times.
✗ Branch 58 → 200 not taken.
1876 subCmd->add_option<std::string>("--target-arch", cliOptions.targetArch,
235 "Target arch for emitted executable (for cross-compiling)");
236 // --target-vendor
237
3/6
✓ Branch 65 → 66 taken 469 times.
✗ Branch 65 → 220 not taken.
✓ Branch 68 → 69 taken 469 times.
✗ Branch 68 → 214 not taken.
✓ Branch 69 → 70 taken 469 times.
✗ Branch 69 → 212 not taken.
1876 subCmd->add_option<std::string>("--target-vendor", cliOptions.targetVendor,
238 "Target vendor for emitted executable (for cross-compiling)");
239 // --target-os
240
3/6
✓ Branch 76 → 77 taken 469 times.
✗ Branch 76 → 232 not taken.
✓ Branch 79 → 80 taken 469 times.
✗ Branch 79 → 226 not taken.
✓ Branch 80 → 81 taken 469 times.
✗ Branch 80 → 224 not taken.
1876 subCmd->add_option<std::string>("--target-os", cliOptions.targetOs, "Target os for emitted executable (for cross-compiling)");
241 // --output
242
3/6
✓ Branch 87 → 88 taken 469 times.
✗ Branch 87 → 244 not taken.
✓ Branch 90 → 91 taken 469 times.
✗ Branch 90 → 238 not taken.
✓ Branch 91 → 92 taken 469 times.
✗ Branch 91 → 236 not taken.
1876 subCmd->add_option<std::filesystem::path>("--output,-o", cliOptions.outputPath, "Set the output file path");
243 // --disable-verifier
244
3/6
✓ Branch 98 → 99 taken 469 times.
✗ Branch 98 → 256 not taken.
✓ Branch 101 → 102 taken 469 times.
✗ Branch 101 → 250 not taken.
✓ Branch 102 → 103 taken 469 times.
✗ Branch 102 → 248 not taken.
1876 subCmd->add_flag<bool>("--disable-verifier", cliOptions.disableVerifier, "Disable LLVM module and function verification");
245 // --no-entry
246
3/6
✓ Branch 109 → 110 taken 469 times.
✗ Branch 109 → 268 not taken.
✓ Branch 112 → 113 taken 469 times.
✗ Branch 112 → 262 not taken.
✓ Branch 113 → 114 taken 469 times.
✗ Branch 113 → 260 not taken.
1876 subCmd->add_flag<bool>("--no-entry", cliOptions.noEntryFct, "Do not generate main function");
247 // --static
248
3/6
✓ Branch 120 → 121 taken 469 times.
✗ Branch 120 → 280 not taken.
✓ Branch 123 → 124 taken 469 times.
✗ Branch 123 → 274 not taken.
✓ Branch 124 → 125 taken 469 times.
✗ Branch 124 → 272 not taken.
1876 subCmd->add_flag<bool>("--static", cliOptions.staticLinking, "Link statically");
249 // --dump-to-files
250
3/6
✓ Branch 131 → 132 taken 469 times.
✗ Branch 131 → 292 not taken.
✓ Branch 134 → 135 taken 469 times.
✗ Branch 134 → 286 not taken.
✓ Branch 135 → 136 taken 469 times.
✗ Branch 135 → 284 not taken.
1876 subCmd->add_flag<bool>("--dump-to-files", cliOptions.dump.dumpToFiles, "Redirect dumps to files instead of printing");
251 // --abort-after-dump
252
3/6
✓ Branch 142 → 143 taken 469 times.
✗ Branch 142 → 304 not taken.
✓ Branch 145 → 146 taken 469 times.
✗ Branch 145 → 298 not taken.
✓ Branch 146 → 147 taken 469 times.
✗ Branch 146 → 296 not taken.
1876 subCmd->add_flag<bool>("--abort-after-dump", cliOptions.dump.abortAfterDump,
253 "Abort the compilation process after dumping the first requested resource");
254 469 }
255
256 /**
257 * Add run subcommand to cli interface
258 */
259 469 void Driver::addRunSubcommand() {
260 // Create sub-command itself
261
3/6
✓ Branch 4 → 5 taken 469 times.
✗ Branch 4 → 45 not taken.
✓ Branch 7 → 8 taken 469 times.
✗ Branch 7 → 39 not taken.
✓ Branch 8 → 9 taken 469 times.
✗ Branch 8 → 37 not taken.
1876 CLI::App *subCmd = app.add_subcommand("run", "Builds your Spice program and runs it immediately");
262
2/4
✓ Branch 15 → 16 taken 469 times.
✗ Branch 15 → 51 not taken.
✓ Branch 16 → 17 taken 469 times.
✗ Branch 16 → 49 not taken.
938 subCmd->alias("r");
263 469 subCmd->allow_non_standard_option_names();
264 469 subCmd->callback([&] {
265 2 shouldCompile = shouldExecute = true; // Requires the source file to be compiled
266 2 });
267
268 469 addCompileSubcommandOptions(subCmd);
269 469 addInstrumentationOptions(subCmd);
270
271 // --disable-verifier
272
3/6
✓ Branch 27 → 28 taken 469 times.
✗ Branch 27 → 63 not taken.
✓ Branch 30 → 31 taken 469 times.
✗ Branch 30 → 57 not taken.
✓ Branch 31 → 32 taken 469 times.
✗ Branch 31 → 55 not taken.
1876 subCmd->add_flag<bool>("--disable-verifier", cliOptions.disableVerifier, "Disable LLVM module and function verification");
273 469 }
274
275 /**
276 * Add test subcommand to cli interface
277 */
278 469 void Driver::addTestSubcommand() {
279 // Create sub-command itself
280
3/6
✓ Branch 4 → 5 taken 469 times.
✗ Branch 4 → 45 not taken.
✓ Branch 7 → 8 taken 469 times.
✗ Branch 7 → 39 not taken.
✓ Branch 8 → 9 taken 469 times.
✗ Branch 8 → 37 not taken.
1876 CLI::App *subCmd = app.add_subcommand("test", "Builds your Spice program and runs all enclosed tests");
281
2/4
✓ Branch 15 → 16 taken 469 times.
✗ Branch 15 → 51 not taken.
✓ Branch 16 → 17 taken 469 times.
✗ Branch 16 → 49 not taken.
938 subCmd->alias("t");
282 469 subCmd->allow_non_standard_option_names();
283 469 subCmd->callback([&] {
284 2 shouldCompile = shouldExecute = true; // Requires the source file to be compiled
285 2 cliOptions.buildMode = BuildMode::TEST; // Set build mode to test
286 2 cliOptions.generateTestMain = true; // An alternative entry function is generated
287 2 cliOptions.noEntryFct = true; // To not have two main functions, disable normal main
288 2 });
289
290 469 addCompileSubcommandOptions(subCmd);
291 469 addInstrumentationOptions(subCmd);
292
293 // --disable-verifier
294
3/6
✓ Branch 27 → 28 taken 469 times.
✗ Branch 27 → 63 not taken.
✓ Branch 30 → 31 taken 469 times.
✗ Branch 30 → 57 not taken.
✓ Branch 31 → 32 taken 469 times.
✗ Branch 31 → 55 not taken.
1876 subCmd->add_flag<bool>("--disable-verifier", cliOptions.disableVerifier, "Disable LLVM module and function verification");
295 469 }
296
297 /**
298 * Add install subcommand to cli interface
299 */
300 469 void Driver::addInstallSubcommand() {
301 // Create sub-command itself
302
3/6
✓ Branch 4 → 5 taken 469 times.
✗ Branch 4 → 33 not taken.
✓ Branch 7 → 8 taken 469 times.
✗ Branch 7 → 27 not taken.
✓ Branch 8 → 9 taken 469 times.
✗ Branch 8 → 25 not taken.
1876 CLI::App *subCmd = app.add_subcommand("install", "Builds your Spice program and installs it to a directory in the PATH");
303
2/4
✓ Branch 15 → 16 taken 469 times.
✗ Branch 15 → 39 not taken.
✓ Branch 16 → 17 taken 469 times.
✗ Branch 16 → 37 not taken.
938 subCmd->alias("i");
304 469 subCmd->allow_non_standard_option_names();
305 469 subCmd->callback([&] {
306 1 shouldCompile = true;
307 1 shouldInstall = true;
308 1 ensureNotDockerized();
309 1 });
310
311 469 addCompileSubcommandOptions(subCmd);
312 469 }
313
314 /**
315 * Add uninstall subcommand to cli interface
316 */
317 469 void Driver::addUninstallSubcommand() {
318 // Create sub-command itself
319
3/6
✓ Branch 4 → 5 taken 469 times.
✗ Branch 4 → 52 not taken.
✓ Branch 7 → 8 taken 469 times.
✗ Branch 7 → 46 not taken.
✓ Branch 8 → 9 taken 469 times.
✗ Branch 8 → 44 not taken.
1876 CLI::App *subCmd = app.add_subcommand("uninstall", "Uninstalls a Spice program from the system");
320
2/4
✓ Branch 15 → 16 taken 469 times.
✗ Branch 15 → 58 not taken.
✓ Branch 16 → 17 taken 469 times.
✗ Branch 16 → 56 not taken.
938 subCmd->alias("u");
321 469 subCmd->allow_non_standard_option_names();
322 469 subCmd->callback([&] {
323 1 shouldUninstall = true;
324 1 ensureNotDockerized();
325 1 });
326
327 // Source file
328
2/4
✓ Branch 25 → 26 taken 469 times.
✗ Branch 25 → 79 not taken.
✓ Branch 28 → 29 taken 469 times.
✗ Branch 28 → 73 not taken.
1407 subCmd->add_option<std::filesystem::path>("<main-source-file>", cliOptions.mainSourceFile, "Main source file")
329
4/8
✓ Branch 29 → 30 taken 469 times.
✗ Branch 29 → 71 not taken.
✓ Branch 32 → 33 taken 469 times.
✗ Branch 32 → 67 not taken.
✓ Branch 33 → 34 taken 469 times.
✗ Branch 33 → 64 not taken.
✓ Branch 34 → 35 taken 469 times.
✗ Branch 34 → 62 not taken.
2345 ->check(CLI::ExistingFile)
330 469 ->required();
331 469 }
332
333 1876 void Driver::addCompileSubcommandOptions(CLI::App *subCmd) const {
334 4 const auto buildModeCallback = [&](const CLI::results_t &results) {
335
1/2
✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 26 not taken.
4 std::string inputString = results.front();
336
1/2
✓ Branch 5 → 6 taken 4 times.
✗ Branch 5 → 24 not taken.
4 std::ranges::transform(inputString, inputString.begin(), tolower);
337
338
2/4
✓ Branch 6 → 7 taken 4 times.
✗ Branch 6 → 24 not taken.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 4 times.
4 if (inputString == BUILD_MODE_DEBUG)
339 cliOptions.buildMode = BuildMode::DEBUG;
340
3/4
✓ Branch 9 → 10 taken 4 times.
✗ Branch 9 → 24 not taken.
✓ Branch 10 → 11 taken 3 times.
✓ Branch 10 → 12 taken 1 time.
4 else if (inputString == BUILD_MODE_RELEASE)
341 3 cliOptions.buildMode = BuildMode::RELEASE;
342
2/4
✓ Branch 12 → 13 taken 1 time.
✗ Branch 12 → 24 not taken.
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 1 time.
1 else if (inputString == BUILD_MODE_TEST)
343 cliOptions.buildMode = BuildMode::TEST;
344 else
345
1/2
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 21 not taken.
1 throw CliError(INVALID_BUILD_MODE, inputString);
346
347 3 return true;
348 4 };
349 3 const auto buildVarCallback = [&](const std::vector<std::string> &inputs) {
350
2/2
✓ Branch 21 → 4 taken 17 times.
✓ Branch 21 → 22 taken 3 times.
20 for (const std::string &input : inputs) {
351 // Skip empty inputs
352
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 17 times.
17 if (input.empty())
353 continue;
354
355 // Parse structure: "key=value". If no value given, save "true" as value.
356 17 const size_t splitPos = input.find_first_of('=');
357
2/2
✓ Branch 9 → 10 taken 12 times.
✓ Branch 9 → 17 taken 5 times.
17 if (splitPos != std::string::npos) {
358
1/2
✓ Branch 10 → 11 taken 12 times.
✗ Branch 10 → 28 not taken.
12 const std::string key = input.substr(0, splitPos);
359
1/2
✓ Branch 11 → 12 taken 12 times.
✗ Branch 11 → 26 not taken.
12 const std::string value = input.substr(splitPos + 1);
360
2/4
✓ Branch 12 → 13 taken 12 times.
✗ Branch 12 → 24 not taken.
✓ Branch 13 → 14 taken 12 times.
✗ Branch 13 → 24 not taken.
12 cliOptions.buildVars[key] = value;
361 12 } else {
362
2/4
✓ Branch 17 → 18 taken 5 times.
✗ Branch 17 → 29 not taken.
✓ Branch 18 → 19 taken 5 times.
✗ Branch 18 → 29 not taken.
5 cliOptions.buildVars[input] = "true";
363 }
364 }
365 3 return true;
366 1876 };
367
368 // --build-mode
369
3/6
✓ Branch 5 → 6 taken 1876 times.
✗ Branch 5 → 318 not taken.
✓ Branch 9 → 10 taken 1876 times.
✗ Branch 9 → 309 not taken.
✓ Branch 10 → 11 taken 1876 times.
✗ Branch 10 → 307 not taken.
9380 subCmd->add_option("--build-mode,-m", buildModeCallback, "Build mode: debug (default), release, test");
370 // --llvm-args
371
3/6
✓ Branch 19 → 20 taken 1876 times.
✗ Branch 19 → 333 not taken.
✓ Branch 22 → 23 taken 1876 times.
✗ Branch 22 → 327 not taken.
✓ Branch 23 → 24 taken 1876 times.
✗ Branch 23 → 325 not taken.
7504 subCmd->add_option<std::string>("--llvm-args,-llvm", cliOptions.llvmArgs, "Additional arguments for LLVM")->join(' ');
372 // --jobs
373
3/6
✓ Branch 31 → 32 taken 1876 times.
✗ Branch 31 → 345 not taken.
✓ Branch 34 → 35 taken 1876 times.
✗ Branch 34 → 339 not taken.
✓ Branch 35 → 36 taken 1876 times.
✗ Branch 35 → 337 not taken.
7504 subCmd->add_option<unsigned short>("--jobs,-j", cliOptions.compileJobCount, "Compile jobs (threads), used for compilation");
374 // --build-var
375
3/6
✓ Branch 42 → 43 taken 1876 times.
✗ Branch 42 → 360 not taken.
✓ Branch 46 → 47 taken 1876 times.
✗ Branch 46 → 351 not taken.
✓ Branch 47 → 48 taken 1876 times.
✗ Branch 47 → 349 not taken.
7504 CLI::Option *buildVarOption = subCmd->add_option_function<std::vector<std::string>>(
376 "--build-var,-b", buildVarCallback, "Add build variable to parametrize the compiled program (e.g. -v key=value)");
377 1876 buildVarOption->multi_option_policy(CLI::MultiOptionPolicy::TakeAll);
378 // --ignore-cache
379
3/6
✓ Branch 56 → 57 taken 1876 times.
✗ Branch 56 → 372 not taken.
✓ Branch 59 → 60 taken 1876 times.
✗ Branch 59 → 366 not taken.
✓ Branch 60 → 61 taken 1876 times.
✗ Branch 60 → 364 not taken.
7504 subCmd->add_flag<bool>("--ignore-cache", cliOptions.ignoreCache, "Force re-compilation of all source files");
380 // --use-lifetime-markers
381
3/6
✓ Branch 67 → 68 taken 1876 times.
✗ Branch 67 → 384 not taken.
✓ Branch 70 → 71 taken 1876 times.
✗ Branch 70 → 378 not taken.
✓ Branch 71 → 72 taken 1876 times.
✗ Branch 71 → 376 not taken.
7504 subCmd->add_flag<bool>("--use-lifetime-markers", cliOptions.useLifetimeMarkers,
382 "Generate lifetime markers to enhance optimizations");
383 // --use-tbaa-metadata
384
3/6
✓ Branch 78 → 79 taken 1876 times.
✗ Branch 78 → 396 not taken.
✓ Branch 81 → 82 taken 1876 times.
✗ Branch 81 → 390 not taken.
✓ Branch 82 → 83 taken 1876 times.
✗ Branch 82 → 388 not taken.
7504 subCmd->add_flag<bool>("--use-tbaa-metadata", cliOptions.useTBAAMetadata,
385 "Generate metadata for type-based alias analysis to enhance optimizations");
386
387 // Opt levels
388
3/6
✓ Branch 89 → 90 taken 1876 times.
✗ Branch 89 → 412 not taken.
✓ Branch 93 → 94 taken 1876 times.
✗ Branch 93 → 402 not taken.
✓ Branch 94 → 95 taken 1876 times.
✗ Branch 94 → 400 not taken.
7504 subCmd->add_flag_callback("-O0", [&] { cliOptions.optLevel = OptLevel::O0; }, "Disable optimization.");
389
3/6
✓ Branch 102 → 103 taken 1876 times.
✗ Branch 102 → 428 not taken.
✓ Branch 106 → 107 taken 1876 times.
✗ Branch 106 → 418 not taken.
✓ Branch 107 → 108 taken 1876 times.
✗ Branch 107 → 416 not taken.
7504 subCmd->add_flag_callback("-O1", [&] { cliOptions.optLevel = OptLevel::O1; }, "Only basic optimization is applied.");
390
3/6
✓ Branch 115 → 116 taken 1876 times.
✗ Branch 115 → 444 not taken.
✓ Branch 119 → 120 taken 1876 times.
✗ Branch 119 → 434 not taken.
✓ Branch 120 → 121 taken 1876 times.
✗ Branch 120 → 432 not taken.
7504 subCmd->add_flag_callback("-O2", [&] { cliOptions.optLevel = OptLevel::O2; }, "More advanced optimization is applied.");
391
3/6
✓ Branch 128 → 129 taken 1876 times.
✗ Branch 128 → 460 not taken.
✓ Branch 132 → 133 taken 1876 times.
✗ Branch 132 → 450 not taken.
✓ Branch 133 → 134 taken 1876 times.
✗ Branch 133 → 448 not taken.
7504 subCmd->add_flag_callback("-O3", [&] { cliOptions.optLevel = OptLevel::O3; }, "Aggressive optimization for best performance.");
392
3/6
✓ Branch 141 → 142 taken 1876 times.
✗ Branch 141 → 476 not taken.
✓ Branch 145 → 146 taken 1876 times.
✗ Branch 145 → 466 not taken.
✓ Branch 146 → 147 taken 1876 times.
✗ Branch 146 → 464 not taken.
7504 subCmd->add_flag_callback("-Os", [&] { cliOptions.optLevel = OptLevel::Os; }, "Size optimization for output executable.");
393
3/6
✓ Branch 154 → 155 taken 1876 times.
✗ Branch 154 → 492 not taken.
✓ Branch 158 → 159 taken 1876 times.
✗ Branch 158 → 482 not taken.
✓ Branch 159 → 160 taken 1876 times.
✗ Branch 159 → 480 not taken.
7504 subCmd->add_flag_callback("-Oz", [&] { cliOptions.optLevel = OptLevel::Oz; }, "Aggressive optimization for best size.");
394
3/6
✓ Branch 167 → 168 taken 1876 times.
✗ Branch 167 → 504 not taken.
✓ Branch 170 → 171 taken 1876 times.
✗ Branch 170 → 498 not taken.
✓ Branch 171 → 172 taken 1876 times.
✗ Branch 171 → 496 not taken.
7504 subCmd->add_flag<bool>("-lto", cliOptions.useLTO, "Enable link time optimization (LTO)");
395
396 // --debug-output
397
3/6
✓ Branch 178 → 179 taken 1876 times.
✗ Branch 178 → 516 not taken.
✓ Branch 181 → 182 taken 1876 times.
✗ Branch 181 → 510 not taken.
✓ Branch 182 → 183 taken 1876 times.
✗ Branch 182 → 508 not taken.
7504 subCmd->add_flag<bool>("--debug-output,-d", cliOptions.printDebugOutput, "Enable debug output");
398 // --dump-cst
399
3/6
✓ Branch 189 → 190 taken 1876 times.
✗ Branch 189 → 528 not taken.
✓ Branch 192 → 193 taken 1876 times.
✗ Branch 192 → 522 not taken.
✓ Branch 193 → 194 taken 1876 times.
✗ Branch 193 → 520 not taken.
7504 subCmd->add_flag<bool>("--dump-cst,-cst", cliOptions.dump.dumpCST, "Dump CST as serialized string and SVG image");
400 // --dump-ast
401
3/6
✓ Branch 200 → 201 taken 1876 times.
✗ Branch 200 → 540 not taken.
✓ Branch 203 → 204 taken 1876 times.
✗ Branch 203 → 534 not taken.
✓ Branch 204 → 205 taken 1876 times.
✗ Branch 204 → 532 not taken.
7504 subCmd->add_flag<bool>("--dump-ast,-ast", cliOptions.dump.dumpAST, "Dump AST as serialized string and SVG image");
402 // --dump-symtab
403
3/6
✓ Branch 211 → 212 taken 1876 times.
✗ Branch 211 → 552 not taken.
✓ Branch 214 → 215 taken 1876 times.
✗ Branch 214 → 546 not taken.
✓ Branch 215 → 216 taken 1876 times.
✗ Branch 215 → 544 not taken.
7504 subCmd->add_flag<bool>("--dump-symtab", cliOptions.dump.dumpSymbolTable, "Dump serialized symbol tables");
404 // --dump-types
405
3/6
✓ Branch 222 → 223 taken 1876 times.
✗ Branch 222 → 564 not taken.
✓ Branch 225 → 226 taken 1876 times.
✗ Branch 225 → 558 not taken.
✓ Branch 226 → 227 taken 1876 times.
✗ Branch 226 → 556 not taken.
7504 subCmd->add_flag<bool>("--dump-types", cliOptions.dump.dumpTypes, "Dump all used types");
406 // --dump-cache-stats
407
3/6
✓ Branch 233 → 234 taken 1876 times.
✗ Branch 233 → 576 not taken.
✓ Branch 236 → 237 taken 1876 times.
✗ Branch 236 → 570 not taken.
✓ Branch 237 → 238 taken 1876 times.
✗ Branch 237 → 568 not taken.
7504 subCmd->add_flag<bool>("--dump-cache-stats", cliOptions.dump.dumpCacheStats, "Dump stats for compiler-internal lookup caches");
408 // --dump-ir
409
3/6
✓ Branch 244 → 245 taken 1876 times.
✗ Branch 244 → 588 not taken.
✓ Branch 247 → 248 taken 1876 times.
✗ Branch 247 → 582 not taken.
✓ Branch 248 → 249 taken 1876 times.
✗ Branch 248 → 580 not taken.
7504 subCmd->add_flag<bool>("--dump-ir,-ir", cliOptions.dump.dumpIR, "Dump LLVM-IR");
410 // --dump-assembly
411
3/6
✓ Branch 255 → 256 taken 1876 times.
✗ Branch 255 → 600 not taken.
✓ Branch 258 → 259 taken 1876 times.
✗ Branch 258 → 594 not taken.
✓ Branch 259 → 260 taken 1876 times.
✗ Branch 259 → 592 not taken.
7504 subCmd->add_flag<bool>("--dump-assembly,-asm,-s", cliOptions.dump.dumpAssembly, "Dump Assembly code");
412 // --dump-object-file
413
3/6
✓ Branch 266 → 267 taken 1876 times.
✗ Branch 266 → 612 not taken.
✓ Branch 269 → 270 taken 1876 times.
✗ Branch 269 → 606 not taken.
✓ Branch 270 → 271 taken 1876 times.
✗ Branch 270 → 604 not taken.
7504 subCmd->add_flag<bool>("--dump-object-file", cliOptions.dump.dumpObjectFiles, "Dump object files");
414 // --dump-dependency-graph
415
3/6
✓ Branch 277 → 278 taken 1876 times.
✗ Branch 277 → 624 not taken.
✓ Branch 280 → 281 taken 1876 times.
✗ Branch 280 → 618 not taken.
✓ Branch 281 → 282 taken 1876 times.
✗ Branch 281 → 616 not taken.
7504 subCmd->add_flag<bool>("--dump-dependency-graph", cliOptions.dump.dumpDependencyGraph, "Dump compile unit dependency graph");
416
417 // Source file
418
2/4
✓ Branch 288 → 289 taken 1876 times.
✗ Branch 288 → 645 not taken.
✓ Branch 291 → 292 taken 1876 times.
✗ Branch 291 → 639 not taken.
5628 subCmd->add_option<std::filesystem::path>("<main-source-file>", cliOptions.mainSourceFile, "Main source file")
419
4/8
✓ Branch 292 → 293 taken 1876 times.
✗ Branch 292 → 637 not taken.
✓ Branch 295 → 296 taken 1876 times.
✗ Branch 295 → 633 not taken.
✓ Branch 296 → 297 taken 1876 times.
✗ Branch 296 → 630 not taken.
✓ Branch 297 → 298 taken 1876 times.
✗ Branch 297 → 628 not taken.
9380 ->check(CLI::ExistingFile)
420 1876 ->required();
421 1876 }
422
423 1407 void Driver::addInstrumentationOptions(CLI::App *subCmd) const {
424 12 const auto sanitizerCallback = [&](const CLI::results_t &results) {
425
1/2
✓ Branch 3 → 4 taken 12 times.
✗ Branch 3 → 32 not taken.
12 std::string inputString = results.front();
426
1/2
✓ Branch 5 → 6 taken 12 times.
✗ Branch 5 → 30 not taken.
12 std::ranges::transform(inputString, inputString.begin(), tolower);
427
428
2/4
✓ Branch 6 → 7 taken 12 times.
✗ Branch 6 → 30 not taken.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 12 times.
12 if (inputString == SANITIZER_NONE)
429 cliOptions.instrumentation.sanitizer = Sanitizer::NONE;
430
3/4
✓ Branch 9 → 10 taken 12 times.
✗ Branch 9 → 30 not taken.
✓ Branch 10 → 11 taken 3 times.
✓ Branch 10 → 12 taken 9 times.
12 else if (inputString == SANITIZER_ADDRESS)
431 3 cliOptions.instrumentation.sanitizer = Sanitizer::ADDRESS;
432
3/4
✓ Branch 12 → 13 taken 9 times.
✗ Branch 12 → 30 not taken.
✓ Branch 13 → 14 taken 3 times.
✓ Branch 13 → 15 taken 6 times.
9 else if (inputString == SANITIZER_THREAD)
433 3 cliOptions.instrumentation.sanitizer = Sanitizer::THREAD;
434
3/4
✓ Branch 15 → 16 taken 6 times.
✗ Branch 15 → 30 not taken.
✓ Branch 16 → 17 taken 3 times.
✓ Branch 16 → 18 taken 3 times.
6 else if (inputString == SANITIZER_MEMORY)
435 3 cliOptions.instrumentation.sanitizer = Sanitizer::MEMORY;
436
3/4
✓ Branch 18 → 19 taken 3 times.
✗ Branch 18 → 30 not taken.
✓ Branch 19 → 20 taken 2 times.
✓ Branch 19 → 21 taken 1 time.
3 else if (inputString == SANITIZER_TYPE)
437 2 cliOptions.instrumentation.sanitizer = Sanitizer::TYPE;
438 else
439
1/2
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 27 not taken.
1 throw CliError(INVALID_SANITIZER, inputString);
440
441 11 return true;
442 12 };
443
444 // --debug-info
445
3/6
✓ Branch 4 → 5 taken 1407 times.
✗ Branch 4 → 37 not taken.
✓ Branch 7 → 8 taken 1407 times.
✗ Branch 7 → 31 not taken.
✓ Branch 8 → 9 taken 1407 times.
✗ Branch 8 → 29 not taken.
5628 subCmd->add_flag<bool>("--debug-info,-g", cliOptions.instrumentation.generateDebugInfo, "Generate debug info");
446 // --sanitizer
447
3/6
✓ Branch 16 → 17 taken 1407 times.
✗ Branch 16 → 52 not taken.
✓ Branch 20 → 21 taken 1407 times.
✗ Branch 20 → 43 not taken.
✓ Branch 21 → 22 taken 1407 times.
✗ Branch 21 → 41 not taken.
7035 subCmd->add_option("--sanitizer", sanitizerCallback, "Enable sanitizer: none (default), address, thread, memory, type");
448 1407 }
449
450 /**
451 * Ensure that the compiler is not running in a Docker container
452 */
453 2 void Driver::ensureNotDockerized() {
454 2 const char *envValue = std::getenv(ENV_VAR_DOCKERIZED);
455 if (envValue != nullptr && std::strcmp(envValue, "true") == 0) { // LCOV_EXCL_START
456 auto errorMsg = "This feature is not supported in a containerized environment. Please use the standalone version of Spice.";
457 throw CliError(FEATURE_NOT_SUPPORTED_WHEN_DOCKERIZED, errorMsg);
458 } // LCOV_EXCL_STOP
459 2 }
460
461 } // namespace spice::compiler
462