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