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