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_TRUE(Out.empty()); 61 EXPECT_TRUE(Tokens.empty()); 62 ASSERT_EQ(1u, Directives.size()); 63 ASSERT_EQ(pp_eof, Directives.back().Kind); 64 } 65 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 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 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 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 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 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 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 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 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 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 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 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 283 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNumber) { 284 SmallVector<char, 128> Out; 285 286 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define 0\n", Out)); 287 } 288 289 TEST(MinimizeSourceToDependencyDirectivesTest, DefineNoName) { 290 SmallVector<char, 128> Out; 291 292 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define &\n", Out)); 293 } 294 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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