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/TargetParser/Host.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
21 using namespace clang
;
23 using ::testing::Contains
;
24 using ::testing::HasSubstr
;
25 using ::testing::StrEq
;
26 using ::testing::StartsWith
;
29 class CommandLineTest
: public ::testing::Test
{
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();
41 : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions(),
42 new TextDiagnosticBuffer())) {
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())
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
;
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.
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()),
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()),
209 TEST_F(CommandLineTest
, BoolOptionDefaultTrueSingleFlagUnknownPresent
) {
210 const char *Args
[] = {"-ftemp-file"};
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"};
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"};
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"};
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<...>;
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
746 // * -cl-unsafe-math-optimizations
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
> {
912 ModuleFileExtensionMetadata
getExtensionMetadata() const override
{
916 void hashExtension(ExtensionHashBuilder
&HBuilder
) const override
{}
918 std::unique_ptr
<ModuleFileExtensionWriter
>
919 createExtensionWriter(ASTWriter
&Writer
) override
{
923 std::unique_ptr
<ModuleFileExtensionReader
>
924 createExtensionReader(const ModuleFileExtensionMetadata
&Metadata
,
925 ASTReader
&Reader
, serialization::ModuleFile
&Mod
,
926 const llvm::BitstreamCursor
&Stream
) override
{
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));
952 Contains(StrEq("-ftest-module-file-extension=first:2:1:0:first")));
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
[] = {
967 "-target-sdk-version=1.2.3",
972 "-fdiagnostics-format",
974 // HeaderSearchOptions
976 "-fimplicit-module-maps",
977 // PreprocessorOptions
983 "ctu-import-threshold=42",
985 // MigratorOptions (no manually handled arguments)
986 "-no-ns-alloc-error",
988 "-debug-info-kind=limited",
990 // DependencyOutputOptions
993 // FileSystemOptions (no manually handled arguments)
994 "-working-directory",
1000 // PreprocessorOutputOptions
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