diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareNotNullCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareNotNullCheck.cpp --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareNotNullCheck.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/DeclareNotNullCheck.cpp @@ -17,13 +17,29 @@ namespace cppcoreguidelines { void DeclareNotNullCheck::registerMatchers(MatchFinder *Finder) { - auto PointerType = hasType(pointerType()); - Finder->addMatcher(parmVarDecl(PointerType).bind("param"), this); + auto NullCondition = expr(ignoringImpCasts(anyOf( + binaryOperator(hasOperatorName("=="), + hasLHS(ignoringImpCasts(cxxNullPtrLiteralExpr())), + hasRHS(ignoringImpCasts(expr().bind("exp")))), + binaryOperator(hasOperatorName("=="), + hasLHS(ignoringImpCasts(expr().bind("exp"))), + hasRHS(ignoringImpCasts(cxxNullPtrLiteralExpr())))))); + auto functMatcher = + functionDecl( + hasAnyParameter(parmVarDecl(hasType(pointerType())).bind("param"))) + .bind("funct"); + Finder->addMatcher(ifStmt(hasParent(compoundStmt(hasParent(functMatcher))), + hasCondition(NullCondition)), + this); } void DeclareNotNullCheck::check(const MatchFinder::MatchResult &Result) { + const FunctionDecl *Funct = Result.Nodes.getNodeAs("funct"); const ParmVarDecl *Par = Result.Nodes.getNodeAs("param"); - diag(Par->getLocation(), "Found a pointer passed as a param") << Par; + const Expr *Ex = Result.Nodes.getNodeAs("exp"); + diag(Ex->getExprLoc(), "pointer parameter checked against nullptr") << Par; + diag(Par->getLocation(), "consider declaring as not_null", + DiagnosticIDs::Note); } } // namespace cppcoreguidelines diff --git a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/declare-not-null.cpp b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/declare-not-null.cpp --- a/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/declare-not-null.cpp +++ b/clang-tools-extra/test/clang-tidy/checkers/cppcoreguidelines/declare-not-null.cpp @@ -1,5 +1,22 @@ // RUN: %check_clang_tidy %s cppcoreguidelines-declare-not-null %t -void f(int *a); -// CHECK-MESSAGES: :[[@LINE-1]]:13: warning: Found a pointer passed as a param [cppcoreguidelines-declare-not-null] -void f2(int a); \ No newline at end of file +namespace gsl { +template +struct not_null {}; +} // namespace gsl + + +void f(int *a){ + if(a == nullptr) + return; + else a++; + return; +} +// CHECK-MESSAGES: [[@LINE-5]]:8: warning: pointer parameter checked against nullptr +// CHECK-MESSAGES: [[@LINE-7]]:13: note: consider declaring as not_null + +void f2(gsl::not_nulla){ + return; +} + +void f3(int a); \ No newline at end of file