[AMDGPU] Infer amdgpu-no-flat-scratch-init attribute in AMDGPUAttributor (#94647)
[llvm-project.git] / clang / unittests / Frontend / CompilerInvocationTest.cpp
blob4ff6824f1e21e3d274c60750185855f1c9160496
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/Support/VirtualFileSystem.h"
16 #include "llvm/TargetParser/Host.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
21 using namespace llvm;
22 using namespace clang;
24 using ::testing::Contains;
25 using ::testing::HasSubstr;
26 using ::testing::StrEq;
27 using ::testing::StartsWith;
29 namespace {
30 class CommandLineTest : public ::testing::Test {
31 public:
32 IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
33 SmallVector<const char *, 32> GeneratedArgs;
34 SmallVector<std::string, 32> GeneratedArgsStorage;
35 CompilerInvocation Invocation;
37 const char *operator()(const Twine &Arg) {
38 return GeneratedArgsStorage.emplace_back(Arg.str()).c_str();
41 CommandLineTest()
42 : Diags(CompilerInstance::createDiagnostics(
43 *llvm::vfs::getRealFileSystem(), new DiagnosticOptions(),
44 new TextDiagnosticBuffer())) {}
47 template <typename M>
48 std::string describeContainsN(M InnerMatcher, unsigned N, bool Negation) {
49 StringRef Contains = Negation ? "doesn't contain" : "contains";
50 StringRef Instance = N == 1 ? " instance " : " instances ";
51 StringRef Element = "of element that ";
53 std::ostringstream Inner;
54 InnerMatcher.impl().DescribeTo(&Inner);
56 return (Contains + " exactly " + Twine(N) + Instance + Element + Inner.str())
57 .str();
60 MATCHER_P2(ContainsN, InnerMatcher, N,
61 describeContainsN(InnerMatcher, N, negation)) {
62 auto InnerMatches = [this](const auto &Element) {
63 ::testing::internal::DummyMatchResultListener InnerListener;
64 return InnerMatcher.impl().MatchAndExplain(Element, &InnerListener);
67 return count_if(arg, InnerMatches) == N;
70 TEST(ContainsN, Empty) {
71 const char *Array[] = {""};
73 ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
74 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
75 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
78 TEST(ContainsN, Zero) {
79 const char *Array[] = {"y"};
81 ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
82 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
83 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
86 TEST(ContainsN, One) {
87 const char *Array[] = {"a", "b", "x", "z"};
89 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
90 ASSERT_THAT(Array, ContainsN(StrEq("x"), 1));
91 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
94 TEST(ContainsN, Two) {
95 const char *Array[] = {"x", "a", "b", "x"};
97 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
98 ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
99 ASSERT_THAT(Array, ContainsN(StrEq("x"), 2));
102 // Copy constructor/assignment perform deep copy of reference-counted pointers.
104 TEST(CompilerInvocationTest, DeepCopyConstructor) {
105 CompilerInvocation A;
106 A.getAnalyzerOpts().Config["Key"] = "Old";
108 CompilerInvocation B(A);
109 B.getAnalyzerOpts().Config["Key"] = "New";
111 ASSERT_EQ(A.getAnalyzerOpts().Config["Key"], "Old");
114 TEST(CompilerInvocationTest, DeepCopyAssignment) {
115 CompilerInvocation A;
116 A.getAnalyzerOpts().Config["Key"] = "Old";
118 CompilerInvocation B;
119 B = A;
120 B.getAnalyzerOpts().Config["Key"] = "New";
122 ASSERT_EQ(A.getAnalyzerOpts().Config["Key"], "Old");
125 TEST(CompilerInvocationTest, CopyOnWriteConstructor) {
126 CowCompilerInvocation A;
127 A.getMutFrontendOpts().OutputFile = "x.o";
129 // B's FrontendOptions are initially shared with A.
130 CowCompilerInvocation B(A);
131 EXPECT_EQ(&A.getFrontendOpts(), &B.getFrontendOpts());
133 // Modifying A's FrontendOptions creates new copy, does not affect other opts.
134 A.getMutFrontendOpts().OutputFile = "y.o";
135 EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
136 EXPECT_EQ(&A.getCodeGenOpts(), &B.getCodeGenOpts());
138 // The new copy reflects the modification, old instance remains unchanged.
139 EXPECT_EQ(A.getFrontendOpts().OutputFile, "y.o");
140 EXPECT_EQ(B.getFrontendOpts().OutputFile, "x.o");
143 TEST(CompilerInvocationTest, CopyOnWriteAssignment) {
144 CowCompilerInvocation A;
145 A.getMutFrontendOpts().OutputFile = "x.o";
147 // B's FrontendOptions are initially independent of A.
148 CowCompilerInvocation B;
149 EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
151 // B's FrontendOptions are shared with A after assignment.
152 B = A;
153 EXPECT_EQ(&A.getFrontendOpts(), &B.getFrontendOpts());
155 // Modifying A's FrontendOptions creates new copy, does not affect other opts.
156 A.getMutFrontendOpts().OutputFile = "y.o";
157 EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
158 EXPECT_EQ(&A.getCodeGenOpts(), &B.getCodeGenOpts());
160 // The new copy reflects the modification, old instance remains unchanged.
161 EXPECT_EQ(A.getFrontendOpts().OutputFile, "y.o");
162 EXPECT_EQ(B.getFrontendOpts().OutputFile, "x.o");
165 // Boolean option with a keypath that defaults to true.
166 // The only flag with a negative spelling can set the keypath to false.
168 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagNotPresent) {
169 const char *Args[] = {""};
171 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
172 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
174 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
176 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file"))));
179 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagPresent) {
180 const char *Args[] = {"-fno-temp-file"};
182 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
183 ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary);
185 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
187 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
190 TEST_F(CommandLineTest, CC1FlagPresentWhenDoingRoundTrip) {
191 const char *Args[] = {"-cc1", "-round-trip-args"};
193 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
195 ASSERT_THAT(std::string(Invocation.getCodeGenOpts().CmdArgs.begin(),
196 Invocation.getCodeGenOpts().CmdArgs.end()),
197 StartsWith("-cc1"));
200 TEST_F(CommandLineTest, CC1FlagPresentWhenNotDoingRoundTrip) {
201 const char *Args[] = {"-cc1", "-no-round-trip-args"};
203 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
205 ASSERT_THAT(std::string(Invocation.getCodeGenOpts().CmdArgs.begin(),
206 Invocation.getCodeGenOpts().CmdArgs.end()),
207 StartsWith("-cc1"));
210 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagUnknownPresent) {
211 const char *Args[] = {"-ftemp-file"};
213 // Driver-only flag.
214 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
215 ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
218 // Boolean option with a keypath that defaults to true.
219 // The flag with negative spelling can set the keypath to false.
220 // The flag with positive spelling can reset the keypath to true.
222 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNone) {
223 const char *Args[] = {""};
225 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
226 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
228 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
229 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
230 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-autolink"))));
233 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNegChange) {
234 const char *Args[] = {"-fno-autolink"};
236 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
237 ASSERT_FALSE(Invocation.getCodeGenOpts().Autolink);
239 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
240 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-autolink")));
241 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
244 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentPosReset) {
245 const char *Args[] = {"-fautolink"};
247 // Driver-only flag.
248 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
249 ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
252 // Boolean option with a keypath that defaults to false.
253 // The flag with negative spelling can set the keypath to true.
254 // The flag with positive spelling can reset the keypath to false.
256 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNone) {
257 const char *Args[] = {""};
259 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
260 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
262 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
263 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
264 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-inline-line-tables"))));
267 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegChange) {
268 const char *Args[] = {"-gno-inline-line-tables"};
270 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
271 ASSERT_TRUE(Invocation.getCodeGenOpts().NoInlineLineTables);
273 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
274 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gno-inline-line-tables")));
275 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
278 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosReset) {
279 const char *Args[] = {"-ginline-line-tables"};
281 // Driver-only flag.
282 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
283 ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
286 // Boolean option with a keypath that defaults to false.
287 // The flag with positive spelling can set the keypath to true.
288 // The flag with negative spelling can reset the keypath to false.
290 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNoneX) {
291 const char *Args[] = {""};
293 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
294 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
296 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
297 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gcodeview-ghash"))));
298 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
301 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosChange) {
302 const char *Args[] = {"-gcodeview-ghash"};
304 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
305 ASSERT_TRUE(Invocation.getCodeGenOpts().CodeViewGHash);
307 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
308 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gcodeview-ghash")));
309 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
312 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegReset) {
313 const char *Args[] = {"-gno-codeview-ghash"};
315 // Driver-only flag.
316 ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
317 ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
320 // Boolean option with a keypath that defaults to an arbitrary expression.
321 // The flag with positive spelling can set the keypath to true.
322 // The flag with negative spelling can set the keypath to false.
324 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentNone) {
325 const char *Args = {""};
327 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
328 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
330 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
332 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
333 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
336 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentChange) {
337 const char *Args[] = {"-clear-ast-before-backend"};
339 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
340 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, true);
342 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
343 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-clear-ast-before-backend")));
344 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
347 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentReset) {
348 const char *Args[] = {"-no-clear-ast-before-backend"};
350 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
351 ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
353 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
354 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
355 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
358 // Boolean option that gets the CC1Option flag from a let statement (which
359 // is applied **after** the record is defined):
361 // let Flags = [CC1Option] in {
362 // defm option : BoolOption<...>;
363 // }
365 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) {
366 const char *Args[] = {""};
368 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
369 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
371 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
373 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
374 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
377 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) {
378 const char *Args[] = {"-fdebug-pass-manager"};
380 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
381 ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager);
383 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
385 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fdebug-pass-manager"), 1));
386 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
389 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) {
390 const char *Args[] = {"-fno-debug-pass-manager"};
392 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
393 ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
395 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
397 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
398 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
401 TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) {
402 const char *Args[] = {"-fmodules-strict-context-hash"};
404 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
406 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
408 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash")));
411 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) {
412 const char *TripleCStr = "i686-apple-darwin9";
413 const char *Args[] = {"-triple", TripleCStr};
415 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
417 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
419 ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
422 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredPresent) {
423 const std::string DefaultTriple =
424 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
425 const char *Args[] = {"-triple", DefaultTriple.c_str()};
427 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
429 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
431 // Triple should always be emitted even if it is the default
432 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
435 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
436 const std::string DefaultTriple =
437 llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
438 const char *Args[] = {""};
440 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
442 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
444 // Triple should always be emitted even if it is the default
445 ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
448 TEST_F(CommandLineTest, SeparateEnumNonDefault) {
449 const char *Args[] = {"-mrelocation-model", "static"};
451 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
452 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static);
454 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
456 // Non default relocation model.
457 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model")));
458 ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
459 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static"))));
462 TEST_F(CommandLineTest, SeparateEnumDefault) {
463 const char *Args[] = {"-mrelocation-model", "pic"};
465 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
466 ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_);
468 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
470 // Default relocation model.
471 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model"))));
472 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
473 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic"))));
476 TEST_F(CommandLineTest, JoinedEnumNonDefault) {
477 const char *Args[] = {"-fobjc-dispatch-method=non-legacy"};
479 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
480 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
481 CodeGenOptions::NonLegacy);
483 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
485 ASSERT_THAT(GeneratedArgs,
486 Contains(StrEq("-fobjc-dispatch-method=non-legacy")));
487 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
488 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy"))));
491 TEST_F(CommandLineTest, JoinedEnumDefault) {
492 const char *Args[] = {"-fobjc-dispatch-method=legacy"};
494 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
495 ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
496 CodeGenOptions::Legacy);
498 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
500 ASSERT_THAT(GeneratedArgs,
501 Not(Contains(StrEq("-fobjc-dispatch-method=legacy"))));
502 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
503 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy"))));
506 TEST_F(CommandLineTest, StringVectorEmpty) {
507 const char *Args[] = {""};
509 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
510 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles.empty());
512 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
514 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-fmodule-map-file"))));
517 TEST_F(CommandLineTest, StringVectorSingle) {
518 const char *Args[] = {"-fmodule-map-file=a"};
520 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
521 ASSERT_EQ(Invocation.getFrontendOpts().ModuleMapFiles,
522 std::vector<std::string>({"a"}));
524 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
526 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
527 ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 1));
530 TEST_F(CommandLineTest, StringVectorMultiple) {
531 const char *Args[] = {"-fmodule-map-file=a", "-fmodule-map-file=b"};
533 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
534 ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles ==
535 std::vector<std::string>({"a", "b"}));
537 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
539 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
540 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=b"), 1));
541 ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 2));
544 // CommaJoined option with MarshallingInfoStringVector.
546 TEST_F(CommandLineTest, StringVectorCommaJoinedNone) {
547 const char *Args[] = {""};
549 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
550 ASSERT_TRUE(Invocation.getLangOpts().CommentOpts.BlockCommandNames.empty());
552 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
554 ASSERT_THAT(GeneratedArgs,
555 Not(Contains(HasSubstr("-fcomment-block-commands"))));
558 TEST_F(CommandLineTest, StringVectorCommaJoinedSingle) {
559 const char *Args[] = {"-fcomment-block-commands=x,y"};
561 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
562 ASSERT_EQ(Invocation.getLangOpts().CommentOpts.BlockCommandNames,
563 std::vector<std::string>({"x", "y"}));
565 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
567 ASSERT_THAT(GeneratedArgs,
568 ContainsN(StrEq("-fcomment-block-commands=x,y"), 1));
571 TEST_F(CommandLineTest, StringVectorCommaJoinedMultiple) {
572 const char *Args[] = {"-fcomment-block-commands=x,y",
573 "-fcomment-block-commands=a,b"};
575 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
576 ASSERT_EQ(Invocation.getLangOpts().CommentOpts.BlockCommandNames,
577 std::vector<std::string>({"x", "y", "a", "b"}));
579 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
581 ASSERT_THAT(GeneratedArgs,
582 ContainsN(StrEq("-fcomment-block-commands=x,y,a,b"), 1));
585 // A flag that should be parsed only if a condition is met.
587 TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagNotPresent) {
588 const char *Args[] = {""};
590 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
592 ASSERT_FALSE(Diags->hasErrorOccurred());
593 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsDevice);
594 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
595 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
597 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
599 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl"))));
600 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
603 TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagPresent) {
604 const char *Args[] = {"-sycl-std=2017"};
606 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
608 ASSERT_FALSE(Diags->hasErrorOccurred());
609 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsDevice);
610 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
611 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
613 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
615 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-device"))));
616 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
617 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
620 TEST_F(CommandLineTest, ConditionalParsingIfNonsenseSyclStdArg) {
621 const char *Args[] = {"-fsycl-is-device", "-sycl-std=garbage"};
623 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
625 ASSERT_TRUE(Diags->hasErrorOccurred());
626 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
627 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
628 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
630 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
632 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
633 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
634 ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
637 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg1) {
638 const char *Args[] = {"-fsycl-is-device", "-sycl-std=121"};
640 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
642 ASSERT_FALSE(Diags->hasErrorOccurred());
643 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
644 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
645 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
647 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
649 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
650 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
651 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
654 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg2) {
655 const char *Args[] = {"-fsycl-is-device", "-sycl-std=1.2.1"};
657 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
659 ASSERT_FALSE(Diags->hasErrorOccurred());
660 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
661 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
662 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
664 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
666 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
667 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
668 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
671 TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg3) {
672 const char *Args[] = {"-fsycl-is-device", "-sycl-std=sycl-1.2.1"};
674 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
676 ASSERT_FALSE(Diags->hasErrorOccurred());
677 ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
678 ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
679 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
681 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
683 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
684 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
685 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
688 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentHost) {
689 const char *Args[] = {"-fsycl-is-host"};
691 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
693 ASSERT_FALSE(Diags->hasErrorOccurred());
694 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(),
695 LangOptions::SYCL_Default);
697 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
699 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-host")));
700 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
703 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentDevice) {
704 const char *Args[] = {"-fsycl-is-device"};
706 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
708 ASSERT_FALSE(Diags->hasErrorOccurred());
709 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(),
710 LangOptions::SYCL_Default);
712 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
714 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
715 ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
718 TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagPresent) {
719 const char *Args[] = {"-fsycl-is-device", "-sycl-std=2017"};
721 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
723 ASSERT_FALSE(Diags->hasErrorOccurred());
724 ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
726 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
728 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
729 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-sycl-std=2017")));
732 // Wide integer option.
734 TEST_F(CommandLineTest, WideIntegerHighValue) {
735 const char *Args[] = {"-fbuild-session-timestamp=1609827494445723662"};
737 CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
739 ASSERT_FALSE(Diags->hasErrorOccurred());
740 ASSERT_EQ(Invocation.getHeaderSearchOpts().BuildSessionTimestamp,
741 1609827494445723662ull);
744 // Tree of boolean options that can be (directly or transitively) implied by
745 // their parent:
747 // * -cl-unsafe-math-optimizations
748 // * -cl-mad-enable
749 // * -funsafe-math-optimizations
750 // * -freciprocal-math
752 TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) {
753 const char *Args[] = {""};
755 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
756 ASSERT_FALSE(Invocation.getLangOpts().CLUnsafeMath);
757 ASSERT_FALSE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
758 ASSERT_FALSE(Invocation.getLangOpts().UnsafeFPMath);
759 ASSERT_FALSE(Invocation.getLangOpts().AllowRecip);
761 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
763 // Not generated - missing.
764 ASSERT_THAT(GeneratedArgs,
765 Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
766 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
767 ASSERT_THAT(GeneratedArgs,
768 Not(Contains(StrEq("-funsafe-math-optimizations"))));
769 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
772 TEST_F(CommandLineTest, ImpliedBoolOptionsRootFlagPresent) {
773 const char *Args[] = {"-cl-unsafe-math-optimizations"};
775 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
776 // Explicitly provided root flag.
777 ASSERT_TRUE(Invocation.getLangOpts().CLUnsafeMath);
778 // Directly implied by explicitly provided root flag.
779 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
780 ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
781 // Transitively implied by explicitly provided root flag.
782 ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
784 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
786 // Generated - explicitly provided.
787 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
788 // Not generated - implied by the generated root flag.
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"))));
795 TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) {
796 const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable",
797 "-funsafe-math-optimizations", "-freciprocal-math"};
799 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
800 ASSERT_TRUE(Invocation.getLangOpts().CLUnsafeMath);
801 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
802 ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
803 ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
805 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
807 // Generated - explicitly provided.
808 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
809 // Not generated - implied by their generated parent.
810 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
811 ASSERT_THAT(GeneratedArgs,
812 Not(Contains(StrEq("-funsafe-math-optimizations"))));
813 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
816 TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) {
817 const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations",
818 "-freciprocal-math"};
820 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
821 ASSERT_FALSE(Invocation.getLangOpts().CLUnsafeMath);
822 ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
823 ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
824 ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
826 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
827 // Not generated - missing.
828 ASSERT_THAT(GeneratedArgs,
829 Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
830 // Generated - explicitly provided.
831 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
832 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
833 // Not generated - implied by its generated parent.
834 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
837 TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
838 const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations"};
840 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
842 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
844 // Present options that were not implied are generated.
845 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
846 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
849 // Diagnostic option.
851 TEST_F(CommandLineTest, DiagnosticOptionPresent) {
852 const char *Args[] = {"-verify=xyz"};
854 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
856 ASSERT_EQ(Invocation.getDiagnosticOpts().VerifyPrefixes,
857 std::vector<std::string>({"xyz"}));
859 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
861 ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-verify=xyz"), 1));
864 // Option default depends on language standard.
866 TEST_F(CommandLineTest, DigraphsImplied) {
867 const char *Args[] = {""};
869 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
870 ASSERT_TRUE(Invocation.getLangOpts().Digraphs);
872 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
873 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
874 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
877 TEST_F(CommandLineTest, DigraphsDisabled) {
878 const char *Args[] = {"-fno-digraphs"};
880 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
881 ASSERT_FALSE(Invocation.getLangOpts().Digraphs);
883 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
884 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-digraphs")));
885 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
888 TEST_F(CommandLineTest, DigraphsNotImplied) {
889 const char *Args[] = {"-std=c89"};
891 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
892 ASSERT_FALSE(Invocation.getLangOpts().Digraphs);
894 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
895 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
896 ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
899 TEST_F(CommandLineTest, DigraphsEnabled) {
900 const char *Args[] = {"-std=c89", "-fdigraphs"};
902 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
903 ASSERT_TRUE(Invocation.getLangOpts().Digraphs);
905 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
906 ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdigraphs")));
909 struct DummyModuleFileExtension
910 : public llvm::RTTIExtends<DummyModuleFileExtension, ModuleFileExtension> {
911 static char ID;
913 ModuleFileExtensionMetadata getExtensionMetadata() const override {
914 return {};
917 void hashExtension(ExtensionHashBuilder &HBuilder) const override {}
919 std::unique_ptr<ModuleFileExtensionWriter>
920 createExtensionWriter(ASTWriter &Writer) override {
921 return {};
924 std::unique_ptr<ModuleFileExtensionReader>
925 createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
926 ASTReader &Reader, serialization::ModuleFile &Mod,
927 const llvm::BitstreamCursor &Stream) override {
928 return {};
932 char DummyModuleFileExtension::ID = 0;
934 TEST_F(CommandLineTest, TestModuleFileExtension) {
935 const char *Args[] = {"-ftest-module-file-extension=first:2:1:0:first",
936 "-ftest-module-file-extension=second:3:2:1:second"};
938 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
939 ASSERT_THAT(Invocation.getFrontendOpts().ModuleFileExtensions.size(), 2);
941 // Exercise the check that only serializes instances of
942 // TestModuleFileExtension by providing an instance of another
943 // ModuleFileExtension subclass.
944 Invocation.getFrontendOpts().ModuleFileExtensions.push_back(
945 std::make_shared<DummyModuleFileExtension>());
947 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
949 ASSERT_THAT(GeneratedArgs,
950 ContainsN(HasSubstr("-ftest-module-file-extension="), 2));
951 ASSERT_THAT(
952 GeneratedArgs,
953 Contains(StrEq("-ftest-module-file-extension=first:2:1:0:first")));
954 ASSERT_THAT(
955 GeneratedArgs,
956 Contains(StrEq("-ftest-module-file-extension=second:3:2:1:second")));
959 TEST_F(CommandLineTest, RoundTrip) {
960 // Testing one marshalled and one manually generated option from each
961 // CompilerInvocation member.
962 const char *Args[] = {
963 "-round-trip-args",
964 // LanguageOptions
965 "-std=c17",
966 "-fmax-tokens=10",
967 // TargetOptions
968 "-target-sdk-version=1.2.3",
969 "-meabi",
970 "4",
971 // DiagnosticOptions
972 "-Wundef-prefix=XY",
973 "-fdiagnostics-format",
974 "clang",
975 // HeaderSearchOptions
976 "-stdlib=libc++",
977 "-fimplicit-module-maps",
978 // PreprocessorOptions
979 "-DXY=AB",
980 "-include-pch",
981 "a.pch",
982 // AnalyzerOptions
983 "-analyzer-config",
984 "ctu-import-threshold=42",
985 "-unoptimized-cfg",
986 // MigratorOptions (no manually handled arguments)
987 "-no-ns-alloc-error",
988 // CodeGenOptions
989 "-debug-info-kind=limited",
990 "-debug-info-macro",
991 // DependencyOutputOptions
992 "--show-includes",
993 "-H",
994 // FileSystemOptions (no manually handled arguments)
995 "-working-directory",
996 "folder",
997 // FrontendOptions
998 "-load",
999 "plugin",
1000 "-ast-merge",
1001 // PreprocessorOutputOptions
1002 "-dD",
1003 "-CC",
1006 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1008 ASSERT_TRUE(Invocation.getLangOpts().C17);
1009 ASSERT_EQ(Invocation.getLangOpts().MaxTokens, 10u);
1011 ASSERT_EQ(Invocation.getTargetOpts().SDKVersion, llvm::VersionTuple(1, 2, 3));
1012 ASSERT_EQ(Invocation.getTargetOpts().EABIVersion, EABI::EABI4);
1014 ASSERT_THAT(Invocation.getDiagnosticOpts().UndefPrefixes,
1015 Contains(StrEq("XY")));
1016 ASSERT_EQ(Invocation.getDiagnosticOpts().getFormat(),
1017 TextDiagnosticFormat::Clang);
1019 ASSERT_TRUE(Invocation.getHeaderSearchOpts().UseLibcxx);
1020 ASSERT_TRUE(Invocation.getHeaderSearchOpts().ImplicitModuleMaps);
1022 ASSERT_THAT(Invocation.getPreprocessorOpts().Macros,
1023 Contains(std::make_pair(std::string("XY=AB"), false)));
1024 ASSERT_EQ(Invocation.getPreprocessorOpts().ImplicitPCHInclude, "a.pch");
1026 ASSERT_EQ(Invocation.getAnalyzerOpts().Config["ctu-import-threshold"], "42");
1027 ASSERT_TRUE(Invocation.getAnalyzerOpts().UnoptimizedCFG);
1029 ASSERT_TRUE(Invocation.getMigratorOpts().NoNSAllocReallocError);
1031 ASSERT_EQ(Invocation.getCodeGenOpts().getDebugInfo(),
1032 codegenoptions::DebugInfoKind::LimitedDebugInfo);
1033 ASSERT_TRUE(Invocation.getCodeGenOpts().MacroDebugInfo);
1035 ASSERT_EQ(Invocation.getDependencyOutputOpts().ShowIncludesDest,
1036 ShowIncludesDestination::Stdout);
1037 ASSERT_TRUE(Invocation.getDependencyOutputOpts().ShowHeaderIncludes);
1040 TEST_F(CommandLineTest, PluginArgsRoundTripDeterminism) {
1041 const char *Args[] = {
1042 "-plugin-arg-blink-gc-plugin", "no-members-in-stack-allocated",
1043 "-plugin-arg-find-bad-constructs", "checked-ptr-as-trivial-member",
1044 "-plugin-arg-find-bad-constructs", "check-ipc",
1045 // Enable round-trip to ensure '-plugin-arg' generation is deterministic.
1046 "-round-trip-args"};
1048 ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1051 TEST_F(CommandLineTest, WarningSuppressionMappings) {
1052 const char *Args[] = {"--warning-suppression-mappings=foo.txt"};
1054 EXPECT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1055 EXPECT_EQ(Invocation.getDiagnosticOpts().DiagnosticSuppressionMappingsFile,
1056 "foo.txt");
1058 Invocation.generateCC1CommandLine(GeneratedArgs, *this);
1059 EXPECT_THAT(GeneratedArgs, Contains(StrEq(Args[0])));
1061 } // anonymous namespace