brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.7 KiB · faa07ff Raw
301 lines · cpp
1//===----------------------------------------------------------------------===//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 "StringviewNullptrCheck.h"10#include "../utils/TransformerClangTidyCheck.h"11#include "clang/AST/Decl.h"12#include "clang/AST/OperationKinds.h"13#include "clang/ASTMatchers/ASTMatchers.h"14#include "clang/Tooling/Transformer/RangeSelector.h"15#include "clang/Tooling/Transformer/RewriteRule.h"16#include "clang/Tooling/Transformer/Stencil.h"17#include "llvm/ADT/StringRef.h"18 19namespace clang::tidy::bugprone {20 21using namespace ::clang::ast_matchers;22using namespace ::clang::transformer;23 24namespace {25 26AST_MATCHER_P(InitListExpr, initCountIs, unsigned, N) {27  return Node.getNumInits() == N;28}29 30AST_MATCHER(clang::VarDecl, isDirectInitialization) {31  return Node.getInitStyle() != clang::VarDecl::InitializationStyle::CInit;32}33 34} // namespace35 36static RewriteRuleWith<std::string> stringviewNullptrCheckImpl() {37  auto ConstructionWarning =38      cat("constructing basic_string_view from null is undefined; replace with "39          "the default constructor");40  auto StaticCastWarning =41      cat("casting to basic_string_view from null is undefined; replace with "42          "the empty string");43  auto ArgumentConstructionWarning =44      cat("passing null as basic_string_view is undefined; replace with the "45          "empty string");46  auto AssignmentWarning =47      cat("assignment to basic_string_view from null is undefined; replace "48          "with the default constructor");49  auto RelativeComparisonWarning =50      cat("comparing basic_string_view to null is undefined; replace with the "51          "empty string");52  auto EqualityComparisonWarning =53      cat("comparing basic_string_view to null is undefined; replace with the "54          "emptiness query");55 56  // Matches declarations and expressions of type `basic_string_view`57  auto HasBasicStringViewType = hasType(hasUnqualifiedDesugaredType(recordType(58      hasDeclaration(cxxRecordDecl(hasName("::std::basic_string_view"))))));59 60  // Matches `nullptr` and `(nullptr)` binding to a pointer61  auto NullLiteral = implicitCastExpr(62      hasCastKind(clang::CK_NullToPointer),63      hasSourceExpression(ignoringParens(cxxNullPtrLiteralExpr())));64 65  // Matches `{nullptr}` and `{(nullptr)}` binding to a pointer66  auto NullInitList = initListExpr(initCountIs(1), hasInit(0, NullLiteral));67 68  // Matches `{}`69  auto EmptyInitList = initListExpr(initCountIs(0));70 71  // Matches null construction without `basic_string_view` type spelling72  auto BasicStringViewConstructingFromNullExpr =73      cxxConstructExpr(74          HasBasicStringViewType, argumentCountIs(1),75          hasAnyArgument(/* `hasArgument` would skip over parens */ anyOf(76              NullLiteral, NullInitList, EmptyInitList)),77          unless(cxxTemporaryObjectExpr(/* filters out type spellings */)),78          has(expr().bind("null_arg_expr")))79          .bind("construct_expr");80 81  // `std::string_view(null_arg_expr)`82  auto HandleTemporaryCXXFunctionalCastExpr =83      makeRule(cxxFunctionalCastExpr(hasSourceExpression(84                   BasicStringViewConstructingFromNullExpr)),85               remove(node("null_arg_expr")), ConstructionWarning);86 87  // `std::string_view{null_arg_expr}` and `(std::string_view){null_arg_expr}`88  auto HandleTemporaryCXXTemporaryObjectExprAndCompoundLiteralExpr = makeRule(89      cxxTemporaryObjectExpr(cxxConstructExpr(90          HasBasicStringViewType, argumentCountIs(1),91          hasAnyArgument(/* `hasArgument` would skip over parens */ anyOf(92              NullLiteral, NullInitList, EmptyInitList)),93          has(expr().bind("null_arg_expr")))),94      remove(node("null_arg_expr")), ConstructionWarning);95 96  // `(std::string_view) null_arg_expr`97  auto HandleTemporaryCStyleCastExpr =98      makeRule(cStyleCastExpr(hasSourceExpression(99                   BasicStringViewConstructingFromNullExpr)),100               changeTo(node("null_arg_expr"), cat("{}")), ConstructionWarning);101 102  // `static_cast<std::string_view>(null_arg_expr)`103  auto HandleTemporaryCXXStaticCastExpr =104      makeRule(cxxStaticCastExpr(hasSourceExpression(105                   BasicStringViewConstructingFromNullExpr)),106               changeTo(node("null_arg_expr"), cat("\"\"")), StaticCastWarning);107 108  // `std::string_view sv = null_arg_expr;`109  auto HandleStackCopyInitialization =110      makeRule(varDecl(HasBasicStringViewType,111                       hasInitializer(ignoringImpCasts(cxxConstructExpr(112                           BasicStringViewConstructingFromNullExpr,113                           unless(isListInitialization())))),114                       unless(isDirectInitialization())),115               changeTo(node("null_arg_expr"), cat("{}")), ConstructionWarning);116 117  // `std::string_view sv = {null_arg_expr};`118  auto HandleStackCopyListInitialization =119      makeRule(varDecl(HasBasicStringViewType,120                       hasInitializer(cxxConstructExpr(121                           BasicStringViewConstructingFromNullExpr,122                           isListInitialization())),123                       unless(isDirectInitialization())),124               remove(node("null_arg_expr")), ConstructionWarning);125 126  // `std::string_view sv(null_arg_expr);`127  auto HandleStackDirectInitialization =128      makeRule(varDecl(HasBasicStringViewType,129                       hasInitializer(cxxConstructExpr(130                           BasicStringViewConstructingFromNullExpr,131                           unless(isListInitialization()))),132                       isDirectInitialization())133                   .bind("var_decl"),134               changeTo(node("construct_expr"), cat(name("var_decl"))),135               ConstructionWarning);136 137  // `std::string_view sv{null_arg_expr};`138  auto HandleStackDirectListInitialization =139      makeRule(varDecl(HasBasicStringViewType,140                       hasInitializer(cxxConstructExpr(141                           BasicStringViewConstructingFromNullExpr,142                           isListInitialization())),143                       isDirectInitialization()),144               remove(node("null_arg_expr")), ConstructionWarning);145 146  // `struct S { std::string_view sv = null_arg_expr; };`147  auto HandleFieldInClassCopyInitialization = makeRule(148      fieldDecl(HasBasicStringViewType,149                hasInClassInitializer(ignoringImpCasts(150                    cxxConstructExpr(BasicStringViewConstructingFromNullExpr,151                                     unless(isListInitialization()))))),152      changeTo(node("null_arg_expr"), cat("{}")), ConstructionWarning);153 154  // `struct S { std::string_view sv = {null_arg_expr}; };` and155  // `struct S { std::string_view sv{null_arg_expr}; };`156  auto HandleFieldInClassCopyListAndDirectListInitialization = makeRule(157      fieldDecl(HasBasicStringViewType,158                hasInClassInitializer(ignoringImpCasts(159                    cxxConstructExpr(BasicStringViewConstructingFromNullExpr,160                                     isListInitialization())))),161      remove(node("null_arg_expr")), ConstructionWarning);162 163  // `class C { std::string_view sv; C() : sv(null_arg_expr) {} };`164  auto HandleConstructorDirectInitialization =165      makeRule(cxxCtorInitializer(forField(fieldDecl(HasBasicStringViewType)),166                                  withInitializer(cxxConstructExpr(167                                      BasicStringViewConstructingFromNullExpr,168                                      unless(isListInitialization())))),169               remove(node("null_arg_expr")), ConstructionWarning);170 171  // `class C { std::string_view sv; C() : sv{null_arg_expr} {} };`172  auto HandleConstructorDirectListInitialization =173      makeRule(cxxCtorInitializer(forField(fieldDecl(HasBasicStringViewType)),174                                  withInitializer(cxxConstructExpr(175                                      BasicStringViewConstructingFromNullExpr,176                                      isListInitialization()))),177               remove(node("null_arg_expr")), ConstructionWarning);178 179  // `void f(std::string_view sv = null_arg_expr);`180  auto HandleDefaultArgumentCopyInitialization =181      makeRule(parmVarDecl(HasBasicStringViewType,182                           hasInitializer(ignoringImpCasts(cxxConstructExpr(183                               BasicStringViewConstructingFromNullExpr,184                               unless(isListInitialization()))))),185               changeTo(node("null_arg_expr"), cat("{}")), ConstructionWarning);186 187  // `void f(std::string_view sv = {null_arg_expr});`188  auto HandleDefaultArgumentCopyListInitialization =189      makeRule(parmVarDecl(HasBasicStringViewType,190                           hasInitializer(cxxConstructExpr(191                               BasicStringViewConstructingFromNullExpr,192                               isListInitialization()))),193               remove(node("null_arg_expr")), ConstructionWarning);194 195  // `new std::string_view(null_arg_expr)`196  auto HandleHeapDirectInitialization = makeRule(197      cxxNewExpr(has(cxxConstructExpr(BasicStringViewConstructingFromNullExpr,198                                      unless(isListInitialization()))),199                 unless(isArray()), unless(hasAnyPlacementArg(anything()))),200      remove(node("null_arg_expr")), ConstructionWarning);201 202  // `new std::string_view{null_arg_expr}`203  auto HandleHeapDirectListInitialization = makeRule(204      cxxNewExpr(has(cxxConstructExpr(BasicStringViewConstructingFromNullExpr,205                                      isListInitialization())),206                 unless(isArray()), unless(hasAnyPlacementArg(anything()))),207      remove(node("null_arg_expr")), ConstructionWarning);208 209  // `function(null_arg_expr)`210  auto HandleFunctionArgumentInitialization =211      makeRule(callExpr(hasAnyArgument(ignoringImpCasts(212                            BasicStringViewConstructingFromNullExpr)),213                        unless(cxxOperatorCallExpr())),214               changeTo(node("construct_expr"), cat("\"\"")),215               ArgumentConstructionWarning);216 217  // `sv = null_arg_expr`218  auto HandleAssignment = makeRule(219      cxxOperatorCallExpr(hasOverloadedOperatorName("="),220                          hasRHS(materializeTemporaryExpr(221                              has(BasicStringViewConstructingFromNullExpr)))),222      changeTo(node("construct_expr"), cat("{}")), AssignmentWarning);223 224  // `sv < null_arg_expr`225  auto HandleRelativeComparison = makeRule(226      cxxOperatorCallExpr(hasAnyOverloadedOperatorName("<", "<=", ">", ">="),227                          hasEitherOperand(ignoringImpCasts(228                              BasicStringViewConstructingFromNullExpr))),229      changeTo(node("construct_expr"), cat("\"\"")), RelativeComparisonWarning);230 231  // `sv == null_arg_expr`232  auto HandleEmptyEqualityComparison = makeRule(233      cxxOperatorCallExpr(234          hasOverloadedOperatorName("=="),235          hasOperands(ignoringImpCasts(BasicStringViewConstructingFromNullExpr),236                      traverse(clang::TK_IgnoreUnlessSpelledInSource,237                               expr().bind("instance"))))238          .bind("root"),239      changeTo(node("root"), cat(access("instance", cat("empty")), "()")),240      EqualityComparisonWarning);241 242  // `sv != null_arg_expr`243  auto HandleNonEmptyEqualityComparison = makeRule(244      cxxOperatorCallExpr(245          hasOverloadedOperatorName("!="),246          hasOperands(ignoringImpCasts(BasicStringViewConstructingFromNullExpr),247                      traverse(clang::TK_IgnoreUnlessSpelledInSource,248                               expr().bind("instance"))))249          .bind("root"),250      changeTo(node("root"), cat("!", access("instance", cat("empty")), "()")),251      EqualityComparisonWarning);252 253  // `return null_arg_expr;`254  auto HandleReturnStatement = makeRule(255      returnStmt(hasReturnValue(256          ignoringImpCasts(BasicStringViewConstructingFromNullExpr))),257      changeTo(node("construct_expr"), cat("{}")), ConstructionWarning);258 259  // `T(null_arg_expr)`260  auto HandleConstructorInvocation =261      makeRule(cxxConstructExpr(262                   hasAnyArgument(/* `hasArgument` would skip over parens */263                                  ignoringImpCasts(264                                      BasicStringViewConstructingFromNullExpr)),265                   unless(HasBasicStringViewType)),266               changeTo(node("construct_expr"), cat("\"\"")),267               ArgumentConstructionWarning);268 269  return applyFirst(270      {HandleTemporaryCXXFunctionalCastExpr,271       HandleTemporaryCXXTemporaryObjectExprAndCompoundLiteralExpr,272       HandleTemporaryCStyleCastExpr,273       HandleTemporaryCXXStaticCastExpr,274       HandleStackCopyInitialization,275       HandleStackCopyListInitialization,276       HandleStackDirectInitialization,277       HandleStackDirectListInitialization,278       HandleFieldInClassCopyInitialization,279       HandleFieldInClassCopyListAndDirectListInitialization,280       HandleConstructorDirectInitialization,281       HandleConstructorDirectListInitialization,282       HandleDefaultArgumentCopyInitialization,283       HandleDefaultArgumentCopyListInitialization,284       HandleHeapDirectInitialization,285       HandleHeapDirectListInitialization,286       HandleFunctionArgumentInitialization,287       HandleAssignment,288       HandleRelativeComparison,289       HandleEmptyEqualityComparison,290       HandleNonEmptyEqualityComparison,291       HandleReturnStatement,292       HandleConstructorInvocation});293}294 295StringviewNullptrCheck::StringviewNullptrCheck(StringRef Name,296                                               ClangTidyContext *Context)297    : utils::TransformerClangTidyCheck(stringviewNullptrCheckImpl(), Name,298                                       Context) {}299 300} // namespace clang::tidy::bugprone301