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/Basic/TargetOptions.h" 11 #include "clang/Frontend/CompilerInstance.h" 12 #include "clang/Frontend/TextDiagnosticBuffer.h" 13 #include "clang/Lex/PreprocessorOptions.h" 14 #include "clang/Serialization/ModuleFileExtension.h" 15 #include "llvm/Support/Host.h" 16 17 #include "gmock/gmock.h" 18 #include "gtest/gtest.h" 19 20 using namespace llvm; 21 using namespace clang; 22 23 using ::testing::Contains; 24 using ::testing::HasSubstr; 25 using ::testing::StrEq; 26 27 namespace { 28 class CommandLineTest : public ::testing::Test { 29 public: 30 IntrusiveRefCntPtr<DiagnosticsEngine> Diags; 31 SmallVector<const char *, 32> GeneratedArgs; 32 SmallVector<std::string, 32> GeneratedArgsStorage; 33 CompilerInvocation Invocation; 34 35 const char *operator()(const Twine &Arg) { 36 return GeneratedArgsStorage.emplace_back(Arg.str()).c_str(); 37 } 38 39 CommandLineTest() 40 : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions(), 41 new TextDiagnosticBuffer())) { 42 } 43 }; 44 45 template <typename M> 46 std::string describeContainsN(M InnerMatcher, unsigned N, bool Negation) { 47 StringRef Contains = Negation ? "doesn't contain" : "contains"; 48 StringRef Instance = N == 1 ? " instance " : " instances "; 49 StringRef Element = "of element that "; 50 51 std::ostringstream Inner; 52 InnerMatcher.impl().DescribeTo(&Inner); 53 54 return (Contains + " exactly " + Twine(N) + Instance + Element + Inner.str()) 55 .str(); 56 } 57 58 MATCHER_P2(ContainsN, InnerMatcher, N, 59 describeContainsN(InnerMatcher, N, negation)) { 60 auto InnerMatches = [this](const auto &Element) { 61 ::testing::internal::DummyMatchResultListener InnerListener; 62 return InnerMatcher.impl().MatchAndExplain(Element, &InnerListener); 63 }; 64 65 return count_if(arg, InnerMatches) == N; 66 } 67 68 TEST(ContainsN, Empty) { 69 const char *Array[] = {""}; 70 71 ASSERT_THAT(Array, ContainsN(StrEq("x"), 0)); 72 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1))); 73 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2))); 74 } 75 76 TEST(ContainsN, Zero) { 77 const char *Array[] = {"y"}; 78 79 ASSERT_THAT(Array, ContainsN(StrEq("x"), 0)); 80 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1))); 81 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2))); 82 } 83 84 TEST(ContainsN, One) { 85 const char *Array[] = {"a", "b", "x", "z"}; 86 87 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0))); 88 ASSERT_THAT(Array, ContainsN(StrEq("x"), 1)); 89 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2))); 90 } 91 92 TEST(ContainsN, Two) { 93 const char *Array[] = {"x", "a", "b", "x"}; 94 95 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0))); 96 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1))); 97 ASSERT_THAT(Array, ContainsN(StrEq("x"), 2)); 98 } 99 100 // Copy constructor/assignment perform deep copy of reference-counted pointers. 101 102 TEST(CompilerInvocationTest, DeepCopyConstructor) { 103 CompilerInvocation A; 104 A.getAnalyzerOpts()->Config["Key"] = "Old"; 105 106 CompilerInvocation B(A); 107 B.getAnalyzerOpts()->Config["Key"] = "New"; 108 109 ASSERT_EQ(A.getAnalyzerOpts()->Config["Key"], "Old"); 110 } 111 112 TEST(CompilerInvocationTest, DeepCopyAssignment) { 113 CompilerInvocation A; 114 A.getAnalyzerOpts()->Config["Key"] = "Old"; 115 116 CompilerInvocation B; 117 B = A; 118 B.getAnalyzerOpts()->Config["Key"] = "New"; 119 120 ASSERT_EQ(A.getAnalyzerOpts()->Config["Key"], "Old"); 121 } 122 123 // Boolean option with a keypath that defaults to true. 124 // The only flag with a negative spelling can set the keypath to false. 125 126 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagNotPresent) { 127 const char *Args[] = {""}; 128 129 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 130 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary); 131 132 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 133 134 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file")))); 135 } 136 137 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagPresent) { 138 const char *Args[] = {"-fno-temp-file"}; 139 140 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 141 ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary); 142 143 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 144 145 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file"))); 146 } 147 148 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagUnknownPresent) { 149 const char *Args[] = {"-ftemp-file"}; 150 151 // Driver-only flag. 152 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 153 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary); 154 } 155 156 // Boolean option with a keypath that defaults to true. 157 // The flag with negative spelling can set the keypath to false. 158 // The flag with positive spelling can reset the keypath to true. 159 160 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNone) { 161 const char *Args[] = {""}; 162 163 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 164 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink); 165 166 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 167 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink")))); 168 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-autolink")))); 169 } 170 171 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNegChange) { 172 const char *Args[] = {"-fno-autolink"}; 173 174 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 175 ASSERT_FALSE(Invocation.getCodeGenOpts().Autolink); 176 177 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 178 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-autolink"))); 179 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink")))); 180 } 181 182 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentPosReset) { 183 const char *Args[] = {"-fautolink"}; 184 185 // Driver-only flag. 186 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 187 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink); 188 } 189 190 // Boolean option with a keypath that defaults to false. 191 // The flag with negative spelling can set the keypath to true. 192 // The flag with positive spelling can reset the keypath to false. 193 194 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNone) { 195 const char *Args[] = {""}; 196 197 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 198 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables); 199 200 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 201 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables")))); 202 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-inline-line-tables")))); 203 } 204 205 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegChange) { 206 const char *Args[] = {"-gno-inline-line-tables"}; 207 208 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 209 ASSERT_TRUE(Invocation.getCodeGenOpts().NoInlineLineTables); 210 211 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 212 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gno-inline-line-tables"))); 213 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables")))); 214 } 215 216 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosReset) { 217 const char *Args[] = {"-ginline-line-tables"}; 218 219 // Driver-only flag. 220 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 221 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables); 222 } 223 224 // Boolean option with a keypath that defaults to false. 225 // The flag with positive spelling can set the keypath to true. 226 // The flag with negative spelling can reset the keypath to false. 227 228 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNoneX) { 229 const char *Args[] = {""}; 230 231 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 232 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash); 233 234 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 235 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gcodeview-ghash")))); 236 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash")))); 237 } 238 239 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosChange) { 240 const char *Args[] = {"-gcodeview-ghash"}; 241 242 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 243 ASSERT_TRUE(Invocation.getCodeGenOpts().CodeViewGHash); 244 245 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 246 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gcodeview-ghash"))); 247 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash")))); 248 } 249 250 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegReset) { 251 const char *Args[] = {"-gno-codeview-ghash"}; 252 253 // Driver-only flag. 254 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 255 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash); 256 } 257 258 // Boolean option with a keypath that defaults to an arbitrary expression. 259 // The flag with positive spelling can set the keypath to true. 260 // The flag with negative spelling can set the keypath to false. 261 262 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentNone) { 263 const char *Args = {""}; 264 265 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 266 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false); 267 268 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 269 270 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend")))); 271 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend")))); 272 } 273 274 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentChange) { 275 const char *Args[] = {"-clear-ast-before-backend"}; 276 277 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 278 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, true); 279 280 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 281 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-clear-ast-before-backend"))); 282 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend")))); 283 } 284 285 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentReset) { 286 const char *Args[] = {"-no-clear-ast-before-backend"}; 287 288 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 289 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false); 290 291 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 292 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend")))); 293 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend")))); 294 } 295 296 // Boolean option that gets the CC1Option flag from a let statement (which 297 // is applied **after** the record is defined): 298 // 299 // let Flags = [CC1Option] in { 300 // defm option : BoolOption<...>; 301 // } 302 303 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) { 304 const char *Args[] = {""}; 305 306 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 307 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager); 308 309 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 310 311 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager")))); 312 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); 313 } 314 315 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) { 316 const char *Args[] = {"-fdebug-pass-manager"}; 317 318 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 319 ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager); 320 321 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 322 323 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fdebug-pass-manager"), 1)); 324 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); 325 } 326 327 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) { 328 const char *Args[] = {"-fno-debug-pass-manager"}; 329 330 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 331 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager); 332 333 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 334 335 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager")))); 336 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager")))); 337 } 338 339 TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) { 340 const char *Args[] = {"-fmodules-strict-context-hash"}; 341 342 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 343 344 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 345 346 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash"))); 347 } 348 349 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) { 350 const char *TripleCStr = "i686-apple-darwin9"; 351 const char *Args[] = {"-triple", TripleCStr}; 352 353 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 354 355 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 356 357 ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr))); 358 } 359 360 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredPresent) { 361 const std::string DefaultTriple = 362 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()); 363 const char *Args[] = {"-triple", DefaultTriple.c_str()}; 364 365 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 366 367 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 368 369 // Triple should always be emitted even if it is the default 370 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str()))); 371 } 372 373 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) { 374 const std::string DefaultTriple = 375 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple()); 376 const char *Args[] = {""}; 377 378 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 379 380 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 381 382 // Triple should always be emitted even if it is the default 383 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str()))); 384 } 385 386 TEST_F(CommandLineTest, SeparateEnumNonDefault) { 387 const char *Args[] = {"-mrelocation-model", "static"}; 388 389 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 390 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static); 391 392 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 393 394 // Non default relocation model. 395 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model"))); 396 ASSERT_THAT(GeneratedArgs, Contains(StrEq("static"))); 397 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static")))); 398 } 399 400 TEST_F(CommandLineTest, SeparateEnumDefault) { 401 const char *Args[] = {"-mrelocation-model", "pic"}; 402 403 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 404 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_); 405 406 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 407 408 // Default relocation model. 409 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model")))); 410 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic")))); 411 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic")))); 412 } 413 414 TEST_F(CommandLineTest, JoinedEnumNonDefault) { 415 const char *Args[] = {"-fobjc-dispatch-method=non-legacy"}; 416 417 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 418 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(), 419 CodeGenOptions::NonLegacy); 420 421 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 422 423 ASSERT_THAT(GeneratedArgs, 424 Contains(StrEq("-fobjc-dispatch-method=non-legacy"))); 425 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method=")))); 426 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy")))); 427 } 428 429 TEST_F(CommandLineTest, JoinedEnumDefault) { 430 const char *Args[] = {"-fobjc-dispatch-method=legacy"}; 431 432 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 433 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(), 434 CodeGenOptions::Legacy); 435 436 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 437 438 ASSERT_THAT(GeneratedArgs, 439 Not(Contains(StrEq("-fobjc-dispatch-method=legacy")))); 440 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method=")))); 441 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy")))); 442 } 443 444 TEST_F(CommandLineTest, StringVectorEmpty) { 445 const char *Args[] = {""}; 446 447 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 448 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles.empty()); 449 450 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 451 452 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-fmodule-map-file")))); 453 } 454 455 TEST_F(CommandLineTest, StringVectorSingle) { 456 const char *Args[] = {"-fmodule-map-file=a"}; 457 458 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 459 ASSERT_EQ(Invocation.getFrontendOpts().ModuleMapFiles, 460 std::vector<std::string>({"a"})); 461 462 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 463 464 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1)); 465 ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 1)); 466 } 467 468 TEST_F(CommandLineTest, StringVectorMultiple) { 469 const char *Args[] = {"-fmodule-map-file=a", "-fmodule-map-file=b"}; 470 471 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 472 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles == 473 std::vector<std::string>({"a", "b"})); 474 475 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 476 477 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1)); 478 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=b"), 1)); 479 ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 2)); 480 } 481 482 // CommaJoined option with MarshallingInfoStringVector. 483 484 TEST_F(CommandLineTest, StringVectorCommaJoinedNone) { 485 const char *Args[] = {""}; 486 487 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 488 ASSERT_TRUE(Invocation.getLangOpts()->CommentOpts.BlockCommandNames.empty()); 489 490 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 491 492 ASSERT_THAT(GeneratedArgs, 493 Not(Contains(HasSubstr("-fcomment-block-commands")))); 494 } 495 496 TEST_F(CommandLineTest, StringVectorCommaJoinedSingle) { 497 const char *Args[] = {"-fcomment-block-commands=x,y"}; 498 499 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 500 ASSERT_EQ(Invocation.getLangOpts()->CommentOpts.BlockCommandNames, 501 std::vector<std::string>({"x", "y"})); 502 503 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 504 505 ASSERT_THAT(GeneratedArgs, 506 ContainsN(StrEq("-fcomment-block-commands=x,y"), 1)); 507 } 508 509 TEST_F(CommandLineTest, StringVectorCommaJoinedMultiple) { 510 const char *Args[] = {"-fcomment-block-commands=x,y", 511 "-fcomment-block-commands=a,b"}; 512 513 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 514 ASSERT_EQ(Invocation.getLangOpts()->CommentOpts.BlockCommandNames, 515 std::vector<std::string>({"x", "y", "a", "b"})); 516 517 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 518 519 ASSERT_THAT(GeneratedArgs, 520 ContainsN(StrEq("-fcomment-block-commands=x,y,a,b"), 1)); 521 } 522 523 // A flag that should be parsed only if a condition is met. 524 525 TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagNotPresent) { 526 const char *Args[] = {""}; 527 528 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 529 530 ASSERT_FALSE(Diags->hasErrorOccurred()); 531 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsDevice); 532 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost); 533 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_None); 534 535 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 536 537 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl")))); 538 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std=")))); 539 } 540 541 TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagPresent) { 542 const char *Args[] = {"-sycl-std=2017"}; 543 544 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 545 546 ASSERT_FALSE(Diags->hasErrorOccurred()); 547 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsDevice); 548 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost); 549 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_None); 550 551 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 552 553 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-device")))); 554 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host")))); 555 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std=")))); 556 } 557 558 TEST_F(CommandLineTest, ConditionalParsingIfNonsenseSyclStdArg) { 559 const char *Args[] = {"-fsycl-is-device", "-sycl-std=garbage"}; 560 561 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 562 563 ASSERT_TRUE(Diags->hasErrorOccurred()); 564 ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice); 565 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost); 566 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_None); 567 568 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 569 570 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device"))); 571 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host")))); 572 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std=")))); 573 } 574 575 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg1) { 576 const char *Args[] = {"-fsycl-is-device", "-sycl-std=121"}; 577 578 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 579 580 ASSERT_FALSE(Diags->hasErrorOccurred()); 581 ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice); 582 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost); 583 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017); 584 585 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 586 587 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device"))); 588 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host")))); 589 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017"))); 590 } 591 592 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg2) { 593 const char *Args[] = {"-fsycl-is-device", "-sycl-std=1.2.1"}; 594 595 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 596 597 ASSERT_FALSE(Diags->hasErrorOccurred()); 598 ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice); 599 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost); 600 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017); 601 602 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 603 604 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device"))); 605 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host")))); 606 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017"))); 607 } 608 609 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg3) { 610 const char *Args[] = {"-fsycl-is-device", "-sycl-std=sycl-1.2.1"}; 611 612 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 613 614 ASSERT_FALSE(Diags->hasErrorOccurred()); 615 ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice); 616 ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost); 617 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017); 618 619 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 620 621 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device"))); 622 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host")))); 623 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017"))); 624 } 625 626 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentHost) { 627 const char *Args[] = {"-fsycl-is-host"}; 628 629 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 630 631 ASSERT_FALSE(Diags->hasErrorOccurred()); 632 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), 633 LangOptions::SYCL_Default); 634 635 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 636 637 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-host"))); 638 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std="))); 639 } 640 641 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentDevice) { 642 const char *Args[] = {"-fsycl-is-device"}; 643 644 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 645 646 ASSERT_FALSE(Diags->hasErrorOccurred()); 647 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), 648 LangOptions::SYCL_Default); 649 650 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 651 652 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device"))); 653 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std="))); 654 } 655 656 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagPresent) { 657 const char *Args[] = {"-fsycl-is-device", "-sycl-std=2017"}; 658 659 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 660 661 ASSERT_FALSE(Diags->hasErrorOccurred()); 662 ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017); 663 664 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 665 666 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device"))); 667 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-sycl-std=2017"))); 668 } 669 670 // Wide integer option. 671 672 TEST_F(CommandLineTest, WideIntegerHighValue) { 673 const char *Args[] = {"-fbuild-session-timestamp=1609827494445723662"}; 674 675 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags); 676 677 ASSERT_FALSE(Diags->hasErrorOccurred()); 678 ASSERT_EQ(Invocation.getHeaderSearchOpts().BuildSessionTimestamp, 679 1609827494445723662ull); 680 } 681 682 // Tree of boolean options that can be (directly or transitively) implied by 683 // their parent: 684 // 685 // * -cl-unsafe-math-optimizations 686 // * -cl-mad-enable 687 // * -menable-unsafe-fp-math 688 // * -freciprocal-math 689 690 TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) { 691 const char *Args[] = {""}; 692 693 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 694 ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath); 695 ASSERT_FALSE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 696 ASSERT_FALSE(Invocation.getLangOpts()->UnsafeFPMath); 697 ASSERT_FALSE(Invocation.getLangOpts()->AllowRecip); 698 699 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 700 701 // Not generated - missing. 702 ASSERT_THAT(GeneratedArgs, 703 Not(Contains(StrEq("-cl-unsafe-math-optimizations")))); 704 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable")))); 705 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math")))); 706 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 707 } 708 709 TEST_F(CommandLineTest, ImpliedBoolOptionsRootFlagPresent) { 710 const char *Args[] = {"-cl-unsafe-math-optimizations"}; 711 712 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 713 // Explicitly provided root flag. 714 ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath); 715 // Directly implied by explicitly provided root flag. 716 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 717 ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath); 718 // Transitively implied by explicitly provided root flag. 719 ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip); 720 721 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 722 723 // Generated - explicitly provided. 724 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations"))); 725 // Not generated - implied by the generated root flag. 726 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable")))); 727 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math")))); 728 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 729 } 730 731 TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) { 732 const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable", 733 "-menable-unsafe-fp-math", "-freciprocal-math"}; 734 735 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 736 ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath); 737 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 738 ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath); 739 ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip); 740 741 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 742 743 // Generated - explicitly provided. 744 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations"))); 745 // Not generated - implied by their generated parent. 746 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable")))); 747 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math")))); 748 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 749 } 750 751 TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) { 752 const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math", 753 "-freciprocal-math"}; 754 755 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 756 ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath); 757 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD); 758 ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath); 759 ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip); 760 761 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 762 // Not generated - missing. 763 ASSERT_THAT(GeneratedArgs, 764 Not(Contains(StrEq("-cl-unsafe-math-optimizations")))); 765 // Generated - explicitly provided. 766 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable"))); 767 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math"))); 768 // Not generated - implied by its generated parent. 769 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math")))); 770 } 771 772 TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) { 773 const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math"}; 774 775 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 776 777 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 778 779 // Present options that were not implied are generated. 780 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable"))); 781 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math"))); 782 } 783 784 // Diagnostic option. 785 786 TEST_F(CommandLineTest, DiagnosticOptionPresent) { 787 const char *Args[] = {"-verify=xyz"}; 788 789 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 790 791 ASSERT_EQ(Invocation.getDiagnosticOpts().VerifyPrefixes, 792 std::vector<std::string>({"xyz"})); 793 794 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 795 796 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-verify=xyz"), 1)); 797 } 798 799 // Option default depends on language standard. 800 801 TEST_F(CommandLineTest, DigraphsImplied) { 802 const char *Args[] = {""}; 803 804 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 805 ASSERT_TRUE(Invocation.getLangOpts()->Digraphs); 806 807 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 808 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs")))); 809 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs")))); 810 } 811 812 TEST_F(CommandLineTest, DigraphsDisabled) { 813 const char *Args[] = {"-fno-digraphs"}; 814 815 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 816 ASSERT_FALSE(Invocation.getLangOpts()->Digraphs); 817 818 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 819 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-digraphs"))); 820 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs")))); 821 } 822 823 TEST_F(CommandLineTest, DigraphsNotImplied) { 824 const char *Args[] = {"-std=c89"}; 825 826 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 827 ASSERT_FALSE(Invocation.getLangOpts()->Digraphs); 828 829 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 830 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs")))); 831 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs")))); 832 } 833 834 TEST_F(CommandLineTest, DigraphsEnabled) { 835 const char *Args[] = {"-std=c89", "-fdigraphs"}; 836 837 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 838 ASSERT_TRUE(Invocation.getLangOpts()->Digraphs); 839 840 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 841 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdigraphs"))); 842 } 843 844 struct DummyModuleFileExtension 845 : public llvm::RTTIExtends<DummyModuleFileExtension, ModuleFileExtension> { 846 static char ID; 847 848 ModuleFileExtensionMetadata getExtensionMetadata() const override { 849 return {}; 850 }; 851 852 void hashExtension(ExtensionHashBuilder &HBuilder) const override {} 853 854 std::unique_ptr<ModuleFileExtensionWriter> 855 createExtensionWriter(ASTWriter &Writer) override { 856 return {}; 857 } 858 859 std::unique_ptr<ModuleFileExtensionReader> 860 createExtensionReader(const ModuleFileExtensionMetadata &Metadata, 861 ASTReader &Reader, serialization::ModuleFile &Mod, 862 const llvm::BitstreamCursor &Stream) override { 863 return {}; 864 } 865 }; 866 867 char DummyModuleFileExtension::ID = 0; 868 869 TEST_F(CommandLineTest, TestModuleFileExtension) { 870 const char *Args[] = {"-ftest-module-file-extension=first:2:1:0:first", 871 "-ftest-module-file-extension=second:3:2:1:second"}; 872 873 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 874 ASSERT_THAT(Invocation.getFrontendOpts().ModuleFileExtensions.size(), 2); 875 876 // Exercise the check that only serializes instances of 877 // TestModuleFileExtension by providing an instance of another 878 // ModuleFileExtension subclass. 879 Invocation.getFrontendOpts().ModuleFileExtensions.push_back( 880 std::make_shared<DummyModuleFileExtension>()); 881 882 Invocation.generateCC1CommandLine(GeneratedArgs, *this); 883 884 ASSERT_THAT(GeneratedArgs, 885 ContainsN(HasSubstr("-ftest-module-file-extension="), 2)); 886 ASSERT_THAT( 887 GeneratedArgs, 888 Contains(StrEq("-ftest-module-file-extension=first:2:1:0:first"))); 889 ASSERT_THAT( 890 GeneratedArgs, 891 Contains(StrEq("-ftest-module-file-extension=second:3:2:1:second"))); 892 } 893 894 TEST_F(CommandLineTest, RoundTrip) { 895 // Testing one marshalled and one manually generated option from each 896 // CompilerInvocation member. 897 const char *Args[] = { 898 "-round-trip-args", 899 // LanguageOptions 900 "-std=c17", 901 "-fmax-tokens=10", 902 // TargetOptions 903 "-target-sdk-version=1.2.3", 904 "-meabi", 905 "4", 906 // DiagnosticOptions 907 "-Wundef-prefix=XY", 908 "-fdiagnostics-format", 909 "clang", 910 // HeaderSearchOptions 911 "-stdlib=libc++", 912 "-fimplicit-module-maps", 913 // PreprocessorOptions 914 "-DXY=AB", 915 "-include-pch", 916 "a.pch", 917 // AnalyzerOptions 918 "-analyzer-config", 919 "ctu-import-threshold=42", 920 "-unoptimized-cfg", 921 // MigratorOptions (no manually handled arguments) 922 "-no-ns-alloc-error", 923 // CodeGenOptions 924 "-debug-info-kind=limited", 925 "-debug-info-macro", 926 // DependencyOutputOptions 927 "--show-includes", 928 "-H", 929 // FileSystemOptions (no manually handled arguments) 930 "-working-directory", 931 "folder", 932 // FrontendOptions 933 "-load", 934 "plugin", 935 "-ast-merge", 936 // PreprocessorOutputOptions 937 "-dD", 938 "-CC", 939 }; 940 941 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 942 943 ASSERT_TRUE(Invocation.getLangOpts()->C17); 944 ASSERT_EQ(Invocation.getLangOpts()->MaxTokens, 10u); 945 946 ASSERT_EQ(Invocation.getTargetOpts().SDKVersion, llvm::VersionTuple(1, 2, 3)); 947 ASSERT_EQ(Invocation.getTargetOpts().EABIVersion, EABI::EABI4); 948 949 ASSERT_THAT(Invocation.getDiagnosticOpts().UndefPrefixes, 950 Contains(StrEq("XY"))); 951 ASSERT_EQ(Invocation.getDiagnosticOpts().getFormat(), 952 TextDiagnosticFormat::Clang); 953 954 ASSERT_TRUE(Invocation.getHeaderSearchOpts().UseLibcxx); 955 ASSERT_TRUE(Invocation.getHeaderSearchOpts().ImplicitModuleMaps); 956 957 ASSERT_THAT(Invocation.getPreprocessorOpts().Macros, 958 Contains(std::make_pair(std::string("XY=AB"), false))); 959 ASSERT_EQ(Invocation.getPreprocessorOpts().ImplicitPCHInclude, "a.pch"); 960 961 ASSERT_EQ(Invocation.getAnalyzerOpts()->Config["ctu-import-threshold"], "42"); 962 ASSERT_TRUE(Invocation.getAnalyzerOpts()->UnoptimizedCFG); 963 964 ASSERT_TRUE(Invocation.getMigratorOpts().NoNSAllocReallocError); 965 966 ASSERT_EQ(Invocation.getCodeGenOpts().getDebugInfo(), 967 codegenoptions::DebugInfoKind::LimitedDebugInfo); 968 ASSERT_TRUE(Invocation.getCodeGenOpts().MacroDebugInfo); 969 970 ASSERT_EQ(Invocation.getDependencyOutputOpts().ShowIncludesDest, 971 ShowIncludesDestination::Stdout); 972 ASSERT_TRUE(Invocation.getDependencyOutputOpts().ShowHeaderIncludes); 973 } 974 975 TEST_F(CommandLineTest, PluginArgsRoundTripDeterminism) { 976 const char *Args[] = { 977 "-plugin-arg-blink-gc-plugin", "no-members-in-stack-allocated", 978 "-plugin-arg-find-bad-constructs", "checked-ptr-as-trivial-member", 979 "-plugin-arg-find-bad-constructs", "check-ipc", 980 // Enable round-trip to ensure '-plugin-arg' generation is deterministic. 981 "-round-trip-args"}; 982 983 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags)); 984 } 985 } // anonymous namespace 986