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"
1529125ddfSDaniel Grumberg #include "llvm/Support/Host.h"
1629125ddfSDaniel Grumberg 
1729125ddfSDaniel Grumberg #include "gmock/gmock.h"
1829125ddfSDaniel Grumberg #include "gtest/gtest.h"
1929125ddfSDaniel Grumberg 
2029125ddfSDaniel Grumberg using namespace llvm;
2129125ddfSDaniel Grumberg using namespace clang;
2229125ddfSDaniel Grumberg 
2329125ddfSDaniel Grumberg using ::testing::Contains;
24ce8c59e6SJan Svoboda using ::testing::HasSubstr;
2529125ddfSDaniel Grumberg using ::testing::StrEq;
2629125ddfSDaniel Grumberg 
2729125ddfSDaniel Grumberg namespace {
28cf2bb223SJan Svoboda class CommandLineTest : public ::testing::Test {
2929125ddfSDaniel Grumberg public:
3029125ddfSDaniel Grumberg   IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
3129125ddfSDaniel Grumberg   SmallVector<const char *, 32> GeneratedArgs;
3229125ddfSDaniel Grumberg   SmallVector<std::string, 32> GeneratedArgsStorage;
33f825ec86SJan Svoboda   CompilerInvocation Invocation;
3429125ddfSDaniel Grumberg 
operator ()(const Twine & Arg)3529125ddfSDaniel Grumberg   const char *operator()(const Twine &Arg) {
3629125ddfSDaniel Grumberg     return GeneratedArgsStorage.emplace_back(Arg.str()).c_str();
3729125ddfSDaniel Grumberg   }
3829125ddfSDaniel Grumberg 
CommandLineTest()39cf2bb223SJan Svoboda   CommandLineTest()
4003692baeSJan Svoboda       : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions(),
4103692baeSJan Svoboda                                                   new TextDiagnosticBuffer())) {
4203692baeSJan Svoboda   }
4329125ddfSDaniel Grumberg };
4429125ddfSDaniel Grumberg 
45c6ea4d5bSJan Svoboda template <typename M>
describeContainsN(M InnerMatcher,unsigned N,bool Negation)46c6ea4d5bSJan Svoboda std::string describeContainsN(M InnerMatcher, unsigned N, bool Negation) {
47c6ea4d5bSJan Svoboda   StringRef Contains = Negation ? "doesn't contain" : "contains";
48c6ea4d5bSJan Svoboda   StringRef Instance = N == 1 ? " instance " : " instances ";
49c6ea4d5bSJan Svoboda   StringRef Element = "of element that ";
50c6ea4d5bSJan Svoboda 
51c6ea4d5bSJan Svoboda   std::ostringstream Inner;
52c6ea4d5bSJan Svoboda   InnerMatcher.impl().DescribeTo(&Inner);
53c6ea4d5bSJan Svoboda 
54c6ea4d5bSJan Svoboda   return (Contains + " exactly " + Twine(N) + Instance + Element + Inner.str())
55c6ea4d5bSJan Svoboda       .str();
56c6ea4d5bSJan Svoboda }
57c6ea4d5bSJan Svoboda 
MATCHER_P2(ContainsN,InnerMatcher,N,describeContainsN (InnerMatcher,N,negation))58c6ea4d5bSJan Svoboda MATCHER_P2(ContainsN, InnerMatcher, N,
59c6ea4d5bSJan Svoboda            describeContainsN(InnerMatcher, N, negation)) {
60c6ea4d5bSJan Svoboda   auto InnerMatches = [this](const auto &Element) {
61c6ea4d5bSJan Svoboda     ::testing::internal::DummyMatchResultListener InnerListener;
62c6ea4d5bSJan Svoboda     return InnerMatcher.impl().MatchAndExplain(Element, &InnerListener);
63c6ea4d5bSJan Svoboda   };
64c6ea4d5bSJan Svoboda 
65c6ea4d5bSJan Svoboda   return count_if(arg, InnerMatches) == N;
66c6ea4d5bSJan Svoboda }
67c6ea4d5bSJan Svoboda 
TEST(ContainsN,Empty)68c6ea4d5bSJan Svoboda TEST(ContainsN, Empty) {
69c6ea4d5bSJan Svoboda   const char *Array[] = {""};
70c6ea4d5bSJan Svoboda 
71c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
72c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
73c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
74c6ea4d5bSJan Svoboda }
75c6ea4d5bSJan Svoboda 
TEST(ContainsN,Zero)76c6ea4d5bSJan Svoboda TEST(ContainsN, Zero) {
77c6ea4d5bSJan Svoboda   const char *Array[] = {"y"};
78c6ea4d5bSJan Svoboda 
79c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 0));
80c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
81c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
82c6ea4d5bSJan Svoboda }
83c6ea4d5bSJan Svoboda 
TEST(ContainsN,One)84c6ea4d5bSJan Svoboda TEST(ContainsN, One) {
85c6ea4d5bSJan Svoboda   const char *Array[] = {"a", "b", "x", "z"};
86c6ea4d5bSJan Svoboda 
87c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
88c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 1));
89c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 2)));
90c6ea4d5bSJan Svoboda }
91c6ea4d5bSJan Svoboda 
TEST(ContainsN,Two)92c6ea4d5bSJan Svoboda TEST(ContainsN, Two) {
93c6ea4d5bSJan Svoboda   const char *Array[] = {"x", "a", "b", "x"};
94c6ea4d5bSJan Svoboda 
95c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 0)));
96c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, Not(ContainsN(StrEq("x"), 1)));
97c6ea4d5bSJan Svoboda   ASSERT_THAT(Array, ContainsN(StrEq("x"), 2));
98c6ea4d5bSJan Svoboda }
99c6ea4d5bSJan Svoboda 
10026bbb870SJan Svoboda // Copy constructor/assignment perform deep copy of reference-counted pointers.
10109d1f6e6SJan Svoboda 
TEST(CompilerInvocationTest,DeepCopyConstructor)10209d1f6e6SJan Svoboda TEST(CompilerInvocationTest, DeepCopyConstructor) {
10309d1f6e6SJan Svoboda   CompilerInvocation A;
10409d1f6e6SJan Svoboda   A.getAnalyzerOpts()->Config["Key"] = "Old";
10509d1f6e6SJan Svoboda 
10609d1f6e6SJan Svoboda   CompilerInvocation B(A);
10709d1f6e6SJan Svoboda   B.getAnalyzerOpts()->Config["Key"] = "New";
10809d1f6e6SJan Svoboda 
10909d1f6e6SJan Svoboda   ASSERT_EQ(A.getAnalyzerOpts()->Config["Key"], "Old");
11009d1f6e6SJan Svoboda }
11109d1f6e6SJan Svoboda 
TEST(CompilerInvocationTest,DeepCopyAssignment)11226bbb870SJan Svoboda TEST(CompilerInvocationTest, DeepCopyAssignment) {
11326bbb870SJan Svoboda   CompilerInvocation A;
11426bbb870SJan Svoboda   A.getAnalyzerOpts()->Config["Key"] = "Old";
11526bbb870SJan Svoboda 
11626bbb870SJan Svoboda   CompilerInvocation B;
11726bbb870SJan Svoboda   B = A;
11826bbb870SJan Svoboda   B.getAnalyzerOpts()->Config["Key"] = "New";
11926bbb870SJan Svoboda 
12026bbb870SJan Svoboda   ASSERT_EQ(A.getAnalyzerOpts()->Config["Key"], "Old");
12126bbb870SJan Svoboda }
12226bbb870SJan Svoboda 
123216d4305SJan Svoboda // Boolean option with a keypath that defaults to true.
124216d4305SJan Svoboda // The only flag with a negative spelling can set the keypath to false.
125216d4305SJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultTrueSingleFlagNotPresent)126216d4305SJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagNotPresent) {
1274894e423SJan Svoboda   const char *Args[] = {""};
1282b84efa0SJan Svoboda 
12933f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
130f825ec86SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
131216d4305SJan Svoboda 
132216d4305SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
133216d4305SJan Svoboda 
134216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file"))));
1352b84efa0SJan Svoboda }
1362b84efa0SJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultTrueSingleFlagPresent)137216d4305SJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagPresent) {
1384894e423SJan Svoboda   const char *Args[] = {"-fno-temp-file"};
1392b84efa0SJan Svoboda 
14033f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
141f825ec86SJan Svoboda   ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary);
142216d4305SJan Svoboda 
143216d4305SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
144216d4305SJan Svoboda 
145216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
1462b84efa0SJan Svoboda }
1472b84efa0SJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultTrueSingleFlagUnknownPresent)148216d4305SJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagUnknownPresent) {
149216d4305SJan Svoboda   const char *Args[] = {"-ftemp-file"};
150dbfa69c5SJan Svoboda 
151216d4305SJan Svoboda   // Driver-only flag.
15233f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
153216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
154dbfa69c5SJan Svoboda }
155dbfa69c5SJan Svoboda 
1566f26a6deSJan Svoboda // Boolean option with a keypath that defaults to true.
1576f26a6deSJan Svoboda // The flag with negative spelling can set the keypath to false.
1586f26a6deSJan Svoboda // The flag with positive spelling can reset the keypath to true.
1596f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultTruePresentNone)1606f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNone) {
1616f26a6deSJan Svoboda   const char *Args[] = {""};
1626f26a6deSJan Svoboda 
16333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1646f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
1656f26a6deSJan Svoboda 
1666baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
1676baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
1686baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-autolink"))));
1696f26a6deSJan Svoboda }
1706f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultTruePresentNegChange)1716f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNegChange) {
1726f26a6deSJan Svoboda   const char *Args[] = {"-fno-autolink"};
1736f26a6deSJan Svoboda 
17433f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1756f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().Autolink);
1766f26a6deSJan Svoboda 
1776baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
1786baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-autolink")));
1796baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
1806f26a6deSJan Svoboda }
1816f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultTruePresentPosReset)1826f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultTruePresentPosReset) {
1836f26a6deSJan Svoboda   const char *Args[] = {"-fautolink"};
1846f26a6deSJan Svoboda 
18533f90f38SJan Svoboda   // Driver-only flag.
18633f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1876f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
1886f26a6deSJan Svoboda }
1896f26a6deSJan Svoboda 
1906f26a6deSJan Svoboda // Boolean option with a keypath that defaults to false.
1916f26a6deSJan Svoboda // The flag with negative spelling can set the keypath to true.
1926f26a6deSJan Svoboda // The flag with positive spelling can reset the keypath to false.
1936f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultFalsePresentNone)1946f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNone) {
1956f26a6deSJan Svoboda   const char *Args[] = {""};
1966f26a6deSJan Svoboda 
19733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
1986f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
1996f26a6deSJan Svoboda 
2006baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2016baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
2026baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-inline-line-tables"))));
2036f26a6deSJan Svoboda }
2046f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultFalsePresentNegChange)2056f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegChange) {
2066f26a6deSJan Svoboda   const char *Args[] = {"-gno-inline-line-tables"};
2076f26a6deSJan Svoboda 
20833f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2096f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().NoInlineLineTables);
2106f26a6deSJan Svoboda 
2116baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2126baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gno-inline-line-tables")));
2136baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
2146f26a6deSJan Svoboda }
2156f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultFalsePresentPosReset)2166f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosReset) {
2176f26a6deSJan Svoboda   const char *Args[] = {"-ginline-line-tables"};
2186f26a6deSJan Svoboda 
21933f90f38SJan Svoboda   // Driver-only flag.
22033f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2216f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
2226f26a6deSJan Svoboda }
2236f26a6deSJan Svoboda 
2246f26a6deSJan Svoboda // Boolean option with a keypath that defaults to false.
2256f26a6deSJan Svoboda // The flag with positive spelling can set the keypath to true.
2266f26a6deSJan Svoboda // The flag with negative spelling can reset the keypath to false.
2276f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultFalsePresentNoneX)2286f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNoneX) {
2296f26a6deSJan Svoboda   const char *Args[] = {""};
2306f26a6deSJan Svoboda 
23133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2326f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
2336f26a6deSJan Svoboda 
2346baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2356baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gcodeview-ghash"))));
2366baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
2376f26a6deSJan Svoboda }
2386f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultFalsePresentPosChange)2396f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosChange) {
2406f26a6deSJan Svoboda   const char *Args[] = {"-gcodeview-ghash"};
2416f26a6deSJan Svoboda 
24233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2436f26a6deSJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().CodeViewGHash);
2446f26a6deSJan Svoboda 
2456baa9769SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2466baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gcodeview-ghash")));
2476baa9769SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
2486f26a6deSJan Svoboda }
2496f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultFalsePresentNegReset)2506f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegReset) {
2516f26a6deSJan Svoboda   const char *Args[] = {"-gno-codeview-ghash"};
2526f26a6deSJan Svoboda 
25333f90f38SJan Svoboda   // Driver-only flag.
25433f90f38SJan Svoboda   ASSERT_FALSE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
2556f26a6deSJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
2566f26a6deSJan Svoboda }
2576f26a6deSJan Svoboda 
2586f26a6deSJan Svoboda // Boolean option with a keypath that defaults to an arbitrary expression.
2596f26a6deSJan Svoboda // The flag with positive spelling can set the keypath to true.
2606f26a6deSJan Svoboda // The flag with negative spelling can set the keypath to false.
2616f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultArbitraryTwoFlagsPresentNone)2626f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentNone) {
2636f26a6deSJan Svoboda   const char *Args = {""};
2646f26a6deSJan Svoboda 
26533f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
266*06285fc9SArthur Eubanks   ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
2676f26a6deSJan Svoboda 
2686f26a6deSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
2696f26a6deSJan Svoboda 
270*06285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
271*06285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
2726f26a6deSJan Svoboda }
2736f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultArbitraryTwoFlagsPresentChange)2746f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentChange) {
275*06285fc9SArthur Eubanks   const char *Args[] = {"-clear-ast-before-backend"};
2766f26a6deSJan Svoboda 
27733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
278*06285fc9SArthur Eubanks   ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, true);
2796f26a6deSJan Svoboda 
2806f26a6deSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
281*06285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-clear-ast-before-backend")));
282*06285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
2836f26a6deSJan Svoboda }
2846f26a6deSJan Svoboda 
TEST_F(CommandLineTest,BoolOptionDefaultArbitraryTwoFlagsPresentReset)2856f26a6deSJan Svoboda TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentReset) {
286*06285fc9SArthur Eubanks   const char *Args[] = {"-no-clear-ast-before-backend"};
2876f26a6deSJan Svoboda 
28833f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
289*06285fc9SArthur Eubanks   ASSERT_EQ(Invocation.getCodeGenOpts().ClearASTBeforeBackend, false);
2906f26a6deSJan Svoboda 
2916f26a6deSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
292*06285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-no-clear-ast-before-backend"))));
293*06285fc9SArthur Eubanks   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-clear-ast-before-backend"))));
2946f26a6deSJan Svoboda }
2956f26a6deSJan Svoboda 
29695114f21SJan Svoboda // Boolean option that gets the CC1Option flag from a let statement (which
29795114f21SJan Svoboda // is applied **after** the record is defined):
29895114f21SJan Svoboda //
29995114f21SJan Svoboda //   let Flags = [CC1Option] in {
30095114f21SJan Svoboda //     defm option : BoolOption<...>;
30195114f21SJan Svoboda //   }
30295114f21SJan Svoboda 
TEST_F(CommandLineTest,BoolOptionCC1ViaLetPresentNone)30395114f21SJan Svoboda TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) {
30495114f21SJan Svoboda   const char *Args[] = {""};
30595114f21SJan Svoboda 
30633f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
30795114f21SJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
30895114f21SJan Svoboda 
30995114f21SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
31095114f21SJan Svoboda 
31195114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
31295114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
31395114f21SJan Svoboda }
31495114f21SJan Svoboda 
TEST_F(CommandLineTest,BoolOptionCC1ViaLetPresentPos)31595114f21SJan Svoboda TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) {
31695114f21SJan Svoboda   const char *Args[] = {"-fdebug-pass-manager"};
31795114f21SJan Svoboda 
31833f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
31995114f21SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager);
32095114f21SJan Svoboda 
32195114f21SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
32295114f21SJan Svoboda 
323c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fdebug-pass-manager"), 1));
32495114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
32595114f21SJan Svoboda }
32695114f21SJan Svoboda 
TEST_F(CommandLineTest,BoolOptionCC1ViaLetPresentNeg)32795114f21SJan Svoboda TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) {
32895114f21SJan Svoboda   const char *Args[] = {"-fno-debug-pass-manager"};
32995114f21SJan Svoboda 
33033f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
33195114f21SJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
33295114f21SJan Svoboda 
33395114f21SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
33495114f21SJan Svoboda 
33595114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
33695114f21SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
33795114f21SJan Svoboda }
33895114f21SJan Svoboda 
TEST_F(CommandLineTest,CanGenerateCC1CommandLineFlag)339cf2bb223SJan Svoboda TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) {
3404894e423SJan Svoboda   const char *Args[] = {"-fmodules-strict-context-hash"};
34129125ddfSDaniel Grumberg 
34233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
34303692baeSJan Svoboda 
344f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
34529125ddfSDaniel Grumberg 
34629125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash")));
34729125ddfSDaniel Grumberg }
34829125ddfSDaniel Grumberg 
TEST_F(CommandLineTest,CanGenerateCC1CommandLineSeparate)349cf2bb223SJan Svoboda TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) {
35029125ddfSDaniel Grumberg   const char *TripleCStr = "i686-apple-darwin9";
3514894e423SJan Svoboda   const char *Args[] = {"-triple", TripleCStr};
35229125ddfSDaniel Grumberg 
35333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
35403692baeSJan Svoboda 
355f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
35629125ddfSDaniel Grumberg 
35729125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
35829125ddfSDaniel Grumberg }
35929125ddfSDaniel Grumberg 
TEST_F(CommandLineTest,CanGenerateCC1CommandLineSeparateRequiredPresent)360cf2bb223SJan Svoboda TEST_F(CommandLineTest,  CanGenerateCC1CommandLineSeparateRequiredPresent) {
36129125ddfSDaniel Grumberg   const std::string DefaultTriple =
36229125ddfSDaniel Grumberg       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
3634894e423SJan Svoboda   const char *Args[] = {"-triple", DefaultTriple.c_str()};
36429125ddfSDaniel Grumberg 
36533f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
36603692baeSJan Svoboda 
367f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
36829125ddfSDaniel Grumberg 
36929125ddfSDaniel Grumberg   // Triple should always be emitted even if it is the default
37029125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
37129125ddfSDaniel Grumberg }
37229125ddfSDaniel Grumberg 
TEST_F(CommandLineTest,CanGenerateCC1CommandLineSeparateRequiredAbsent)373cf2bb223SJan Svoboda TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
374e4e2d8e4SDaniel Grumberg   const std::string DefaultTriple =
375e4e2d8e4SDaniel Grumberg       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
3764894e423SJan Svoboda   const char *Args[] = {""};
37729125ddfSDaniel Grumberg 
37833f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
37903692baeSJan Svoboda 
380f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
38129125ddfSDaniel Grumberg 
38229125ddfSDaniel Grumberg   // Triple should always be emitted even if it is the default
38329125ddfSDaniel Grumberg   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
38429125ddfSDaniel Grumberg }
38529125ddfSDaniel Grumberg 
TEST_F(CommandLineTest,SeparateEnumNonDefault)386ce8c59e6SJan Svoboda TEST_F(CommandLineTest, SeparateEnumNonDefault) {
3874894e423SJan Svoboda   const char *Args[] = {"-mrelocation-model", "static"};
38829125ddfSDaniel Grumberg 
38933f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
390ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::Static);
39103692baeSJan Svoboda 
392f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
39329125ddfSDaniel Grumberg 
3945afff86dSJan Svoboda   // Non default relocation model.
395ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-mrelocation-model")));
3965afff86dSJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
397ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=static"))));
3985afff86dSJan Svoboda }
39929125ddfSDaniel Grumberg 
TEST_F(CommandLineTest,SeparateEnumDefault)400ce8c59e6SJan Svoboda TEST_F(CommandLineTest, SeparateEnumDefault) {
4014894e423SJan Svoboda   const char *Args[] = {"-mrelocation-model", "pic"};
40229125ddfSDaniel Grumberg 
40333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
404ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().RelocationModel, Reloc::Model::PIC_);
40503692baeSJan Svoboda 
4065afff86dSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
4075afff86dSJan Svoboda 
4085afff86dSJan Svoboda   // Default relocation model.
409ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model"))));
4105afff86dSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
411ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-mrelocation-model=pic"))));
412ce8c59e6SJan Svoboda }
413ce8c59e6SJan Svoboda 
TEST_F(CommandLineTest,JoinedEnumNonDefault)414ce8c59e6SJan Svoboda TEST_F(CommandLineTest, JoinedEnumNonDefault) {
415ce8c59e6SJan Svoboda   const char *Args[] = {"-fobjc-dispatch-method=non-legacy"};
416ce8c59e6SJan Svoboda 
41733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
418ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
419ce8c59e6SJan Svoboda             CodeGenOptions::NonLegacy);
420ce8c59e6SJan Svoboda 
421ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
422ce8c59e6SJan Svoboda 
423ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs,
424ce8c59e6SJan Svoboda               Contains(StrEq("-fobjc-dispatch-method=non-legacy")));
425ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
426ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("non-legacy"))));
427ce8c59e6SJan Svoboda }
428ce8c59e6SJan Svoboda 
TEST_F(CommandLineTest,JoinedEnumDefault)429ce8c59e6SJan Svoboda TEST_F(CommandLineTest, JoinedEnumDefault) {
430ce8c59e6SJan Svoboda   const char *Args[] = {"-fobjc-dispatch-method=legacy"};
431ce8c59e6SJan Svoboda 
43233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
433ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().getObjCDispatchMethod(),
434ce8c59e6SJan Svoboda             CodeGenOptions::Legacy);
435ce8c59e6SJan Svoboda 
436ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
437ce8c59e6SJan Svoboda 
438ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs,
439ce8c59e6SJan Svoboda               Not(Contains(StrEq("-fobjc-dispatch-method=legacy"))));
440ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fobjc-dispatch-method="))));
441ce8c59e6SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("legacy"))));
442ce8c59e6SJan Svoboda }
443ce8c59e6SJan Svoboda 
TEST_F(CommandLineTest,StringVectorEmpty)444ce8c59e6SJan Svoboda TEST_F(CommandLineTest, StringVectorEmpty) {
445ce8c59e6SJan Svoboda   const char *Args[] = {""};
446ce8c59e6SJan Svoboda 
44733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
448ce8c59e6SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles.empty());
449ce8c59e6SJan Svoboda 
450ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
451c6ea4d5bSJan Svoboda 
452c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-fmodule-map-file"))));
453ce8c59e6SJan Svoboda }
454ce8c59e6SJan Svoboda 
TEST_F(CommandLineTest,StringVectorSingle)455ce8c59e6SJan Svoboda TEST_F(CommandLineTest, StringVectorSingle) {
456ce8c59e6SJan Svoboda   const char *Args[] = {"-fmodule-map-file=a"};
457ce8c59e6SJan Svoboda 
45833f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
459ce8c59e6SJan Svoboda   ASSERT_EQ(Invocation.getFrontendOpts().ModuleMapFiles,
460ce8c59e6SJan Svoboda             std::vector<std::string>({"a"}));
461ce8c59e6SJan Svoboda 
462ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
463c6ea4d5bSJan Svoboda 
464c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
465c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 1));
466ce8c59e6SJan Svoboda }
467ce8c59e6SJan Svoboda 
TEST_F(CommandLineTest,StringVectorMultiple)468ce8c59e6SJan Svoboda TEST_F(CommandLineTest, StringVectorMultiple) {
469ce8c59e6SJan Svoboda   const char *Args[] = {"-fmodule-map-file=a", "-fmodule-map-file=b"};
470ce8c59e6SJan Svoboda 
47133f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
472ce8c59e6SJan Svoboda   ASSERT_TRUE(Invocation.getFrontendOpts().ModuleMapFiles ==
473ce8c59e6SJan Svoboda               std::vector<std::string>({"a", "b"}));
474ce8c59e6SJan Svoboda 
475ce8c59e6SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
476c6ea4d5bSJan Svoboda 
477c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=a"), 1));
478c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-fmodule-map-file=b"), 1));
479c6ea4d5bSJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(HasSubstr("-fmodule-map-file"), 2));
48063a24816SJan Svoboda }
48163a24816SJan Svoboda 
482a828fb46SJan Svoboda // CommaJoined option with MarshallingInfoStringVector.
483a828fb46SJan Svoboda 
TEST_F(CommandLineTest,StringVectorCommaJoinedNone)484a828fb46SJan Svoboda TEST_F(CommandLineTest, StringVectorCommaJoinedNone) {
485a828fb46SJan Svoboda   const char *Args[] = {""};
486a828fb46SJan Svoboda 
48733f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
488a828fb46SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->CommentOpts.BlockCommandNames.empty());
489a828fb46SJan Svoboda 
490a828fb46SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
491a828fb46SJan Svoboda 
492a828fb46SJan Svoboda   ASSERT_THAT(GeneratedArgs,
493a828fb46SJan Svoboda               Not(Contains(HasSubstr("-fcomment-block-commands"))));
494a828fb46SJan Svoboda }
495a828fb46SJan Svoboda 
TEST_F(CommandLineTest,StringVectorCommaJoinedSingle)496a828fb46SJan Svoboda TEST_F(CommandLineTest, StringVectorCommaJoinedSingle) {
497a828fb46SJan Svoboda   const char *Args[] = {"-fcomment-block-commands=x,y"};
498a828fb46SJan Svoboda 
49933f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
500a828fb46SJan Svoboda   ASSERT_EQ(Invocation.getLangOpts()->CommentOpts.BlockCommandNames,
501a828fb46SJan Svoboda             std::vector<std::string>({"x", "y"}));
502a828fb46SJan Svoboda 
503a828fb46SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
504a828fb46SJan Svoboda 
505a828fb46SJan Svoboda   ASSERT_THAT(GeneratedArgs,
506a828fb46SJan Svoboda               ContainsN(StrEq("-fcomment-block-commands=x,y"), 1));
507a828fb46SJan Svoboda }
508a828fb46SJan Svoboda 
TEST_F(CommandLineTest,StringVectorCommaJoinedMultiple)509a828fb46SJan Svoboda TEST_F(CommandLineTest, StringVectorCommaJoinedMultiple) {
510a828fb46SJan Svoboda   const char *Args[] = {"-fcomment-block-commands=x,y",
511a828fb46SJan Svoboda                         "-fcomment-block-commands=a,b"};
512a828fb46SJan Svoboda 
51333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
514a828fb46SJan Svoboda   ASSERT_EQ(Invocation.getLangOpts()->CommentOpts.BlockCommandNames,
515a828fb46SJan Svoboda             std::vector<std::string>({"x", "y", "a", "b"}));
516a828fb46SJan Svoboda 
517a828fb46SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
518a828fb46SJan Svoboda 
519a828fb46SJan Svoboda   ASSERT_THAT(GeneratedArgs,
520a828fb46SJan Svoboda               ContainsN(StrEq("-fcomment-block-commands=x,y,a,b"), 1));
521a828fb46SJan Svoboda }
522a828fb46SJan Svoboda 
52367a4c672SJan Svoboda // A flag that should be parsed only if a condition is met.
52467a4c672SJan Svoboda 
TEST_F(CommandLineTest,ConditionalParsingIfFalseFlagNotPresent)52567a4c672SJan Svoboda TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagNotPresent) {
52667a4c672SJan Svoboda   const char *Args[] = {""};
52767a4c672SJan Svoboda 
52867a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
52967a4c672SJan Svoboda 
53067a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
531c165a99aSAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsDevice);
532c165a99aSAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost);
53367a4c672SJan Svoboda   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_None);
53467a4c672SJan Svoboda 
53567a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
53667a4c672SJan Svoboda 
53767a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl"))));
53867a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
53967a4c672SJan Svoboda }
54067a4c672SJan Svoboda 
TEST_F(CommandLineTest,ConditionalParsingIfFalseFlagPresent)54167a4c672SJan Svoboda TEST_F(CommandLineTest, ConditionalParsingIfFalseFlagPresent) {
54267a4c672SJan Svoboda   const char *Args[] = {"-sycl-std=2017"};
54367a4c672SJan Svoboda 
54467a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
54567a4c672SJan Svoboda 
54667a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
547c165a99aSAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsDevice);
548c165a99aSAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost);
54967a4c672SJan Svoboda   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_None);
55067a4c672SJan Svoboda 
55167a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
55267a4c672SJan Svoboda 
553c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-device"))));
554c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
55567a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
55667a4c672SJan Svoboda }
55767a4c672SJan Svoboda 
TEST_F(CommandLineTest,ConditionalParsingIfNonsenseSyclStdArg)55863816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfNonsenseSyclStdArg) {
55963816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=garbage"};
56063816645SAaron Ballman 
56163816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
56263816645SAaron Ballman 
56363816645SAaron Ballman   ASSERT_TRUE(Diags->hasErrorOccurred());
56463816645SAaron Ballman   ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice);
56563816645SAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost);
56663816645SAaron Ballman   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_None);
56763816645SAaron Ballman 
56863816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
56963816645SAaron Ballman 
57063816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
57163816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
57263816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(HasSubstr("-sycl-std="))));
57363816645SAaron Ballman }
57463816645SAaron Ballman 
TEST_F(CommandLineTest,ConditionalParsingIfOddSyclStdArg1)57563816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg1) {
57663816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=121"};
57763816645SAaron Ballman 
57863816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
57963816645SAaron Ballman 
58063816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
58163816645SAaron Ballman   ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice);
58263816645SAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost);
58363816645SAaron Ballman   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017);
58463816645SAaron Ballman 
58563816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
58663816645SAaron Ballman 
58763816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
58863816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
58963816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
59063816645SAaron Ballman }
59163816645SAaron Ballman 
TEST_F(CommandLineTest,ConditionalParsingIfOddSyclStdArg2)59263816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg2) {
59363816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=1.2.1"};
59463816645SAaron Ballman 
59563816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
59663816645SAaron Ballman 
59763816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
59863816645SAaron Ballman   ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice);
59963816645SAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost);
60063816645SAaron Ballman   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017);
60163816645SAaron Ballman 
60263816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
60363816645SAaron Ballman 
60463816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
60563816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
60663816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
60763816645SAaron Ballman }
60863816645SAaron Ballman 
TEST_F(CommandLineTest,ConditionalParsingIfOddSyclStdArg3)60963816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfOddSyclStdArg3) {
61063816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=sycl-1.2.1"};
61163816645SAaron Ballman 
61263816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
61363816645SAaron Ballman 
61463816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
61563816645SAaron Ballman   ASSERT_TRUE(Invocation.getLangOpts()->SYCLIsDevice);
61663816645SAaron Ballman   ASSERT_FALSE(Invocation.getLangOpts()->SYCLIsHost);
61763816645SAaron Ballman   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017);
61863816645SAaron Ballman 
61963816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
62063816645SAaron Ballman 
62163816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
62263816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fsycl-is-host"))));
62363816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=2017")));
62463816645SAaron Ballman }
62563816645SAaron Ballman 
TEST_F(CommandLineTest,ConditionalParsingIfTrueFlagNotPresentHost)62663816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentHost) {
627c165a99aSAaron Ballman   const char *Args[] = {"-fsycl-is-host"};
62867a4c672SJan Svoboda 
62967a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
63067a4c672SJan Svoboda 
63167a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
63263816645SAaron Ballman   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(),
63363816645SAaron Ballman             LangOptions::SYCL_Default);
63467a4c672SJan Svoboda 
63567a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
63667a4c672SJan Svoboda 
637c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-host")));
63863816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
63963816645SAaron Ballman }
64063816645SAaron Ballman 
TEST_F(CommandLineTest,ConditionalParsingIfTrueFlagNotPresentDevice)64163816645SAaron Ballman TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagNotPresentDevice) {
64263816645SAaron Ballman   const char *Args[] = {"-fsycl-is-device"};
64363816645SAaron Ballman 
64463816645SAaron Ballman   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
64563816645SAaron Ballman 
64663816645SAaron Ballman   ASSERT_FALSE(Diags->hasErrorOccurred());
64763816645SAaron Ballman   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(),
64863816645SAaron Ballman             LangOptions::SYCL_Default);
64963816645SAaron Ballman 
65063816645SAaron Ballman   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
65163816645SAaron Ballman 
65263816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
65363816645SAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(HasSubstr("-sycl-std=")));
65467a4c672SJan Svoboda }
65567a4c672SJan Svoboda 
TEST_F(CommandLineTest,ConditionalParsingIfTrueFlagPresent)65667a4c672SJan Svoboda TEST_F(CommandLineTest, ConditionalParsingIfTrueFlagPresent) {
657c165a99aSAaron Ballman   const char *Args[] = {"-fsycl-is-device", "-sycl-std=2017"};
65867a4c672SJan Svoboda 
65967a4c672SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
66067a4c672SJan Svoboda 
66167a4c672SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
66267a4c672SJan Svoboda   ASSERT_EQ(Invocation.getLangOpts()->getSYCLVersion(), LangOptions::SYCL_2017);
66367a4c672SJan Svoboda 
66467a4c672SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
66567a4c672SJan Svoboda 
666c165a99aSAaron Ballman   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fsycl-is-device")));
66767a4c672SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-sycl-std=2017")));
66867a4c672SJan Svoboda }
66967a4c672SJan Svoboda 
670f111cf99SJan Svoboda // Wide integer option.
671f111cf99SJan Svoboda 
TEST_F(CommandLineTest,WideIntegerHighValue)672f111cf99SJan Svoboda TEST_F(CommandLineTest, WideIntegerHighValue) {
673f111cf99SJan Svoboda   const char *Args[] = {"-fbuild-session-timestamp=1609827494445723662"};
674f111cf99SJan Svoboda 
675f111cf99SJan Svoboda   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
676f111cf99SJan Svoboda 
677f111cf99SJan Svoboda   ASSERT_FALSE(Diags->hasErrorOccurred());
678f111cf99SJan Svoboda   ASSERT_EQ(Invocation.getHeaderSearchOpts().BuildSessionTimestamp,
679f111cf99SJan Svoboda             1609827494445723662ull);
680f111cf99SJan Svoboda }
681f111cf99SJan Svoboda 
682216d4305SJan Svoboda // Tree of boolean options that can be (directly or transitively) implied by
683216d4305SJan Svoboda // their parent:
684216d4305SJan Svoboda //
685216d4305SJan Svoboda //   * -cl-unsafe-math-optimizations
686216d4305SJan Svoboda //     * -cl-mad-enable
687216d4305SJan Svoboda //     * -menable-unsafe-fp-math
688216d4305SJan Svoboda //       * -freciprocal-math
689216d4305SJan Svoboda 
TEST_F(CommandLineTest,ImpliedBoolOptionsNoFlagPresent)690216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) {
6914894e423SJan Svoboda   const char *Args[] = {""};
6922b84efa0SJan Svoboda 
69333f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
694216d4305SJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath);
695216d4305SJan Svoboda   ASSERT_FALSE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
696216d4305SJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts()->UnsafeFPMath);
697216d4305SJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts()->AllowRecip);
69803692baeSJan Svoboda 
699f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
7002b84efa0SJan Svoboda 
701216d4305SJan Svoboda   // Not generated - missing.
70288ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs,
70388ab3844SJan Svoboda               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
70488ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
70588ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
706216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
70788ab3844SJan Svoboda }
70888ab3844SJan Svoboda 
TEST_F(CommandLineTest,ImpliedBoolOptionsRootFlagPresent)709216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsRootFlagPresent) {
7104894e423SJan Svoboda   const char *Args[] = {"-cl-unsafe-math-optimizations"};
71188ab3844SJan Svoboda 
71233f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
713216d4305SJan Svoboda   // Explicitly provided root flag.
714216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath);
715216d4305SJan Svoboda   // Directly implied by explicitly provided root flag.
716216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
717216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath);
718216d4305SJan Svoboda   // Transitively implied by explicitly provided root flag.
719216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip);
72003692baeSJan Svoboda 
721f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
72288ab3844SJan Svoboda 
723216d4305SJan Svoboda   // Generated - explicitly provided.
72488ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
725216d4305SJan Svoboda   // Not generated - implied by the generated root flag.
72688ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
72788ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
728216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
72988ab3844SJan Svoboda }
73088ab3844SJan Svoboda 
TEST_F(CommandLineTest,ImpliedBoolOptionsAllFlagsPresent)731216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) {
7324894e423SJan Svoboda   const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable",
733216d4305SJan Svoboda                         "-menable-unsafe-fp-math", "-freciprocal-math"};
734dbfa69c5SJan Svoboda 
73533f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
736216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath);
737216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
738216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath);
739216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip);
74003692baeSJan Svoboda 
741f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
742dbfa69c5SJan Svoboda 
743216d4305SJan Svoboda   // Generated - explicitly provided.
744dbfa69c5SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
745216d4305SJan Svoboda   // Not generated - implied by their generated parent.
746dbfa69c5SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
747dbfa69c5SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
748216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
749216d4305SJan Svoboda }
750216d4305SJan Svoboda 
TEST_F(CommandLineTest,ImpliedBoolOptionsImpliedFlagsPresent)751216d4305SJan Svoboda TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) {
752216d4305SJan Svoboda   const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math",
753216d4305SJan Svoboda                         "-freciprocal-math"};
754216d4305SJan Svoboda 
75533f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
756216d4305SJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath);
757216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
758216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath);
759216d4305SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip);
760216d4305SJan Svoboda 
761216d4305SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
762216d4305SJan Svoboda   // Not generated - missing.
763216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs,
764216d4305SJan Svoboda               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
765216d4305SJan Svoboda   // Generated - explicitly provided.
766216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
767216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
768216d4305SJan Svoboda   // Not generated - implied by its generated parent.
769216d4305SJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
770dbfa69c5SJan Svoboda }
771dbfa69c5SJan Svoboda 
TEST_F(CommandLineTest,PresentAndNotImpliedGenerated)772cf2bb223SJan Svoboda TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
7734894e423SJan Svoboda   const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math"};
77488ab3844SJan Svoboda 
77533f90f38SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
77603692baeSJan Svoboda 
777f825ec86SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
77888ab3844SJan Svoboda 
77988ab3844SJan Svoboda   // Present options that were not implied are generated.
78088ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
78188ab3844SJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
78288ab3844SJan Svoboda }
78397100646SJan Svoboda 
78497100646SJan Svoboda // Diagnostic option.
78597100646SJan Svoboda 
TEST_F(CommandLineTest,DiagnosticOptionPresent)78697100646SJan Svoboda TEST_F(CommandLineTest, DiagnosticOptionPresent) {
78797100646SJan Svoboda   const char *Args[] = {"-verify=xyz"};
78897100646SJan Svoboda 
78997100646SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
79097100646SJan Svoboda 
79197100646SJan Svoboda   ASSERT_EQ(Invocation.getDiagnosticOpts().VerifyPrefixes,
79297100646SJan Svoboda             std::vector<std::string>({"xyz"}));
79397100646SJan Svoboda 
79497100646SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
79597100646SJan Svoboda 
79697100646SJan Svoboda   ASSERT_THAT(GeneratedArgs, ContainsN(StrEq("-verify=xyz"), 1));
79797100646SJan Svoboda }
7982154cffdSJan Svoboda 
7992154cffdSJan Svoboda // Option default depends on language standard.
8002154cffdSJan Svoboda 
TEST_F(CommandLineTest,DigraphsImplied)8012154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsImplied) {
8022154cffdSJan Svoboda   const char *Args[] = {""};
8032154cffdSJan Svoboda 
8042154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8052154cffdSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->Digraphs);
8062154cffdSJan Svoboda 
8072154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8082154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
8092154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
8102154cffdSJan Svoboda }
8112154cffdSJan Svoboda 
TEST_F(CommandLineTest,DigraphsDisabled)8122154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsDisabled) {
8132154cffdSJan Svoboda   const char *Args[] = {"-fno-digraphs"};
8142154cffdSJan Svoboda 
8152154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8162154cffdSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts()->Digraphs);
8172154cffdSJan Svoboda 
8182154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8192154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-digraphs")));
8202154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
8212154cffdSJan Svoboda }
8222154cffdSJan Svoboda 
TEST_F(CommandLineTest,DigraphsNotImplied)8232154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsNotImplied) {
8242154cffdSJan Svoboda   const char *Args[] = {"-std=c89"};
8252154cffdSJan Svoboda 
8262154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8272154cffdSJan Svoboda   ASSERT_FALSE(Invocation.getLangOpts()->Digraphs);
8282154cffdSJan Svoboda 
8292154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8302154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-digraphs"))));
8312154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdigraphs"))));
8322154cffdSJan Svoboda }
8332154cffdSJan Svoboda 
TEST_F(CommandLineTest,DigraphsEnabled)8342154cffdSJan Svoboda TEST_F(CommandLineTest, DigraphsEnabled) {
8352154cffdSJan Svoboda   const char *Args[] = {"-std=c89", "-fdigraphs"};
8362154cffdSJan Svoboda 
8372154cffdSJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8382154cffdSJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->Digraphs);
8392154cffdSJan Svoboda 
8402154cffdSJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8412154cffdSJan Svoboda   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdigraphs")));
8422154cffdSJan Svoboda }
843ed863285SJan Svoboda 
8444295ae96SJan Svoboda struct DummyModuleFileExtension
8454295ae96SJan Svoboda     : public llvm::RTTIExtends<DummyModuleFileExtension, ModuleFileExtension> {
8464295ae96SJan Svoboda   static char ID;
8474295ae96SJan Svoboda 
getExtensionMetadata__anon91b32dea0111::DummyModuleFileExtension8484295ae96SJan Svoboda   ModuleFileExtensionMetadata getExtensionMetadata() const override {
8494295ae96SJan Svoboda     return {};
8504295ae96SJan Svoboda   };
8514295ae96SJan Svoboda 
hashExtension__anon91b32dea0111::DummyModuleFileExtension852655bea42SAlexandre Rames   void hashExtension(ExtensionHashBuilder &HBuilder) const override {}
8534295ae96SJan Svoboda 
8544295ae96SJan Svoboda   std::unique_ptr<ModuleFileExtensionWriter>
createExtensionWriter__anon91b32dea0111::DummyModuleFileExtension8554295ae96SJan Svoboda   createExtensionWriter(ASTWriter &Writer) override {
8564295ae96SJan Svoboda     return {};
8574295ae96SJan Svoboda   }
8584295ae96SJan Svoboda 
8594295ae96SJan Svoboda   std::unique_ptr<ModuleFileExtensionReader>
createExtensionReader__anon91b32dea0111::DummyModuleFileExtension8604295ae96SJan Svoboda   createExtensionReader(const ModuleFileExtensionMetadata &Metadata,
8614295ae96SJan Svoboda                         ASTReader &Reader, serialization::ModuleFile &Mod,
8624295ae96SJan Svoboda                         const llvm::BitstreamCursor &Stream) override {
8634295ae96SJan Svoboda     return {};
8644295ae96SJan Svoboda   }
8654295ae96SJan Svoboda };
8664295ae96SJan Svoboda 
8674295ae96SJan Svoboda char DummyModuleFileExtension::ID = 0;
8684295ae96SJan Svoboda 
TEST_F(CommandLineTest,TestModuleFileExtension)8694295ae96SJan Svoboda TEST_F(CommandLineTest, TestModuleFileExtension) {
8704295ae96SJan Svoboda   const char *Args[] = {"-ftest-module-file-extension=first:2:1:0:first",
8714295ae96SJan Svoboda                         "-ftest-module-file-extension=second:3:2:1:second"};
8724295ae96SJan Svoboda 
8734295ae96SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
8744295ae96SJan Svoboda   ASSERT_THAT(Invocation.getFrontendOpts().ModuleFileExtensions.size(), 2);
8754295ae96SJan Svoboda 
8764295ae96SJan Svoboda   // Exercise the check that only serializes instances of
8774295ae96SJan Svoboda   // TestModuleFileExtension by providing an instance of another
8784295ae96SJan Svoboda   // ModuleFileExtension subclass.
8794295ae96SJan Svoboda   Invocation.getFrontendOpts().ModuleFileExtensions.push_back(
8804295ae96SJan Svoboda       std::make_shared<DummyModuleFileExtension>());
8814295ae96SJan Svoboda 
8824295ae96SJan Svoboda   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
8834295ae96SJan Svoboda 
8844295ae96SJan Svoboda   ASSERT_THAT(GeneratedArgs,
8854295ae96SJan Svoboda               ContainsN(HasSubstr("-ftest-module-file-extension="), 2));
8864295ae96SJan Svoboda   ASSERT_THAT(
8874295ae96SJan Svoboda       GeneratedArgs,
8884295ae96SJan Svoboda       Contains(StrEq("-ftest-module-file-extension=first:2:1:0:first")));
8894295ae96SJan Svoboda   ASSERT_THAT(
8904295ae96SJan Svoboda       GeneratedArgs,
8914295ae96SJan Svoboda       Contains(StrEq("-ftest-module-file-extension=second:3:2:1:second")));
8924295ae96SJan Svoboda }
8934295ae96SJan Svoboda 
TEST_F(CommandLineTest,RoundTrip)894ed863285SJan Svoboda TEST_F(CommandLineTest, RoundTrip) {
895ed863285SJan Svoboda   // Testing one marshalled and one manually generated option from each
896ed863285SJan Svoboda   // CompilerInvocation member.
897ed863285SJan Svoboda   const char *Args[] = {
898ed863285SJan Svoboda       "-round-trip-args",
899ed863285SJan Svoboda       // LanguageOptions
900ed863285SJan Svoboda       "-std=c17",
901ed863285SJan Svoboda       "-fmax-tokens=10",
902ed863285SJan Svoboda       // TargetOptions
903ed863285SJan Svoboda       "-target-sdk-version=1.2.3",
904ed863285SJan Svoboda       "-meabi",
905ed863285SJan Svoboda       "4",
906ed863285SJan Svoboda       // DiagnosticOptions
907ed863285SJan Svoboda       "-Wundef-prefix=XY",
908ed863285SJan Svoboda       "-fdiagnostics-format",
909ed863285SJan Svoboda       "clang",
910ed863285SJan Svoboda       // HeaderSearchOptions
911ed863285SJan Svoboda       "-stdlib=libc++",
912ed863285SJan Svoboda       "-fimplicit-module-maps",
913ed863285SJan Svoboda       // PreprocessorOptions
914ed863285SJan Svoboda       "-DXY=AB",
915ed863285SJan Svoboda       "-include-pch",
916ed863285SJan Svoboda       "a.pch",
917ed863285SJan Svoboda       // AnalyzerOptions
918ed863285SJan Svoboda       "-analyzer-config",
919ed863285SJan Svoboda       "ctu-import-threshold=42",
920ed863285SJan Svoboda       "-unoptimized-cfg",
921ed863285SJan Svoboda       // MigratorOptions (no manually handled arguments)
922ed863285SJan Svoboda       "-no-ns-alloc-error",
923ed863285SJan Svoboda       // CodeGenOptions
924ed863285SJan Svoboda       "-debug-info-kind=limited",
925ed863285SJan Svoboda       "-debug-info-macro",
926ed863285SJan Svoboda       // DependencyOutputOptions
927ed863285SJan Svoboda       "--show-includes",
928ed863285SJan Svoboda       "-H",
929ed863285SJan Svoboda       // FileSystemOptions (no manually handled arguments)
930ed863285SJan Svoboda       "-working-directory",
931ed863285SJan Svoboda       "folder",
932ed863285SJan Svoboda       // FrontendOptions
933ed863285SJan Svoboda       "-load",
934ed863285SJan Svoboda       "plugin",
935ed863285SJan Svoboda       "-ast-merge",
936ed863285SJan Svoboda       // PreprocessorOutputOptions
937ed863285SJan Svoboda       "-dD",
938ed863285SJan Svoboda       "-CC",
939ed863285SJan Svoboda   };
940ed863285SJan Svoboda 
941ed863285SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
942ed863285SJan Svoboda 
943ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getLangOpts()->C17);
944ed863285SJan Svoboda   ASSERT_EQ(Invocation.getLangOpts()->MaxTokens, 10u);
945ed863285SJan Svoboda 
946ed863285SJan Svoboda   ASSERT_EQ(Invocation.getTargetOpts().SDKVersion, llvm::VersionTuple(1, 2, 3));
947ed863285SJan Svoboda   ASSERT_EQ(Invocation.getTargetOpts().EABIVersion, EABI::EABI4);
948ed863285SJan Svoboda 
949ed863285SJan Svoboda   ASSERT_THAT(Invocation.getDiagnosticOpts().UndefPrefixes,
950ed863285SJan Svoboda               Contains(StrEq("XY")));
951ed863285SJan Svoboda   ASSERT_EQ(Invocation.getDiagnosticOpts().getFormat(),
952ed863285SJan Svoboda             TextDiagnosticFormat::Clang);
953ed863285SJan Svoboda 
954ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getHeaderSearchOpts().UseLibcxx);
955ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getHeaderSearchOpts().ImplicitModuleMaps);
956ed863285SJan Svoboda 
957ed863285SJan Svoboda   ASSERT_THAT(Invocation.getPreprocessorOpts().Macros,
958ed863285SJan Svoboda               Contains(std::make_pair(std::string("XY=AB"), false)));
959ed863285SJan Svoboda   ASSERT_EQ(Invocation.getPreprocessorOpts().ImplicitPCHInclude, "a.pch");
960ed863285SJan Svoboda 
961ed863285SJan Svoboda   ASSERT_EQ(Invocation.getAnalyzerOpts()->Config["ctu-import-threshold"], "42");
962ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getAnalyzerOpts()->UnoptimizedCFG);
963ed863285SJan Svoboda 
964ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getMigratorOpts().NoNSAllocReallocError);
965ed863285SJan Svoboda 
966ed863285SJan Svoboda   ASSERT_EQ(Invocation.getCodeGenOpts().getDebugInfo(),
967ed863285SJan Svoboda             codegenoptions::DebugInfoKind::LimitedDebugInfo);
968ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getCodeGenOpts().MacroDebugInfo);
969ed863285SJan Svoboda 
970ed863285SJan Svoboda   ASSERT_EQ(Invocation.getDependencyOutputOpts().ShowIncludesDest,
971ed863285SJan Svoboda             ShowIncludesDestination::Stdout);
972ed863285SJan Svoboda   ASSERT_TRUE(Invocation.getDependencyOutputOpts().ShowHeaderIncludes);
973ed863285SJan Svoboda }
974cc269433SJan Svoboda 
TEST_F(CommandLineTest,PluginArgsRoundTripDeterminism)975cc269433SJan Svoboda TEST_F(CommandLineTest, PluginArgsRoundTripDeterminism) {
976cc269433SJan Svoboda   const char *Args[] = {
977cc269433SJan Svoboda       "-plugin-arg-blink-gc-plugin", "no-members-in-stack-allocated",
978cc269433SJan Svoboda       "-plugin-arg-find-bad-constructs", "checked-ptr-as-trivial-member",
979cc269433SJan Svoboda       "-plugin-arg-find-bad-constructs", "check-ipc",
980cc269433SJan Svoboda       // Enable round-trip to ensure '-plugin-arg' generation is deterministic.
981cc269433SJan Svoboda       "-round-trip-args"};
982cc269433SJan Svoboda 
983cc269433SJan Svoboda   ASSERT_TRUE(CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags));
984cc269433SJan Svoboda }
98529125ddfSDaniel Grumberg } // anonymous namespace
986