1 #include "../../clang/unittests/ASTMatchers/ASTMatchersTest.h" 2 #include "ClangTidyTest.h" 3 #include "readability/BracesAroundStatementsCheck.h" 4 #include "readability/NamespaceCommentCheck.h" 5 #include "readability/SimplifyBooleanExprMatchers.h" 6 #include "clang/ASTMatchers/ASTMatchers.h" 7 #include "gtest/gtest.h" 8 9 namespace clang { 10 namespace tidy { 11 namespace test { 12 13 using readability::BracesAroundStatementsCheck; 14 using readability::NamespaceCommentCheck; 15 using namespace ast_matchers; 16 17 TEST_P(ASTMatchersTest, HasCaseSubstatement) { 18 EXPECT_TRUE(matches( 19 "void f() { switch (1) { case 1: return; break; default: break; } }", 20 traverse(TK_AsIs, caseStmt(hasSubstatement(returnStmt()))))); 21 } 22 23 TEST_P(ASTMatchersTest, HasDefaultSubstatement) { 24 EXPECT_TRUE(matches( 25 "void f() { switch (1) { case 1: return; break; default: break; } }", 26 traverse(TK_AsIs, defaultStmt(hasSubstatement(breakStmt()))))); 27 } 28 29 TEST_P(ASTMatchersTest, HasLabelSubstatement) { 30 EXPECT_TRUE( 31 matches("void f() { while (1) { bar: break; foo: return; } }", 32 traverse(TK_AsIs, labelStmt(hasSubstatement(breakStmt()))))); 33 } 34 35 TEST_P(ASTMatchersTest, HasSubstatementSequenceSimple) { 36 const char *Text = "int f() { int x = 5; if (x < 0) return 1; return 0; }"; 37 EXPECT_TRUE(matches( 38 Text, compoundStmt(hasSubstatementSequence(ifStmt(), returnStmt())))); 39 EXPECT_FALSE(matches( 40 Text, compoundStmt(hasSubstatementSequence(ifStmt(), labelStmt())))); 41 EXPECT_FALSE(matches( 42 Text, compoundStmt(hasSubstatementSequence(returnStmt(), ifStmt())))); 43 EXPECT_FALSE(matches( 44 Text, compoundStmt(hasSubstatementSequence(switchStmt(), labelStmt())))); 45 } 46 47 TEST_P(ASTMatchersTest, HasSubstatementSequenceAlmost) { 48 const char *Text = R"code( 49 int f() { 50 int x = 5; 51 if (x < 10) 52 ; 53 if (x < 0) 54 return 1; 55 return 0; 56 } 57 )code"; 58 EXPECT_TRUE(matches( 59 Text, compoundStmt(hasSubstatementSequence(ifStmt(), returnStmt())))); 60 EXPECT_TRUE( 61 matches(Text, compoundStmt(hasSubstatementSequence(ifStmt(), ifStmt())))); 62 } 63 64 TEST_P(ASTMatchersTest, HasSubstatementSequenceComplex) { 65 const char *Text = R"code( 66 int f() { 67 int x = 5; 68 if (x < 10) 69 x -= 10; 70 if (x < 0) 71 return 1; 72 return 0; 73 } 74 )code"; 75 EXPECT_TRUE(matches( 76 Text, compoundStmt(hasSubstatementSequence(ifStmt(), returnStmt())))); 77 EXPECT_FALSE( 78 matches(Text, compoundStmt(hasSubstatementSequence(ifStmt(), expr())))); 79 } 80 81 TEST_P(ASTMatchersTest, HasSubstatementSequenceExpression) { 82 const char *Text = R"code( 83 int f() { 84 return ({ int x = 5; 85 int result; 86 if (x < 10) 87 x -= 10; 88 if (x < 0) 89 result = 1; 90 else 91 result = 0; 92 result; 93 }); 94 } 95 )code"; 96 EXPECT_TRUE( 97 matches(Text, stmtExpr(hasSubstatementSequence(ifStmt(), expr())))); 98 EXPECT_FALSE( 99 matches(Text, stmtExpr(hasSubstatementSequence(ifStmt(), returnStmt())))); 100 } 101 102 // Copied from ASTMatchersTests 103 static std::vector<TestClangConfig> allTestClangConfigs() { 104 std::vector<TestClangConfig> all_configs; 105 for (TestLanguage lang : {Lang_C89, Lang_C99, Lang_CXX03, Lang_CXX11, 106 Lang_CXX14, Lang_CXX17, Lang_CXX20}) { 107 TestClangConfig config; 108 config.Language = lang; 109 110 // Use an unknown-unknown triple so we don't instantiate the full system 111 // toolchain. On Linux, instantiating the toolchain involves stat'ing 112 // large portions of /usr/lib, and this slows down not only this test, but 113 // all other tests, via contention in the kernel. 114 // 115 // FIXME: This is a hack to work around the fact that there's no way to do 116 // the equivalent of runToolOnCodeWithArgs without instantiating a full 117 // Driver. We should consider having a function, at least for tests, that 118 // invokes cc1. 119 config.Target = "i386-unknown-unknown"; 120 all_configs.push_back(config); 121 122 // Windows target is interesting to test because it enables 123 // `-fdelayed-template-parsing`. 124 config.Target = "x86_64-pc-win32-msvc"; 125 all_configs.push_back(config); 126 } 127 return all_configs; 128 } 129 130 INSTANTIATE_TEST_SUITE_P(ASTMatchersTests, ASTMatchersTest, 131 testing::ValuesIn(allTestClangConfigs())); 132 133 TEST(NamespaceCommentCheckTest, Basic) { 134 EXPECT_EQ("namespace i {\n} // namespace i", 135 runCheckOnCode<NamespaceCommentCheck>("namespace i {\n}")); 136 EXPECT_EQ("namespace {\n} // namespace", 137 runCheckOnCode<NamespaceCommentCheck>("namespace {\n}")); 138 EXPECT_EQ("namespace i { namespace j {\n} // namespace j\n } // namespace i", 139 runCheckOnCode<NamespaceCommentCheck>( 140 "namespace i { namespace j {\n} }")); 141 } 142 143 TEST(NamespaceCommentCheckTest, SingleLineNamespaces) { 144 EXPECT_EQ( 145 "namespace i { namespace j { } }", 146 runCheckOnCode<NamespaceCommentCheck>("namespace i { namespace j { } }")); 147 } 148 149 TEST(NamespaceCommentCheckTest, CheckExistingComments) { 150 EXPECT_EQ("namespace i { namespace j {\n" 151 "} /* namespace j */ } // namespace i\n" 152 " /* random comment */", 153 runCheckOnCode<NamespaceCommentCheck>( 154 "namespace i { namespace j {\n" 155 "} /* namespace j */ } /* random comment */")); 156 EXPECT_EQ("namespace {\n" 157 "} // namespace", 158 runCheckOnCode<NamespaceCommentCheck>("namespace {\n" 159 "} // namespace")); 160 EXPECT_EQ("namespace {\n" 161 "} //namespace", 162 runCheckOnCode<NamespaceCommentCheck>("namespace {\n" 163 "} //namespace")); 164 EXPECT_EQ("namespace {\n" 165 "} // anonymous namespace", 166 runCheckOnCode<NamespaceCommentCheck>("namespace {\n" 167 "} // anonymous namespace")); 168 EXPECT_EQ("namespace {\n" 169 "} // Anonymous namespace.", 170 runCheckOnCode<NamespaceCommentCheck>("namespace {\n" 171 "} // Anonymous namespace.")); 172 EXPECT_EQ( 173 "namespace q {\n" 174 "} // namespace q", 175 runCheckOnCode<NamespaceCommentCheck>("namespace q {\n" 176 "} // anonymous namespace q")); 177 EXPECT_EQ( 178 "namespace My_NameSpace123 {\n" 179 "} // namespace My_NameSpace123", 180 runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n" 181 "} // namespace My_NameSpace123")); 182 EXPECT_EQ( 183 "namespace My_NameSpace123 {\n" 184 "} //namespace My_NameSpace123", 185 runCheckOnCode<NamespaceCommentCheck>("namespace My_NameSpace123 {\n" 186 "} //namespace My_NameSpace123")); 187 EXPECT_EQ("namespace My_NameSpace123 {\n" 188 "} // end namespace My_NameSpace123", 189 runCheckOnCode<NamespaceCommentCheck>( 190 "namespace My_NameSpace123 {\n" 191 "} // end namespace My_NameSpace123")); 192 // Understand comments only on the same line. 193 EXPECT_EQ("namespace {\n" 194 "} // namespace\n" 195 "// namespace", 196 runCheckOnCode<NamespaceCommentCheck>("namespace {\n" 197 "}\n" 198 "// namespace")); 199 } 200 201 TEST(NamespaceCommentCheckTest, FixWrongComments) { 202 EXPECT_EQ("namespace i { namespace jJ0_ {\n" 203 "} // namespace jJ0_\n" 204 " } // namespace i\n" 205 " /* random comment */", 206 runCheckOnCode<NamespaceCommentCheck>( 207 "namespace i { namespace jJ0_ {\n" 208 "} /* namespace qqq */ } /* random comment */")); 209 EXPECT_EQ("namespace {\n" 210 "} // namespace", 211 runCheckOnCode<NamespaceCommentCheck>("namespace {\n" 212 "} // namespace asdf")); 213 // Remove unknown line comments. These are likely to be an unrecognized form 214 // of a namespace ending comment. 215 EXPECT_EQ("namespace {\n" 216 "} // namespace", 217 runCheckOnCode<NamespaceCommentCheck>("namespace {\n" 218 "} // random text")); 219 } 220 221 TEST(BracesAroundStatementsCheckTest, IfWithComments) { 222 EXPECT_EQ("int main() {\n" 223 " if (false /*dummy token*/) {\n" 224 " // comment\n" 225 " return -1; /**/\n" 226 "}\n" 227 " if (false) {\n" 228 " return -1; // comment\n" 229 "}\n" 230 " if (false) {\n" 231 " return -1; \n" 232 "}/* multi-line \n comment */\n" 233 "}", 234 runCheckOnCode<BracesAroundStatementsCheck>( 235 "int main() {\n" 236 " if (false /*dummy token*/)\n" 237 " // comment\n" 238 " return -1; /**/\n" 239 " if (false)\n" 240 " return -1; // comment\n" 241 " if (false)\n" 242 " return -1; /* multi-line \n comment */\n" 243 "}")); 244 EXPECT_EQ("int main() {\n" 245 " if (false /*dummy token*/) {\n" 246 " // comment\n" 247 " return -1 /**/ ;\n" 248 "}\n" 249 "}", 250 runCheckOnCode<BracesAroundStatementsCheck>( 251 "int main() {\n" 252 " if (false /*dummy token*/)\n" 253 " // comment\n" 254 " return -1 /**/ ;\n" 255 "}")); 256 } 257 258 TEST(BracesAroundStatementsCheckTest, If) { 259 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" 260 " if (false) {\n" 261 " return -1;\n" 262 " }\n" 263 "}"); 264 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" 265 " if (auto Cond = false) {\n" 266 " return -1;\n" 267 " }\n" 268 "}"); 269 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" 270 " if (false) {\n" 271 " return -1;\n" 272 " } else {\n" 273 " return -2;\n" 274 " }\n" 275 "}"); 276 EXPECT_EQ("int main() {\n" 277 " if (false) {\n" 278 " return -1;\n" 279 "}\n" 280 "}", 281 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 282 " if (false)\n" 283 " return -1;\n" 284 "}")); 285 EXPECT_EQ("int main() {\n" 286 " if (auto Cond = false /**/ ) {\n" 287 " return -1;\n" 288 "}\n" 289 "}", 290 runCheckOnCode<BracesAroundStatementsCheck>( 291 "int main() {\n" 292 " if (auto Cond = false /**/ )\n" 293 " return -1;\n" 294 "}")); 295 // FIXME: Consider adding braces before EMPTY_MACRO and after the statement. 296 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, 297 "#define EMPTY_MACRO\n" 298 "int main() {\n" 299 " if (auto Cond = false EMPTY_MACRO /**/ ) EMPTY_MACRO\n" 300 " return -1;\n" 301 "}"); 302 EXPECT_EQ("int main() {\n" 303 " if (true) { return -1/**/ ;\n" 304 "}\n" 305 "}", 306 runCheckOnCode<BracesAroundStatementsCheck>( 307 "int main() {\n" 308 " if (true) return -1/**/ ;\n" 309 "}")); 310 EXPECT_EQ("int main() {\n" 311 " if (false) {\n" 312 " return -1;\n" 313 " } else {\n" 314 " return -2;\n" 315 "}\n" 316 "}", 317 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 318 " if (false)\n" 319 " return -1;\n" 320 " else\n" 321 " return -2;\n" 322 "}")); 323 EXPECT_EQ("int main() {\n" 324 " if (false) {\n" 325 " return -1;\n" 326 " } else if (1 == 2) {\n" 327 " return -2;\n" 328 " } else {\n" 329 " return -3;\n" 330 "}\n" 331 "}", 332 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 333 " if (false)\n" 334 " return -1;\n" 335 " else if (1 == 2)\n" 336 " return -2;\n" 337 " else\n" 338 " return -3;\n" 339 "}")); 340 EXPECT_EQ("int main() {\n" 341 " if (false) {\n" 342 " return -1;\n" 343 " } else if (1 == 2) {\n" 344 " return -2;\n" 345 " } else {\n" 346 " return -3;\n" 347 "}\n" 348 "}", 349 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 350 " if (false)\n" 351 " return -1;\n" 352 " else if (1 == 2) {\n" 353 " return -2;\n" 354 " } else\n" 355 " return -3;\n" 356 "}")); 357 } 358 359 TEST(BracesAroundStatementsCheckTest, IfElseWithShortStatements) { 360 ClangTidyOptions Options; 361 Options.CheckOptions["test-check-0.ShortStatementLines"] = "1"; 362 363 EXPECT_EQ("int main() {\n" 364 " if (true) return 1;\n" 365 " if (false) { return -1;\n" 366 " } else if (1 == 2) { return -2;\n" 367 " } else { return -3;\n" 368 "}\n" 369 "}", 370 runCheckOnCode<BracesAroundStatementsCheck>( 371 "int main() {\n" 372 " if (true) return 1;\n" 373 " if (false) return -1;\n" 374 " else if (1 == 2) return -2;\n" 375 " else return -3;\n" 376 "}", 377 nullptr, "input.cc", None, Options)); 378 379 // If the last else is an else-if, we also force it. 380 EXPECT_EQ("int main() {\n" 381 " if (false) { return -1;\n" 382 " } else if (1 == 2) { return -2;\n" 383 "}\n" 384 "}", 385 runCheckOnCode<BracesAroundStatementsCheck>( 386 "int main() {\n" 387 " if (false) return -1;\n" 388 " else if (1 == 2) return -2;\n" 389 "}", 390 nullptr, "input.cc", None, Options)); 391 } 392 393 TEST(BracesAroundStatementsCheckTest, For) { 394 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" 395 " for (;;) {\n" 396 " ;\n" 397 " }\n" 398 "}"); 399 EXPECT_EQ("int main() {\n" 400 " for (;;) {\n" 401 " ;\n" 402 "}\n" 403 "}", 404 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 405 " for (;;)\n" 406 " ;\n" 407 "}")); 408 EXPECT_EQ("int main() {\n" 409 " for (;;) {\n" 410 " /**/ ;\n" 411 "}\n" 412 "}", 413 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 414 " for (;;)\n" 415 " /**/ ;\n" 416 "}")); 417 EXPECT_EQ("int main() {\n" 418 " for (;;) {\n" 419 " return -1 /**/ ;\n" 420 "}\n" 421 "}", 422 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 423 " for (;;)\n" 424 " return -1 /**/ ;\n" 425 "}")); 426 } 427 428 TEST(BracesAroundStatementsCheckTest, ForRange) { 429 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" 430 " int arr[4];\n" 431 " for (int i : arr) {\n" 432 " ;\n" 433 " }\n" 434 "}"); 435 EXPECT_EQ("int main() {\n" 436 " int arr[4];\n" 437 " for (int i : arr) {\n" 438 " ;\n" 439 "}\n" 440 " for (int i : arr) {\n" 441 " return -1 ;\n" 442 "}\n" 443 "}", 444 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 445 " int arr[4];\n" 446 " for (int i : arr)\n" 447 " ;\n" 448 " for (int i : arr)\n" 449 " return -1 ;\n" 450 "}")); 451 } 452 453 TEST(BracesAroundStatementsCheckTest, DoWhile) { 454 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" 455 " do {\n" 456 " ;\n" 457 " } while (false);\n" 458 "}"); 459 EXPECT_EQ("int main() {\n" 460 " do {\n" 461 " ;\n" 462 " } while (false);\n" 463 "}", 464 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 465 " do\n" 466 " ;\n" 467 " while (false);\n" 468 "}")); 469 } 470 471 TEST(BracesAroundStatementsCheckTest, While) { 472 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, "int main() {\n" 473 " while (false) {\n" 474 " ;\n" 475 " }\n" 476 "}"); 477 EXPECT_EQ("int main() {\n" 478 " while (false) {\n" 479 " ;\n" 480 "}\n" 481 "}", 482 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 483 " while (false)\n" 484 " ;\n" 485 "}")); 486 EXPECT_EQ("int main() {\n" 487 " while (auto Cond = false) {\n" 488 " ;\n" 489 "}\n" 490 "}", 491 runCheckOnCode<BracesAroundStatementsCheck>( 492 "int main() {\n" 493 " while (auto Cond = false)\n" 494 " ;\n" 495 "}")); 496 EXPECT_EQ("int main() {\n" 497 " while (false /*dummy token*/) {\n" 498 " ;\n" 499 "}\n" 500 "}", 501 runCheckOnCode<BracesAroundStatementsCheck>( 502 "int main() {\n" 503 " while (false /*dummy token*/)\n" 504 " ;\n" 505 "}")); 506 EXPECT_EQ("int main() {\n" 507 " while (false) {\n" 508 " break;\n" 509 "}\n" 510 "}", 511 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 512 " while (false)\n" 513 " break;\n" 514 "}")); 515 EXPECT_EQ("int main() {\n" 516 " while (false) {\n" 517 " break /**/;\n" 518 "}\n" 519 "}", 520 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 521 " while (false)\n" 522 " break /**/;\n" 523 "}")); 524 EXPECT_EQ("int main() {\n" 525 " while (false) {\n" 526 " /**/;\n" 527 "}\n" 528 "}", 529 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 530 " while (false)\n" 531 " /**/;\n" 532 "}")); 533 } 534 535 TEST(BracesAroundStatementsCheckTest, Nested) { 536 EXPECT_EQ("int main() {\n" 537 " do { if (true) {}} while (false);\n" 538 "}", 539 runCheckOnCode<BracesAroundStatementsCheck>( 540 "int main() {\n" 541 " do if (true) {}while (false);\n" 542 "}")); 543 EXPECT_EQ("int main() {\n" 544 " do { if (true) {}} while (false);\n" 545 "}", 546 runCheckOnCode<BracesAroundStatementsCheck>( 547 "int main() {\n" 548 " do if (true) {}while (false);\n" 549 "}")); 550 EXPECT_EQ( 551 "int main() {\n" 552 " if (true) {\n" 553 " // comment\n" 554 " if (false) {\n" 555 " // comment\n" 556 " /**/ ; // comment\n" 557 " }\n" 558 "}\n" 559 "}", 560 runCheckOnCode<BracesAroundStatementsCheck>("int main() {\n" 561 " if (true)\n" 562 " // comment\n" 563 " if (false) {\n" 564 " // comment\n" 565 " /**/ ; // comment\n" 566 " }\n" 567 "}")); 568 } 569 570 TEST(BracesAroundStatementsCheckTest, Macros) { 571 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, 572 "#define IF(COND) if (COND) return -1;\n" 573 "int main() {\n" 574 " IF(false)\n" 575 "}"); 576 EXPECT_NO_CHANGES(BracesAroundStatementsCheck, 577 "#define FOR(COND) for (COND) return -1;\n" 578 "int main() {\n" 579 " FOR(;;)\n" 580 "}"); 581 EXPECT_EQ("#define DO_IT ++i\n" 582 "int i = 0;\n" 583 "int main() {\n" 584 " if (false) {\n" 585 " DO_IT;\n" 586 " } else if (1 == 2) {\n" 587 " DO_IT;\n" 588 " } else {\n" 589 " DO_IT;\n" 590 "}\n" 591 "}", 592 runCheckOnCode<BracesAroundStatementsCheck>("#define DO_IT ++i\n" 593 "int i = 0;\n" 594 "int main() {\n" 595 " if (false)\n" 596 " DO_IT;\n" 597 " else if (1 == 2)\n" 598 " DO_IT;\n" 599 " else\n" 600 " DO_IT;\n" 601 "}")); 602 } 603 604 #define EXPECT_NO_CHANGES_WITH_OPTS(Check, Opts, Code) \ 605 EXPECT_EQ(Code, runCheckOnCode<Check>(Code, nullptr, "input.cc", None, Opts)) 606 TEST(BracesAroundStatementsCheckTest, ImplicitCastInReturn) { 607 ClangTidyOptions Opts; 608 Opts.CheckOptions["test-check-0.ShortStatementLines"] = "1"; 609 610 StringRef Input = "const char *f() {\n" 611 " if (true) return \"\";\n" 612 " return \"abc\";\n" 613 "}\n"; 614 EXPECT_NO_CHANGES_WITH_OPTS(BracesAroundStatementsCheck, Opts, Input); 615 EXPECT_EQ("const char *f() {\n" 616 " if (true) { return \"\";\n" 617 "}\n" 618 " return \"abc\";\n" 619 "}\n", 620 runCheckOnCode<BracesAroundStatementsCheck>(Input)); 621 } 622 623 } // namespace test 624 } // namespace tidy 625 } // namespace clang 626