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