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(Source: Input, Directives, OS); |
29 | if (!Out.empty() && Out.back() != '\n') |
30 | Out.push_back(Elt: '\n'); |
31 | Out.push_back(Elt: '\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 | // FIXME: R"()" strings depend on using C++11 language mode |
587 | ASSERT_FALSE(minimizeSourceToDependencyDirectives( |
588 | R"(_Pragma(R"abc(clang module import)abc"))" , Out)); |
589 | EXPECT_STREQ("<TokBeforeEOF>\n" , Out.data()); |
590 | } |
591 | |
592 | TEST(MinimizeSourceToDependencyDirectivesTest, Include) { |
593 | SmallVector<char, 128> Out; |
594 | |
595 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include \"A\"\n" , Out)); |
596 | EXPECT_STREQ("#include \"A\"\n" , Out.data()); |
597 | |
598 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include <A>\n" , Out)); |
599 | EXPECT_STREQ("#include <A>\n" , Out.data()); |
600 | |
601 | ASSERT_FALSE( |
602 | minimizeSourceToDependencyDirectives("#include <A//A.h>\n" , Out)); |
603 | EXPECT_STREQ("#include <A//A.h>\n" , Out.data()); |
604 | |
605 | ASSERT_FALSE( |
606 | minimizeSourceToDependencyDirectives("#include \"A//A.h\"\n" , Out)); |
607 | EXPECT_STREQ("#include \"A//A.h\"\n" , Out.data()); |
608 | |
609 | ASSERT_FALSE( |
610 | minimizeSourceToDependencyDirectives("#include_next <A>\n" , Out)); |
611 | EXPECT_STREQ("#include_next <A>\n" , Out.data()); |
612 | |
613 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#import <A>\n" , Out)); |
614 | EXPECT_STREQ("#import <A>\n" , Out.data()); |
615 | |
616 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#import <A//A.h>\n" , Out)); |
617 | EXPECT_STREQ("#import <A//A.h>\n" , Out.data()); |
618 | |
619 | ASSERT_FALSE( |
620 | minimizeSourceToDependencyDirectives("#import \"A//A.h\"\n" , Out)); |
621 | EXPECT_STREQ("#import \"A//A.h\"\n" , Out.data()); |
622 | |
623 | ASSERT_FALSE( |
624 | minimizeSourceToDependencyDirectives("#__include_macros <A>\n" , Out)); |
625 | EXPECT_STREQ("#__include_macros <A>\n" , Out.data()); |
626 | |
627 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#include MACRO\n" , Out)); |
628 | EXPECT_STREQ("#include MACRO\n" , Out.data()); |
629 | } |
630 | |
631 | TEST(MinimizeSourceToDependencyDirectivesTest, AtImport) { |
632 | SmallVector<char, 128> Out; |
633 | |
634 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A;\n" , Out)); |
635 | EXPECT_STREQ("@import A;\n" , Out.data()); |
636 | |
637 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(" @ import A;\n" , Out)); |
638 | EXPECT_STREQ("@import A;\n" , Out.data()); |
639 | |
640 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A\n;" , Out)); |
641 | EXPECT_STREQ("@import A;\n" , Out.data()); |
642 | |
643 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import A.B;\n" , Out)); |
644 | EXPECT_STREQ("@import A.B;\n" , Out.data()); |
645 | |
646 | ASSERT_FALSE(minimizeSourceToDependencyDirectives( |
647 | "@import /*x*/ A /*x*/ . /*x*/ B /*x*/ \n /*x*/ ; /*x*/" , Out)); |
648 | EXPECT_STREQ("@import A.B;\n" , Out.data()); |
649 | } |
650 | |
651 | TEST(MinimizeSourceToDependencyDirectivesTest, AtImportFailures) { |
652 | SmallVector<char, 128> Out; |
653 | |
654 | ASSERT_TRUE(minimizeSourceToDependencyDirectives("@import A\n" , Out)); |
655 | ASSERT_FALSE( |
656 | minimizeSourceToDependencyDirectives("@import MACRO(A);\n" , Out)); |
657 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("@import \" \";\n" , Out)); |
658 | } |
659 | |
660 | TEST(MinimizeSourceToDependencyDirectivesTest, RawStringLiteral) { |
661 | SmallVector<char, 128> Out; |
662 | |
663 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifndef GUARD\n" |
664 | "#define GUARD\n" |
665 | "R\"()\"\n" |
666 | "#endif\n" , |
667 | Out)); |
668 | EXPECT_STREQ("#ifndef GUARD\n" |
669 | "#define GUARD\n" |
670 | "#endif\n" , |
671 | Out.data()); |
672 | |
673 | bool RawStringLiteralResult = minimizeSourceToDependencyDirectives( |
674 | Input: "#ifndef GUARD\n" |
675 | "#define GUARD\n" |
676 | R"raw(static constexpr char bytes[] = R"(-?:\,[]{}#&*!|>'"%@`)";)raw" |
677 | "\n" |
678 | "#endif\n" , |
679 | Out); |
680 | ASSERT_FALSE(RawStringLiteralResult); |
681 | EXPECT_STREQ("#ifndef GUARD\n" |
682 | "#define GUARD\n" |
683 | "#endif\n" , |
684 | Out.data()); |
685 | |
686 | bool RawStringLiteralResult2 = minimizeSourceToDependencyDirectives( |
687 | Input: "#ifndef GUARD\n" |
688 | "#define GUARD\n" |
689 | R"raw(static constexpr char bytes[] = R"abc(-?:\,[]{}#&*!|>'"%@`)abc";)raw" |
690 | "\n" |
691 | "#endif\n" , |
692 | Out); |
693 | ASSERT_FALSE(RawStringLiteralResult2); |
694 | EXPECT_STREQ("#ifndef GUARD\n" |
695 | "#define GUARD\n" |
696 | "#endif\n" , |
697 | Out.data()); |
698 | } |
699 | |
700 | TEST(MinimizeSourceToDependencyDirectivesTest, SplitIdentifier) { |
701 | SmallVector<char, 128> Out; |
702 | |
703 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#if\\\n" |
704 | "ndef GUARD\n" |
705 | "#define GUARD\n" |
706 | "#endif\n" , |
707 | Out)); |
708 | EXPECT_STREQ("#if\\\n" |
709 | "ndef GUARD\n" |
710 | "#define GUARD\n" |
711 | "#endif\n" , |
712 | Out.data()); |
713 | |
714 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n" |
715 | "RD\n" , |
716 | Out)); |
717 | EXPECT_STREQ("#define GUA\\\n" |
718 | "RD\n" , |
719 | Out.data()); |
720 | |
721 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\r" |
722 | "RD\n" , |
723 | Out)); |
724 | EXPECT_STREQ("#define GUA\\\r" |
725 | "RD\n" , |
726 | Out.data()); |
727 | |
728 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n" |
729 | " RD\n" , |
730 | Out)); |
731 | EXPECT_STREQ("#define GUA RD\n" , Out.data()); |
732 | } |
733 | |
734 | TEST(MinimizeSourceToDependencyDirectivesTest, |
735 | WhitespaceAfterLineContinuationSlash) { |
736 | SmallVector<char, 128> Out; |
737 | |
738 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define A 1 + \\ \n" |
739 | "2 + \\\t\n" |
740 | "3\n" , |
741 | Out)); |
742 | EXPECT_STREQ("#define A 1+\\ \n" |
743 | "2+\\\t\n" |
744 | "3\n" , |
745 | Out.data()); |
746 | } |
747 | |
748 | TEST(MinimizeSourceToDependencyDirectivesTest, PoundWarningAndError) { |
749 | SmallVector<char, 128> Out; |
750 | |
751 | for (auto Source : { |
752 | "#warning '\n#include <t.h>\n" , |
753 | "#warning \"\n#include <t.h>\n" , |
754 | "#warning /*\n#include <t.h>\n" , |
755 | "#warning \\\n#include <t.h>\n#include <t.h>\n" , |
756 | "#error '\n#include <t.h>\n" , |
757 | "#error \"\n#include <t.h>\n" , |
758 | "#error /*\n#include <t.h>\n" , |
759 | "#error \\\n#include <t.h>\n#include <t.h>\n" , |
760 | }) { |
761 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
762 | EXPECT_STREQ("#include <t.h>\n" , Out.data()); |
763 | } |
764 | |
765 | for (auto Source : { |
766 | "#warning \\\n#include <t.h>\n" , |
767 | "#error \\\n#include <t.h>\n" , |
768 | }) { |
769 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
770 | EXPECT_STREQ("<TokBeforeEOF>\n" , Out.data()); |
771 | } |
772 | |
773 | for (auto Source : { |
774 | "#if MACRO\n#warning '\n#endif\n" , |
775 | "#if MACRO\n#warning \"\n#endif\n" , |
776 | "#if MACRO\n#warning /*\n#endif\n" , |
777 | "#if MACRO\n#error '\n#endif\n" , |
778 | "#if MACRO\n#error \"\n#endif\n" , |
779 | "#if MACRO\n#error /*\n#endif\n" , |
780 | }) { |
781 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
782 | EXPECT_STREQ("#if MACRO\n#endif\n" , Out.data()); |
783 | } |
784 | } |
785 | |
786 | TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteral) { |
787 | SmallVector<char, 128> Out; |
788 | |
789 | StringRef Source = R"( |
790 | #include <bob> |
791 | int a = 0'1; |
792 | int b = 0xfa'af'fa; |
793 | int c = 12 ' '; |
794 | #include <foo> |
795 | )" ; |
796 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
797 | EXPECT_STREQ("#include <bob>\n#include <foo>\n" , Out.data()); |
798 | } |
799 | |
800 | TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixL) { |
801 | SmallVector<char, 128> Out; |
802 | |
803 | StringRef Source = R"(L'P' |
804 | #if DEBUG |
805 | // ' |
806 | #endif |
807 | #include <test.h> |
808 | )" ; |
809 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
810 | EXPECT_STREQ("#if DEBUG\n#endif\n#include <test.h>\n" , Out.data()); |
811 | } |
812 | |
813 | TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixU) { |
814 | SmallVector<char, 128> Out; |
815 | |
816 | StringRef Source = R"(int x = U'P'; |
817 | #include <test.h> |
818 | // ' |
819 | )" ; |
820 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
821 | EXPECT_STREQ("#include <test.h>\n" , Out.data()); |
822 | } |
823 | |
824 | TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixu) { |
825 | SmallVector<char, 128> Out; |
826 | |
827 | StringRef Source = R"(int x = u'b'; |
828 | int y = u8'a'; |
829 | int z = 128'78; |
830 | #include <test.h> |
831 | // ' |
832 | )" ; |
833 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
834 | EXPECT_STREQ("#include <test.h>\n" , Out.data()); |
835 | } |
836 | |
837 | TEST(MinimizeSourceToDependencyDirectivesTest, PragmaOnce) { |
838 | SmallVector<char, 128> Out; |
839 | SmallVector<dependency_directives_scan::Token, 4> Tokens; |
840 | SmallVector<Directive, 4> Directives; |
841 | |
842 | StringRef Source = R"(// comment |
843 | #pragma once |
844 | // another comment |
845 | #include <test.h> |
846 | _Pragma("once") |
847 | )" ; |
848 | ASSERT_FALSE( |
849 | minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives)); |
850 | EXPECT_STREQ("#pragma once\n#include <test.h>\n_Pragma(\"once\")\n" , |
851 | Out.data()); |
852 | ASSERT_EQ(Directives.size(), 4u); |
853 | EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_pragma_once); |
854 | EXPECT_EQ(Directives[2].Kind, dependency_directives_scan::pp_pragma_once); |
855 | |
856 | Source = R"(// comment |
857 | #pragma once extra tokens |
858 | // another comment |
859 | #include <test.h> |
860 | _Pragma("once") extra tokens |
861 | )" ; |
862 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
863 | EXPECT_STREQ("#pragma once extra tokens\n#include " |
864 | "<test.h>\n_Pragma(\"once\")<TokBeforeEOF>\n" , |
865 | Out.data()); |
866 | } |
867 | |
868 | TEST(MinimizeSourceToDependencyDirectivesTest, |
869 | SkipLineStringCharLiteralsUntilNewline) { |
870 | SmallVector<char, 128> Out; |
871 | |
872 | StringRef Source = R"(#if NEVER_ENABLED |
873 | #define why(fmt, ...) #error don't try me |
874 | #endif |
875 | |
876 | void foo(); |
877 | )" ; |
878 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
879 | EXPECT_STREQ( |
880 | "#if NEVER_ENABLED\n#define why(fmt,...) #error don't try me\n#endif\n" |
881 | "<TokBeforeEOF>\n" , |
882 | Out.data()); |
883 | |
884 | Source = R"(#if NEVER_ENABLED |
885 | #define why(fmt, ...) "quote dropped |
886 | #endif |
887 | |
888 | void foo(); |
889 | )" ; |
890 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
891 | EXPECT_STREQ( |
892 | "#if NEVER_ENABLED\n#define why(fmt,...) \"quote dropped\n#endif\n" |
893 | "<TokBeforeEOF>\n" , |
894 | Out.data()); |
895 | } |
896 | |
897 | TEST(MinimizeSourceToDependencyDirectivesTest, |
898 | SupportWhitespaceBeforeLineContinuation) { |
899 | SmallVector<char, 128> Out; |
900 | |
901 | ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define FOO(BAR) \\\n" |
902 | " #BAR\\\n" |
903 | " baz\n" , |
904 | Out)); |
905 | EXPECT_STREQ("#define FOO(BAR) #BAR baz\n" , Out.data()); |
906 | } |
907 | |
908 | TEST(MinimizeSourceToDependencyDirectivesTest, |
909 | SupportWhitespaceBeforeLineContinuationInStringSkipping) { |
910 | SmallVector<char, 128> Out; |
911 | |
912 | StringRef Source = "#define X '\\ \t\nx'\nvoid foo() {}" ; |
913 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
914 | EXPECT_STREQ("#define X '\\ \t\nx'\n<TokBeforeEOF>\n" , Out.data()); |
915 | |
916 | Source = "#define X \"\\ \r\nx\"\nvoid foo() {}" ; |
917 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
918 | EXPECT_STREQ("#define X \"\\ \r\nx\"\n<TokBeforeEOF>\n" , Out.data()); |
919 | |
920 | Source = "#define X \"\\ \r\nx\n#include <x>\n" ; |
921 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
922 | EXPECT_STREQ("#define X\"\\ \r\nx\n#include <x>\n" , Out.data()); |
923 | } |
924 | |
925 | TEST(MinimizeSourceToDependencyDirectivesTest, CxxModules) { |
926 | SmallVector<char, 128> Out; |
927 | SmallVector<dependency_directives_scan::Token, 4> Tokens; |
928 | SmallVector<Directive, 4> Directives; |
929 | |
930 | StringRef Source = R"( |
931 | module; |
932 | #include "textual-header.h" |
933 | |
934 | export module m; |
935 | exp\ |
936 | ort \ |
937 | import \ |
938 | :l [[rename]]; |
939 | |
940 | export void f(); |
941 | |
942 | void h() { |
943 | import.a = 3; |
944 | import = 3; |
945 | import <<= 3; |
946 | import->a = 3; |
947 | import(); |
948 | import . a(); |
949 | |
950 | import a b d e d e f e; |
951 | import foo [[no_unique_address]]; |
952 | import foo(); |
953 | import f(:sefse); |
954 | import f(->a = 3); |
955 | } |
956 | )" ; |
957 | ASSERT_FALSE( |
958 | minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives)); |
959 | EXPECT_STREQ("#include \"textual-header.h\"\nexport module m;" |
960 | "exp\\\nort import:l[[rename]];" |
961 | "import<<=3;import a b d e d e f e;" |
962 | "import foo[[no_unique_address]];import foo();" |
963 | "import f(:sefse);import f(->a=3);" |
964 | "<TokBeforeEOF>\n" , |
965 | Out.data()); |
966 | ASSERT_EQ(Directives.size(), 11u); |
967 | EXPECT_EQ(Directives[0].Kind, pp_include); |
968 | EXPECT_EQ(Directives[1].Kind, cxx_export_module_decl); |
969 | } |
970 | |
971 | TEST(MinimizeSourceToDependencyDirectivesTest, TokensBeforeEOF) { |
972 | SmallString<128> Out; |
973 | |
974 | StringRef Source = R"( |
975 | #define A |
976 | #ifdef B |
977 | int x; |
978 | #endif |
979 | )" ; |
980 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
981 | EXPECT_STREQ("#define A\n<TokBeforeEOF>\n" , Out.data()); |
982 | |
983 | Source = R"( |
984 | #ifndef A |
985 | #define A |
986 | #endif // some comment |
987 | |
988 | // other comment |
989 | )" ; |
990 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
991 | EXPECT_STREQ("#ifndef A\n#define A\n#endif\n" , Out.data()); |
992 | |
993 | Source = R"( |
994 | #ifndef A |
995 | #define A |
996 | #endif /* some comment |
997 | |
998 | */ |
999 | )" ; |
1000 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
1001 | EXPECT_STREQ("#ifndef A\n#define A\n#endif\n" , Out.data()); |
1002 | |
1003 | Source = R"( |
1004 | #ifndef A |
1005 | #define A |
1006 | #endif /* some comment |
1007 | |
1008 | */ |
1009 | int x; |
1010 | )" ; |
1011 | ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out)); |
1012 | EXPECT_STREQ("#ifndef A\n#define A\n#endif\n<TokBeforeEOF>\n" , Out.data()); |
1013 | } |
1014 | |
1015 | } // end anonymous namespace |
1016 | |