xref: /llvm-project/clang/unittests/Frontend/CompilerInvocationTest.cpp (revision 95114f21f5bf1704672dadb45ca7c25efca72e03)
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 "clang/Frontend/TextDiagnosticBuffer.h"
12 #include "llvm/Support/Host.h"
13 
14 #include "gmock/gmock.h"
15 #include "gtest/gtest.h"
16 
17 using namespace llvm;
18 using namespace clang;
19 
20 using ::testing::Contains;
21 using ::testing::StrEq;
22 
23 namespace {
24 class CommandLineTest : public ::testing::Test {
25 public:
26   IntrusiveRefCntPtr<DiagnosticsEngine> Diags;
27   SmallVector<const char *, 32> GeneratedArgs;
28   SmallVector<std::string, 32> GeneratedArgsStorage;
29   CompilerInvocation Invocation;
30 
31   const char *operator()(const Twine &Arg) {
32     return GeneratedArgsStorage.emplace_back(Arg.str()).c_str();
33   }
34 
35   CommandLineTest()
36       : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions(),
37                                                   new TextDiagnosticBuffer())) {
38   }
39 };
40 
41 // Boolean option with a keypath that defaults to true.
42 // The only flag with a negative spelling can set the keypath to false.
43 
44 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagNotPresent) {
45   const char *Args[] = {""};
46 
47   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
48 
49   ASSERT_FALSE(Diags->hasErrorOccurred());
50   ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
51 
52   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
53 
54   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-temp-file"))));
55 }
56 
57 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagPresent) {
58   const char *Args[] = {"-fno-temp-file"};
59 
60   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
61 
62   ASSERT_FALSE(Diags->hasErrorOccurred());
63   ASSERT_FALSE(Invocation.getFrontendOpts().UseTemporary);
64 
65   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
66 
67   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-temp-file")));
68 }
69 
70 TEST_F(CommandLineTest, BoolOptionDefaultTrueSingleFlagUnknownPresent) {
71   const char *Args[] = {"-ftemp-file"};
72 
73   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
74 
75   // Driver-only flag.
76   ASSERT_TRUE(Diags->hasErrorOccurred());
77   ASSERT_TRUE(Invocation.getFrontendOpts().UseTemporary);
78 }
79 
80 // Boolean option with a keypath that defaults to true.
81 // The flag with negative spelling can set the keypath to false.
82 // The flag with positive spelling can reset the keypath to true.
83 
84 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNone) {
85   const char *Args[] = {""};
86 
87   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
88   ASSERT_FALSE(Diags->hasErrorOccurred());
89   ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
90 
91   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
92   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
93   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-autolink"))));
94 }
95 
96 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentNegChange) {
97   const char *Args[] = {"-fno-autolink"};
98 
99   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
100   ASSERT_FALSE(Diags->hasErrorOccurred());
101   ASSERT_FALSE(Invocation.getCodeGenOpts().Autolink);
102 
103   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
104   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fno-autolink")));
105   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fautolink"))));
106 }
107 
108 TEST_F(CommandLineTest, BoolOptionDefaultTruePresentPosReset) {
109   const char *Args[] = {"-fautolink"};
110 
111   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
112   ASSERT_TRUE(Diags->hasErrorOccurred()); // Driver-only flag.
113   ASSERT_TRUE(Invocation.getCodeGenOpts().Autolink);
114 }
115 
116 // Boolean option with a keypath that defaults to false.
117 // The flag with negative spelling can set the keypath to true.
118 // The flag with positive spelling can reset the keypath to false.
119 
120 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNone) {
121   const char *Args[] = {""};
122 
123   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
124   ASSERT_FALSE(Diags->hasErrorOccurred());
125   ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
126 
127   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
128   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
129   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-inline-line-tables"))));
130 }
131 
132 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegChange) {
133   const char *Args[] = {"-gno-inline-line-tables"};
134 
135   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
136   ASSERT_FALSE(Diags->hasErrorOccurred());
137   ASSERT_TRUE(Invocation.getCodeGenOpts().NoInlineLineTables);
138 
139   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
140   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gno-inline-line-tables")));
141   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-ginline-line-tables"))));
142 }
143 
144 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosReset) {
145   const char *Args[] = {"-ginline-line-tables"};
146 
147   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
148   ASSERT_TRUE(Diags->hasErrorOccurred()); // Driver-only flag.
149   ASSERT_FALSE(Invocation.getCodeGenOpts().NoInlineLineTables);
150 }
151 
152 // Boolean option with a keypath that defaults to false.
153 // The flag with positive spelling can set the keypath to true.
154 // The flag with negative spelling can reset the keypath to false.
155 
156 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNoneX) {
157   const char *Args[] = {""};
158 
159   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
160   ASSERT_FALSE(Diags->hasErrorOccurred());
161   ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
162 
163   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
164   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gcodeview-ghash"))));
165   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
166 }
167 
168 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentPosChange) {
169   const char *Args[] = {"-gcodeview-ghash"};
170 
171   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
172   ASSERT_FALSE(Diags->hasErrorOccurred());
173   ASSERT_TRUE(Invocation.getCodeGenOpts().CodeViewGHash);
174 
175   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
176   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-gcodeview-ghash")));
177   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-gno-codeview-ghash"))));
178 }
179 
180 TEST_F(CommandLineTest, BoolOptionDefaultFalsePresentNegReset) {
181   const char *Args[] = {"-gno-codeview-ghash"};
182 
183   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
184   ASSERT_TRUE(Diags->hasErrorOccurred()); // Driver-only flag.
185   ASSERT_FALSE(Invocation.getCodeGenOpts().CodeViewGHash);
186 }
187 
188 // Boolean option with a keypath that defaults to an arbitrary expression.
189 // The flag with positive spelling can set the keypath to true.
190 // The flag with negative spelling can set the keypath to false.
191 
192 static constexpr unsigned PassManagerDefault =
193     !static_cast<unsigned>(LLVM_ENABLE_NEW_PASS_MANAGER);
194 
195 static constexpr const char *PassManagerResetByFlag =
196     LLVM_ENABLE_NEW_PASS_MANAGER ? "-fno-legacy-pass-manager"
197                                  : "-flegacy-pass-manager";
198 
199 static constexpr const char *PassManagerChangedByFlag =
200     LLVM_ENABLE_NEW_PASS_MANAGER ? "-flegacy-pass-manager"
201                                  : "-fno-legacy-pass-manager";
202 
203 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentNone) {
204   const char *Args = {""};
205 
206   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
207 
208   ASSERT_FALSE(Diags->hasErrorOccurred());
209   ASSERT_EQ(Invocation.getCodeGenOpts().LegacyPassManager, PassManagerDefault);
210 
211   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
212 
213   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerResetByFlag))));
214   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerChangedByFlag))));
215 }
216 
217 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentChange) {
218   const char *Args[] = {PassManagerChangedByFlag};
219 
220   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
221   ASSERT_FALSE(Diags->hasErrorOccurred());
222   ASSERT_EQ(Invocation.getCodeGenOpts().LegacyPassManager, !PassManagerDefault);
223 
224   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
225   ASSERT_THAT(GeneratedArgs, Contains(StrEq(PassManagerChangedByFlag)));
226   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerResetByFlag))));
227 }
228 
229 TEST_F(CommandLineTest, BoolOptionDefaultArbitraryTwoFlagsPresentReset) {
230   const char *Args[] = {PassManagerResetByFlag};
231 
232   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
233   ASSERT_FALSE(Diags->hasErrorOccurred());
234   ASSERT_EQ(Invocation.getCodeGenOpts().LegacyPassManager, PassManagerDefault);
235 
236   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
237   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerResetByFlag))));
238   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq(PassManagerChangedByFlag))));
239 }
240 
241 // Boolean option that gets the CC1Option flag from a let statement (which
242 // is applied **after** the record is defined):
243 //
244 //   let Flags = [CC1Option] in {
245 //     defm option : BoolOption<...>;
246 //   }
247 
248 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNone) {
249   const char *Args[] = {""};
250 
251   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
252 
253   ASSERT_FALSE(Diags->hasErrorOccurred());
254   ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
255 
256   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
257 
258   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
259   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
260 }
261 
262 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentPos) {
263   const char *Args[] = {"-fdebug-pass-manager"};
264 
265   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
266 
267   ASSERT_FALSE(Diags->hasErrorOccurred());
268   ASSERT_TRUE(Invocation.getCodeGenOpts().DebugPassManager);
269 
270   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
271 
272   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fdebug-pass-manager")));
273   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
274 }
275 
276 TEST_F(CommandLineTest, BoolOptionCC1ViaLetPresentNeg) {
277   const char *Args[] = {"-fno-debug-pass-manager"};
278 
279   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
280 
281   ASSERT_FALSE(Diags->hasErrorOccurred());
282   ASSERT_FALSE(Invocation.getCodeGenOpts().DebugPassManager);
283 
284   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
285 
286   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fno-debug-pass-manager"))));
287   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-fdebug-pass-manager"))));
288 }
289 
290 TEST_F(CommandLineTest, CanGenerateCC1CommandLineFlag) {
291   const char *Args[] = {"-fmodules-strict-context-hash"};
292 
293   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
294 
295   ASSERT_FALSE(Diags->hasErrorOccurred());
296 
297   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
298 
299   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-fmodules-strict-context-hash")));
300 }
301 
302 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparate) {
303   const char *TripleCStr = "i686-apple-darwin9";
304   const char *Args[] = {"-triple", TripleCStr};
305 
306   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
307 
308   ASSERT_FALSE(Diags->hasErrorOccurred());
309 
310   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
311 
312   ASSERT_THAT(GeneratedArgs, Contains(StrEq(TripleCStr)));
313 }
314 
315 TEST_F(CommandLineTest,  CanGenerateCC1CommandLineSeparateRequiredPresent) {
316   const std::string DefaultTriple =
317       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
318   const char *Args[] = {"-triple", DefaultTriple.c_str()};
319 
320   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
321 
322   ASSERT_FALSE(Diags->hasErrorOccurred());
323 
324   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
325 
326   // Triple should always be emitted even if it is the default
327   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
328 }
329 
330 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateRequiredAbsent) {
331   const std::string DefaultTriple =
332       llvm::Triple::normalize(llvm::sys::getDefaultTargetTriple());
333   const char *Args[] = {""};
334 
335   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
336 
337   ASSERT_FALSE(Diags->hasErrorOccurred());
338 
339   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
340 
341   // Triple should always be emitted even if it is the default
342   ASSERT_THAT(GeneratedArgs, Contains(StrEq(DefaultTriple.c_str())));
343 }
344 
345 TEST_F(CommandLineTest, CanGenerateCC1CommandLineSeparateEnumNonDefault) {
346   const char *Args[] = {"-mrelocation-model", "static"};
347 
348   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
349 
350   ASSERT_FALSE(Diags->hasErrorOccurred());
351 
352   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
353 
354   // Non default relocation model.
355   ASSERT_THAT(GeneratedArgs, Contains(StrEq("static")));
356 }
357 
358 TEST_F(CommandLineTest, CanGenerateCC1COmmandLineSeparateEnumDefault) {
359   const char *Args[] = {"-mrelocation-model", "pic"};
360 
361   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
362 
363   ASSERT_FALSE(Diags->hasErrorOccurred());
364 
365   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
366 
367   // Default relocation model.
368   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("pic"))));
369 }
370 
371 // Tree of boolean options that can be (directly or transitively) implied by
372 // their parent:
373 //
374 //   * -cl-unsafe-math-optimizations
375 //     * -cl-mad-enable
376 //     * -menable-unsafe-fp-math
377 //       * -freciprocal-math
378 
379 TEST_F(CommandLineTest, ImpliedBoolOptionsNoFlagPresent) {
380   const char *Args[] = {""};
381 
382   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
383 
384   ASSERT_FALSE(Diags->hasErrorOccurred());
385   ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath);
386   ASSERT_FALSE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
387   ASSERT_FALSE(Invocation.getLangOpts()->UnsafeFPMath);
388   ASSERT_FALSE(Invocation.getLangOpts()->AllowRecip);
389 
390   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
391 
392   // Not generated - missing.
393   ASSERT_THAT(GeneratedArgs,
394               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
395   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
396   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
397   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
398 }
399 
400 TEST_F(CommandLineTest, ImpliedBoolOptionsRootFlagPresent) {
401   const char *Args[] = {"-cl-unsafe-math-optimizations"};
402 
403   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
404 
405   ASSERT_FALSE(Diags->hasErrorOccurred());
406   // Explicitly provided root flag.
407   ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath);
408   // Directly implied by explicitly provided root flag.
409   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
410   ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath);
411   // Transitively implied by explicitly provided root flag.
412   ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip);
413 
414   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
415 
416   // Generated - explicitly provided.
417   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
418   // Not generated - implied by the generated root flag.
419   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
420   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
421   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
422 }
423 
424 TEST_F(CommandLineTest, ImpliedBoolOptionsAllFlagsPresent) {
425   const char *Args[] = {"-cl-unsafe-math-optimizations", "-cl-mad-enable",
426                         "-menable-unsafe-fp-math", "-freciprocal-math"};
427 
428   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
429 
430   ASSERT_FALSE(Diags->hasErrorOccurred());
431   ASSERT_TRUE(Invocation.getLangOpts()->CLUnsafeMath);
432   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
433   ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath);
434   ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip);
435 
436   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
437 
438   // Generated - explicitly provided.
439   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
440   // Not generated - implied by their generated parent.
441   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
442   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
443   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
444 }
445 
446 TEST_F(CommandLineTest, ImpliedBoolOptionsImpliedFlagsPresent) {
447   const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math",
448                         "-freciprocal-math"};
449 
450   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
451   ASSERT_FALSE(Diags->hasErrorOccurred());
452   ASSERT_FALSE(Invocation.getLangOpts()->CLUnsafeMath);
453   ASSERT_TRUE(Invocation.getCodeGenOpts().LessPreciseFPMAD);
454   ASSERT_TRUE(Invocation.getLangOpts()->UnsafeFPMath);
455   ASSERT_TRUE(Invocation.getLangOpts()->AllowRecip);
456 
457   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
458   // Not generated - missing.
459   ASSERT_THAT(GeneratedArgs,
460               Not(Contains(StrEq("-cl-unsafe-math-optimizations"))));
461   // Generated - explicitly provided.
462   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
463   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
464   // Not generated - implied by its generated parent.
465   ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-freciprocal-math"))));
466 }
467 
468 TEST_F(CommandLineTest, PresentAndNotImpliedGenerated) {
469   const char *Args[] = {"-cl-mad-enable", "-menable-unsafe-fp-math"};
470 
471   CompilerInvocation::CreateFromArgs(Invocation, Args, *Diags);
472 
473   ASSERT_FALSE(Diags->hasErrorOccurred());
474 
475   Invocation.generateCC1CommandLine(GeneratedArgs, *this);
476 
477   // Present options that were not implied are generated.
478   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-mad-enable")));
479   ASSERT_THAT(GeneratedArgs, Contains(StrEq("-menable-unsafe-fp-math")));
480 }
481 } // anonymous namespace
482