1 //===- unittests/Frontend/CompilerInvocationTest.cpp - CI tests //---------===//
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
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"
22 using namespace clang
;
24 using ::testing::Contains
;
25 using ::testing::HasSubstr
;
26 using ::testing::StrEq
;
27 using ::testing::StartsWith
;
30 class CommandLineTest
: public ::testing::Test
{
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();
42 : Diags(CompilerInstance::createDiagnostics(
43 *llvm::vfs::getRealFileSystem(), new DiagnosticOptions(),
44 new TextDiagnosticBuffer())) {}
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())
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
;
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.
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()),
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()),
210 TEST_F(CommandLineTest
, BoolOptionDefaultTrueSingleFlagUnknownPresent
) {
211 const char *Args
[] = {"-ftemp-file"};
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"};
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"};
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"};
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<...>;
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
747 // * -cl-unsafe-math-optimizations
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
> {
913 ModuleFileExtensionMetadata
getExtensionMetadata() const override
{
917 void hashExtension(ExtensionHashBuilder
&HBuilder
) const override
{}
919 std::unique_ptr
<ModuleFileExtensionWriter
>
920 createExtensionWriter(ASTWriter
&Writer
) override
{
924 std::unique_ptr
<ModuleFileExtensionReader
>
925 createExtensionReader(const ModuleFileExtensionMetadata
&Metadata
,
926 ASTReader
&Reader
, serialization::ModuleFile
&Mod
,
927 const llvm::BitstreamCursor
&Stream
) override
{
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));
953 Contains(StrEq("-ftest-module-file-extension=first:2:1:0:first")));
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
[] = {
968 "-target-sdk-version=1.2.3",
973 "-fdiagnostics-format",
975 // HeaderSearchOptions
977 "-fimplicit-module-maps",
978 // PreprocessorOptions
984 "ctu-import-threshold=42",
986 // MigratorOptions (no manually handled arguments)
987 "-no-ns-alloc-error",
989 "-debug-info-kind=limited",
991 // DependencyOutputOptions
994 // FileSystemOptions (no manually handled arguments)
995 "-working-directory",
1001 // PreprocessorOutputOptions
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
,
1058 Invocation
.generateCC1CommandLine(GeneratedArgs
, *this);
1059 EXPECT_THAT(GeneratedArgs
, Contains(StrEq(Args
[0])));
1061 } // anonymous namespace