1 //===- unittests/Frontend/CompilerInvocationTest.cpp - CI tests //---------===// 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 9 #include "clang/Frontend/CompilerInvocation.h" 10 #include "clang/Frontend/CompilerInstance.h" 11 #include "clang/Frontend/TextDiagnosticBuffer.h" 12 #include "llvm/Support/Host.h" 13 14 #include "gmock/gmock.h" 15 #include "gtest/gtest.h" 16 17 using namespace llvm; 18 using namespace clang; 19 20 using ::testing::Contains; 21 using ::testing::HasSubstr; 22 using ::testing::StrEq; 23 24 namespace { 25 class CommandLineTest : public ::testing::Test { 26 public: 27 IntrusiveRefCntPtr<DiagnosticsEngine> Diags; 28 SmallVector<const char *, 32> GeneratedArgs; 29 SmallVector<std::string, 32> GeneratedArgsStorage; 30 CompilerInvocation Invocation; 31 32 const char *operator()(const Twine &Arg) { 33 return GeneratedArgsStorage.emplace_back(Arg.str()).c_str(); 34 } 35 36 CommandLineTest() 37 : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions(), 38 new TextDiagnosticBuffer())) { 39 } 40 }; 41 42 // Boolean option with a keypath that defaults to true. 43 // The only flag with a negative spelling can set the keypath to false. 44 45 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagNotPresent) { 46 const char *Args[] = {""}; 47 48 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 49 50 ASSERT_FALSE(Diags->hasErrorOccurred()); 51 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary); 52 53 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 54 55 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file")))); 56 } 57 58 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagPresent) { 59 const char *Args[] = {"-fno-temp-file"}; 60 61 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 62 63 ASSERT_FALSE(Diags->hasErrorOccurred()); 64 ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary); 65 66 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 67 68 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file"))); 69 } 70 71 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagUnknownPresent) { 72 const char *Args[] = {"-ftemp-file"}; 73 74 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 75 76 // Driver-only flag. 77 ASSERT_TRUE(Diags->hasErrorOccurred()); 78 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary); 79 } 80 81 // Boolean option with a keypath that defaults to true. 82 // The flag with negative spelling can set the keypath to false. 83 // The flag with positive spelling can reset the keypath to true. 84 85 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNone) { 86 const char *Args[] = {""}; 87 88 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 89 ASSERT_FALSE(Diags->hasErrorOccurred()); 90 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink); 91 92 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 93 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink")))); 94 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-autolink")))); 95 } 96 97 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNegChange) { 98 const char *Args[] = {"-fno-autolink"}; 99 100 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 101 ASSERT_FALSE(Diags->hasErrorOccurred()); 102 ASSERT_FALSE(Invocation.getCodeGenOpts().Autolink); 103 104 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 105 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-autolink"))); 106 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink")))); 107 } 108 109 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentPosReset) { 110 const char *Args[] = {"-fautolink"}; 111 112 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 113 ASSERT_TRUE(Diags->hasErrorOccurred()); // Driver-only flag. 114 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink); 115 } 116 117 // Boolean option with a keypath that defaults to false. 118 // The flag with negative spelling can set the keypath to true. 119 // The flag with positive spelling can reset the keypath to false. 120 121 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNone) { 122 const char *Args[] = {""}; 123 124 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 125 ASSERT_FALSE(Diags->hasErrorOccurred()); 126 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables); 127 128 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 129 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables")))); 130 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-inline-line-tables")))); 131 } 132 133 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegChange) { 134 const char *Args[] = {"-gno-inline-line-tables"}; 135 136 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 137 ASSERT_FALSE(Diags->hasErrorOccurred()); 138 ASSERT_TRUE(Invocation.getCodeGenOpts().NoInlineLineTables); 139 140 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 141 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gno-inline-line-tables"))); 142 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables")))); 143 } 144 145 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosReset) { 146 const char *Args[] = {"-ginline-line-tables"}; 147 148 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 149 ASSERT_TRUE(Diags->hasErrorOccurred()); // Driver-only flag. 150 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables); 151 } 152 153 // Boolean option with a keypath that defaults to false. 154 // The flag with positive spelling can set the keypath to true. 155 // The flag with negative spelling can reset the keypath to false. 156 157 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNoneX) { 158 const char *Args[] = {""}; 159 160 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 161 ASSERT_FALSE(Diags->hasErrorOccurred()); 162 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash); 163 164 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 165 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gcodeview-ghash")))); 166 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash")))); 167 } 168 169 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosChange) { 170 const char *Args[] = {"-gcodeview-ghash"}; 171 172 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 173 ASSERT_FALSE(Diags->hasErrorOccurred()); 174 ASSERT_TRUE(Invocation.getCodeGenOpts().CodeViewGHash); 175 176 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 177 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gcodeview-ghash"))); 178 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash")))); 179 } 180 181 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegReset) { 182 const char *Args[] = {"-gno-codeview-ghash"}; 183 184 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 185 ASSERT_TRUE(Diags->hasErrorOccurred()); // Driver-only flag. 186 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash); 187 } 188 189 // Boolean option with a keypath that defaults to an arbitrary expression. 190 // The flag with positive spelling can set the keypath to true. 191 // The flag with negative spelling can set the keypath to false. 192 193 static constexpr unsigned PassManagerDefault = 194 !static_cast<unsigned>(LLVM_ENABLE_NEW_PASS_MANAGER); 195 196 static constexpr const char *PassManagerResetByFlag = 197 LLVM_ENABLE_NEW_PASS_MANAGER ? "-fno-legacy-pass-manager" 198 : "-flegacy-pass-manager"; 199 200 static constexpr const char *PassManagerChangedByFlag = 201 LLVM_ENABLE_NEW_PASS_MANAGER ? "-flegacy-pass-manager" 202 : "-fno-legacy-pass-manager"; 203 204 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentNone) { 205 const char *Args = {""}; 206 207 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 208 209 ASSERT_FALSE(Diags->hasErrorOccurred()); 210 ASSERT_EQ(Invocation.getCodeGenOpts().LegacyPassManager, PassManagerDefault); 211 212 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 213 214 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerResetByFlag)))); 215 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerChangedByFlag)))); 216 } 217 218 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentChange) { 219 const char *Args[] = {PassManagerChangedByFlag}; 220 221 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 222 ASSERT_FALSE(Diags->hasErrorOccurred()); 223 ASSERT_EQ(Invocation.getCodeGenOpts().LegacyPassManager, !PassManagerDefault); 224 225 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 226 ASSERT_THAT(GeneratedArgs, Contains(StrEq(PassManagerChangedByFlag))); 227 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerResetByFlag)))); 228 } 229 230 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentReset) { 231 const char *Args[] = {PassManagerResetByFlag}; 232 233 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 234 ASSERT_FALSE(Diags->hasErrorOccurred()); 235 ASSERT_EQ(Invocation.getCodeGenOpts().LegacyPassManager, PassManagerDefault); 236 237 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 238 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerResetByFlag)))); 239 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerChangedByFlag)))); 240 } 241 242 // Boolean option that gets the CC1Option flag from a let statement (which 243 // is applied **after** the record is defined): 244 // 245 // let Flags = [CC1Option] in { 246 // defm option : BoolOption<...>; 247 // } 248 249 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) { 250 const char *Args[] = {""}; 251 252 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 253 254 ASSERT_FALSE(Diags->hasErrorOccurred()); 255 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager); 256 257 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 258 259 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager")))); 260 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); 261 } 262 263 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) { 264 const char *Args[] = {"-fdebug-pass-manager"}; 265 266 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 267 268 ASSERT_FALSE(Diags->hasErrorOccurred()); 269 ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager); 270 271 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 272 273 ASSERT_EQ(count(GeneratedArgs, StringRef("-fdebug-pass-manager")), 1); 274 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); 275 } 276 277 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) { 278 const char *Args[] = {"-fno-debug-pass-manager"}; 279 280 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 281 282 ASSERT_FALSE(Diags->hasErrorOccurred()); 283 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager); 284 285 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 286 287 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); 288 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager")))); 289 } 290 291 TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) { 292 const char *Args[] = {"-fmodules-strict-context-hash"}; 293 294 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 295 296 ASSERT_FALSE(Diags->hasErrorOccurred()); 297 298 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 299 300 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash"))); 301 } 302 303 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) { 304 const char *TripleCStr = "i686-apple-darwin9"; 305 const char *Args[] = {"-triple", TripleCStr}; 306 307 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 308 309 ASSERT_FALSE(Diags->hasErrorOccurred()); 310 311 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 312 313 ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr))); 314 } 315 316 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredPresent) { 317 const std::string DefaultTriple = 318 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()); 319 const char *Args[] = {"-triple", DefaultTriple.c_str()}; 320 321 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 322 323 ASSERT_FALSE(Diags->hasErrorOccurred()); 324 325 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 326 327 // Triple should always be emitted even if it is the default 328 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str()))); 329 } 330 331 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) { 332 const std::string DefaultTriple = 333 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()); 334 const char *Args[] = {""}; 335 336 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 337 338 ASSERT_FALSE(Diags->hasErrorOccurred()); 339 340 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 341 342 // Triple should always be emitted even if it is the default 343 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str()))); 344 } 345 346 TEST_F(CommandLineTest, SeparateEnumNonDefault) { 347 const char *Args[] = {"-mrelocation-model", "static"}; 348 349 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 350 351 ASSERT_FALSE(Diags->hasErrorOccurred()); 352 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static); 353 354 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 355 356 // Non default relocation model. 357 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model"))); 358 ASSERT_THAT(GeneratedArgs, Contains(StrEq("static"))); 359 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static")))); 360 } 361 362 TEST_F(CommandLineTest, SeparateEnumDefault) { 363 const char *Args[] = {"-mrelocation-model", "pic"}; 364 365 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 366 367 ASSERT_FALSE(Diags->hasErrorOccurred()); 368 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_); 369 370 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 371 372 // Default relocation model. 373 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model")))); 374 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic")))); 375 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic")))); 376 } 377 378 TEST_F(CommandLineTest, JoinedEnumNonDefault) { 379 const char *Args[] = {"-fobjc-dispatch-method=non-legacy"}; 380 381 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 382 383 ASSERT_FALSE(Diags->hasErrorOccurred()); 384 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(), 385 CodeGenOptions::NonLegacy); 386 387 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 388 389 ASSERT_THAT(GeneratedArgs, 390 Contains(StrEq("-fobjc-dispatch-method=non-legacy"))); 391 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method=")))); 392 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy")))); 393 } 394 395 TEST_F(CommandLineTest, JoinedEnumDefault) { 396 const char *Args[] = {"-fobjc-dispatch-method=legacy"}; 397 398 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 399 400 ASSERT_FALSE(Diags->hasErrorOccurred()); 401 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(), 402 CodeGenOptions::Legacy); 403 404 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 405 406 ASSERT_THAT(GeneratedArgs, 407 Not(Contains(StrEq("-fobjc-dispatch-method=legacy")))); 408 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method=")))); 409 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy")))); 410 } 411 412 TEST_F(CommandLineTest, StringVectorEmpty) { 413 const char *Args[] = {""}; 414 415 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 416 417 ASSERT_FALSE(Diags->hasErrorOccurred()); 418 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles.empty()); 419 420 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 421 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-fmodule-map-file=")))); 422 } 423 424 TEST_F(CommandLineTest, StringVectorSingle) { 425 const char *Args[] = {"-fmodule-map-file=a"}; 426 427 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 428 429 ASSERT_FALSE(Diags->hasErrorOccurred()); 430 ASSERT_EQ(Invocation.getFrontendOpts().ModuleMapFiles, 431 std::vector<std::string>({"a"})); 432 433 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 434 ASSERT_EQ(count(GeneratedArgs, StringRef("-fmodule-map-file=a")), 1); 435 } 436 437 TEST_F(CommandLineTest, StringVectorMultiple) { 438 const char *Args[] = {"-fmodule-map-file=a", "-fmodule-map-file=b"}; 439 440 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 441 442 ASSERT_FALSE(Diags->hasErrorOccurred()); 443 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles == 444 std::vector<std::string>({"a", "b"})); 445 446 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 447 ASSERT_EQ(count(GeneratedArgs, StringRef("-fmodule-map-file=a")), 1); 448 ASSERT_EQ(count(GeneratedArgs, StringRef("-fmodule-map-file=b")), 1); 449 } 450 451 // Wide integer option. 452 453 TEST_F(CommandLineTest, WideIntegerHighValue) { 454 const char *Args[] = {"-fbuild-session-timestamp=1609827494445723662"}; 455 456 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 457 458 ASSERT_FALSE(Diags->hasErrorOccurred()); 459 ASSERT_EQ(Invocation.getHeaderSearchOpts().BuildSessionTimestamp, 460 1609827494445723662ull); 461 } 462 463 // Tree of boolean options that can be (directly or transitively) implied by 464 // their parent: 465 // 466 // * -cl-unsafe-math-optimizations 467 // * -cl-mad-enable 468 // * -menable-unsafe-fp-math 469 // * -freciprocal-math 470 471 TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) { 472 const char *Args[] = {""}; 473 474 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 475 476 ASSERT_FALSE(Diags->hasErrorOccurred()); 477 ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath); 478 ASSERT_FALSE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 479 ASSERT_FALSE(Invocation.getLangOpts()->UnsafeFPMath); 480 ASSERT_FALSE(Invocation.getLangOpts()->AllowRecip); 481 482 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 483 484 // Not generated - missing. 485 ASSERT_THAT(GeneratedArgs, 486 Not(Contains(StrEq("-cl-unsafe-math-optimizations")))); 487 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable")))); 488 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math")))); 489 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 490 } 491 492 TEST_F(CommandLineTest, ImpliedBoolOptionsRootFlagPresent) { 493 const char *Args[] = {"-cl-unsafe-math-optimizations"}; 494 495 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 496 497 ASSERT_FALSE(Diags->hasErrorOccurred()); 498 // Explicitly provided root flag. 499 ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath); 500 // Directly implied by explicitly provided root flag. 501 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 502 ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath); 503 // Transitively implied by explicitly provided root flag. 504 ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip); 505 506 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 507 508 // Generated - explicitly provided. 509 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations"))); 510 // Not generated - implied by the generated root flag. 511 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable")))); 512 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math")))); 513 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 514 } 515 516 TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) { 517 const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable", 518 "-menable-unsafe-fp-math", "-freciprocal-math"}; 519 520 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 521 522 ASSERT_FALSE(Diags->hasErrorOccurred()); 523 ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath); 524 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 525 ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath); 526 ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip); 527 528 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 529 530 // Generated - explicitly provided. 531 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations"))); 532 // Not generated - implied by their generated parent. 533 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable")))); 534 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math")))); 535 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 536 } 537 538 TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) { 539 const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math", 540 "-freciprocal-math"}; 541 542 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 543 ASSERT_FALSE(Diags->hasErrorOccurred()); 544 ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath); 545 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 546 ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath); 547 ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip); 548 549 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 550 // Not generated - missing. 551 ASSERT_THAT(GeneratedArgs, 552 Not(Contains(StrEq("-cl-unsafe-math-optimizations")))); 553 // Generated - explicitly provided. 554 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable"))); 555 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math"))); 556 // Not generated - implied by its generated parent. 557 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 558 } 559 560 TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) { 561 const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math"}; 562 563 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 564 565 ASSERT_FALSE(Diags->hasErrorOccurred()); 566 567 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 568 569 // Present options that were not implied are generated. 570 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable"))); 571 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math"))); 572 } 573 } // anonymous namespace 574