xref: /llvm-project/clang/unittests/Frontend/CompilerInvocationTest.cpp (revision 8bf19ec444593b3076a446a8eeb5042bbf79dc65)
129125ddfSDaniel Grumberg //===- unittests/Frontend/CompilerInvocationTest.cpp - CI tests //---------===//
229125ddfSDaniel Grumberg //
329125ddfSDaniel Grumberg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
429125ddfSDaniel Grumberg // See https://llvm.org/LICENSE.txt for license information.
529125ddfSDaniel Grumberg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
629125ddfSDaniel Grumberg //
729125ddfSDaniel Grumberg //===----------------------------------------------------------------------===//
829125ddfSDaniel Grumberg 
929125ddfSDaniel Grumberg #include "clang/Frontend/CompilerInvocation.h"
10ed863285SJan Svoboda #include "clang/Basic/TargetOptions.h"
1129125ddfSDaniel Grumberg #include "clang/Frontend/CompilerInstance.h"
1203692baeSJan Svoboda #include "clang/Frontend/TextDiagnosticBuffer.h"
13ed863285SJan Svoboda #include "clang/Lex/PreprocessorOptions.h"
144295ae96SJan Svoboda #include "clang/Serialization/ModuleFileExtension.h"
15df9a14d7SKadir Cetinkaya #include "llvm/Support/VirtualFileSystem.h"
16d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
1729125ddfSDaniel Grumberg 
1829125ddfSDaniel Grumberg #include "gmock/gmock.h"
1929125ddfSDaniel Grumberg #include "gtest/gtest.h"
2029125ddfSDaniel Grumberg 
2129125ddfSDaniel Grumberg using namespace llvm;
2229125ddfSDaniel Grumberg using namespace clang;
2329125ddfSDaniel Grumberg 
2429125ddfSDaniel Grumberg using ::testing::Contains;
25ce8c59e6SJan Svoboda using ::testing::HasSubstr;
2629125ddfSDaniel Grumberg using ::testing::StrEq;
27afb4efd3SAiden Grossman using ::testing::StartsWith;
2829125ddfSDaniel Grumberg 
2929125ddfSDaniel Grumberg namespace {
30cf2bb223SJan Svoboda class CommandLineTest : public ::testing::Test {
3129125ddfSDaniel Grumberg public:
3229125ddfSDaniel Grumberg   IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
3329125ddfSDaniel Grumberg   SmallVector<const char *, 32> GeneratedArgs;
34*8bf19ec4Smacurtis-amd   BumpPtrAllocator Alloc;
35*8bf19ec4Smacurtis-amd   StringSaver StringPool;
36f825ec86SJan Svoboda   CompilerInvocation Invocation;
3729125ddfSDaniel Grumberg 
3829125ddfSDaniel Grumberg   const char *operator()(const Twine &Arg) {
39*8bf19ec4Smacurtis-amd     return StringPool.save(Arg).data();
4029125ddfSDaniel Grumberg   }
4129125ddfSDaniel Grumberg 
42cf2bb223SJan Svoboda   CommandLineTest()
43df9a14d7SKadir Cetinkaya       : Diags(CompilerInstance::createDiagnostics(
44df9a14d7SKadir Cetinkaya             *llvm::vfs::getRealFileSystem(), new DiagnosticOptions(),
45*8bf19ec4Smacurtis-amd             new TextDiagnosticBuffer())),
46*8bf19ec4Smacurtis-amd         StringPool(Alloc) {}
4729125ddfSDaniel Grumberg };
4829125ddfSDaniel Grumberg 
49c6ea4d5bSJan Svoboda template <typename M>
50c6ea4d5bSJan Svoboda std::string describeContainsN(M InnerMatcher, unsigned N, bool Negation) {
51c6ea4d5bSJan Svoboda   StringRef Contains = Negation ? "doesn't contain" : "contains";
52c6ea4d5bSJan Svoboda   StringRef Instance = N == 1 ? " instance " : " instances ";
53c6ea4d5bSJan Svoboda   StringRef Element = "of element that ";
54c6ea4d5bSJan Svoboda 
55c6ea4d5bSJan Svoboda   std::ostringstream Inner;
56c6ea4d5bSJan Svoboda   InnerMatcher.impl().DescribeTo(&Inner);
57c6ea4d5bSJan Svoboda 
58c6ea4d5bSJan Svoboda   return (Contains + " exactly " + Twine(N) + Instance + Element + Inner.str())
59c6ea4d5bSJan Svoboda       .str();
60c6ea4d5bSJan Svoboda }
61c6ea4d5bSJan Svoboda 
62c6ea4d5bSJan Svoboda MATCHER_P2(ContainsN, InnerMatcher, N,
63c6ea4d5bSJan Svoboda            describeContainsN(InnerMatcher, N, negation)) {
64c6ea4d5bSJan Svoboda   auto InnerMatches = [this](const auto &Element) {
65c6ea4d5bSJan Svoboda     ::testing::internal::DummyMatchResultListener InnerListener;
66c6ea4d5bSJan Svoboda     return InnerMatcher.impl().MatchAndExplain(Element, &InnerListener);
67c6ea4d5bSJan Svoboda   };
68c6ea4d5bSJan Svoboda 
69c6ea4d5bSJan Svoboda   return count_if(arg, InnerMatches) == N;
70c6ea4d5bSJan Svoboda }
71c6ea4d5bSJan Svoboda 
72c6ea4d5bSJan Svoboda TEST(ContainsN, Empty) {
73c6ea4d5bSJan Svoboda   const char *Array[] = {""};
74c6ea4d5bSJan Svoboda 
75c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
76c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
77c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
78c6ea4d5bSJan Svoboda }
79c6ea4d5bSJan Svoboda 
80c6ea4d5bSJan Svoboda TEST(ContainsN, Zero) {
81c6ea4d5bSJan Svoboda   const char *Array[] = {"y"};
82c6ea4d5bSJan Svoboda 
83c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
84c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
85c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
86c6ea4d5bSJan Svoboda }
87c6ea4d5bSJan Svoboda 
88c6ea4d5bSJan Svoboda TEST(ContainsN, One) {
89c6ea4d5bSJan Svoboda   const char *Array[] = {"a", "b", "x", "z"};
90c6ea4d5bSJan Svoboda 
91c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
92c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 1));
93c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
94c6ea4d5bSJan Svoboda }
95c6ea4d5bSJan Svoboda 
96c6ea4d5bSJan Svoboda TEST(ContainsN, Two) {
97c6ea4d5bSJan Svoboda   const char *Array[] = {"x", "a", "b", "x"};
98c6ea4d5bSJan Svoboda 
99c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
100c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
101c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 2));
102c6ea4d5bSJan Svoboda }
103c6ea4d5bSJan Svoboda 
10426bbb870SJan Svoboda // Copy constructor/assignment perform deep copy of reference-counted pointers.
10509d1f6e6SJan Svoboda 
10609d1f6e6SJan Svoboda TEST(CompilerInvocationTest, DeepCopyConstructor) {
10709d1f6e6SJan Svoboda   CompilerInvocation A;
1088e0c9bb9SJan Svoboda   A.getAnalyzerOpts().Config["Key"] = "Old";
10909d1f6e6SJan Svoboda 
11009d1f6e6SJan Svoboda   CompilerInvocation B(A);
1118e0c9bb9SJan Svoboda   B.getAnalyzerOpts().Config["Key"] = "New";
11209d1f6e6SJan Svoboda 
1138e0c9bb9SJan Svoboda   ASSERT_EQ(A.getAnalyzerOpts().Config["Key"], "Old");
11409d1f6e6SJan Svoboda }
11509d1f6e6SJan Svoboda 
11626bbb870SJan Svoboda TEST(CompilerInvocationTest, DeepCopyAssignment) {
11726bbb870SJan Svoboda   CompilerInvocation A;
1188e0c9bb9SJan Svoboda   A.getAnalyzerOpts().Config["Key"] = "Old";
11926bbb870SJan Svoboda 
12026bbb870SJan Svoboda   CompilerInvocation B;
12126bbb870SJan Svoboda   B = A;
1228e0c9bb9SJan Svoboda   B.getAnalyzerOpts().Config["Key"] = "New";
12326bbb870SJan Svoboda 
1248e0c9bb9SJan Svoboda   ASSERT_EQ(A.getAnalyzerOpts().Config["Key"], "Old");
12526bbb870SJan Svoboda }
12626bbb870SJan Svoboda 
127e1cc299eSJan Svoboda TEST(CompilerInvocationTest, CopyOnWriteConstructor) {
128e1cc299eSJan Svoboda   CowCompilerInvocation A;
129e1cc299eSJan Svoboda   A.getMutFrontendOpts().OutputFile = "x.o";
130e1cc299eSJan Svoboda 
131e1cc299eSJan Svoboda   // B's FrontendOptions are initially shared with A.
132e1cc299eSJan Svoboda   CowCompilerInvocation B(A);
133e1cc299eSJan Svoboda   EXPECT_EQ(&A.getFrontendOpts(), &B.getFrontendOpts());
134e1cc299eSJan Svoboda 
135e1cc299eSJan Svoboda   // Modifying A's FrontendOptions creates new copy, does not affect other opts.
136e1cc299eSJan Svoboda   A.getMutFrontendOpts().OutputFile = "y.o";
137e1cc299eSJan Svoboda   EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
138e1cc299eSJan Svoboda   EXPECT_EQ(&A.getCodeGenOpts(), &B.getCodeGenOpts());
139e1cc299eSJan Svoboda 
140e1cc299eSJan Svoboda   // The new copy reflects the modification, old instance remains unchanged.
141e1cc299eSJan Svoboda   EXPECT_EQ(A.getFrontendOpts().OutputFile, "y.o");
142e1cc299eSJan Svoboda   EXPECT_EQ(B.getFrontendOpts().OutputFile, "x.o");
143e1cc299eSJan Svoboda }
144e1cc299eSJan Svoboda 
145e1cc299eSJan Svoboda TEST(CompilerInvocationTest, CopyOnWriteAssignment) {
146e1cc299eSJan Svoboda   CowCompilerInvocation A;
147e1cc299eSJan Svoboda   A.getMutFrontendOpts().OutputFile = "x.o";
148e1cc299eSJan Svoboda 
149e1cc299eSJan Svoboda   // B's FrontendOptions are initially independent of A.
150e1cc299eSJan Svoboda   CowCompilerInvocation B;
151e1cc299eSJan Svoboda   EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
152e1cc299eSJan Svoboda 
153e1cc299eSJan Svoboda   // B's FrontendOptions are shared with A after assignment.
154e1cc299eSJan Svoboda   B = A;
155e1cc299eSJan Svoboda   EXPECT_EQ(&A.getFrontendOpts(), &B.getFrontendOpts());
156e1cc299eSJan Svoboda 
157e1cc299eSJan Svoboda   // Modifying A's FrontendOptions creates new copy, does not affect other opts.
158e1cc299eSJan Svoboda   A.getMutFrontendOpts().OutputFile = "y.o";
159e1cc299eSJan Svoboda   EXPECT_NE(&A.getFrontendOpts(), &B.getFrontendOpts());
160e1cc299eSJan Svoboda   EXPECT_EQ(&A.getCodeGenOpts(), &B.getCodeGenOpts());
161e1cc299eSJan Svoboda 
162e1cc299eSJan Svoboda   // The new copy reflects the modification, old instance remains unchanged.
163e1cc299eSJan Svoboda   EXPECT_EQ(A.getFrontendOpts().OutputFile, "y.o");
164e1cc299eSJan Svoboda   EXPECT_EQ(B.getFrontendOpts().OutputFile, "x.o");
165e1cc299eSJan Svoboda }
166e1cc299eSJan Svoboda 
167216d4305SJan Svoboda // Boolean option with a keypath that defaults to true.
168216d4305SJan Svoboda // The only flag with a negative spelling can set the keypath to false.
169216d4305SJan Svoboda 
170216d4305SJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagNotPresent) {
1714894e423SJan Svoboda   const char *Args[] = {""};
1722b84efa0SJan Svoboda 
17333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
174f825ec86SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
175216d4305SJan Svoboda 
176216d4305SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
177216d4305SJan Svoboda 
178216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file"))));
1792b84efa0SJan Svoboda }
1802b84efa0SJan Svoboda 
181216d4305SJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagPresent) {
1824894e423SJan Svoboda   const char *Args[] = {"-fno-temp-file"};
1832b84efa0SJan Svoboda 
18433f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
185f825ec86SJan Svoboda   ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary);
186216d4305SJan Svoboda 
187216d4305SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
188216d4305SJan Svoboda 
189216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
1902b84efa0SJan Svoboda }
1912b84efa0SJan Svoboda 
192afb4efd3SAiden Grossman TEST_F(CommandLineTest, CC1FlagPresentWhenDoingRoundTrip) {
193afb4efd3SAiden Grossman   const char *Args[] = {"-cc1", "-round-trip-args"};
194afb4efd3SAiden Grossman 
195afb4efd3SAiden Grossman   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
196afb4efd3SAiden Grossman 
197afb4efd3SAiden Grossman   ASSERT_THAT(std::string(Invocation.getCodeGenOpts().CmdArgs.begin(),
198afb4efd3SAiden Grossman                           Invocation.getCodeGenOpts().CmdArgs.end()),
199afb4efd3SAiden Grossman               StartsWith("-cc1"));
200afb4efd3SAiden Grossman }
201afb4efd3SAiden Grossman 
202afb4efd3SAiden Grossman TEST_F(CommandLineTest, CC1FlagPresentWhenNotDoingRoundTrip) {
203afb4efd3SAiden Grossman   const char *Args[] = {"-cc1", "-no-round-trip-args"};
204afb4efd3SAiden Grossman 
205afb4efd3SAiden Grossman   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
206afb4efd3SAiden Grossman 
207afb4efd3SAiden Grossman   ASSERT_THAT(std::string(Invocation.getCodeGenOpts().CmdArgs.begin(),
208afb4efd3SAiden Grossman                           Invocation.getCodeGenOpts().CmdArgs.end()),
209afb4efd3SAiden Grossman               StartsWith("-cc1"));
210afb4efd3SAiden Grossman }
211afb4efd3SAiden Grossman 
212216d4305SJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagUnknownPresent) {
213216d4305SJan Svoboda   const char *Args[] = {"-ftemp-file"};
214dbfa69c5SJan Svoboda 
215216d4305SJan Svoboda   // Driver-only flag.
21633f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
217216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
218dbfa69c5SJan Svoboda }
219dbfa69c5SJan Svoboda 
2206f26a6deSJan Svoboda // Boolean option with a keypath that defaults to true.
2216f26a6deSJan Svoboda // The flag with negative spelling can set the keypath to false.
2226f26a6deSJan Svoboda // The flag with positive spelling can reset the keypath to true.
2236f26a6deSJan Svoboda 
2246f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNone) {
2256f26a6deSJan Svoboda   const char *Args[] = {""};
2266f26a6deSJan Svoboda 
22733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2286f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
2296f26a6deSJan Svoboda 
2306baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2316baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
2326baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-autolink"))));
2336f26a6deSJan Svoboda }
2346f26a6deSJan Svoboda 
2356f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNegChange) {
2366f26a6deSJan Svoboda   const char *Args[] = {"-fno-autolink"};
2376f26a6deSJan Svoboda 
23833f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2396f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().Autolink);
2406f26a6deSJan Svoboda 
2416baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2426baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-autolink")));
2436baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
2446f26a6deSJan Svoboda }
2456f26a6deSJan Svoboda 
2466f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTruePresentPosReset) {
2476f26a6deSJan Svoboda   const char *Args[] = {"-fautolink"};
2486f26a6deSJan Svoboda 
24933f90f38SJan Svoboda   // Driver-only flag.
25033f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2516f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
2526f26a6deSJan Svoboda }
2536f26a6deSJan Svoboda 
2546f26a6deSJan Svoboda // Boolean option with a keypath that defaults to false.
2556f26a6deSJan Svoboda // The flag with negative spelling can set the keypath to true.
2566f26a6deSJan Svoboda // The flag with positive spelling can reset the keypath to false.
2576f26a6deSJan Svoboda 
2586f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNone) {
2596f26a6deSJan Svoboda   const char *Args[] = {""};
2606f26a6deSJan Svoboda 
26133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2626f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
2636f26a6deSJan Svoboda 
2646baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2656baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
2666baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-inline-line-tables"))));
2676f26a6deSJan Svoboda }
2686f26a6deSJan Svoboda 
2696f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegChange) {
2706f26a6deSJan Svoboda   const char *Args[] = {"-gno-inline-line-tables"};
2716f26a6deSJan Svoboda 
27233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2736f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().NoInlineLineTables);
2746f26a6deSJan Svoboda 
2756baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2766baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gno-inline-line-tables")));
2776baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
2786f26a6deSJan Svoboda }
2796f26a6deSJan Svoboda 
2806f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosReset) {
2816f26a6deSJan Svoboda   const char *Args[] = {"-ginline-line-tables"};
2826f26a6deSJan Svoboda 
28333f90f38SJan Svoboda   // Driver-only flag.
28433f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2856f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
2866f26a6deSJan Svoboda }
2876f26a6deSJan Svoboda 
2886f26a6deSJan Svoboda // Boolean option with a keypath that defaults to false.
2896f26a6deSJan Svoboda // The flag with positive spelling can set the keypath to true.
2906f26a6deSJan Svoboda // The flag with negative spelling can reset the keypath to false.
2916f26a6deSJan Svoboda 
2926f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNoneX) {
2936f26a6deSJan Svoboda   const char *Args[] = {""};
2946f26a6deSJan Svoboda 
29533f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2966f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
2976f26a6deSJan Svoboda 
2986baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2996baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gcodeview-ghash"))));
3006baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
3016f26a6deSJan Svoboda }
3026f26a6deSJan Svoboda 
3036f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosChange) {
3046f26a6deSJan Svoboda   const char *Args[] = {"-gcodeview-ghash"};
3056f26a6deSJan Svoboda 
30633f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
3076f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().CodeViewGHash);
3086f26a6deSJan Svoboda 
3096baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
3106baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gcodeview-ghash")));
3116baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
3126f26a6deSJan Svoboda }
3136f26a6deSJan Svoboda 
3146f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegReset) {
3156f26a6deSJan Svoboda   const char *Args[] = {"-gno-codeview-ghash"};
3166f26a6deSJan Svoboda 
31733f90f38SJan Svoboda   // Driver-only flag.
31833f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
3196f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
3206f26a6deSJan Svoboda }
3216f26a6deSJan Svoboda 
3226f26a6deSJan Svoboda // Boolean option with a keypath that defaults to an arbitrary expression.
3236f26a6deSJan Svoboda // The flag with positive spelling can set the keypath to true.
3246f26a6deSJan Svoboda // The flag with negative spelling can set the keypath to false.
3256f26a6deSJan Svoboda 
3266f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentNone) {
3276f26a6deSJan Svoboda   const char *Args = {""};
3286f26a6deSJan Svoboda 
32933f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
33006285fc9SArthur Eubanks   ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
3316f26a6deSJan Svoboda 
3326f26a6deSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
3336f26a6deSJan Svoboda 
33406285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
33506285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
3366f26a6deSJan Svoboda }
3376f26a6deSJan Svoboda 
3386f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentChange) {
33906285fc9SArthur Eubanks   const char *Args[] = {"-clear-ast-before-backend"};
3406f26a6deSJan Svoboda 
34133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
34206285fc9SArthur Eubanks   ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, true);
3436f26a6deSJan Svoboda 
3446f26a6deSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
34506285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-clear-ast-before-backend")));
34606285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
3476f26a6deSJan Svoboda }
3486f26a6deSJan Svoboda 
3496f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentReset) {
35006285fc9SArthur Eubanks   const char *Args[] = {"-no-clear-ast-before-backend"};
3516f26a6deSJan Svoboda 
35233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
35306285fc9SArthur Eubanks   ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
3546f26a6deSJan Svoboda 
3556f26a6deSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
35606285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
35706285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
3586f26a6deSJan Svoboda }
3596f26a6deSJan Svoboda 
36095114f21SJan Svoboda // Boolean option that gets the CC1Option flag from a let statement (which
36195114f21SJan Svoboda // is applied **after** the record is defined):
36295114f21SJan Svoboda //
36395114f21SJan Svoboda //   let Flags = [CC1Option] in {
36495114f21SJan Svoboda //     defm option : BoolOption<...>;
36595114f21SJan Svoboda //   }
36695114f21SJan Svoboda 
36795114f21SJan Svoboda TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) {
36895114f21SJan Svoboda   const char *Args[] = {""};
36995114f21SJan Svoboda 
37033f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
37195114f21SJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
37295114f21SJan Svoboda 
37395114f21SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
37495114f21SJan Svoboda 
37595114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
37695114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
37795114f21SJan Svoboda }
37895114f21SJan Svoboda 
37995114f21SJan Svoboda TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) {
38095114f21SJan Svoboda   const char *Args[] = {"-fdebug-pass-manager"};
38195114f21SJan Svoboda 
38233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
38395114f21SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager);
38495114f21SJan Svoboda 
38595114f21SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
38695114f21SJan Svoboda 
387c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fdebug-pass-manager"), 1));
38895114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
38995114f21SJan Svoboda }
39095114f21SJan Svoboda 
39195114f21SJan Svoboda TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) {
39295114f21SJan Svoboda   const char *Args[] = {"-fno-debug-pass-manager"};
39395114f21SJan Svoboda 
39433f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
39595114f21SJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
39695114f21SJan Svoboda 
39795114f21SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
39895114f21SJan Svoboda 
39995114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
40095114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
40195114f21SJan Svoboda }
40295114f21SJan Svoboda 
403cf2bb223SJan Svoboda TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) {
4044894e423SJan Svoboda   const char *Args[] = {"-fmodules-strict-context-hash"};
40529125ddfSDaniel Grumberg 
40633f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
40703692baeSJan Svoboda 
408f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
40929125ddfSDaniel Grumberg 
41029125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash")));
41129125ddfSDaniel Grumberg }
41229125ddfSDaniel Grumberg 
413cf2bb223SJan Svoboda TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) {
41429125ddfSDaniel Grumberg   const char *TripleCStr = "i686-apple-darwin9";
4154894e423SJan Svoboda   const char *Args[] = {"-triple", TripleCStr};
41629125ddfSDaniel Grumberg 
41733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
41803692baeSJan Svoboda 
419f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
42029125ddfSDaniel Grumberg 
42129125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
42229125ddfSDaniel Grumberg }
42329125ddfSDaniel Grumberg 
424cf2bb223SJan Svoboda TEST_F(CommandLineTest,  CanGenerateCC1CommandLineSeparateRequiredPresent) {
42529125ddfSDaniel Grumberg   const std::string DefaultTriple =
42629125ddfSDaniel Grumberg       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
4274894e423SJan Svoboda   const char *Args[] = {"-triple", DefaultTriple.c_str()};
42829125ddfSDaniel Grumberg 
42933f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
43003692baeSJan Svoboda 
431f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
43229125ddfSDaniel Grumberg 
43329125ddfSDaniel Grumberg   // Triple should always be emitted even if it is the default
43429125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
43529125ddfSDaniel Grumberg }
43629125ddfSDaniel Grumberg 
437cf2bb223SJan Svoboda TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
438e4e2d8e4SDaniel Grumberg   const std::string DefaultTriple =
439e4e2d8e4SDaniel Grumberg       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
4404894e423SJan Svoboda   const char *Args[] = {""};
44129125ddfSDaniel Grumberg 
44233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
44303692baeSJan Svoboda 
444f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
44529125ddfSDaniel Grumberg 
44629125ddfSDaniel Grumberg   // Triple should always be emitted even if it is the default
44729125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
44829125ddfSDaniel Grumberg }
44929125ddfSDaniel Grumberg 
450ce8c59e6SJan Svoboda TEST_F(CommandLineTest, SeparateEnumNonDefault) {
4514894e423SJan Svoboda   const char *Args[] = {"-mrelocation-model", "static"};
45229125ddfSDaniel Grumberg 
45333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
454ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static);
45503692baeSJan Svoboda 
456f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
45729125ddfSDaniel Grumberg 
4585afff86dSJan Svoboda   // Non default relocation model.
459ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model")));
4605afff86dSJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
461ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static"))));
4625afff86dSJan Svoboda }
46329125ddfSDaniel Grumberg 
464ce8c59e6SJan Svoboda TEST_F(CommandLineTest, SeparateEnumDefault) {
4654894e423SJan Svoboda   const char *Args[] = {"-mrelocation-model", "pic"};
46629125ddfSDaniel Grumberg 
46733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
468ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_);
46903692baeSJan Svoboda 
4705afff86dSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
4715afff86dSJan Svoboda 
4725afff86dSJan Svoboda   // Default relocation model.
473ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model"))));
4745afff86dSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
475ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic"))));
476ce8c59e6SJan Svoboda }
477ce8c59e6SJan Svoboda 
478ce8c59e6SJan Svoboda TEST_F(CommandLineTest, JoinedEnumNonDefault) {
479ce8c59e6SJan Svoboda   const char *Args[] = {"-fobjc-dispatch-method=non-legacy"};
480ce8c59e6SJan Svoboda 
48133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
482ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
483ce8c59e6SJan Svoboda             CodeGenOptions::NonLegacy);
484ce8c59e6SJan Svoboda 
485ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
486ce8c59e6SJan Svoboda 
487ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs,
488ce8c59e6SJan Svoboda               Contains(StrEq("-fobjc-dispatch-method=non-legacy")));
489ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
490ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy"))));
491ce8c59e6SJan Svoboda }
492ce8c59e6SJan Svoboda 
493ce8c59e6SJan Svoboda TEST_F(CommandLineTest, JoinedEnumDefault) {
494ce8c59e6SJan Svoboda   const char *Args[] = {"-fobjc-dispatch-method=legacy"};
495ce8c59e6SJan Svoboda 
49633f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
497ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
498ce8c59e6SJan Svoboda             CodeGenOptions::Legacy);
499ce8c59e6SJan Svoboda 
500ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
501ce8c59e6SJan Svoboda 
502ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs,
503ce8c59e6SJan Svoboda               Not(Contains(StrEq("-fobjc-dispatch-method=legacy"))));
504ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
505ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy"))));
506ce8c59e6SJan Svoboda }
507ce8c59e6SJan Svoboda 
508ce8c59e6SJan Svoboda TEST_F(CommandLineTest, StringVectorEmpty) {
509ce8c59e6SJan Svoboda   const char *Args[] = {""};
510ce8c59e6SJan Svoboda 
51133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
512ce8c59e6SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles.empty());
513ce8c59e6SJan Svoboda 
514ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
515c6ea4d5bSJan Svoboda 
516c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-fmodule-map-file"))));
517ce8c59e6SJan Svoboda }
518ce8c59e6SJan Svoboda 
519ce8c59e6SJan Svoboda TEST_F(CommandLineTest, StringVectorSingle) {
520ce8c59e6SJan Svoboda   const char *Args[] = {"-fmodule-map-file=a"};
521ce8c59e6SJan Svoboda 
52233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
523ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getFrontendOpts().ModuleMapFiles,
524ce8c59e6SJan Svoboda             std::vector<std::string>({"a"}));
525ce8c59e6SJan Svoboda 
526ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
527c6ea4d5bSJan Svoboda 
528c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
529c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 1));
530ce8c59e6SJan Svoboda }
531ce8c59e6SJan Svoboda 
532ce8c59e6SJan Svoboda TEST_F(CommandLineTest, StringVectorMultiple) {
533ce8c59e6SJan Svoboda   const char *Args[] = {"-fmodule-map-file=a", "-fmodule-map-file=b"};
534ce8c59e6SJan Svoboda 
53533f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
536ce8c59e6SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles ==
537ce8c59e6SJan Svoboda               std::vector<std::string>({"a", "b"}));
538ce8c59e6SJan Svoboda 
539ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
540c6ea4d5bSJan Svoboda 
541c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
542c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=b"), 1));
543c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 2));
54463a24816SJan Svoboda }
54563a24816SJan Svoboda 
546a828fb46SJan Svoboda // CommaJoined option with MarshallingInfoStringVector.
547a828fb46SJan Svoboda 
548a828fb46SJan Svoboda TEST_F(CommandLineTest, StringVectorCommaJoinedNone) {
549a828fb46SJan Svoboda   const char *Args[] = {""};
550a828fb46SJan Svoboda 
55133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
5525746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().CommentOpts.BlockCommandNames.empty());
553a828fb46SJan Svoboda 
554a828fb46SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
555a828fb46SJan Svoboda 
556a828fb46SJan Svoboda   ASSERT_THAT(GeneratedArgs,
557a828fb46SJan Svoboda               Not(Contains(HasSubstr("-fcomment-block-commands"))));
558a828fb46SJan Svoboda }
559a828fb46SJan Svoboda 
560a828fb46SJan Svoboda TEST_F(CommandLineTest, StringVectorCommaJoinedSingle) {
561a828fb46SJan Svoboda   const char *Args[] = {"-fcomment-block-commands=x,y"};
562a828fb46SJan Svoboda 
56333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
5645746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().CommentOpts.BlockCommandNames,
565a828fb46SJan Svoboda             std::vector<std::string>({"x", "y"}));
566a828fb46SJan Svoboda 
567a828fb46SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
568a828fb46SJan Svoboda 
569a828fb46SJan Svoboda   ASSERT_THAT(GeneratedArgs,
570a828fb46SJan Svoboda               ContainsN(StrEq("-fcomment-block-commands=x,y"), 1));
571a828fb46SJan Svoboda }
572a828fb46SJan Svoboda 
573a828fb46SJan Svoboda TEST_F(CommandLineTest, StringVectorCommaJoinedMultiple) {
574a828fb46SJan Svoboda   const char *Args[] = {"-fcomment-block-commands=x,y",
575a828fb46SJan Svoboda                         "-fcomment-block-commands=a,b"};
576a828fb46SJan Svoboda 
57733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
5785746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().CommentOpts.BlockCommandNames,
579a828fb46SJan Svoboda             std::vector<std::string>({"x", "y", "a", "b"}));
580a828fb46SJan Svoboda 
581a828fb46SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
582a828fb46SJan Svoboda 
583a828fb46SJan Svoboda   ASSERT_THAT(GeneratedArgs,
584a828fb46SJan Svoboda               ContainsN(StrEq("-fcomment-block-commands=x,y,a,b"), 1));
585a828fb46SJan Svoboda }
586a828fb46SJan Svoboda 
58767a4c672SJan Svoboda // A flag that should be parsed only if a condition is met.
58867a4c672SJan Svoboda 
58967a4c672SJan Svoboda TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagNotPresent) {
59067a4c672SJan Svoboda   const char *Args[] = {""};
59167a4c672SJan Svoboda 
59267a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
59367a4c672SJan Svoboda 
59467a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
5955746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsDevice);
5965746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
5975746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
59867a4c672SJan Svoboda 
59967a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
60067a4c672SJan Svoboda 
60167a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl"))));
60267a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
60367a4c672SJan Svoboda }
60467a4c672SJan Svoboda 
60567a4c672SJan Svoboda TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagPresent) {
60667a4c672SJan Svoboda   const char *Args[] = {"-sycl-std=2017"};
60767a4c672SJan Svoboda 
60867a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
60967a4c672SJan Svoboda 
61067a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
6115746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsDevice);
6125746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
6135746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
61467a4c672SJan Svoboda 
61567a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
61667a4c672SJan Svoboda 
617c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-device"))));
618c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
61967a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
62067a4c672SJan Svoboda }
62167a4c672SJan Svoboda 
62263816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfNonsenseSyclStdArg) {
62363816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=garbage"};
62463816645SAaron Ballman 
62563816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
62663816645SAaron Ballman 
62763816645SAaron Ballman   ASSERT_TRUE(Diags->hasErrorOccurred());
6285746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
6295746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
6305746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_None);
63163816645SAaron Ballman 
63263816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
63363816645SAaron Ballman 
63463816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
63563816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
63663816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
63763816645SAaron Ballman }
63863816645SAaron Ballman 
63963816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg1) {
64063816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=121"};
64163816645SAaron Ballman 
64263816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
64363816645SAaron Ballman 
64463816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
6455746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
6465746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
6475746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
64863816645SAaron Ballman 
64963816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
65063816645SAaron Ballman 
65163816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
65263816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
65363816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
65463816645SAaron Ballman }
65563816645SAaron Ballman 
65663816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg2) {
65763816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=1.2.1"};
65863816645SAaron Ballman 
65963816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
66063816645SAaron Ballman 
66163816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
6625746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
6635746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
6645746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
66563816645SAaron Ballman 
66663816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
66763816645SAaron Ballman 
66863816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
66963816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
67063816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
67163816645SAaron Ballman }
67263816645SAaron Ballman 
67363816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg3) {
67463816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=sycl-1.2.1"};
67563816645SAaron Ballman 
67663816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
67763816645SAaron Ballman 
67863816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
6795746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().SYCLIsDevice);
6805746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().SYCLIsHost);
6815746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
68263816645SAaron Ballman 
68363816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
68463816645SAaron Ballman 
68563816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
68663816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
68763816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
68863816645SAaron Ballman }
68963816645SAaron Ballman 
69063816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentHost) {
691c165a99aSAaron Ballman   const char *Args[] = {"-fsycl-is-host"};
69267a4c672SJan Svoboda 
69367a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
69467a4c672SJan Svoboda 
69567a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
6965746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(),
69763816645SAaron Ballman             LangOptions::SYCL_Default);
69867a4c672SJan Svoboda 
69967a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
70067a4c672SJan Svoboda 
701c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-host")));
70263816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
70363816645SAaron Ballman }
70463816645SAaron Ballman 
70563816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentDevice) {
70663816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device"};
70763816645SAaron Ballman 
70863816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
70963816645SAaron Ballman 
71063816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
7115746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(),
71263816645SAaron Ballman             LangOptions::SYCL_Default);
71363816645SAaron Ballman 
71463816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
71563816645SAaron Ballman 
71663816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
71763816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
71867a4c672SJan Svoboda }
71967a4c672SJan Svoboda 
72067a4c672SJan Svoboda TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagPresent) {
721c165a99aSAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=2017"};
72267a4c672SJan Svoboda 
72367a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
72467a4c672SJan Svoboda 
72567a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
7265746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().getSYCLVersion(), LangOptions::SYCL_2017);
72767a4c672SJan Svoboda 
72867a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
72967a4c672SJan Svoboda 
730c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
73167a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-sycl-std=2017")));
73267a4c672SJan Svoboda }
73367a4c672SJan Svoboda 
734f111cf99SJan Svoboda // Wide integer option.
735f111cf99SJan Svoboda 
736f111cf99SJan Svoboda TEST_F(CommandLineTest, WideIntegerHighValue) {
737f111cf99SJan Svoboda   const char *Args[] = {"-fbuild-session-timestamp=1609827494445723662"};
738f111cf99SJan Svoboda 
739f111cf99SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
740f111cf99SJan Svoboda 
741f111cf99SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
742f111cf99SJan Svoboda   ASSERT_EQ(Invocation.getHeaderSearchOpts().BuildSessionTimestamp,
743f111cf99SJan Svoboda             1609827494445723662ull);
744f111cf99SJan Svoboda }
745f111cf99SJan Svoboda 
746216d4305SJan Svoboda // Tree of boolean options that can be (directly or transitively) implied by
747216d4305SJan Svoboda // their parent:
748216d4305SJan Svoboda //
749216d4305SJan Svoboda //   * -cl-unsafe-math-optimizations
750216d4305SJan Svoboda //     * -cl-mad-enable
75184a9ec2fSZahira Ammarguellat //     * -funsafe-math-optimizations
752216d4305SJan Svoboda //       * -freciprocal-math
753216d4305SJan Svoboda 
754216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) {
7554894e423SJan Svoboda   const char *Args[] = {""};
7562b84efa0SJan Svoboda 
75733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
7585746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().CLUnsafeMath);
759216d4305SJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
7605746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().UnsafeFPMath);
7615746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().AllowRecip);
76203692baeSJan Svoboda 
763f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
7642b84efa0SJan Svoboda 
765216d4305SJan Svoboda   // Not generated - missing.
76688ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs,
76788ab3844SJan Svoboda               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
76888ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
76984a9ec2fSZahira Ammarguellat   ASSERT_THAT(GeneratedArgs,
77084a9ec2fSZahira Ammarguellat               Not(Contains(StrEq("-funsafe-math-optimizations"))));
771216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
77288ab3844SJan Svoboda }
77388ab3844SJan Svoboda 
774216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsRootFlagPresent) {
7754894e423SJan Svoboda   const char *Args[] = {"-cl-unsafe-math-optimizations"};
77688ab3844SJan Svoboda 
77733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
778216d4305SJan Svoboda   // Explicitly provided root flag.
7795746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().CLUnsafeMath);
780216d4305SJan Svoboda   // Directly implied by explicitly provided root flag.
781216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
7825746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
783216d4305SJan Svoboda   // Transitively implied by explicitly provided root flag.
7845746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
78503692baeSJan Svoboda 
786f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
78788ab3844SJan Svoboda 
788216d4305SJan Svoboda   // Generated - explicitly provided.
78988ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
790216d4305SJan Svoboda   // Not generated - implied by the generated root flag.
79188ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
79284a9ec2fSZahira Ammarguellat   ASSERT_THAT(GeneratedArgs,
79384a9ec2fSZahira Ammarguellat               Not(Contains(StrEq("-funsafe-math-optimizations"))));
794216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
79588ab3844SJan Svoboda }
79688ab3844SJan Svoboda 
797216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) {
7984894e423SJan Svoboda   const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable",
79984a9ec2fSZahira Ammarguellat                         "-funsafe-math-optimizations", "-freciprocal-math"};
800dbfa69c5SJan Svoboda 
80133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8025746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().CLUnsafeMath);
803216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
8045746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
8055746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
80603692baeSJan Svoboda 
807f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
808dbfa69c5SJan Svoboda 
809216d4305SJan Svoboda   // Generated - explicitly provided.
810dbfa69c5SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
811216d4305SJan Svoboda   // Not generated - implied by their generated parent.
812dbfa69c5SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
81384a9ec2fSZahira Ammarguellat   ASSERT_THAT(GeneratedArgs,
81484a9ec2fSZahira Ammarguellat               Not(Contains(StrEq("-funsafe-math-optimizations"))));
815216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
816216d4305SJan Svoboda }
817216d4305SJan Svoboda 
818216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) {
81984a9ec2fSZahira Ammarguellat   const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations",
820216d4305SJan Svoboda                         "-freciprocal-math"};
821216d4305SJan Svoboda 
82233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8235746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().CLUnsafeMath);
824216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
8255746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().UnsafeFPMath);
8265746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().AllowRecip);
827216d4305SJan Svoboda 
828216d4305SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
829216d4305SJan Svoboda   // Not generated - missing.
830216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs,
831216d4305SJan Svoboda               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
832216d4305SJan Svoboda   // Generated - explicitly provided.
833216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
83484a9ec2fSZahira Ammarguellat   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
835216d4305SJan Svoboda   // Not generated - implied by its generated parent.
836216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
837dbfa69c5SJan Svoboda }
838dbfa69c5SJan Svoboda 
839cf2bb223SJan Svoboda TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
84084a9ec2fSZahira Ammarguellat   const char *Args[] = {"-cl-mad-enable", "-funsafe-math-optimizations"};
84188ab3844SJan Svoboda 
84233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
84303692baeSJan Svoboda 
844f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
84588ab3844SJan Svoboda 
84688ab3844SJan Svoboda   // Present options that were not implied are generated.
84788ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
84884a9ec2fSZahira Ammarguellat   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-funsafe-math-optimizations")));
84988ab3844SJan Svoboda }
85097100646SJan Svoboda 
85197100646SJan Svoboda // Diagnostic option.
85297100646SJan Svoboda 
85397100646SJan Svoboda TEST_F(CommandLineTest, DiagnosticOptionPresent) {
85497100646SJan Svoboda   const char *Args[] = {"-verify=xyz"};
85597100646SJan Svoboda 
85697100646SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
85797100646SJan Svoboda 
85897100646SJan Svoboda   ASSERT_EQ(Invocation.getDiagnosticOpts().VerifyPrefixes,
85997100646SJan Svoboda             std::vector<std::string>({"xyz"}));
86097100646SJan Svoboda 
86197100646SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
86297100646SJan Svoboda 
86397100646SJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-verify=xyz"), 1));
86497100646SJan Svoboda }
8652154cffdSJan Svoboda 
8662154cffdSJan Svoboda // Option default depends on language standard.
8672154cffdSJan Svoboda 
8682154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsImplied) {
8692154cffdSJan Svoboda   const char *Args[] = {""};
8702154cffdSJan Svoboda 
8712154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8725746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().Digraphs);
8732154cffdSJan Svoboda 
8742154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8752154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
8762154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
8772154cffdSJan Svoboda }
8782154cffdSJan Svoboda 
8792154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsDisabled) {
8802154cffdSJan Svoboda   const char *Args[] = {"-fno-digraphs"};
8812154cffdSJan Svoboda 
8822154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8835746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().Digraphs);
8842154cffdSJan Svoboda 
8852154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8862154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-digraphs")));
8872154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
8882154cffdSJan Svoboda }
8892154cffdSJan Svoboda 
8902154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsNotImplied) {
8912154cffdSJan Svoboda   const char *Args[] = {"-std=c89"};
8922154cffdSJan Svoboda 
8932154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8945746002eSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts().Digraphs);
8952154cffdSJan Svoboda 
8962154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8972154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
8982154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
8992154cffdSJan Svoboda }
9002154cffdSJan Svoboda 
9012154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsEnabled) {
9022154cffdSJan Svoboda   const char *Args[] = {"-std=c89", "-fdigraphs"};
9032154cffdSJan Svoboda 
9042154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
9055746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().Digraphs);
9062154cffdSJan Svoboda 
9072154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
9082154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdigraphs")));
9092154cffdSJan Svoboda }
910ed863285SJan Svoboda 
9114295ae96SJan Svoboda struct DummyModuleFileExtension
9124295ae96SJan Svoboda     : public llvm::RTTIExtends<DummyModuleFileExtension, ModuleFileExtension> {
9134295ae96SJan Svoboda   static char ID;
9144295ae96SJan Svoboda 
9154295ae96SJan Svoboda   ModuleFileExtensionMetadata getExtensionMetadata() const override {
9164295ae96SJan Svoboda     return {};
9174295ae96SJan Svoboda   };
9184295ae96SJan Svoboda 
919655bea42SAlexandre Rames   void hashExtension(ExtensionHashBuilder &HBuilder) const override {}
9204295ae96SJan Svoboda 
9214295ae96SJan Svoboda   std::unique_ptr<ModuleFileExtensionWriter>
9224295ae96SJan Svoboda   createExtensionWriter(ASTWriter &Writer) override {
9234295ae96SJan Svoboda     return {};
9244295ae96SJan Svoboda   }
9254295ae96SJan Svoboda 
9264295ae96SJan Svoboda   std::unique_ptr<ModuleFileExtensionReader>
9274295ae96SJan Svoboda   createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
9284295ae96SJan Svoboda                         ASTReader &Reader, serialization::ModuleFile &Mod,
9294295ae96SJan Svoboda                         const llvm::BitstreamCursor &Stream) override {
9304295ae96SJan Svoboda     return {};
9314295ae96SJan Svoboda   }
9324295ae96SJan Svoboda };
9334295ae96SJan Svoboda 
9344295ae96SJan Svoboda char DummyModuleFileExtension::ID = 0;
9354295ae96SJan Svoboda 
9364295ae96SJan Svoboda TEST_F(CommandLineTest, TestModuleFileExtension) {
9374295ae96SJan Svoboda   const char *Args[] = {"-ftest-module-file-extension=first:2:1:0:first",
9384295ae96SJan Svoboda                         "-ftest-module-file-extension=second:3:2:1:second"};
9394295ae96SJan Svoboda 
9404295ae96SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
9414295ae96SJan Svoboda   ASSERT_THAT(Invocation.getFrontendOpts().ModuleFileExtensions.size(), 2);
9424295ae96SJan Svoboda 
9434295ae96SJan Svoboda   // Exercise the check that only serializes instances of
9444295ae96SJan Svoboda   // TestModuleFileExtension by providing an instance of another
9454295ae96SJan Svoboda   // ModuleFileExtension subclass.
9464295ae96SJan Svoboda   Invocation.getFrontendOpts().ModuleFileExtensions.push_back(
9474295ae96SJan Svoboda       std::make_shared<DummyModuleFileExtension>());
9484295ae96SJan Svoboda 
9494295ae96SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
9504295ae96SJan Svoboda 
9514295ae96SJan Svoboda   ASSERT_THAT(GeneratedArgs,
9524295ae96SJan Svoboda               ContainsN(HasSubstr("-ftest-module-file-extension="), 2));
9534295ae96SJan Svoboda   ASSERT_THAT(
9544295ae96SJan Svoboda       GeneratedArgs,
9554295ae96SJan Svoboda       Contains(StrEq("-ftest-module-file-extension=first:2:1:0:first")));
9564295ae96SJan Svoboda   ASSERT_THAT(
9574295ae96SJan Svoboda       GeneratedArgs,
9584295ae96SJan Svoboda       Contains(StrEq("-ftest-module-file-extension=second:3:2:1:second")));
9594295ae96SJan Svoboda }
9604295ae96SJan Svoboda 
961ed863285SJan Svoboda TEST_F(CommandLineTest, RoundTrip) {
962ed863285SJan Svoboda   // Testing one marshalled and one manually generated option from each
963ed863285SJan Svoboda   // CompilerInvocation member.
964ed863285SJan Svoboda   const char *Args[] = {
965ed863285SJan Svoboda       "-round-trip-args",
966ed863285SJan Svoboda       // LanguageOptions
967ed863285SJan Svoboda       "-std=c17",
968ed863285SJan Svoboda       "-fmax-tokens=10",
969ed863285SJan Svoboda       // TargetOptions
970ed863285SJan Svoboda       "-target-sdk-version=1.2.3",
971ed863285SJan Svoboda       "-meabi",
972ed863285SJan Svoboda       "4",
973ed863285SJan Svoboda       // DiagnosticOptions
974ed863285SJan Svoboda       "-Wundef-prefix=XY",
975ed863285SJan Svoboda       "-fdiagnostics-format",
976ed863285SJan Svoboda       "clang",
977ed863285SJan Svoboda       // HeaderSearchOptions
978ed863285SJan Svoboda       "-stdlib=libc++",
979ed863285SJan Svoboda       "-fimplicit-module-maps",
980ed863285SJan Svoboda       // PreprocessorOptions
981ed863285SJan Svoboda       "-DXY=AB",
982ed863285SJan Svoboda       "-include-pch",
983ed863285SJan Svoboda       "a.pch",
984ed863285SJan Svoboda       // AnalyzerOptions
985ed863285SJan Svoboda       "-analyzer-config",
986ed863285SJan Svoboda       "ctu-import-threshold=42",
987ed863285SJan Svoboda       "-unoptimized-cfg",
988ed863285SJan Svoboda       // MigratorOptions (no manually handled arguments)
989ed863285SJan Svoboda       "-no-ns-alloc-error",
990ed863285SJan Svoboda       // CodeGenOptions
991ed863285SJan Svoboda       "-debug-info-kind=limited",
992ed863285SJan Svoboda       "-debug-info-macro",
993ed863285SJan Svoboda       // DependencyOutputOptions
994ed863285SJan Svoboda       "--show-includes",
995ed863285SJan Svoboda       "-H",
996ed863285SJan Svoboda       // FileSystemOptions (no manually handled arguments)
997ed863285SJan Svoboda       "-working-directory",
998ed863285SJan Svoboda       "folder",
999ed863285SJan Svoboda       // FrontendOptions
1000ed863285SJan Svoboda       "-load",
1001ed863285SJan Svoboda       "plugin",
1002ed863285SJan Svoboda       "-ast-merge",
1003ed863285SJan Svoboda       // PreprocessorOutputOptions
1004ed863285SJan Svoboda       "-dD",
1005ed863285SJan Svoboda       "-CC",
1006ed863285SJan Svoboda   };
1007ed863285SJan Svoboda 
1008ed863285SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1009ed863285SJan Svoboda 
10105746002eSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts().C17);
10115746002eSJan Svoboda   ASSERT_EQ(Invocation.getLangOpts().MaxTokens, 10u);
1012ed863285SJan Svoboda 
1013ed863285SJan Svoboda   ASSERT_EQ(Invocation.getTargetOpts().SDKVersion, llvm::VersionTuple(1, 2, 3));
1014ed863285SJan Svoboda   ASSERT_EQ(Invocation.getTargetOpts().EABIVersion, EABI::EABI4);
1015ed863285SJan Svoboda 
1016ed863285SJan Svoboda   ASSERT_THAT(Invocation.getDiagnosticOpts().UndefPrefixes,
1017ed863285SJan Svoboda               Contains(StrEq("XY")));
1018ed863285SJan Svoboda   ASSERT_EQ(Invocation.getDiagnosticOpts().getFormat(),
1019ed863285SJan Svoboda             TextDiagnosticFormat::Clang);
1020ed863285SJan Svoboda 
1021ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getHeaderSearchOpts().UseLibcxx);
1022ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getHeaderSearchOpts().ImplicitModuleMaps);
1023ed863285SJan Svoboda 
1024ed863285SJan Svoboda   ASSERT_THAT(Invocation.getPreprocessorOpts().Macros,
1025ed863285SJan Svoboda               Contains(std::make_pair(std::string("XY=AB"), false)));
1026ed863285SJan Svoboda   ASSERT_EQ(Invocation.getPreprocessorOpts().ImplicitPCHInclude, "a.pch");
1027ed863285SJan Svoboda 
10288e0c9bb9SJan Svoboda   ASSERT_EQ(Invocation.getAnalyzerOpts().Config["ctu-import-threshold"], "42");
10298e0c9bb9SJan Svoboda   ASSERT_TRUE(Invocation.getAnalyzerOpts().UnoptimizedCFG);
1030ed863285SJan Svoboda 
1031ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getMigratorOpts().NoNSAllocReallocError);
1032ed863285SJan Svoboda 
1033ed863285SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().getDebugInfo(),
1034ed863285SJan Svoboda             codegenoptions::DebugInfoKind::LimitedDebugInfo);
1035ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().MacroDebugInfo);
1036ed863285SJan Svoboda 
1037ed863285SJan Svoboda   ASSERT_EQ(Invocation.getDependencyOutputOpts().ShowIncludesDest,
1038ed863285SJan Svoboda             ShowIncludesDestination::Stdout);
1039ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getDependencyOutputOpts().ShowHeaderIncludes);
1040ed863285SJan Svoboda }
1041cc269433SJan Svoboda 
1042cc269433SJan Svoboda TEST_F(CommandLineTest, PluginArgsRoundTripDeterminism) {
1043cc269433SJan Svoboda   const char *Args[] = {
1044cc269433SJan Svoboda       "-plugin-arg-blink-gc-plugin", "no-members-in-stack-allocated",
1045cc269433SJan Svoboda       "-plugin-arg-find-bad-constructs", "checked-ptr-as-trivial-member",
1046cc269433SJan Svoboda       "-plugin-arg-find-bad-constructs", "check-ipc",
1047cc269433SJan Svoboda       // Enable round-trip to ensure '-plugin-arg' generation is deterministic.
1048cc269433SJan Svoboda       "-round-trip-args"};
1049cc269433SJan Svoboda 
1050cc269433SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1051cc269433SJan Svoboda }
10525845688eSKadir Cetinkaya 
10535845688eSKadir Cetinkaya TEST_F(CommandLineTest, WarningSuppressionMappings) {
10545845688eSKadir Cetinkaya   const char *Args[] = {"--warning-suppression-mappings=foo.txt"};
10555845688eSKadir Cetinkaya 
10565845688eSKadir Cetinkaya   EXPECT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
10575845688eSKadir Cetinkaya   EXPECT_EQ(Invocation.getDiagnosticOpts().DiagnosticSuppressionMappingsFile,
10585845688eSKadir Cetinkaya             "foo.txt");
10595845688eSKadir Cetinkaya 
10605845688eSKadir Cetinkaya   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
10615845688eSKadir Cetinkaya   EXPECT_THAT(GeneratedArgs, Contains(StrEq(Args[0])));
10625845688eSKadir Cetinkaya }
106329125ddfSDaniel Grumberg } // anonymous namespace
1064