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