Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / unittests / Frontend / CompilerInvocationTest.cpp
blob7912253b761e9ba96a565a967541f871dc4aec5e
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 //===----------------------------------------------------------------------===//
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/TargetParser/Host.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
20 using namespace llvm;
21 using namespace clang;
23 using ::testing::Contains;
24 using ::testing::HasSubstr;
25 using ::testing::StrEq;
26 using ::testing::StartsWith;
28 namespace {
29 class CommandLineTest : public ::testing::Test {
30 public:
31 IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
32 SmallVector<const char *, 32> GeneratedArgs;
33 SmallVector<std::string, 32> GeneratedArgsStorage;
34 CompilerInvocation Invocation;
36 const char *operator()(const Twine &Arg) {
37 return GeneratedArgsStorage.emplace_back(Arg.str()).c_str();
40 CommandLineTest()
41 : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions(),
42 new TextDiagnosticBuffer())) {
46 template <typename M>
47 std::string describeContainsN(M InnerMatcher, unsigned N, bool Negation) {
48 StringRef Contains = Negation ? "doesn't contain" : "contains";
49 StringRef Instance = N == 1 ? " instance " : " instances ";
50 StringRef Element = "of element that ";
52 std::ostringstream Inner;
53 InnerMatcher.impl().DescribeTo(&Inner);
55 return (Contains + " exactly " + Twine(N) + Instance + Element + Inner.str())
56 .str();
59 MATCHER_P2(ContainsN, InnerMatcher, N,
60 describeContainsN(InnerMatcher, N, negation)) {
61 auto InnerMatches = [this](const auto &Element) {
62 ::testing::internal::DummyMatchResultListener InnerListener;
63 return InnerMatcher.impl().MatchAndExplain(Element, &InnerListener);
66 return count_if(arg, InnerMatches) == N;
69 TEST(ContainsN, Empty) {
70 const char *Array[] = {""};
72 ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
73 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
74 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
77 TEST(ContainsN, Zero) {
78 const char *Array[] = {"y"};
80 ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
81 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
82 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
85 TEST(ContainsN, One) {
86 const char *Array[] = {"a", "b", "x", "z"};
88 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
89 ASSERT_THAT(Array, ContainsN(StrEq("x"), 1));
90 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
93 TEST(ContainsN, Two) {
94 const char *Array[] = {"x", "a", "b", "x"};
96 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
97 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
98 ASSERT_THAT(Array, ContainsN(StrEq("x"), 2));
101 // Copy constructor/assignment perform deep copy of reference-counted pointers.
103 TEST(CompilerInvocationTest, DeepCopyConstructor) {
104 CompilerInvocation A;
105 A.getAnalyzerOpts().Config["Key"] = "Old";
107 CompilerInvocation B(A);
108 B.getAnalyzerOpts().Config["Key"] = "New";
110 ASSERT_EQ(A.getAnalyzerOpts().Config["Key"], "Old");
113 TEST(CompilerInvocationTest, DeepCopyAssignment) {
114 CompilerInvocation A;
115 A.getAnalyzerOpts().Config["Key"] = "Old";
117 CompilerInvocation B;
118 B = A;
119 B.getAnalyzerOpts().Config["Key"] = "New";
121 ASSERT_EQ(A.getAnalyzerOpts().Config["Key"], "Old");
124 TEST(CompilerInvocationTest, CopyOnWriteConstructor) {
125 CowCompilerInvocation A;
126 A.getMutFrontendOpts().OutputFile = "x.o";
128 // B's FrontendOptions are initially shared with A.
129 CowCompilerInvocation B(A);
130 EXPECT_EQ(&A.getFrontendOpts(), &B.getFrontendOpts());
132 // Modifying A's FrontendOptions creates new copy, does not affect other opts.
133 A.getMutFrontendOpts().OutputFile = "y.o";
134 EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
135 EXPECT_EQ(&A.getCodeGenOpts(), &B.getCodeGenOpts());
137 // The new copy reflects the modification, old instance remains unchanged.
138 EXPECT_EQ(A.getFrontendOpts().OutputFile, "y.o");
139 EXPECT_EQ(B.getFrontendOpts().OutputFile, "x.o");
142 TEST(CompilerInvocationTest, CopyOnWriteAssignment) {
143 CowCompilerInvocation A;
144 A.getMutFrontendOpts().OutputFile = "x.o";
146 // B's FrontendOptions are initially independent of A.
147 CowCompilerInvocation B;
148 EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
150 // B's FrontendOptions are shared with A after assignment.
151 B = A;
152 EXPECT_EQ(&A.getFrontendOpts(), &B.getFrontendOpts());
154 // Modifying A's FrontendOptions creates new copy, does not affect other opts.
155 A.getMutFrontendOpts().OutputFile = "y.o";
156 EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
157 EXPECT_EQ(&A.getCodeGenOpts(), &B.getCodeGenOpts());
159 // The new copy reflects the modification, old instance remains unchanged.
160 EXPECT_EQ(A.getFrontendOpts().OutputFile, "y.o");
161 EXPECT_EQ(B.getFrontendOpts().OutputFile, "x.o");
164 // Boolean option with a keypath that defaults to true.
165 // The only flag with a negative spelling can set the keypath to false.
167 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagNotPresent) {
168 const char *Args[] = {""};
170 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
171 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
173 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
175 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file"))));
178 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagPresent) {
179 const char *Args[] = {"-fno-temp-file"};
181 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
182 ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary);
184 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
186 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
189 TEST_F(CommandLineTest, CC1FlagPresentWhenDoingRoundTrip) {
190 const char *Args[] = {"-cc1", "-round-trip-args"};
192 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
194 ASSERT_THAT(std::string(Invocation.getCodeGenOpts().CmdArgs.begin(),
195 Invocation.getCodeGenOpts().CmdArgs.end()),
196 StartsWith("-cc1"));
199 TEST_F(CommandLineTest, CC1FlagPresentWhenNotDoingRoundTrip) {
200 const char *Args[] = {"-cc1", "-no-round-trip-args"};
202 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
204 ASSERT_THAT(std::string(Invocation.getCodeGenOpts().CmdArgs.begin(),
205 Invocation.getCodeGenOpts().CmdArgs.end()),
206 StartsWith("-cc1"));
209 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagUnknownPresent) {
210 const char *Args[] = {"-ftemp-file"};
212 // Driver-only flag.
213 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
214 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
217 // Boolean option with a keypath that defaults to true.
218 // The flag with negative spelling can set the keypath to false.
219 // The flag with positive spelling can reset the keypath to true.
221 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNone) {
222 const char *Args[] = {""};
224 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
225 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
227 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
228 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
229 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-autolink"))));
232 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNegChange) {
233 const char *Args[] = {"-fno-autolink"};
235 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
236 ASSERT_FALSE(Invocation.getCodeGenOpts().Autolink);
238 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
239 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-autolink")));
240 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
243 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentPosReset) {
244 const char *Args[] = {"-fautolink"};
246 // Driver-only flag.
247 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
248 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
251 // Boolean option with a keypath that defaults to false.
252 // The flag with negative spelling can set the keypath to true.
253 // The flag with positive spelling can reset the keypath to false.
255 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNone) {
256 const char *Args[] = {""};
258 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
259 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
261 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
262 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
263 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-inline-line-tables"))));
266 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegChange) {
267 const char *Args[] = {"-gno-inline-line-tables"};
269 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
270 ASSERT_TRUE(Invocation.getCodeGenOpts().NoInlineLineTables);
272 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
273 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gno-inline-line-tables")));
274 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
277 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosReset) {
278 const char *Args[] = {"-ginline-line-tables"};
280 // Driver-only flag.
281 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
282 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
285 // Boolean option with a keypath that defaults to false.
286 // The flag with positive spelling can set the keypath to true.
287 // The flag with negative spelling can reset the keypath to false.
289 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNoneX) {
290 const char *Args[] = {""};
292 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
293 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
295 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
296 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gcodeview-ghash"))));
297 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
300 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosChange) {
301 const char *Args[] = {"-gcodeview-ghash"};
303 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
304 ASSERT_TRUE(Invocation.getCodeGenOpts().CodeViewGHash);
306 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
307 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gcodeview-ghash")));
308 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
311 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegReset) {
312 const char *Args[] = {"-gno-codeview-ghash"};
314 // Driver-only flag.
315 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
316 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
319 // Boolean option with a keypath that defaults to an arbitrary expression.
320 // The flag with positive spelling can set the keypath to true.
321 // The flag with negative spelling can set the keypath to false.
323 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentNone) {
324 const char *Args = {""};
326 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
327 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
329 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
331 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
332 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
335 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentChange) {
336 const char *Args[] = {"-clear-ast-before-backend"};
338 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
339 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, true);
341 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
342 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-clear-ast-before-backend")));
343 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
346 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentReset) {
347 const char *Args[] = {"-no-clear-ast-before-backend"};
349 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
350 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
352 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
353 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
354 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
357 // Boolean option that gets the CC1Option flag from a let statement (which
358 // is applied **after** the record is defined):
360 // let Flags = [CC1Option] in {
361 // defm option : BoolOption<...>;
362 // }
364 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) {
365 const char *Args[] = {""};
367 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
368 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
370 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
372 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
373 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
376 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) {
377 const char *Args[] = {"-fdebug-pass-manager"};
379 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
380 ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager);
382 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
384 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fdebug-pass-manager"), 1));
385 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
388 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) {
389 const char *Args[] = {"-fno-debug-pass-manager"};
391 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
392 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
394 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
396 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
397 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
400 TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) {
401 const char *Args[] = {"-fmodules-strict-context-hash"};
403 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
405 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
407 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash")));
410 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) {
411 const char *TripleCStr = "i686-apple-darwin9";
412 const char *Args[] = {"-triple", TripleCStr};
414 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
416 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
418 ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
421 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredPresent) {
422 const std::string DefaultTriple =
423 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
424 const char *Args[] = {"-triple", DefaultTriple.c_str()};
426 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
428 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
430 // Triple should always be emitted even if it is the default
431 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
434 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
435 const std::string DefaultTriple =
436 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
437 const char *Args[] = {""};
439 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
441 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
443 // Triple should always be emitted even if it is the default
444 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
447 TEST_F(CommandLineTest, SeparateEnumNonDefault) {
448 const char *Args[] = {"-mrelocation-model", "static"};
450 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
451 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static);
453 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
455 // Non default relocation model.
456 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model")));
457 ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
458 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static"))));
461 TEST_F(CommandLineTest, SeparateEnumDefault) {
462 const char *Args[] = {"-mrelocation-model", "pic"};
464 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
465 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_);
467 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
469 // Default relocation model.
470 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model"))));
471 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
472 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic"))));
475 TEST_F(CommandLineTest, JoinedEnumNonDefault) {
476 const char *Args[] = {"-fobjc-dispatch-method=non-legacy"};
478 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
479 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
480 CodeGenOptions::NonLegacy);
482 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
484 ASSERT_THAT(GeneratedArgs,
485 Contains(StrEq("-fobjc-dispatch-method=non-legacy")));
486 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
487 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy"))));
490 TEST_F(CommandLineTest, JoinedEnumDefault) {
491 const char *Args[] = {"-fobjc-dispatch-method=legacy"};
493 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
494 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
495 CodeGenOptions::Legacy);
497 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
499 ASSERT_THAT(GeneratedArgs,
500 Not(Contains(StrEq("-fobjc-dispatch-method=legacy"))));
501 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
502 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy"))));
505 TEST_F(CommandLineTest, StringVectorEmpty) {
506 const char *Args[] = {""};
508 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
509 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles.empty());
511 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
513 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-fmodule-map-file"))));
516 TEST_F(CommandLineTest, StringVectorSingle) {
517 const char *Args[] = {"-fmodule-map-file=a"};
519 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
520 ASSERT_EQ(Invocation.getFrontendOpts().ModuleMapFiles,
521 std::vector<std::string>({"a"}));
523 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
525 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
526 ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 1));
529 TEST_F(CommandLineTest, StringVectorMultiple) {
530 const char *Args[] = {"-fmodule-map-file=a", "-fmodule-map-file=b"};
532 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
533 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles ==
534 std::vector<std::string>({"a", "b"}));
536 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
538 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
539 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=b"), 1));
540 ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 2));
543 // CommaJoined option with MarshallingInfoStringVector.
545 TEST_F(CommandLineTest, StringVectorCommaJoinedNone) {
546 const char *Args[] = {""};
548 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
549 ASSERT_TRUE(Invocation.getLangOpts().CommentOpts.BlockCommandNames.empty());
551 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
553 ASSERT_THAT(GeneratedArgs,
554 Not(Contains(HasSubstr("-fcomment-block-commands"))));
557 TEST_F(CommandLineTest, StringVectorCommaJoinedSingle) {
558 const char *Args[] = {"-fcomment-block-commands=x,y"};
560 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
561 ASSERT_EQ(Invocation.getLangOpts().CommentOpts.BlockCommandNames,
562 std::vector<std::string>({"x", "y"}));
564 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
566 ASSERT_THAT(GeneratedArgs,
567 ContainsN(StrEq("-fcomment-block-commands=x,y"), 1));
570 TEST_F(CommandLineTest, StringVectorCommaJoinedMultiple) {
571 const char *Args[] = {"-fcomment-block-commands=x,y",
572 "-fcomment-block-commands=a,b"};
574 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
575 ASSERT_EQ(Invocation.getLangOpts().CommentOpts.BlockCommandNames,
576 std::vector<std::string>({"x", "y", "a", "b"}));
578 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
580 ASSERT_THAT(GeneratedArgs,
581 ContainsN(StrEq("-fcomment-block-commands=x,y,a,b"), 1));
584 // A flag that should be parsed only if a condition is met.
586 TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagNotPresent) {
587 const char *Args[] = {""};
589 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
591 ASSERT_FALSE(Diags->hasErrorOccurred());
592 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsDevice);
593 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
594 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
596 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
598 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl"))));
599 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
602 TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagPresent) {
603 const char *Args[] = {"-sycl-std=2017"};
605 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
607 ASSERT_FALSE(Diags->hasErrorOccurred());
608 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsDevice);
609 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
610 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
612 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
614 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-device"))));
615 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
616 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
619 TEST_F(CommandLineTest, ConditionalParsingIfNonsenseSyclStdArg) {
620 const char *Args[] = {"-fsycl-is-device", "-sycl-std=garbage"};
622 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
624 ASSERT_TRUE(Diags->hasErrorOccurred());
625 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
626 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
627 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
629 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
631 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
632 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
633 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
636 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg1) {
637 const char *Args[] = {"-fsycl-is-device", "-sycl-std=121"};
639 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
641 ASSERT_FALSE(Diags->hasErrorOccurred());
642 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
643 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
644 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
646 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
648 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
649 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
650 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
653 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg2) {
654 const char *Args[] = {"-fsycl-is-device", "-sycl-std=1.2.1"};
656 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
658 ASSERT_FALSE(Diags->hasErrorOccurred());
659 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
660 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
661 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
663 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
665 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
666 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
667 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
670 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg3) {
671 const char *Args[] = {"-fsycl-is-device", "-sycl-std=sycl-1.2.1"};
673 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
675 ASSERT_FALSE(Diags->hasErrorOccurred());
676 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
677 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
678 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
680 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
682 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
683 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
684 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
687 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentHost) {
688 const char *Args[] = {"-fsycl-is-host"};
690 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
692 ASSERT_FALSE(Diags->hasErrorOccurred());
693 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(),
694 LangOptions::SYCL_Default);
696 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
698 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-host")));
699 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
702 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentDevice) {
703 const char *Args[] = {"-fsycl-is-device"};
705 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
707 ASSERT_FALSE(Diags->hasErrorOccurred());
708 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(),
709 LangOptions::SYCL_Default);
711 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
713 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
714 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
717 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagPresent) {
718 const char *Args[] = {"-fsycl-is-device", "-sycl-std=2017"};
720 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
722 ASSERT_FALSE(Diags->hasErrorOccurred());
723 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
725 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
727 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
728 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-sycl-std=2017")));
731 // Wide integer option.
733 TEST_F(CommandLineTest, WideIntegerHighValue) {
734 const char *Args[] = {"-fbuild-session-timestamp=1609827494445723662"};
736 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
738 ASSERT_FALSE(Diags->hasErrorOccurred());
739 ASSERT_EQ(Invocation.getHeaderSearchOpts().BuildSessionTimestamp,
740 1609827494445723662ull);
743 // Tree of boolean options that can be (directly or transitively) implied by
744 // their parent:
746 // * -cl-unsafe-math-optimizations
747 // * -cl-mad-enable
748 // * -funsafe-math-optimizations
749 // * -freciprocal-math
751 TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) {
752 const char *Args[] = {""};
754 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
755 ASSERT_FALSE(Invocation.getLangOpts().CLUnsafeMath);
756 ASSERT_FALSE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
757 ASSERT_FALSE(Invocation.getLangOpts().UnsafeFPMath);
758 ASSERT_FALSE(Invocation.getLangOpts().AllowRecip);
760 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
762 // Not generated - missing.
763 ASSERT_THAT(GeneratedArgs,
764 Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
765 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
766 ASSERT_THAT(GeneratedArgs,
767 Not(Contains(StrEq("-funsafe-math-optimizations"))));
768 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
771 TEST_F(CommandLineTest, ImpliedBoolOptionsRootFlagPresent) {
772 const char *Args[] = {"-cl-unsafe-math-optimizations"};
774 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
775 // Explicitly provided root flag.
776 ASSERT_TRUE(Invocation.getLangOpts().CLUnsafeMath);
777 // Directly implied by explicitly provided root flag.
778 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
779 ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
780 // Transitively implied by explicitly provided root flag.
781 ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
783 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
785 // Generated - explicitly provided.
786 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
787 // Not generated - implied by the generated root flag.
788 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
789 ASSERT_THAT(GeneratedArgs,
790 Not(Contains(StrEq("-funsafe-math-optimizations"))));
791 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
794 TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) {
795 const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable",
796 "-funsafe-math-optimizations", "-freciprocal-math"};
798 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
799 ASSERT_TRUE(Invocation.getLangOpts().CLUnsafeMath);
800 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
801 ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
802 ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
804 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
806 // Generated - explicitly provided.
807 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
808 // Not generated - implied by their generated parent.
809 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
810 ASSERT_THAT(GeneratedArgs,
811 Not(Contains(StrEq("-funsafe-math-optimizations"))));
812 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
815 TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) {
816 const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations",
817 "-freciprocal-math"};
819 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
820 ASSERT_FALSE(Invocation.getLangOpts().CLUnsafeMath);
821 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
822 ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
823 ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
825 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
826 // Not generated - missing.
827 ASSERT_THAT(GeneratedArgs,
828 Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
829 // Generated - explicitly provided.
830 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
831 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
832 // Not generated - implied by its generated parent.
833 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
836 TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
837 const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations"};
839 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
841 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
843 // Present options that were not implied are generated.
844 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
845 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
848 // Diagnostic option.
850 TEST_F(CommandLineTest, DiagnosticOptionPresent) {
851 const char *Args[] = {"-verify=xyz"};
853 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
855 ASSERT_EQ(Invocation.getDiagnosticOpts().VerifyPrefixes,
856 std::vector<std::string>({"xyz"}));
858 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
860 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-verify=xyz"), 1));
863 // Option default depends on language standard.
865 TEST_F(CommandLineTest, DigraphsImplied) {
866 const char *Args[] = {""};
868 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
869 ASSERT_TRUE(Invocation.getLangOpts().Digraphs);
871 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
872 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
873 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
876 TEST_F(CommandLineTest, DigraphsDisabled) {
877 const char *Args[] = {"-fno-digraphs"};
879 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
880 ASSERT_FALSE(Invocation.getLangOpts().Digraphs);
882 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
883 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-digraphs")));
884 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
887 TEST_F(CommandLineTest, DigraphsNotImplied) {
888 const char *Args[] = {"-std=c89"};
890 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
891 ASSERT_FALSE(Invocation.getLangOpts().Digraphs);
893 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
894 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
895 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
898 TEST_F(CommandLineTest, DigraphsEnabled) {
899 const char *Args[] = {"-std=c89", "-fdigraphs"};
901 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
902 ASSERT_TRUE(Invocation.getLangOpts().Digraphs);
904 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
905 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdigraphs")));
908 struct DummyModuleFileExtension
909 : public llvm::RTTIExtends<DummyModuleFileExtension, ModuleFileExtension> {
910 static char ID;
912 ModuleFileExtensionMetadata getExtensionMetadata() const override {
913 return {};
916 void hashExtension(ExtensionHashBuilder &HBuilder) const override {}
918 std::unique_ptr<ModuleFileExtensionWriter>
919 createExtensionWriter(ASTWriter &Writer) override {
920 return {};
923 std::unique_ptr<ModuleFileExtensionReader>
924 createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
925 ASTReader &Reader, serialization::ModuleFile &Mod,
926 const llvm::BitstreamCursor &Stream) override {
927 return {};
931 char DummyModuleFileExtension::ID = 0;
933 TEST_F(CommandLineTest, TestModuleFileExtension) {
934 const char *Args[] = {"-ftest-module-file-extension=first:2:1:0:first",
935 "-ftest-module-file-extension=second:3:2:1:second"};
937 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
938 ASSERT_THAT(Invocation.getFrontendOpts().ModuleFileExtensions.size(), 2);
940 // Exercise the check that only serializes instances of
941 // TestModuleFileExtension by providing an instance of another
942 // ModuleFileExtension subclass.
943 Invocation.getFrontendOpts().ModuleFileExtensions.push_back(
944 std::make_shared<DummyModuleFileExtension>());
946 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
948 ASSERT_THAT(GeneratedArgs,
949 ContainsN(HasSubstr("-ftest-module-file-extension="), 2));
950 ASSERT_THAT(
951 GeneratedArgs,
952 Contains(StrEq("-ftest-module-file-extension=first:2:1:0:first")));
953 ASSERT_THAT(
954 GeneratedArgs,
955 Contains(StrEq("-ftest-module-file-extension=second:3:2:1:second")));
958 TEST_F(CommandLineTest, RoundTrip) {
959 // Testing one marshalled and one manually generated option from each
960 // CompilerInvocation member.
961 const char *Args[] = {
962 "-round-trip-args",
963 // LanguageOptions
964 "-std=c17",
965 "-fmax-tokens=10",
966 // TargetOptions
967 "-target-sdk-version=1.2.3",
968 "-meabi",
969 "4",
970 // DiagnosticOptions
971 "-Wundef-prefix=XY",
972 "-fdiagnostics-format",
973 "clang",
974 // HeaderSearchOptions
975 "-stdlib=libc++",
976 "-fimplicit-module-maps",
977 // PreprocessorOptions
978 "-DXY=AB",
979 "-include-pch",
980 "a.pch",
981 // AnalyzerOptions
982 "-analyzer-config",
983 "ctu-import-threshold=42",
984 "-unoptimized-cfg",
985 // MigratorOptions (no manually handled arguments)
986 "-no-ns-alloc-error",
987 // CodeGenOptions
988 "-debug-info-kind=limited",
989 "-debug-info-macro",
990 // DependencyOutputOptions
991 "--show-includes",
992 "-H",
993 // FileSystemOptions (no manually handled arguments)
994 "-working-directory",
995 "folder",
996 // FrontendOptions
997 "-load",
998 "plugin",
999 "-ast-merge",
1000 // PreprocessorOutputOptions
1001 "-dD",
1002 "-CC",
1005 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1007 ASSERT_TRUE(Invocation.getLangOpts().C17);
1008 ASSERT_EQ(Invocation.getLangOpts().MaxTokens, 10u);
1010 ASSERT_EQ(Invocation.getTargetOpts().SDKVersion, llvm::VersionTuple(1, 2, 3));
1011 ASSERT_EQ(Invocation.getTargetOpts().EABIVersion, EABI::EABI4);
1013 ASSERT_THAT(Invocation.getDiagnosticOpts().UndefPrefixes,
1014 Contains(StrEq("XY")));
1015 ASSERT_EQ(Invocation.getDiagnosticOpts().getFormat(),
1016 TextDiagnosticFormat::Clang);
1018 ASSERT_TRUE(Invocation.getHeaderSearchOpts().UseLibcxx);
1019 ASSERT_TRUE(Invocation.getHeaderSearchOpts().ImplicitModuleMaps);
1021 ASSERT_THAT(Invocation.getPreprocessorOpts().Macros,
1022 Contains(std::make_pair(std::string("XY=AB"), false)));
1023 ASSERT_EQ(Invocation.getPreprocessorOpts().ImplicitPCHInclude, "a.pch");
1025 ASSERT_EQ(Invocation.getAnalyzerOpts().Config["ctu-import-threshold"], "42");
1026 ASSERT_TRUE(Invocation.getAnalyzerOpts().UnoptimizedCFG);
1028 ASSERT_TRUE(Invocation.getMigratorOpts().NoNSAllocReallocError);
1030 ASSERT_EQ(Invocation.getCodeGenOpts().getDebugInfo(),
1031 codegenoptions::DebugInfoKind::LimitedDebugInfo);
1032 ASSERT_TRUE(Invocation.getCodeGenOpts().MacroDebugInfo);
1034 ASSERT_EQ(Invocation.getDependencyOutputOpts().ShowIncludesDest,
1035 ShowIncludesDestination::Stdout);
1036 ASSERT_TRUE(Invocation.getDependencyOutputOpts().ShowHeaderIncludes);
1039 TEST_F(CommandLineTest, PluginArgsRoundTripDeterminism) {
1040 const char *Args[] = {
1041 "-plugin-arg-blink-gc-plugin", "no-members-in-stack-allocated",
1042 "-plugin-arg-find-bad-constructs", "checked-ptr-as-trivial-member",
1043 "-plugin-arg-find-bad-constructs", "check-ipc",
1044 // Enable round-trip to ensure '-plugin-arg' generation is deterministic.
1045 "-round-trip-args"};
1047 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1049 } // anonymous namespace