xref: /llvm-project/clang/unittests/Frontend/CompilerInvocationTest.cpp (revision 5afff86d26163bc3ba93fb299ccfc2522d3fdc94)
1 //===- unittests/Frontend/CompilerInvocationTest.cpp - CI tests //---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "clang/Frontend/CompilerInvocation.h"
10 #include "clang/Frontend/CompilerInstance.h"
11 #include "llvm/Support/Host.h"
12 
13 #include "gmock/gmock.h"
14 #include "gtest/gtest.h"
15 
16 using namespace llvm;
17 using namespace clang;
18 
19 using ::testing::Contains;
20 using ::testing::StrEq;
21 
22 namespace {
23 class CommandLineTest : public ::testing::Test {
24 public:
25   IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
26   SmallVector<const char *, 32> GeneratedArgs;
27   SmallVector<std::string, 32> GeneratedArgsStorage;
28   CompilerInvocation Invocation;
29 
30   const char *operator()(const Twine &Arg) {
31     return GeneratedArgsStorage.emplace_back(Arg.str()).c_str();
32   }
33 
34   CommandLineTest()
35       : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions())) {}
36 };
37 
38 TEST_F(CommandLineTest, OptIsInitializedWithCustomDefaultValue) {
39   const char *Args[] = {"clang", "-xc++"};
40 
41   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
42 
43   ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
44 }
45 
46 TEST_F(CommandLineTest, OptOfNegativeFlagIsPopulatedWithFalse) {
47   const char *Args[] = {"clang", "-xc++", "-fno-temp-file"};
48 
49   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
50 
51   ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary);
52 }
53 
54 TEST_F(CommandLineTest, OptsOfImpliedPositiveFlagArePopulatedWithTrue) {
55   const char *Args[] = {"clang", "-xc++", "-cl-unsafe-math-optimizations"};
56 
57   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
58 
59   // Explicitly provided flag.
60   ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath);
61 
62   // Flags directly implied by explicitly provided flag.
63   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
64   ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath);
65 
66   // Flag transitively implied by explicitly provided flag.
67   ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip);
68 }
69 
70 TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) {
71   const char *Args[] = {"clang", "-xc++", "-fmodules-strict-context-hash", "-"};
72 
73   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
74 
75   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
76 
77   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash")));
78 }
79 
80 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) {
81   const char *TripleCStr = "i686-apple-darwin9";
82   const char *Args[] = {"clang", "-xc++", "-triple", TripleCStr, "-"};
83 
84   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
85 
86   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
87 
88   ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
89 }
90 
91 TEST_F(CommandLineTest,  CanGenerateCC1CommandLineSeparateRequiredPresent) {
92   const std::string DefaultTriple =
93       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
94   const char *Args[] = {"clang", "-xc++", "-triple", DefaultTriple.c_str(),
95                         "-"};
96 
97   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
98 
99   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
100 
101   // Triple should always be emitted even if it is the default
102   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
103 }
104 
105 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
106   const std::string DefaultTriple =
107       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
108   const char *Args[] = {"clang", "-xc++", "-"};
109 
110   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
111 
112   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
113 
114   // Triple should always be emitted even if it is the default
115   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
116 }
117 
118 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateEnumNonDefault) {
119   const char *Args[] = {"clang", "-xc++", "-mrelocation-model", "static", "-"};
120 
121   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
122 
123   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
124 
125   // Non default relocation model.
126   ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
127 }
128 
129 TEST_F(CommandLineTest, CanGenerateCC1COmmandLineSeparateEnumDefault) {
130   const char *Args[] = {"clang", "-xc++", "-mrelocation-model", "pic", "-"};
131 
132   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
133 
134   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
135 
136   // Default relocation model.
137   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
138 }
139 
140 TEST_F(CommandLineTest, NotPresentNegativeFlagNotGenerated) {
141   const char *Args[] = {"clang", "-xc++"};
142 
143   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
144 
145   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
146 
147   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file"))));
148 }
149 
150 TEST_F(CommandLineTest, PresentNegativeFlagGenerated) {
151   const char *Args[] = {"clang", "-xc++", "-fno-temp-file"};
152 
153   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
154 
155   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
156 
157   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
158 }
159 
160 TEST_F(CommandLineTest, NotPresentAndNotImpliedNotGenerated) {
161   const char *Args[] = {"clang", "-xc++"};
162 
163   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
164 
165   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
166 
167   // Missing options are not generated.
168   ASSERT_THAT(GeneratedArgs,
169               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
170   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
171   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
172 }
173 
174 TEST_F(CommandLineTest, NotPresentAndImpliedNotGenerated) {
175   const char *Args[] = {"clang", "-xc++", "-cl-unsafe-math-optimizations"};
176 
177   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
178 
179   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
180 
181   // Missing options that were implied are not generated.
182   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
183   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
184   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
185 }
186 
187 TEST_F(CommandLineTest, PresentAndImpliedNotGenerated) {
188   const char *Args[] = {"clang", "-xc++", "-cl-unsafe-math-optimizations",
189                         "-cl-mad-enable", "-menable-unsafe-fp-math"};
190 
191   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
192 
193   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
194 
195   // Present options that were also implied are not generated.
196   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
197   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
198   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
199 }
200 
201 TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
202   const char *Args[] = {"clang", "-xc++", "-cl-mad-enable",
203                         "-menable-unsafe-fp-math"};
204 
205   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
206 
207   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
208 
209   // Present options that were not implied are generated.
210   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
211   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
212 }
213 } // anonymous namespace
214