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