• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- unittests/Lex/DependencyDirectivesSourceMinimizer.cpp -  -----------===//
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/Lex/DependencyDirectivesSourceMinimizer.h"
10 #include "llvm/ADT/SmallString.h"
11 #include "gtest/gtest.h"
12 
13 using namespace llvm;
14 using namespace clang;
15 using namespace clang::minimize_source_to_dependency_directives;
16 
17 namespace clang {
18 
minimizeSourceToDependencyDirectives(StringRef Input,SmallVectorImpl<char> & Out)19 bool minimizeSourceToDependencyDirectives(StringRef Input,
20                                           SmallVectorImpl<char> &Out) {
21   SmallVector<minimize_source_to_dependency_directives::Token, 32> Tokens;
22   return minimizeSourceToDependencyDirectives(Input, Out, Tokens);
23 }
24 
25 } // end namespace clang
26 
27 namespace {
28 
TEST(MinimizeSourceToDependencyDirectivesTest,Empty)29 TEST(MinimizeSourceToDependencyDirectivesTest, Empty) {
30   SmallVector<char, 128> Out;
31   SmallVector<Token, 4> Tokens;
32 
33   ASSERT_FALSE(minimizeSourceToDependencyDirectives("", Out, Tokens));
34   EXPECT_TRUE(Out.empty());
35   ASSERT_EQ(1u, Tokens.size());
36   ASSERT_EQ(pp_eof, Tokens.back().K);
37 
38   ASSERT_FALSE(
39       minimizeSourceToDependencyDirectives("abc def\nxyz", Out, Tokens));
40   EXPECT_TRUE(Out.empty());
41   ASSERT_EQ(1u, Tokens.size());
42   ASSERT_EQ(pp_eof, Tokens.back().K);
43 }
44 
TEST(MinimizeSourceToDependencyDirectivesTest,AllTokens)45 TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
46   SmallVector<char, 128> Out;
47   SmallVector<Token, 4> Tokens;
48 
49   ASSERT_FALSE(
50       minimizeSourceToDependencyDirectives("#define A\n"
51                                            "#undef A\n"
52                                            "#endif\n"
53                                            "#if A\n"
54                                            "#ifdef A\n"
55                                            "#ifndef A\n"
56                                            "#elif A\n"
57                                            "#else\n"
58                                            "#include <A>\n"
59                                            "#include_next <A>\n"
60                                            "#__include_macros <A>\n"
61                                            "#import <A>\n"
62                                            "@import A;\n"
63                                            "#pragma clang module import A\n"
64                                            "export module m;\n"
65                                            "import m;\n",
66                                            Out, Tokens));
67   EXPECT_EQ(pp_define, Tokens[0].K);
68   EXPECT_EQ(pp_undef, Tokens[1].K);
69   EXPECT_EQ(pp_endif, Tokens[2].K);
70   EXPECT_EQ(pp_if, Tokens[3].K);
71   EXPECT_EQ(pp_ifdef, Tokens[4].K);
72   EXPECT_EQ(pp_ifndef, Tokens[5].K);
73   EXPECT_EQ(pp_elif, Tokens[6].K);
74   EXPECT_EQ(pp_else, Tokens[7].K);
75   EXPECT_EQ(pp_include, Tokens[8].K);
76   EXPECT_EQ(pp_include_next, Tokens[9].K);
77   EXPECT_EQ(pp___include_macros, Tokens[10].K);
78   EXPECT_EQ(pp_import, Tokens[11].K);
79   EXPECT_EQ(decl_at_import, Tokens[12].K);
80   EXPECT_EQ(pp_pragma_import, Tokens[13].K);
81   EXPECT_EQ(cxx_export_decl, Tokens[14].K);
82   EXPECT_EQ(cxx_module_decl, Tokens[15].K);
83   EXPECT_EQ(cxx_import_decl, Tokens[16].K);
84   EXPECT_EQ(pp_eof, Tokens[17].K);
85 }
86 
TEST(MinimizeSourceToDependencyDirectivesTest,Define)87 TEST(MinimizeSourceToDependencyDirectivesTest, Define) {
88   SmallVector<char, 128> Out;
89   SmallVector<Token, 4> Tokens;
90 
91   ASSERT_FALSE(
92       minimizeSourceToDependencyDirectives("#define MACRO", Out, Tokens));
93   EXPECT_STREQ("#define MACRO\n", Out.data());
94   ASSERT_EQ(2u, Tokens.size());
95   ASSERT_EQ(pp_define, Tokens.front().K);
96 }
97 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineSpacing)98 TEST(MinimizeSourceToDependencyDirectivesTest, DefineSpacing) {
99   SmallVector<char, 128> Out;
100 
101   ASSERT_FALSE(
102       minimizeSourceToDependencyDirectives("#define MACRO\n\n\n", Out));
103   EXPECT_STREQ("#define MACRO\n", Out.data());
104 
105   ASSERT_FALSE(
106       minimizeSourceToDependencyDirectives("#define MACRO \n\n\n", Out));
107   EXPECT_STREQ("#define MACRO\n", Out.data());
108 
109   ASSERT_FALSE(
110       minimizeSourceToDependencyDirectives("#define MACRO a \n\n\n", Out));
111   EXPECT_STREQ("#define MACRO a\n", Out.data());
112 
113   ASSERT_FALSE(
114       minimizeSourceToDependencyDirectives("#define   MACRO\n\n\n", Out));
115   EXPECT_STREQ("#define MACRO\n", Out.data());
116 }
117 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineMacroArguments)118 TEST(MinimizeSourceToDependencyDirectivesTest, DefineMacroArguments) {
119   SmallVector<char, 128> Out;
120 
121   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO()", Out));
122   EXPECT_STREQ("#define MACRO()\n", Out.data());
123 
124   ASSERT_FALSE(
125       minimizeSourceToDependencyDirectives("#define MACRO(a, b...)", Out));
126   EXPECT_STREQ("#define MACRO(a,b...)\n", Out.data());
127 
128   ASSERT_FALSE(
129       minimizeSourceToDependencyDirectives("#define MACRO content", Out));
130   EXPECT_STREQ("#define MACRO content\n", Out.data());
131 
132   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
133       "#define MACRO   con  tent   ", Out));
134   EXPECT_STREQ("#define MACRO con  tent\n", Out.data());
135 
136   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
137       "#define MACRO()   con  tent   ", Out));
138   EXPECT_STREQ("#define MACRO() con  tent\n", Out.data());
139 }
140 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineInvalidMacroArguments)141 TEST(MinimizeSourceToDependencyDirectivesTest, DefineInvalidMacroArguments) {
142   SmallVector<char, 128> Out;
143 
144   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO((a))", Out));
145   EXPECT_STREQ("#define MACRO(/* invalid */\n", Out.data());
146 
147   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO(", Out));
148   EXPECT_STREQ("#define MACRO(/* invalid */\n", Out.data());
149 
150   ASSERT_FALSE(
151       minimizeSourceToDependencyDirectives("#define MACRO(a * b)", Out));
152   EXPECT_STREQ("#define MACRO(/* invalid */\n", Out.data());
153 }
154 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineHorizontalWhitespace)155 TEST(MinimizeSourceToDependencyDirectivesTest, DefineHorizontalWhitespace) {
156   SmallVector<char, 128> Out;
157 
158   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
159       "#define MACRO(\t)\tcon \t tent\t", Out));
160   EXPECT_STREQ("#define MACRO() con \t tent\n", Out.data());
161 
162   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
163       "#define MACRO(\f)\fcon \f tent\f", Out));
164   EXPECT_STREQ("#define MACRO() con \f tent\n", Out.data());
165 
166   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
167       "#define MACRO(\v)\vcon \v tent\v", Out));
168   EXPECT_STREQ("#define MACRO() con \v tent\n", Out.data());
169 
170   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
171       "#define MACRO \t\v\f\v\t con\f\t\vtent\v\f \v", Out));
172   EXPECT_STREQ("#define MACRO con\f\t\vtent\n", Out.data());
173 }
174 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineMultilineArgs)175 TEST(MinimizeSourceToDependencyDirectivesTest, DefineMultilineArgs) {
176   SmallVector<char, 128> Out;
177 
178   ASSERT_FALSE(
179       minimizeSourceToDependencyDirectives("#define MACRO(a        \\\n"
180                                            "              )",
181                                            Out));
182   EXPECT_STREQ("#define MACRO(a)\n", Out.data());
183 
184   ASSERT_FALSE(
185       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\n"
186                                            "              b)       \\\n"
187                                            "        call((a),      \\\n"
188                                            "             (b))",
189                                            Out));
190   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
191 }
192 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineMultilineArgsCarriageReturn)193 TEST(MinimizeSourceToDependencyDirectivesTest,
194      DefineMultilineArgsCarriageReturn) {
195   SmallVector<char, 128> Out;
196 
197   ASSERT_FALSE(
198       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\r"
199                                            "              b)       \\\r"
200                                            "        call((a),      \\\r"
201                                            "             (b))",
202                                            Out));
203   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
204 }
205 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineMultilineArgsStringize)206 TEST(MinimizeSourceToDependencyDirectivesTest, DefineMultilineArgsStringize) {
207   SmallVector<char, 128> Out;
208 
209   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO(a,b) \\\n"
210                                                     "                #a \\\n"
211                                                     "                #b",
212                                                     Out));
213   EXPECT_STREQ("#define MACRO(a,b) #a #b\n", Out.data());
214 }
215 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineMultilineArgsCarriageReturnNewline)216 TEST(MinimizeSourceToDependencyDirectivesTest,
217      DefineMultilineArgsCarriageReturnNewline) {
218   SmallVector<char, 128> Out;
219 
220   ASSERT_FALSE(
221       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\r\n"
222                                            "              b)       \\\r\n"
223                                            "        call((a),      \\\r\n"
224                                            "             (b))",
225                                            Out));
226   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
227 }
228 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineMultilineArgsNewlineCarriageReturn)229 TEST(MinimizeSourceToDependencyDirectivesTest,
230      DefineMultilineArgsNewlineCarriageReturn) {
231   SmallVector<char, 128> Out;
232 
233   ASSERT_FALSE(
234       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\n\r"
235                                            "              b)       \\\n\r"
236                                            "        call((a),      \\\n\r"
237                                            "             (b))",
238                                            Out));
239   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
240 }
241 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineNumber)242 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNumber) {
243   SmallVector<char, 128> Out;
244 
245   ASSERT_TRUE(minimizeSourceToDependencyDirectives("#define 0\n", Out));
246 }
247 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineNoName)248 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNoName) {
249   SmallVector<char, 128> Out;
250 
251   ASSERT_TRUE(minimizeSourceToDependencyDirectives("#define &\n", Out));
252 }
253 
TEST(MinimizeSourceToDependencyDirectivesTest,DefineNoWhitespace)254 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNoWhitespace) {
255   SmallVector<char, 128> Out;
256 
257   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define AND&\n", Out));
258   EXPECT_STREQ("#define AND &\n", Out.data());
259 
260   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define AND\\\n"
261                                                     "&\n",
262                                                     Out));
263   EXPECT_STREQ("#define AND &\n", Out.data());
264 }
265 
TEST(MinimizeSourceToDependencyDirectivesTest,MultilineComment)266 TEST(MinimizeSourceToDependencyDirectivesTest, MultilineComment) {
267   SmallVector<char, 128> Out;
268 
269   ASSERT_FALSE(
270       minimizeSourceToDependencyDirectives("#define MACRO a/*\n"
271                                            "  /*\n"
272                                            "#define MISSING abc\n"
273                                            "  /*\n"
274                                            "  /* something */ \n"
275                                            "#include  /* \"def\" */ <abc> \n",
276                                            Out));
277   EXPECT_STREQ("#define MACRO a\n"
278                "#include <abc>\n",
279                Out.data());
280 }
281 
TEST(MinimizeSourceToDependencyDirectivesTest,MultilineCommentInStrings)282 TEST(MinimizeSourceToDependencyDirectivesTest, MultilineCommentInStrings) {
283   SmallVector<char, 128> Out;
284 
285   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO1 \"/*\"\n"
286                                                     "#define MACRO2 \"*/\"\n",
287                                                     Out));
288   EXPECT_STREQ("#define MACRO1 \"/*\"\n"
289                "#define MACRO2 \"*/\"\n",
290                Out.data());
291 }
292 
TEST(MinimizeSourceToDependencyDirectivesTest,Ifdef)293 TEST(MinimizeSourceToDependencyDirectivesTest, Ifdef) {
294   SmallVector<char, 128> Out;
295 
296   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
297                                                     "#define B\n"
298                                                     "#endif\n",
299                                                     Out));
300   EXPECT_STREQ("#ifdef A\n"
301                "#define B\n"
302                "#endif\n",
303                Out.data());
304 
305   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
306                                                     "#define B\n"
307                                                     "#elif B\n"
308                                                     "#define C\n"
309                                                     "#elif C\n"
310                                                     "#define D\n"
311                                                     "#else\n"
312                                                     "#define E\n"
313                                                     "#endif\n",
314                                                     Out));
315   EXPECT_STREQ("#ifdef A\n"
316                "#define B\n"
317                "#elif B\n"
318                "#define C\n"
319                "#elif C\n"
320                "#define D\n"
321                "#else\n"
322                "#define E\n"
323                "#endif\n",
324                Out.data());
325 }
326 
TEST(MinimizeSourceToDependencyDirectivesTest,EmptyIfdef)327 TEST(MinimizeSourceToDependencyDirectivesTest, EmptyIfdef) {
328   SmallVector<char, 128> Out;
329 
330   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
331                                                     "void skip();\n"
332                                                     "#elif B\n"
333                                                     "#elif C\n"
334                                                     "#else D\n"
335                                                     "#endif\n",
336                                                     Out));
337   EXPECT_STREQ("#ifdef A\n"
338                "#elif B\n"
339                "#elif C\n"
340                "#endif\n",
341                Out.data());
342 }
343 
TEST(MinimizeSourceToDependencyDirectivesTest,Pragma)344 TEST(MinimizeSourceToDependencyDirectivesTest, Pragma) {
345   SmallVector<char, 128> Out;
346 
347   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#pragma A\n", Out));
348   EXPECT_STREQ("", Out.data());
349 
350   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#pragma clang\n", Out));
351   EXPECT_STREQ("", Out.data());
352 
353   ASSERT_FALSE(
354       minimizeSourceToDependencyDirectives("#pragma clang module\n", Out));
355   EXPECT_STREQ("", Out.data());
356 
357   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
358       "#pragma clang module impor\n", Out));
359   EXPECT_STREQ("", Out.data());
360 
361   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
362       "#pragma clang module import\n", Out));
363   EXPECT_STREQ("#pragma clang module import\n", Out.data());
364 }
365 
TEST(MinimizeSourceToDependencyDirectivesTest,Include)366 TEST(MinimizeSourceToDependencyDirectivesTest, Include) {
367   SmallVector<char, 128> Out;
368 
369   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include \"A\"\n", Out));
370   EXPECT_STREQ("#include \"A\"\n", Out.data());
371 
372   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include <A>\n", Out));
373   EXPECT_STREQ("#include <A>\n", Out.data());
374 
375   ASSERT_FALSE(
376       minimizeSourceToDependencyDirectives("#include_next <A>\n", Out));
377   EXPECT_STREQ("#include_next <A>\n", Out.data());
378 
379   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#import <A>\n", Out));
380   EXPECT_STREQ("#import <A>\n", Out.data());
381 
382   ASSERT_FALSE(
383       minimizeSourceToDependencyDirectives("#__include_macros <A>\n", Out));
384   EXPECT_STREQ("#__include_macros <A>\n", Out.data());
385 }
386 
TEST(MinimizeSourceToDependencyDirectivesTest,AtImport)387 TEST(MinimizeSourceToDependencyDirectivesTest, AtImport) {
388   SmallVector<char, 128> Out;
389 
390   ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A;\n", Out));
391   EXPECT_STREQ("@import A;\n", Out.data());
392 
393   ASSERT_FALSE(minimizeSourceToDependencyDirectives(" @ import  A;\n", Out));
394   EXPECT_STREQ("@import A;\n", Out.data());
395 
396   ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A\n;", Out));
397   EXPECT_STREQ("@import A;\n", Out.data());
398 
399   ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A.B;\n", Out));
400   EXPECT_STREQ("@import A.B;\n", Out.data());
401 
402   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
403       "@import /*x*/ A /*x*/ . /*x*/ B /*x*/ \n /*x*/ ; /*x*/", Out));
404   EXPECT_STREQ("@import A.B;\n", Out.data());
405 }
406 
TEST(MinimizeSourceToDependencyDirectivesTest,AtImportFailures)407 TEST(MinimizeSourceToDependencyDirectivesTest, AtImportFailures) {
408   SmallVector<char, 128> Out;
409 
410   ASSERT_TRUE(minimizeSourceToDependencyDirectives("@import A\n", Out));
411   ASSERT_TRUE(minimizeSourceToDependencyDirectives("@import MACRO(A);\n", Out));
412   ASSERT_TRUE(minimizeSourceToDependencyDirectives("@import \" \";\n", Out));
413 }
414 
TEST(MinimizeSourceToDependencyDirectivesTest,RawStringLiteral)415 TEST(MinimizeSourceToDependencyDirectivesTest, RawStringLiteral) {
416   SmallVector<char, 128> Out;
417 
418   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifndef GUARD\n"
419                                                     "#define GUARD\n"
420                                                     "R\"()\"\n"
421                                                     "#endif\n",
422                                                     Out));
423   EXPECT_STREQ("#ifndef GUARD\n"
424                "#define GUARD\n"
425                "#endif\n",
426                Out.data());
427 
428   bool RawStringLiteralResult = minimizeSourceToDependencyDirectives(
429       "#ifndef GUARD\n"
430       "#define GUARD\n"
431       R"raw(static constexpr char bytes[] = R"(-?:\,[]{}#&*!|>'"%@`)";)raw"
432       "\n"
433       "#endif\n",
434       Out);
435   ASSERT_FALSE(RawStringLiteralResult);
436   EXPECT_STREQ("#ifndef GUARD\n"
437                "#define GUARD\n"
438                "#endif\n",
439                Out.data());
440 
441   bool RawStringLiteralResult2 = minimizeSourceToDependencyDirectives(
442       "#ifndef GUARD\n"
443       "#define GUARD\n"
444       R"raw(static constexpr char bytes[] = R"abc(-?:\,[]{}#&*!|>'"%@`)abc";)raw"
445       "\n"
446       "#endif\n",
447       Out);
448   ASSERT_FALSE(RawStringLiteralResult2);
449   EXPECT_STREQ("#ifndef GUARD\n"
450                "#define GUARD\n"
451                "#endif\n",
452                Out.data());
453 }
454 
455 TEST(MinimizeSourceToDependencyDirectivesTest, SplitIdentifier) {
456   SmallVector<char, 128> Out;
457 
458   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#if\\\n"
459                                                     "ndef GUARD\n"
460                                                     "#define GUARD\n"
461                                                     "#endif\n",
462                                                     Out));
463   EXPECT_STREQ("#ifndef GUARD\n"
464                "#define GUARD\n"
465                "#endif\n",
466                Out.data());
467 
468   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n"
469                                                     "RD\n",
470                                                     Out));
471   EXPECT_STREQ("#define GUARD\n", Out.data());
472 
473   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\r"
474                                                     "RD\n",
475                                                     Out));
476   EXPECT_STREQ("#define GUARD\n", Out.data());
477 
478   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n"
479                                                     "           RD\n",
480                                                     Out));
481   EXPECT_STREQ("#define GUA RD\n", Out.data());
482 }
483 
484 TEST(MinimizeSourceToDependencyDirectivesTest,
485      WhitespaceAfterLineContinuationSlash) {
486   SmallVector<char, 128> Out;
487 
488   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define A 1 + \\  \n"
489                                                     "2 + \\\t\n"
490                                                     "3\n",
491                                                     Out));
492   EXPECT_STREQ("#define A 1 + 2 + 3\n", Out.data());
493 }
494 
495 TEST(MinimizeSourceToDependencyDirectivesTest, PoundWarningAndError) {
496   SmallVector<char, 128> Out;
497 
498   for (auto Source : {
499            "#warning '\n#include <t.h>\n",
500            "#warning \"\n#include <t.h>\n",
501            "#warning /*\n#include <t.h>\n",
502            "#warning \\\n#include <t.h>\n#include <t.h>\n",
503            "#error '\n#include <t.h>\n",
504            "#error \"\n#include <t.h>\n",
505            "#error /*\n#include <t.h>\n",
506            "#error \\\n#include <t.h>\n#include <t.h>\n",
507        }) {
508     ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
509     EXPECT_STREQ("#include <t.h>\n", Out.data());
510   }
511 
512   for (auto Source : {
513            "#warning \\\n#include <t.h>\n",
514            "#error \\\n#include <t.h>\n",
515        }) {
516     ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
517     EXPECT_STREQ("", Out.data());
518   }
519 
520   for (auto Source : {
521            "#if MACRO\n#warning '\n#endif\n",
522            "#if MACRO\n#warning \"\n#endif\n",
523            "#if MACRO\n#warning /*\n#endif\n",
524            "#if MACRO\n#error '\n#endif\n",
525            "#if MACRO\n#error \"\n#endif\n",
526            "#if MACRO\n#error /*\n#endif\n",
527        }) {
528     ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
529     EXPECT_STREQ("#if MACRO\n#endif\n", Out.data());
530   }
531 }
532 
TEST(MinimizeSourceToDependencyDirectivesTest,CharacterLiteral)533 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteral) {
534   SmallVector<char, 128> Out;
535 
536   StringRef Source = R"(
537 #include <bob>
538 int a = 0'1;
539 int b = 0xfa'af'fa;
540 int c = 12 ' ';
541 #include <foo>
542 )";
543   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
544   EXPECT_STREQ("#include <bob>\n#include <foo>\n", Out.data());
545 }
546 
TEST(MinimizeSourceToDependencyDirectivesTest,CharacterLiteralPrefixL)547 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixL) {
548   SmallVector<char, 128> Out;
549 
550   StringRef Source = R"(L'P'
551 #if DEBUG
552 // '
553 #endif
554 #include <test.h>
555 )";
556   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
557   EXPECT_STREQ("#if DEBUG\n#endif\n#include <test.h>\n", Out.data());
558 }
559 
TEST(MinimizeSourceToDependencyDirectivesTest,CharacterLiteralPrefixU)560 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixU) {
561   SmallVector<char, 128> Out;
562 
563   StringRef Source = R"(int x = U'P';
564 #include <test.h>
565 // '
566 )";
567   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
568   EXPECT_STREQ("#include <test.h>\n", Out.data());
569 }
570 
TEST(MinimizeSourceToDependencyDirectivesTest,CharacterLiteralPrefixu)571 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixu) {
572   SmallVector<char, 128> Out;
573 
574   StringRef Source = R"(int x = u'b';
575 int y = u8'a';
576 int z = 128'78;
577 #include <test.h>
578 // '
579 )";
580   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
581   EXPECT_STREQ("#include <test.h>\n", Out.data());
582 }
583 
TEST(MinimizeSourceToDependencyDirectivesTest,PragmaOnce)584 TEST(MinimizeSourceToDependencyDirectivesTest, PragmaOnce) {
585   SmallVector<char, 128> Out;
586   SmallVector<Token, 4> Tokens;
587 
588   StringRef Source = R"(// comment
589 #pragma once
590 // another comment
591 #include <test.h>
592 )";
593   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens));
594   EXPECT_STREQ("#pragma once\n#include <test.h>\n", Out.data());
595   ASSERT_EQ(Tokens.size(), 3u);
596   EXPECT_EQ(Tokens[0].K,
597             minimize_source_to_dependency_directives::pp_pragma_once);
598 
599   Source = R"(// comment
600     #pragma once extra tokens
601     // another comment
602     #include <test.h>
603     )";
604   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
605   EXPECT_STREQ("#pragma once\n#include <test.h>\n", Out.data());
606 }
607 
TEST(MinimizeSourceToDependencyDirectivesTest,SkipLineStringCharLiteralsUntilNewline)608 TEST(MinimizeSourceToDependencyDirectivesTest,
609      SkipLineStringCharLiteralsUntilNewline) {
610   SmallVector<char, 128> Out;
611 
612   StringRef Source = R"(#if NEVER_ENABLED
613     #define why(fmt, ...) #error don't try me
614     #endif
615 
616     void foo();
617 )";
618   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
619   EXPECT_STREQ(
620       "#if NEVER_ENABLED\n#define why(fmt,...) #error don't try me\n#endif\n",
621       Out.data());
622 
623   Source = R"(#if NEVER_ENABLED
624       #define why(fmt, ...) "quote dropped
625       #endif
626 
627       void foo();
628   )";
629   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
630   EXPECT_STREQ(
631       "#if NEVER_ENABLED\n#define why(fmt,...) \"quote dropped\n#endif\n",
632       Out.data());
633 }
634 
TEST(MinimizeSourceToDependencyDirectivesTest,SupportWhitespaceBeforeLineContinuationInStringSkipping)635 TEST(MinimizeSourceToDependencyDirectivesTest,
636      SupportWhitespaceBeforeLineContinuationInStringSkipping) {
637   SmallVector<char, 128> Out;
638 
639   StringRef Source = "#define X '\\ \t\nx'\nvoid foo() {}";
640   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
641   EXPECT_STREQ("#define X '\\ \t\nx'\n", Out.data());
642 
643   Source = "#define X \"\\ \r\nx\"\nvoid foo() {}";
644   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
645   EXPECT_STREQ("#define X \"\\ \r\nx\"\n", Out.data());
646 
647   Source = "#define X \"\\ \r\nx\n#include <x>\n";
648   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
649   EXPECT_STREQ("#define X \"\\ \r\nx\n#include <x>\n", Out.data());
650 }
651 
TEST(MinimizeSourceToDependencyDirectivesTest,CxxModules)652 TEST(MinimizeSourceToDependencyDirectivesTest, CxxModules) {
653   SmallVector<char, 128> Out;
654   SmallVector<Token, 4> Tokens;
655 
656   StringRef Source = R"(
657     module;
658     #include "textual-header.h"
659 
660     export module m;
661     exp\
662 ort \
663       import \
664       :l [[rename]];
665 
666     export void f();
667 
668     void h() {
669       import.a = 3;
670       import = 3;
671       import <<= 3;
672       import->a = 3;
673       import();
674       import . a();
675 
676       import a b d e d e f e;
677       import foo [[no_unique_address]];
678       import foo();
679       import f(:sefse);
680       import f(->a = 3);
681     }
682     )";
683   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens));
684   EXPECT_STREQ("#include \"textual-header.h\"\nexport module m;\n"
685                "export import :l [[rename]];\n"
686                "import <<= 3;\nimport a b d e d e f e;\n"
687                "import foo [[no_unique_address]];\nimport foo();\n"
688                "import f(:sefse);\nimport f(->a = 3);\n", Out.data());
689   ASSERT_EQ(Tokens.size(), 12u);
690   EXPECT_EQ(Tokens[0].K,
691             minimize_source_to_dependency_directives::pp_include);
692   EXPECT_EQ(Tokens[2].K,
693             minimize_source_to_dependency_directives::cxx_module_decl);
694 }
695 
TEST(MinimizeSourceToDependencyDirectivesTest,SkippedPPRangesBasic)696 TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesBasic) {
697   SmallString<128> Out;
698   SmallVector<Token, 32> Toks;
699   StringRef Source = "#ifndef GUARD\n"
700                      "#define GUARD\n"
701                      "void foo();\n"
702                      "#endif\n";
703   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Toks));
704   SmallVector<SkippedRange, 4> Ranges;
705   ASSERT_FALSE(computeSkippedRanges(Toks, Ranges));
706   EXPECT_EQ(Ranges.size(), 1u);
707   EXPECT_EQ(Ranges[0].Offset, 0);
708   EXPECT_EQ(Ranges[0].Length, (int)Out.find("#endif"));
709 }
710 
TEST(MinimizeSourceToDependencyDirectivesTest,SkippedPPRangesNested)711 TEST(MinimizeSourceToDependencyDirectivesTest, SkippedPPRangesNested) {
712   SmallString<128> Out;
713   SmallVector<Token, 32> Toks;
714   StringRef Source = "#ifndef GUARD\n"
715                      "#define GUARD\n"
716                      "#if FOO\n"
717                      "#include hello\n"
718                      "#elif BAR\n"
719                      "#include bye\n"
720                      "#endif\n"
721                      "#else\n"
722                      "#include nothing\n"
723                      "#endif\n";
724   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Toks));
725   SmallVector<SkippedRange, 4> Ranges;
726   ASSERT_FALSE(computeSkippedRanges(Toks, Ranges));
727   EXPECT_EQ(Ranges.size(), 4u);
728   EXPECT_EQ(Ranges[0].Offset, (int)Out.find("#if FOO"));
729   EXPECT_EQ(Ranges[0].Offset + Ranges[0].Length, (int)Out.find("#elif"));
730   EXPECT_EQ(Ranges[1].Offset, (int)Out.find("#elif BAR"));
731   EXPECT_EQ(Ranges[1].Offset + Ranges[1].Length, (int)Out.find("#endif"));
732   EXPECT_EQ(Ranges[2].Offset, 0);
733   EXPECT_EQ(Ranges[2].Length, (int)Out.find("#else"));
734   EXPECT_EQ(Ranges[3].Offset, (int)Out.find("#else"));
735   EXPECT_EQ(Ranges[3].Offset + Ranges[3].Length, (int)Out.rfind("#endif"));
736 }
737 
738 } // end anonymous namespace
739