xref: /llvm-project/clang/unittests/Lex/DependencyDirectivesScannerTest.cpp (revision d19e71db8a3de65de5da5d5bc4e1f9c1020c574c)
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 
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 
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 
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_STREQ("<TokBeforeEOF>\n", Out.data());
61   EXPECT_TRUE(Tokens.empty());
62   ASSERT_EQ(2u, Directives.size());
63   EXPECT_EQ(tokens_present_before_eof, Directives[0].Kind);
64   EXPECT_EQ(pp_eof, Directives[1].Kind);
65 }
66 
67 TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
68   SmallVector<char, 128> Out;
69   SmallVector<dependency_directives_scan::Token, 4> Tokens;
70   SmallVector<Directive, 4> Directives;
71 
72   ASSERT_FALSE(
73       minimizeSourceToDependencyDirectives("#define A\n"
74                                            "#undef A\n"
75                                            "#endif\n"
76                                            "#if A\n"
77                                            "#ifdef A\n"
78                                            "#ifndef A\n"
79                                            "#elifdef A\n"
80                                            "#elifndef A\n"
81                                            "#elif A\n"
82                                            "#else\n"
83                                            "#include <A>\n"
84                                            "#include_next <A>\n"
85                                            "#__include_macros <A>\n"
86                                            "#import <A>\n"
87                                            "@import A;\n"
88                                            "#pragma clang module import A\n"
89                                            "#pragma push_macro(A)\n"
90                                            "#pragma pop_macro(A)\n"
91                                            "#pragma include_alias(<A>, <B>)\n"
92                                            "export module m;\n"
93                                            "import m;\n"
94                                            "#pragma clang system_header\n",
95                                            Out, Tokens, Directives));
96   EXPECT_EQ(pp_define, Directives[0].Kind);
97   EXPECT_EQ(pp_undef, Directives[1].Kind);
98   EXPECT_EQ(pp_endif, Directives[2].Kind);
99   EXPECT_EQ(pp_if, Directives[3].Kind);
100   EXPECT_EQ(pp_ifdef, Directives[4].Kind);
101   EXPECT_EQ(pp_ifndef, Directives[5].Kind);
102   EXPECT_EQ(pp_elifdef, Directives[6].Kind);
103   EXPECT_EQ(pp_elifndef, Directives[7].Kind);
104   EXPECT_EQ(pp_elif, Directives[8].Kind);
105   EXPECT_EQ(pp_else, Directives[9].Kind);
106   EXPECT_EQ(pp_include, Directives[10].Kind);
107   EXPECT_EQ(pp_include_next, Directives[11].Kind);
108   EXPECT_EQ(pp___include_macros, Directives[12].Kind);
109   EXPECT_EQ(pp_import, Directives[13].Kind);
110   EXPECT_EQ(decl_at_import, Directives[14].Kind);
111   EXPECT_EQ(pp_pragma_import, Directives[15].Kind);
112   EXPECT_EQ(pp_pragma_push_macro, Directives[16].Kind);
113   EXPECT_EQ(pp_pragma_pop_macro, Directives[17].Kind);
114   EXPECT_EQ(pp_pragma_include_alias, Directives[18].Kind);
115   EXPECT_EQ(cxx_export_module_decl, Directives[19].Kind);
116   EXPECT_EQ(cxx_import_decl, Directives[20].Kind);
117   EXPECT_EQ(pp_pragma_system_header, Directives[21].Kind);
118   EXPECT_EQ(pp_eof, Directives[22].Kind);
119 }
120 
121 TEST(MinimizeSourceToDependencyDirectivesTest, EmptyHash) {
122   SmallVector<char, 128> Out;
123 
124   ASSERT_FALSE(
125       minimizeSourceToDependencyDirectives("#\n#define MACRO a\n", Out));
126   EXPECT_STREQ("#define MACRO a\n", Out.data());
127 }
128 
129 TEST(MinimizeSourceToDependencyDirectivesTest, HashHash) {
130   SmallVector<char, 128> Out;
131 
132   StringRef Source = R"(
133     #define S
134     #if 0
135       ##pragma cool
136       ##include "t.h"
137     #endif
138     #define E
139     )";
140   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
141   EXPECT_STREQ("#define S\n#if 0\n#endif\n#define E\n", Out.data());
142 }
143 
144 TEST(MinimizeSourceToDependencyDirectivesTest, Define) {
145   SmallVector<char, 128> Out;
146   SmallVector<dependency_directives_scan::Token, 4> Tokens;
147   SmallVector<Directive, 4> Directives;
148 
149   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO", Out,
150                                                     Tokens, Directives));
151   EXPECT_STREQ("#define MACRO\n", Out.data());
152   ASSERT_EQ(4u, Tokens.size());
153   ASSERT_EQ(2u, Directives.size());
154   ASSERT_EQ(pp_define, Directives.front().Kind);
155 }
156 
157 TEST(MinimizeSourceToDependencyDirectivesTest, DefineSpacing) {
158   SmallVector<char, 128> Out;
159 
160   ASSERT_FALSE(
161       minimizeSourceToDependencyDirectives("#define MACRO\n\n\n", Out));
162   EXPECT_STREQ("#define MACRO\n", Out.data());
163 
164   ASSERT_FALSE(
165       minimizeSourceToDependencyDirectives("#define MACRO \n\n\n", Out));
166   EXPECT_STREQ("#define MACRO\n", Out.data());
167 
168   ASSERT_FALSE(
169       minimizeSourceToDependencyDirectives("#define MACRO a \n\n\n", Out));
170   EXPECT_STREQ("#define MACRO a\n", Out.data());
171 
172   ASSERT_FALSE(
173       minimizeSourceToDependencyDirectives("#define   MACRO\n\n\n", Out));
174   EXPECT_STREQ("#define MACRO\n", Out.data());
175 }
176 
177 TEST(MinimizeSourceToDependencyDirectivesTest, DefineMacroArguments) {
178   SmallVector<char, 128> Out;
179 
180   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO()", Out));
181   EXPECT_STREQ("#define MACRO()\n", Out.data());
182 
183   ASSERT_FALSE(
184       minimizeSourceToDependencyDirectives("#define MACRO(a, b...)", Out));
185   EXPECT_STREQ("#define MACRO(a,b...)\n", Out.data());
186 
187   ASSERT_FALSE(
188       minimizeSourceToDependencyDirectives("#define MACRO content", Out));
189   EXPECT_STREQ("#define MACRO content\n", Out.data());
190 
191   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
192       "#define MACRO   con  tent   ", Out));
193   EXPECT_STREQ("#define MACRO con tent\n", Out.data());
194 
195   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
196       "#define MACRO()   con  tent   ", Out));
197   EXPECT_STREQ("#define MACRO() con tent\n", Out.data());
198 }
199 
200 TEST(MinimizeSourceToDependencyDirectivesTest, DefineInvalidMacroArguments) {
201   SmallVector<char, 128> Out;
202 
203   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO((a))", Out));
204   EXPECT_STREQ("#define MACRO((a))\n", Out.data());
205 
206   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO(", Out));
207   EXPECT_STREQ("#define MACRO(\n", Out.data());
208 
209   ASSERT_FALSE(
210       minimizeSourceToDependencyDirectives("#define MACRO(a * b)", Out));
211   EXPECT_STREQ("#define MACRO(a*b)\n", Out.data());
212 }
213 
214 TEST(MinimizeSourceToDependencyDirectivesTest, DefineHorizontalWhitespace) {
215   SmallVector<char, 128> Out;
216 
217   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
218       "#define MACRO(\t)\tcon \t tent\t", Out));
219   EXPECT_STREQ("#define MACRO() con tent\n", Out.data());
220 
221   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
222       "#define MACRO(\f)\fcon \f tent\f", Out));
223   EXPECT_STREQ("#define MACRO() con tent\n", Out.data());
224 
225   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
226       "#define MACRO(\v)\vcon \v tent\v", Out));
227   EXPECT_STREQ("#define MACRO() con tent\n", Out.data());
228 
229   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
230       "#define MACRO \t\v\f\v\t con\f\t\vtent\v\f \v", Out));
231   EXPECT_STREQ("#define MACRO con tent\n", Out.data());
232 }
233 
234 TEST(MinimizeSourceToDependencyDirectivesTest, DefineMultilineArgs) {
235   SmallVector<char, 128> Out;
236 
237   ASSERT_FALSE(
238       minimizeSourceToDependencyDirectives("#define MACRO(a        \\\n"
239                                            "              )",
240                                            Out));
241   EXPECT_STREQ("#define MACRO(a)\n", Out.data());
242 
243   ASSERT_FALSE(
244       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\n"
245                                            "              b)       \\\n"
246                                            "        call((a),      \\\n"
247                                            "             (b))",
248                                            Out));
249   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
250 }
251 
252 TEST(MinimizeSourceToDependencyDirectivesTest,
253      DefineMultilineArgsCarriageReturn) {
254   SmallVector<char, 128> Out;
255 
256   ASSERT_FALSE(
257       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\r"
258                                            "              b)       \\\r"
259                                            "        call((a),      \\\r"
260                                            "             (b))",
261                                            Out));
262   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
263 }
264 
265 TEST(MinimizeSourceToDependencyDirectivesTest, DefineMultilineArgsStringize) {
266   SmallVector<char, 128> Out;
267 
268   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO(a,b) \\\n"
269                                                     "                #a \\\n"
270                                                     "                #b",
271                                                     Out));
272   EXPECT_STREQ("#define MACRO(a,b) #a #b\n", Out.data());
273 }
274 
275 TEST(MinimizeSourceToDependencyDirectivesTest,
276      DefineMultilineArgsCarriageReturnNewline) {
277   SmallVector<char, 128> Out;
278 
279   ASSERT_FALSE(
280       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\r\n"
281                                            "              b)       \\\r\n"
282                                            "        call((a),      \\\r\n"
283                                            "             (b))",
284                                            Out));
285   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
286 }
287 
288 TEST(MinimizeSourceToDependencyDirectivesTest,
289      DefineMultilineArgsNewlineCarriageReturn) {
290   SmallVector<char, 128> Out;
291 
292   ASSERT_FALSE(
293       minimizeSourceToDependencyDirectives("#define MACRO(a,       \\\n\r"
294                                            "              b)       \\\n\r"
295                                            "        call((a),      \\\n\r"
296                                            "             (b))",
297                                            Out));
298   EXPECT_STREQ("#define MACRO(a,b) call((a), (b))\n", Out.data());
299 }
300 
301 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNumber) {
302   SmallVector<char, 128> Out;
303 
304   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define 0\n", Out));
305 }
306 
307 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNoName) {
308   SmallVector<char, 128> Out;
309 
310   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define &\n", Out));
311 }
312 
313 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNoWhitespace) {
314   SmallVector<char, 128> Out;
315 
316   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define AND&\n", Out));
317   EXPECT_STREQ("#define AND&\n", Out.data());
318 
319   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define AND\\\n"
320                                                     "&\n",
321                                                     Out));
322   EXPECT_STREQ("#define AND\\\n"
323                "&\n",
324                Out.data());
325 }
326 
327 TEST(MinimizeSourceToDependencyDirectivesTest, MultilineComment) {
328   SmallVector<char, 128> Out;
329 
330   ASSERT_FALSE(
331       minimizeSourceToDependencyDirectives("#define MACRO a/*\n"
332                                            "  /*\n"
333                                            "#define MISSING abc\n"
334                                            "  /*\n"
335                                            "  /* something */ \n"
336                                            "#include  /* \"def\" */ <abc> \n",
337                                            Out));
338   EXPECT_STREQ("#define MACRO a\n"
339                "#include <abc>\n",
340                Out.data());
341 }
342 
343 TEST(MinimizeSourceToDependencyDirectivesTest, MultilineCommentInStrings) {
344   SmallVector<char, 128> Out;
345 
346   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO1 \"/*\"\n"
347                                                     "#define MACRO2 \"*/\"\n",
348                                                     Out));
349   EXPECT_STREQ("#define MACRO1 \"/*\"\n"
350                "#define MACRO2 \"*/\"\n",
351                Out.data());
352 }
353 
354 TEST(MinimizeSourceToDependencyDirectivesTest, CommentSlashSlashStar) {
355   SmallVector<char, 128> Out;
356 
357   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
358       "#define MACRO 1 //* blah */\n", Out));
359   EXPECT_STREQ("#define MACRO 1\n", Out.data());
360 }
361 
362 TEST(MinimizeSourceToDependencyDirectivesTest, Ifdef) {
363   SmallVector<char, 128> Out;
364 
365   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
366                                                     "#define B\n"
367                                                     "#endif\n",
368                                                     Out));
369   EXPECT_STREQ("#ifdef A\n"
370                "#define B\n"
371                "#endif\n",
372                Out.data());
373 
374   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
375                                                     "#define B\n"
376                                                     "#elif B\n"
377                                                     "#define C\n"
378                                                     "#elif C\n"
379                                                     "#define D\n"
380                                                     "#else\n"
381                                                     "#define E\n"
382                                                     "#endif\n",
383                                                     Out));
384   EXPECT_STREQ("#ifdef A\n"
385                "#define B\n"
386                "#elif B\n"
387                "#define C\n"
388                "#elif C\n"
389                "#define D\n"
390                "#else\n"
391                "#define E\n"
392                "#endif\n",
393                Out.data());
394 }
395 
396 TEST(MinimizeSourceToDependencyDirectivesTest, Elifdef) {
397   SmallVector<char, 128> Out;
398 
399   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
400                                                     "#define B\n"
401                                                     "#elifdef C\n"
402                                                     "#define D\n"
403                                                     "#endif\n",
404                                                     Out));
405   EXPECT_STREQ("#ifdef A\n"
406                "#define B\n"
407                "#elifdef C\n"
408                "#define D\n"
409                "#endif\n",
410                Out.data());
411 
412   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
413                                                     "#define B\n"
414                                                     "#elifdef B\n"
415                                                     "#define C\n"
416                                                     "#elifndef C\n"
417                                                     "#define D\n"
418                                                     "#else\n"
419                                                     "#define E\n"
420                                                     "#endif\n",
421                                                     Out));
422   EXPECT_STREQ("#ifdef A\n"
423                "#define B\n"
424                "#elifdef B\n"
425                "#define C\n"
426                "#elifndef C\n"
427                "#define D\n"
428                "#else\n"
429                "#define E\n"
430                "#endif\n",
431                Out.data());
432 }
433 
434 TEST(MinimizeSourceToDependencyDirectivesTest, EmptyIfdef) {
435   SmallVector<char, 128> Out;
436 
437   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
438                                                     "void skip();\n"
439                                                     "#elif B\n"
440                                                     "#elif C\n"
441                                                     "#else D\n"
442                                                     "#endif\n",
443                                                     Out));
444   EXPECT_STREQ("#ifdef A\n"
445                "#elif B\n"
446                "#elif C\n"
447                "#endif\n",
448                Out.data());
449 }
450 
451 TEST(MinimizeSourceToDependencyDirectivesTest, EmptyElifdef) {
452   SmallVector<char, 128> Out;
453 
454   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
455                                                     "void skip();\n"
456                                                     "#elifdef B\n"
457                                                     "#elifndef C\n"
458                                                     "#else D\n"
459                                                     "#endif\n",
460                                                     Out));
461   EXPECT_STREQ("#ifdef A\n"
462                "#elifdef B\n"
463                "#elifndef C\n"
464                "#endif\n",
465                Out.data());
466 }
467 
468 TEST(MinimizeSourceToDependencyDirectivesTest, Pragma) {
469   SmallVector<char, 128> Out;
470 
471   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#pragma A\n", Out));
472   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
473 
474   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
475       "#pragma push_macro(\"MACRO\")\n", Out));
476   EXPECT_STREQ("#pragma push_macro(\"MACRO\")\n", Out.data());
477 
478   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
479       "#pragma pop_macro(\"MACRO\")\n", Out));
480   EXPECT_STREQ("#pragma pop_macro(\"MACRO\")\n", Out.data());
481 
482   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
483       "#pragma include_alias(\"A\", \"B\")\n", Out));
484   EXPECT_STREQ("#pragma include_alias(\"A\", \"B\")\n", Out.data());
485 
486   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
487       "#pragma include_alias(<A>, <B>)\n", Out));
488   EXPECT_STREQ("#pragma include_alias(<A>, <B>)\n", Out.data());
489 
490   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#pragma clang\n", Out));
491   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
492 
493   ASSERT_FALSE(
494       minimizeSourceToDependencyDirectives("#pragma clang module\n", Out));
495   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
496 
497   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
498       "#pragma clang module impor\n", Out));
499   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
500 
501   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
502       "#pragma clang module import\n", Out));
503   EXPECT_STREQ("#pragma clang module import\n", Out.data());
504 }
505 
506 TEST(MinimizeSourceToDependencyDirectivesTest, UnderscorePragma) {
507   SmallVector<char, 128> Out;
508 
509   ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_)", Out));
510   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
511   ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma)", Out));
512   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
513   ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma()", Out));
514   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
515   ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma())", Out));
516   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
517   ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma(")", Out));
518   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
519   ASSERT_FALSE(minimizeSourceToDependencyDirectives(R"(_Pragma("A"))", Out));
520   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
521 
522   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
523       R"x(_Pragma("push_macro(\"MACRO\")"))x", Out));
524   EXPECT_STREQ(R"x(_Pragma("push_macro(\"MACRO\")"))x"
525                "\n",
526                Out.data());
527 
528   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
529       R"x(_Pragma("pop_macro(\"MACRO\")"))x", Out));
530   EXPECT_STREQ(R"x(_Pragma("pop_macro(\"MACRO\")"))x"
531                "\n",
532                Out.data());
533 
534   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
535       R"x(_Pragma("include_alias(\"A\", \"B\")"))x", Out));
536   EXPECT_STREQ(R"x(_Pragma("include_alias(\"A\", \"B\")"))x"
537                "\n",
538                Out.data());
539 
540   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
541       R"x(_Pragma("include_alias(<A>, <B>)"))x", Out));
542   EXPECT_STREQ(R"x(_Pragma("include_alias(<A>, <B>)"))x"
543                "\n",
544                Out.data());
545 
546   ASSERT_FALSE(
547       minimizeSourceToDependencyDirectives(R"(_Pragma("clang"))", Out));
548   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
549 
550   ASSERT_FALSE(
551       minimizeSourceToDependencyDirectives(R"(_Pragma("clang module"))", Out));
552   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
553 
554   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
555       R"(_Pragma("clang module impor"))", Out));
556   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
557 
558   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
559       R"(_Pragma("clang module import"))", Out));
560   EXPECT_STREQ(R"(_Pragma("clang module import"))"
561                "\n",
562                Out.data());
563 
564   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
565       R"(_Pragma("clang \
566   module \
567   import"))",
568       Out));
569   EXPECT_STREQ(R"(_Pragma("clang \
570   module \
571   import"))"
572                "\n",
573                Out.data());
574 
575   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
576       R"(_Pragma(L"clang module import"))", Out));
577   EXPECT_STREQ(R"(_Pragma(L"clang module import"))"
578                "\n",
579                Out.data());
580 
581   // FIXME: u"" strings depend on using C11 language mode
582   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
583       R"(_Pragma(u"clang module import"))", Out));
584   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
585 
586   // R"()" strings are enabled by default.
587   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
588       R"(_Pragma(R"abc(clang module import)abc"))", Out));
589   EXPECT_STREQ(R"(_Pragma(R"abc(clang module import)abc"))"
590                "\n",
591                Out.data());
592 }
593 
594 TEST(MinimizeSourceToDependencyDirectivesTest, Include) {
595   SmallVector<char, 128> Out;
596 
597   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include \"A\"\n", Out));
598   EXPECT_STREQ("#include \"A\"\n", Out.data());
599 
600   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include <A>\n", Out));
601   EXPECT_STREQ("#include <A>\n", Out.data());
602 
603   ASSERT_FALSE(
604       minimizeSourceToDependencyDirectives("#include <A//A.h>\n", Out));
605   EXPECT_STREQ("#include <A//A.h>\n", Out.data());
606 
607   ASSERT_FALSE(
608       minimizeSourceToDependencyDirectives("#include \"A//A.h\"\n", Out));
609   EXPECT_STREQ("#include \"A//A.h\"\n", Out.data());
610 
611   ASSERT_FALSE(
612       minimizeSourceToDependencyDirectives("#include_next <A>\n", Out));
613   EXPECT_STREQ("#include_next <A>\n", Out.data());
614 
615   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#import <A>\n", Out));
616   EXPECT_STREQ("#import <A>\n", Out.data());
617 
618   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#import <A//A.h>\n", Out));
619   EXPECT_STREQ("#import <A//A.h>\n", Out.data());
620 
621   ASSERT_FALSE(
622       minimizeSourceToDependencyDirectives("#import \"A//A.h\"\n", Out));
623   EXPECT_STREQ("#import \"A//A.h\"\n", Out.data());
624 
625   ASSERT_FALSE(
626       minimizeSourceToDependencyDirectives("#__include_macros <A>\n", Out));
627   EXPECT_STREQ("#__include_macros <A>\n", Out.data());
628 
629   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include MACRO\n", Out));
630   EXPECT_STREQ("#include MACRO\n", Out.data());
631 }
632 
633 TEST(MinimizeSourceToDependencyDirectivesTest, AtImport) {
634   SmallVector<char, 128> Out;
635 
636   ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A;\n", Out));
637   EXPECT_STREQ("@import A;\n", Out.data());
638 
639   ASSERT_FALSE(minimizeSourceToDependencyDirectives(" @ import  A;\n", Out));
640   EXPECT_STREQ("@import A;\n", Out.data());
641 
642   ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A\n;", Out));
643   EXPECT_STREQ("@import A;\n", Out.data());
644 
645   ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A.B;\n", Out));
646   EXPECT_STREQ("@import A.B;\n", Out.data());
647 
648   ASSERT_FALSE(minimizeSourceToDependencyDirectives(
649       "@import /*x*/ A /*x*/ . /*x*/ B /*x*/ \n /*x*/ ; /*x*/", Out));
650   EXPECT_STREQ("@import A.B;\n", Out.data());
651 }
652 
653 TEST(MinimizeSourceToDependencyDirectivesTest, EmptyIncludesAndImports) {
654   SmallVector<char, 128> Out;
655 
656   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#import\n", Out));
657   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
658 
659   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include\n", Out));
660   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
661 
662   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
663                                                     "#import \n"
664                                                     "#endif\n",
665                                                     Out));
666   // The ifdef block is removed because it's "empty".
667   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
668 
669   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifdef A\n"
670                                                     "#import \n"
671                                                     "#define B\n"
672                                                     "#endif\n",
673                                                     Out));
674   EXPECT_STREQ("#ifdef A\n"
675                "#define B\n"
676                "#endif\n",
677                Out.data());
678 }
679 
680 TEST(MinimizeSourceToDependencyDirectivesTest, AtImportFailures) {
681   SmallVector<char, 128> Out;
682 
683   ASSERT_TRUE(minimizeSourceToDependencyDirectives("@import A\n", Out));
684   ASSERT_FALSE(
685       minimizeSourceToDependencyDirectives("@import MACRO(A);\n", Out));
686   ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import \" \";\n", Out));
687 }
688 
689 TEST(MinimizeSourceToDependencyDirectivesTest, RawStringLiteral) {
690   SmallVector<char, 128> Out;
691 
692   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifndef GUARD\n"
693                                                     "#define GUARD\n"
694                                                     "R\"()\"\n"
695                                                     "#endif\n",
696                                                     Out));
697   EXPECT_STREQ("#ifndef GUARD\n"
698                "#define GUARD\n"
699                "#endif\n",
700                Out.data());
701 
702   bool RawStringLiteralResult = minimizeSourceToDependencyDirectives(
703       "#ifndef GUARD\n"
704       "#define GUARD\n"
705       R"raw(static constexpr char bytes[] = R"(-?:\,[]{}#&*!|>'"%@`)";)raw"
706       "\n"
707       "#endif\n",
708       Out);
709   ASSERT_FALSE(RawStringLiteralResult);
710   EXPECT_STREQ("#ifndef GUARD\n"
711                "#define GUARD\n"
712                "#endif\n",
713                Out.data());
714 
715   bool RawStringLiteralResult2 = minimizeSourceToDependencyDirectives(
716       "#ifndef GUARD\n"
717       "#define GUARD\n"
718       R"raw(static constexpr char bytes[] = R"abc(-?:\,[]{}#&*!|>'"%@`)abc";)raw"
719       "\n"
720       "#endif\n",
721       Out);
722   ASSERT_FALSE(RawStringLiteralResult2);
723   EXPECT_STREQ("#ifndef GUARD\n"
724                "#define GUARD\n"
725                "#endif\n",
726                Out.data());
727 }
728 
729 TEST(MinimizeSourceToDependencyDirectivesTest, SplitIdentifier) {
730   SmallVector<char, 128> Out;
731 
732   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#if\\\n"
733                                                     "ndef GUARD\n"
734                                                     "#define GUARD\n"
735                                                     "#endif\n",
736                                                     Out));
737   EXPECT_STREQ("#if\\\n"
738                "ndef GUARD\n"
739                "#define GUARD\n"
740                "#endif\n",
741                Out.data());
742 
743   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n"
744                                                     "RD\n",
745                                                     Out));
746   EXPECT_STREQ("#define GUA\\\n"
747                "RD\n",
748                Out.data());
749 
750   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\r"
751                                                     "RD\n",
752                                                     Out));
753   EXPECT_STREQ("#define GUA\\\r"
754                "RD\n",
755                Out.data());
756 
757   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n"
758                                                     "           RD\n",
759                                                     Out));
760   EXPECT_STREQ("#define GUA RD\n", Out.data());
761 }
762 
763 TEST(MinimizeSourceToDependencyDirectivesTest,
764      WhitespaceAfterLineContinuationSlash) {
765   SmallVector<char, 128> Out;
766 
767   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define A 1 + \\  \n"
768                                                     "2 + \\\t\n"
769                                                     "3\n",
770                                                     Out));
771   EXPECT_STREQ("#define A 1+\\  \n"
772                "2+\\\t\n"
773                "3\n",
774                Out.data());
775 }
776 
777 TEST(MinimizeSourceToDependencyDirectivesTest, PoundWarningAndError) {
778   SmallVector<char, 128> Out;
779 
780   for (auto Source : {
781            "#warning '\n#include <t.h>\n",
782            "#warning \"\n#include <t.h>\n",
783            "#warning /*\n#include <t.h>\n",
784            "#warning \\\n#include <t.h>\n#include <t.h>\n",
785            "#error '\n#include <t.h>\n",
786            "#error \"\n#include <t.h>\n",
787            "#error /*\n#include <t.h>\n",
788            "#error \\\n#include <t.h>\n#include <t.h>\n",
789        }) {
790     ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
791     EXPECT_STREQ("#include <t.h>\n", Out.data());
792   }
793 
794   for (auto Source : {
795            "#warning \\\n#include <t.h>\n",
796            "#error \\\n#include <t.h>\n",
797        }) {
798     ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
799     EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
800   }
801 
802   for (auto Source : {
803            "#if MACRO\n#warning '\n#endif\n",
804            "#if MACRO\n#warning \"\n#endif\n",
805            "#if MACRO\n#warning /*\n#endif\n",
806            "#if MACRO\n#error '\n#endif\n",
807            "#if MACRO\n#error \"\n#endif\n",
808            "#if MACRO\n#error /*\n#endif\n",
809        }) {
810     ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
811     EXPECT_STREQ("#if MACRO\n#endif\n", Out.data());
812   }
813 }
814 
815 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteral) {
816   SmallVector<char, 128> Out;
817 
818   StringRef Source = R"(
819 #include <bob>
820 int a = 0'1;
821 int b = 0xfa'af'fa;
822 int c = 12 ' ';
823 #include <foo>
824 )";
825   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
826   EXPECT_STREQ("#include <bob>\n#include <foo>\n", Out.data());
827 }
828 
829 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixL) {
830   SmallVector<char, 128> Out;
831 
832   StringRef Source = R"(L'P'
833 #if DEBUG
834 // '
835 #endif
836 #include <test.h>
837 )";
838   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
839   EXPECT_STREQ("#if DEBUG\n#endif\n#include <test.h>\n", Out.data());
840 }
841 
842 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixU) {
843   SmallVector<char, 128> Out;
844 
845   StringRef Source = R"(int x = U'P';
846 #include <test.h>
847 // '
848 )";
849   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
850   EXPECT_STREQ("#include <test.h>\n", Out.data());
851 }
852 
853 TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixu) {
854   SmallVector<char, 128> Out;
855 
856   StringRef Source = R"(int x = u'b';
857 int y = u8'a';
858 int z = 128'78;
859 #include <test.h>
860 // '
861 )";
862   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
863   EXPECT_STREQ("#include <test.h>\n", Out.data());
864 }
865 
866 TEST(MinimizeSourceToDependencyDirectivesTest, PragmaOnce) {
867   SmallVector<char, 128> Out;
868   SmallVector<dependency_directives_scan::Token, 4> Tokens;
869   SmallVector<Directive, 4> Directives;
870 
871   StringRef Source = R"(// comment
872 #pragma once
873 // another comment
874 #include <test.h>
875 _Pragma("once")
876 )";
877   ASSERT_FALSE(
878       minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives));
879   EXPECT_STREQ("#pragma once\n#include <test.h>\n_Pragma(\"once\")\n",
880                Out.data());
881   ASSERT_EQ(Directives.size(), 4u);
882   EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_pragma_once);
883   EXPECT_EQ(Directives[2].Kind, dependency_directives_scan::pp_pragma_once);
884 
885   Source = R"(// comment
886     #pragma once extra tokens
887     // another comment
888     #include <test.h>
889     _Pragma("once") extra tokens
890     )";
891   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
892   EXPECT_STREQ("#pragma once extra tokens\n#include "
893                "<test.h>\n_Pragma(\"once\")<TokBeforeEOF>\n",
894                Out.data());
895 }
896 
897 TEST(MinimizeSourceToDependencyDirectivesTest,
898      SkipLineStringCharLiteralsUntilNewline) {
899   SmallVector<char, 128> Out;
900 
901   StringRef Source = R"(#if NEVER_ENABLED
902     #define why(fmt, ...) #error don't try me
903     #endif
904 
905     void foo();
906 )";
907   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
908   EXPECT_STREQ(
909       "#if NEVER_ENABLED\n#define why(fmt,...) #error don't try me\n#endif\n"
910       "<TokBeforeEOF>\n",
911       Out.data());
912 
913   Source = R"(#if NEVER_ENABLED
914       #define why(fmt, ...) "quote dropped
915       #endif
916 
917       void foo();
918   )";
919   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
920   EXPECT_STREQ(
921       "#if NEVER_ENABLED\n#define why(fmt,...) \"quote dropped\n#endif\n"
922       "<TokBeforeEOF>\n",
923       Out.data());
924 }
925 
926 TEST(MinimizeSourceToDependencyDirectivesTest,
927      SupportWhitespaceBeforeLineContinuation) {
928   SmallVector<char, 128> Out;
929 
930   ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define FOO(BAR) \\\n"
931                                                     "  #BAR\\\n"
932                                                     "  baz\n",
933                                                     Out));
934   EXPECT_STREQ("#define FOO(BAR) #BAR baz\n", Out.data());
935 }
936 
937 TEST(MinimizeSourceToDependencyDirectivesTest,
938      SupportWhitespaceBeforeLineContinuationInStringSkipping) {
939   SmallVector<char, 128> Out;
940 
941   StringRef Source = "#define X '\\ \t\nx'\nvoid foo() {}";
942   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
943   EXPECT_STREQ("#define X '\\ \t\nx'\n<TokBeforeEOF>\n", Out.data());
944 
945   Source = "#define X \"\\ \r\nx\"\nvoid foo() {}";
946   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
947   EXPECT_STREQ("#define X \"\\ \r\nx\"\n<TokBeforeEOF>\n", Out.data());
948 
949   Source = "#define X \"\\ \r\nx\n#include <x>\n";
950   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
951   EXPECT_STREQ("#define X\"\\ \r\nx\n#include <x>\n", Out.data());
952 }
953 
954 TEST(MinimizeSourceToDependencyDirectivesTest, CxxModules) {
955   SmallVector<char, 128> Out;
956   SmallVector<dependency_directives_scan::Token, 4> Tokens;
957   SmallVector<Directive, 4> Directives;
958 
959   StringRef Source = R"(
960     module;
961     #include "textual-header.h"
962 
963     export module m;
964     exp\
965 ort \
966       import \
967       :l [[rename]];
968 
969     export void f();
970 
971     void h() {
972       import.a = 3;
973       import = 3;
974       import <<= 3;
975       import->a = 3;
976       import();
977       import . a();
978 
979       import a b d e d e f e;
980       import foo [[no_unique_address]];
981       import foo();
982       import f(:sefse);
983       import f(->a = 3);
984     }
985     )";
986   ASSERT_FALSE(
987       minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives));
988   EXPECT_STREQ("#include \"textual-header.h\"\nexport module m;"
989                "exp\\\nort import:l[[rename]];"
990                "import<<=3;import a b d e d e f e;"
991                "import foo[[no_unique_address]];import foo();"
992                "import f(:sefse);import f(->a=3);"
993                "<TokBeforeEOF>\n",
994                Out.data());
995   ASSERT_EQ(Directives.size(), 11u);
996   EXPECT_EQ(Directives[0].Kind, pp_include);
997   EXPECT_EQ(Directives[1].Kind, cxx_export_module_decl);
998 }
999 
1000 TEST(MinimizeSourceToDependencyDirectivesTest, ObjCMethodArgs) {
1001   SmallVector<char, 128> Out;
1002 
1003   StringRef Source = R"(
1004     @interface SomeObjcClass
1005       - (void)func:(int)otherData
1006               module:(int)module
1007               import:(int)import;
1008     @end
1009   )";
1010 
1011   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
1012   // `module :` and `import :` not followed by an identifier are not treated as
1013   // directive lines because they can be method argument decls.
1014   EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
1015 }
1016 
1017 TEST(MinimizeSourceToDependencyDirectivesTest, TokensBeforeEOF) {
1018   SmallString<128> Out;
1019 
1020   StringRef Source = R"(
1021     #define A
1022     #ifdef B
1023     int x;
1024     #endif
1025     )";
1026   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
1027   EXPECT_STREQ("#define A\n<TokBeforeEOF>\n", Out.data());
1028 
1029   Source = R"(
1030     #ifndef A
1031     #define A
1032     #endif // some comment
1033 
1034     // other comment
1035     )";
1036   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
1037   EXPECT_STREQ("#ifndef A\n#define A\n#endif\n", Out.data());
1038 
1039   Source = R"(
1040     #ifndef A
1041     #define A
1042     #endif /* some comment
1043 
1044     */
1045     )";
1046   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
1047   EXPECT_STREQ("#ifndef A\n#define A\n#endif\n", Out.data());
1048 
1049   Source = R"(
1050     #ifndef A
1051     #define A
1052     #endif /* some comment
1053 
1054     */
1055     int x;
1056     )";
1057   ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));
1058   EXPECT_STREQ("#ifndef A\n#define A\n#endif\n<TokBeforeEOF>\n", Out.data());
1059 }
1060 
1061 } // end anonymous namespace
1062