brintos

brintos / llvm-project-archived public Read only

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