xref: /llvm-project/clang/unittests/Frontend/CompilerInvocationTest.cpp (revision 4894e423e7b4b121bd4fb23cdba9870ff0f2a6b6)
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[] = {""};
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[] = {"-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[] = {"-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[] = {"-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[] = {"-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[] = {"-triple", DefaultTriple.c_str()};
95 
96   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
97 
98   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
99 
100   // Triple should always be emitted even if it is the default
101   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
102 }
103 
104 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
105   const std::string DefaultTriple =
106       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
107   const char *Args[] = {""};
108 
109   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
110 
111   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
112 
113   // Triple should always be emitted even if it is the default
114   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
115 }
116 
117 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateEnumNonDefault) {
118   const char *Args[] = {"-mrelocation-model", "static"};
119 
120   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
121 
122   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
123 
124   // Non default relocation model.
125   ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
126 }
127 
128 TEST_F(CommandLineTest, CanGenerateCC1COmmandLineSeparateEnumDefault) {
129   const char *Args[] = {"-mrelocation-model", "pic"};
130 
131   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
132 
133   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
134 
135   // Default relocation model.
136   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
137 }
138 
139 TEST_F(CommandLineTest, NotPresentNegativeFlagNotGenerated) {
140   const char *Args[] = {""};
141 
142   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
143 
144   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
145 
146   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file"))));
147 }
148 
149 TEST_F(CommandLineTest, PresentNegativeFlagGenerated) {
150   const char *Args[] = {"-fno-temp-file"};
151 
152   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
153 
154   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
155 
156   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
157 }
158 
159 TEST_F(CommandLineTest, NotPresentAndNotImpliedNotGenerated) {
160   const char *Args[] = {""};
161 
162   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
163 
164   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
165 
166   // Missing options are not generated.
167   ASSERT_THAT(GeneratedArgs,
168               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
169   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
170   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
171 }
172 
173 TEST_F(CommandLineTest, NotPresentAndImpliedNotGenerated) {
174   const char *Args[] = {"-cl-unsafe-math-optimizations"};
175 
176   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
177 
178   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
179 
180   // Missing options that were implied are not generated.
181   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
182   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
183   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
184 }
185 
186 TEST_F(CommandLineTest, PresentAndImpliedNotGenerated) {
187   const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable",
188                         "-menable-unsafe-fp-math"};
189 
190   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
191 
192   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
193 
194   // Present options that were also implied are not generated.
195   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
196   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
197   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
198 }
199 
200 TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
201   const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math"};
202 
203   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
204 
205   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
206 
207   // Present options that were not implied are generated.
208   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
209   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
210 }
211 } // anonymous namespace
212