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