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