1219 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Lex/DependencyDirectivesScanner.h"10#include "llvm/ADT/SmallString.h"11#include "gtest/gtest.h"12 13using namespace llvm;14using namespace clang;15using namespace clang::dependency_directives_scan;16 17static 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 37static 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 44namespace {45 46TEST(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 67TEST(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 121TEST(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 129TEST(MinimizeSourceToDependencyDirectivesTest, HashHash) {130 SmallVector<char, 128> Out;131 132 StringRef Source = R"(133 #define S134 #if 0135 ##pragma cool136 ##include "t.h"137 #endif138 #define E139 )";140 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));141 EXPECT_STREQ("#define S\n#if 0\n#endif\n#define E\n", Out.data());142}143 144TEST(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 157TEST(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 177TEST(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 200TEST(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 214TEST(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 234TEST(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 252TEST(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 265TEST(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 275TEST(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 288TEST(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 301TEST(MinimizeSourceToDependencyDirectivesTest, DefineNumber) {302 SmallVector<char, 128> Out;303 304 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define 0\n", Out));305}306 307TEST(MinimizeSourceToDependencyDirectivesTest, DefineNoName) {308 SmallVector<char, 128> Out;309 310 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define &\n", Out));311}312 313TEST(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 327TEST(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 343TEST(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 354TEST(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 362TEST(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 396TEST(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 434TEST(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 451TEST(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 468TEST(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 506TEST(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 mode582 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 594TEST(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 633TEST(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;\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;\n", Out.data());651}652 653TEST(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 680TEST(MinimizeSourceToDependencyDirectivesTest, ImportFailures) {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 ASSERT_FALSE(minimizeSourceToDependencyDirectives("import <Foo.h>\n"689 "@import Foo;",690 Out));691 EXPECT_STREQ("@import Foo;\n", Out.data());692 693 ASSERT_FALSE(694 minimizeSourceToDependencyDirectives("import <Foo.h>\n"695 "#import <Foo.h>\n"696 "@;\n"697 "#pragma clang module import Foo",698 Out));699 EXPECT_STREQ("#import <Foo.h>\n"700 "#pragma clang module import Foo\n",701 Out.data());702}703 704TEST(MinimizeSourceToDependencyDirectivesTest, RawStringLiteral) {705 SmallVector<char, 128> Out;706 707 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#ifndef GUARD\n"708 "#define GUARD\n"709 "R\"()\"\n"710 "#endif\n",711 Out));712 EXPECT_STREQ("#ifndef GUARD\n"713 "#define GUARD\n"714 "#endif\n",715 Out.data());716 717 bool RawStringLiteralResult = minimizeSourceToDependencyDirectives(718 "#ifndef GUARD\n"719 "#define GUARD\n"720 R"raw(static constexpr char bytes[] = R"(-?:\,[]{}#&*!|>'"%@`)";)raw"721 "\n"722 "#endif\n",723 Out);724 ASSERT_FALSE(RawStringLiteralResult);725 EXPECT_STREQ("#ifndef GUARD\n"726 "#define GUARD\n"727 "#endif\n",728 Out.data());729 730 bool RawStringLiteralResult2 = minimizeSourceToDependencyDirectives(731 "#ifndef GUARD\n"732 "#define GUARD\n"733 R"raw(static constexpr char bytes[] = R"abc(-?:\,[]{}#&*!|>'"%@`)abc";)raw"734 "\n"735 "#endif\n",736 Out);737 ASSERT_FALSE(RawStringLiteralResult2);738 EXPECT_STREQ("#ifndef GUARD\n"739 "#define GUARD\n"740 "#endif\n",741 Out.data());742}743 744TEST(MinimizeSourceToDependencyDirectivesTest, SplitIdentifier) {745 SmallVector<char, 128> Out;746 747 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#if\\\n"748 "ndef GUARD\n"749 "#define GUARD\n"750 "#endif\n",751 Out));752 EXPECT_STREQ("#if\\\n"753 "ndef GUARD\n"754 "#define GUARD\n"755 "#endif\n",756 Out.data());757 758 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n"759 "RD\n",760 Out));761 EXPECT_STREQ("#define GUA\\\n"762 "RD\n",763 Out.data());764 765 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\r"766 "RD\n",767 Out));768 EXPECT_STREQ("#define GUA\\\r"769 "RD\n",770 Out.data());771 772 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define GUA\\\n"773 " RD\n",774 Out));775 EXPECT_STREQ("#define GUA RD\n", Out.data());776}777 778TEST(MinimizeSourceToDependencyDirectivesTest,779 WhitespaceAfterLineContinuationSlash) {780 SmallVector<char, 128> Out;781 782 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define A 1 + \\ \n"783 "2 + \\\t\n"784 "3\n",785 Out));786 EXPECT_STREQ("#define A 1+\\ \n"787 "2+\\\t\n"788 "3\n",789 Out.data());790}791 792TEST(MinimizeSourceToDependencyDirectivesTest,793 WhitespaceAfterLineContinuationSlashLineComment) {794 SmallVector<char, 128> Out;795 796 ASSERT_FALSE(minimizeSourceToDependencyDirectives("// some comment \\ \n"797 "module A;\n",798 Out));799 EXPECT_STREQ("", Out.data());800}801 802TEST(MinimizeSourceToDependencyDirectivesTest,803 WhitespaceAfterLineContinuationSlashAllDirectives) {804 SmallVector<char, 512> Out;805 SmallVector<dependency_directives_scan::Token, 16> Tokens;806 SmallVector<Directive, 16> Directives;807 808 StringRef Input = "#define \\ \n"809 "A\n"810 "#undef\t\\ \n"811 "A\n"812 "#endif \\\t\t\n"813 "\n"814 "#if \\ \t\n"815 "A\n"816 "#ifdef\t\\ \n"817 "A\n"818 "#ifndef \\ \t\n"819 "A\n"820 "#elifdef \\ \n"821 "A\n"822 "#elifndef \\ \n"823 "A\n"824 "#elif \\\t\t \n"825 "A\n"826 "#else \\\t \t\n"827 "\n"828 "#include \\ \n"829 "<A>\n"830 "#include_next \\ \n"831 "<A>\n"832 "#__include_macros\\ \n"833 "<A>\n"834 "#import \\ \t\n"835 "<A>\n"836 "@import \\\t \n"837 "A;\n"838 "#pragma clang \\ \n"839 "module \\ \n"840 "import A\n"841 "#pragma \\ \n"842 "push_macro(A)\n"843 "#pragma \\\t \n"844 "pop_macro(A)\n"845 "#pragma \\ \n"846 "include_alias(<A>,\\ \n"847 "<B>)\n"848 "export \\ \n"849 "module m;\n"850 "import\t\\\t \n"851 "m;\n"852 "#pragma\t\\ \n"853 "clang\t\\ \t\n"854 "system_header\n";855 ASSERT_FALSE(856 minimizeSourceToDependencyDirectives(Input, Out, Tokens, Directives));857 858 EXPECT_EQ(pp_define, Directives[0].Kind);859 EXPECT_EQ(pp_undef, Directives[1].Kind);860 EXPECT_EQ(pp_endif, Directives[2].Kind);861 EXPECT_EQ(pp_if, Directives[3].Kind);862 EXPECT_EQ(pp_ifdef, Directives[4].Kind);863 EXPECT_EQ(pp_ifndef, Directives[5].Kind);864 EXPECT_EQ(pp_elifdef, Directives[6].Kind);865 EXPECT_EQ(pp_elifndef, Directives[7].Kind);866 EXPECT_EQ(pp_elif, Directives[8].Kind);867 EXPECT_EQ(pp_else, Directives[9].Kind);868 EXPECT_EQ(pp_include, Directives[10].Kind);869 EXPECT_EQ(pp_include_next, Directives[11].Kind);870 EXPECT_EQ(pp___include_macros, Directives[12].Kind);871 EXPECT_EQ(pp_import, Directives[13].Kind);872 EXPECT_EQ(decl_at_import, Directives[14].Kind);873 EXPECT_EQ(pp_pragma_import, Directives[15].Kind);874 EXPECT_EQ(pp_pragma_push_macro, Directives[16].Kind);875 EXPECT_EQ(pp_pragma_pop_macro, Directives[17].Kind);876 EXPECT_EQ(pp_pragma_include_alias, Directives[18].Kind);877 EXPECT_EQ(cxx_export_module_decl, Directives[19].Kind);878 EXPECT_EQ(cxx_import_decl, Directives[20].Kind);879 EXPECT_EQ(pp_pragma_system_header, Directives[21].Kind);880 EXPECT_EQ(pp_eof, Directives[22].Kind);881}882 883TEST(MinimizeSourceToDependencyDirectivesTest,884 TestFixedBugThatReportUnterminatedDirectiveFalsely) {885 SmallVector<char, 512> Out;886 SmallVector<dependency_directives_scan::Token, 16> Tokens;887 SmallVector<Directive, 16> Directives;888 889 StringRef Input = "#ifndef __TEST \n"890 "#define __TEST \n"891 "#if defined(__TEST_DUMMY) \n"892 "#if defined(__TEST_DUMMY2) \n"893 "#pragma GCC warning \\ \n"894 "\"hello!\"\n"895 "#else\n"896 "#pragma GCC error \\ \n"897 "\"world!\" \n"898 "#endif // defined(__TEST_DUMMY2) \n"899 "#endif // defined(__TEST_DUMMY) \n"900 "#endif // #ifndef __TEST \n";901 ASSERT_FALSE( // False on no error:902 minimizeSourceToDependencyDirectives(Input, Out, Tokens, Directives));903 ASSERT_TRUE(Directives.size() == 8);904 EXPECT_EQ(pp_ifndef, Directives[0].Kind);905 EXPECT_EQ(pp_define, Directives[1].Kind);906 EXPECT_EQ(pp_if, Directives[2].Kind);907 EXPECT_EQ(pp_if, Directives[3].Kind);908 EXPECT_EQ(pp_endif, Directives[4].Kind);909 EXPECT_EQ(pp_endif, Directives[5].Kind);910 EXPECT_EQ(pp_endif, Directives[6].Kind);911 EXPECT_EQ(pp_eof, Directives[7].Kind);912}913 914TEST(MinimizeSourceToDependencyDirectivesTest, PoundWarningAndError) {915 SmallVector<char, 128> Out;916 917 for (auto Source : {918 "#warning '\n#include <t.h>\n",919 "#warning \"\n#include <t.h>\n",920 "#warning /*\n#include <t.h>\n",921 "#warning \\\n#include <t.h>\n#include <t.h>\n",922 "#error '\n#include <t.h>\n",923 "#error \"\n#include <t.h>\n",924 "#error /*\n#include <t.h>\n",925 "#error \\\n#include <t.h>\n#include <t.h>\n",926 }) {927 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));928 EXPECT_STREQ("#include <t.h>\n", Out.data());929 }930 931 for (auto Source : {932 "#warning \\\n#include <t.h>\n",933 "#error \\\n#include <t.h>\n",934 }) {935 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));936 EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());937 }938 939 for (auto Source : {940 "#if MACRO\n#warning '\n#endif\n",941 "#if MACRO\n#warning \"\n#endif\n",942 "#if MACRO\n#warning /*\n#endif\n",943 "#if MACRO\n#error '\n#endif\n",944 "#if MACRO\n#error \"\n#endif\n",945 "#if MACRO\n#error /*\n#endif\n",946 }) {947 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));948 EXPECT_STREQ("#if MACRO\n#endif\n", Out.data());949 }950}951 952TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteral) {953 SmallVector<char, 128> Out;954 955 StringRef Source = R"(956#include <bob>957int a = 0'1;958int b = 0xfa'af'fa;959int c = 12 ' ';960#include <foo>961)";962 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));963 EXPECT_STREQ("#include <bob>\n#include <foo>\n", Out.data());964}965 966TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixL) {967 SmallVector<char, 128> Out;968 969 StringRef Source = R"(L'P'970#if DEBUG971// '972#endif973#include <test.h>974)";975 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));976 EXPECT_STREQ("#if DEBUG\n#endif\n#include <test.h>\n", Out.data());977}978 979TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixU) {980 SmallVector<char, 128> Out;981 982 StringRef Source = R"(int x = U'P';983#include <test.h>984// '985)";986 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));987 EXPECT_STREQ("#include <test.h>\n", Out.data());988}989 990TEST(MinimizeSourceToDependencyDirectivesTest, CharacterLiteralPrefixu) {991 SmallVector<char, 128> Out;992 993 StringRef Source = R"(int x = u'b';994int y = u8'a';995int z = 128'78;996#include <test.h>997// '998)";999 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1000 EXPECT_STREQ("#include <test.h>\n", Out.data());1001}1002 1003TEST(MinimizeSourceToDependencyDirectivesTest, PragmaOnce) {1004 SmallVector<char, 128> Out;1005 SmallVector<dependency_directives_scan::Token, 4> Tokens;1006 SmallVector<Directive, 4> Directives;1007 1008 StringRef Source = R"(// comment1009#pragma once1010// another comment1011#include <test.h>1012_Pragma("once")1013)";1014 ASSERT_FALSE(1015 minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives));1016 EXPECT_STREQ("#pragma once\n#include <test.h>\n_Pragma(\"once\")\n",1017 Out.data());1018 ASSERT_EQ(Directives.size(), 4u);1019 EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_pragma_once);1020 EXPECT_EQ(Directives[2].Kind, dependency_directives_scan::pp_pragma_once);1021 1022 Source = R"(// comment1023 #pragma once extra tokens1024 // another comment1025 #include <test.h>1026 _Pragma("once") extra tokens1027 )";1028 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1029 EXPECT_STREQ("#pragma once extra tokens\n#include "1030 "<test.h>\n_Pragma(\"once\")<TokBeforeEOF>\n",1031 Out.data());1032}1033 1034TEST(MinimizeSourceToDependencyDirectivesTest,1035 SkipLineStringCharLiteralsUntilNewline) {1036 SmallVector<char, 128> Out;1037 1038 StringRef Source = R"(#if NEVER_ENABLED1039 #define why(fmt, ...) #error don't try me1040 #endif1041 1042 void foo();1043)";1044 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1045 EXPECT_STREQ(1046 "#if NEVER_ENABLED\n#define why(fmt,...) #error don't try me\n#endif\n"1047 "<TokBeforeEOF>\n",1048 Out.data());1049 1050 Source = R"(#if NEVER_ENABLED1051 #define why(fmt, ...) "quote dropped1052 #endif1053 1054 void foo();1055 )";1056 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1057 EXPECT_STREQ(1058 "#if NEVER_ENABLED\n#define why(fmt,...) \"quote dropped\n#endif\n"1059 "<TokBeforeEOF>\n",1060 Out.data());1061}1062 1063TEST(MinimizeSourceToDependencyDirectivesTest,1064 SupportWhitespaceBeforeLineContinuation) {1065 SmallVector<char, 128> Out;1066 1067 ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define FOO(BAR) \\\n"1068 " #BAR\\\n"1069 " baz\n",1070 Out));1071 EXPECT_STREQ("#define FOO(BAR) #BAR baz\n", Out.data());1072}1073 1074TEST(MinimizeSourceToDependencyDirectivesTest,1075 SupportWhitespaceBeforeLineContinuationInStringSkipping) {1076 SmallVector<char, 128> Out;1077 1078 StringRef Source = "#define X '\\ \t\nx'\nvoid foo() {}";1079 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1080 EXPECT_STREQ("#define X '\\ \t\nx'\n<TokBeforeEOF>\n", Out.data());1081 1082 Source = "#define X \"\\ \r\nx\"\nvoid foo() {}";1083 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1084 EXPECT_STREQ("#define X \"\\ \r\nx\"\n<TokBeforeEOF>\n", Out.data());1085 1086 Source = "#define X \"\\ \r\nx\n#include <x>\n";1087 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1088 EXPECT_STREQ("#define X\"\\ \r\nx\n#include <x>\n", Out.data());1089}1090 1091TEST(MinimizeSourceToDependencyDirectivesTest, CxxModules) {1092 SmallVector<char, 128> Out;1093 SmallVector<dependency_directives_scan::Token, 4> Tokens;1094 SmallVector<Directive, 4> Directives;1095 1096 StringRef Source = R"(1097 module;1098 #include "textual-header.h"1099 1100 export module m;1101 exp\1102ort \1103 import \1104 :l [[rename]];1105 1106 export void f();1107 1108 void h() {1109 import.a = 3;1110 import = 3;1111 import <<= 3;1112 import->a = 3;1113 import();1114 import . a();1115 1116 import a b d e d e f e;1117 import foo [[no_unique_address]];1118 import foo();1119 import f(:sefse);1120 import f(->a = 3);1121 }1122 )";1123 ASSERT_FALSE(1124 minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives));1125 1126 EXPECT_STREQ("module;\n"1127 "#include \"textual-header.h\"\n"1128 "export module m;\n"1129 "exp\\\nort import:l[[rename]];\n"1130 "import<<=3;\n"1131 "import a b d e d e f e;\n"1132 "import foo[[no_unique_address]];\n"1133 "import foo();\n"1134 "import f(:sefse);\n"1135 "import f(->a=3);\n"1136 "<TokBeforeEOF>\n",1137 Out.data());1138 ASSERT_EQ(Directives.size(), 12u);1139 EXPECT_EQ(Directives[0].Kind, cxx_module_decl);1140 EXPECT_EQ(Directives[1].Kind, pp_include);1141 EXPECT_EQ(Directives[2].Kind, cxx_export_module_decl);1142}1143 1144TEST(MinimizeSourceToDependencyDirectivesTest, ObjCMethodArgs) {1145 SmallVector<char, 128> Out;1146 1147 StringRef Source = R"(1148 @interface SomeObjcClass1149 - (void)func:(int)otherData1150 module:(int)module1151 import:(int)import;1152 @end1153 )";1154 1155 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1156 // `module :` and `import :` not followed by an identifier are not treated as1157 // directive lines because they can be method argument decls.1158 EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());1159}1160 1161TEST(MinimizeSourceToDependencyDirectivesTest,1162 CxxModulesImportScopeResolution) {1163 SmallString<16> Out;1164 SmallVector<dependency_directives_scan::Token, 2> Tokens;1165 SmallVector<Directive, 1> Directives;1166 1167 StringRef Source = "import::inner xi = {};'\n"1168 "module::inner yi = {};";1169 ASSERT_FALSE(1170 minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives));1171 EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());1172}1173 1174TEST(MinimizeSourceToDependencyDirectivesTest, TokensBeforeEOF) {1175 SmallString<128> Out;1176 1177 StringRef Source = R"(1178 #define A1179 #ifdef B1180 int x;1181 #endif1182 )";1183 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1184 EXPECT_STREQ("#define A\n<TokBeforeEOF>\n", Out.data());1185 1186 Source = R"(1187 #ifndef A1188 #define A1189 #endif // some comment1190 1191 // other comment1192 )";1193 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1194 EXPECT_STREQ("#ifndef A\n#define A\n#endif\n", Out.data());1195 1196 Source = R"(1197 #ifndef A1198 #define A1199 #endif /* some comment1200 1201 */1202 )";1203 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1204 EXPECT_STREQ("#ifndef A\n#define A\n#endif\n", Out.data());1205 1206 Source = R"(1207 #ifndef A1208 #define A1209 #endif /* some comment1210 1211 */1212 int x;1213 )";1214 ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out));1215 EXPECT_STREQ("#ifndef A\n#define A\n#endif\n<TokBeforeEOF>\n", Out.data());1216}1217 1218} // end anonymous namespace1219