Index: clang-tidy/readability/ImplicitBoolCastCheck.h =================================================================== --- clang-tidy/readability/ImplicitBoolCastCheck.h +++ clang-tidy/readability/ImplicitBoolCastCheck.h @@ -26,10 +26,17 @@ AllowConditionalIntegerCasts( Options.get("AllowConditionalIntegerCasts", 0) != 0), AllowConditionalPointerCasts( - Options.get("AllowConditionalPointerCasts", 0) != 0) {} + Options.get("AllowConditionalPointerCasts", 0) != 0), + NullPointerLiteral( + Options.get("NullPointerLiteral", + Context->getLangOpts().CPlusPlus11 ? "nullptr" : "0")) {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + StringRef getNullPointerLiteral() const { + return NullPointerLiteral; + } + private: void handleCastToBool(const ImplicitCastExpr *CastExpression, const Stmt *ParentStatement, ASTContext &Context); @@ -37,8 +44,9 @@ const ImplicitCastExpr *FurtherImplicitCastExpression, ASTContext &Context); - bool AllowConditionalIntegerCasts; - bool AllowConditionalPointerCasts; + const bool AllowConditionalIntegerCasts; + const bool AllowConditionalPointerCasts; + const std::string NullPointerLiteral; }; } // namespace tidy Index: clang-tidy/readability/ImplicitBoolCastCheck.cpp =================================================================== --- clang-tidy/readability/ImplicitBoolCastCheck.cpp +++ clang-tidy/readability/ImplicitBoolCastCheck.cpp @@ -66,7 +66,8 @@ } StringRef -getZeroLiteralToCompareWithForGivenType(CastKind CastExpressionKind, +getZeroLiteralToCompareWithForGivenType(ImplicitBoolCastCheck *Check, + CastKind CastExpressionKind, QualType CastSubExpressionType, ASTContext &Context) { switch (CastExpressionKind) { @@ -79,7 +80,7 @@ case CK_PointerToBoolean: case CK_MemberPointerToBoolean: // Fall-through on purpose. - return Context.getLangOpts().CPlusPlus11 ? "nullptr" : "0"; + return Check->getNullPointerLiteral(); default: llvm_unreachable("Unexpected cast kind"); @@ -122,8 +123,9 @@ } void addFixItHintsForGenericExpressionCastToBool( - DiagnosticBuilder &Diagnostic, const ImplicitCastExpr *CastExpression, - const Stmt *ParentStatement, ASTContext &Context) { + ImplicitBoolCastCheck *Check, DiagnosticBuilder &Diagnostic, + const ImplicitCastExpr *CastExpression, const Stmt *ParentStatement, + ASTContext &Context) { // In case of expressions like (! integer), we should remove the redundant not // operator and use inverted comparison (integer == 0). bool InvertComparison = @@ -172,7 +174,7 @@ EndLocInsertion += " != "; } - EndLocInsertion += getZeroLiteralToCompareWithForGivenType( + EndLocInsertion += getZeroLiteralToCompareWithForGivenType(Check, CastExpression->getCastKind(), SubExpression->getType(), Context); if (NeedOuterParens) { @@ -395,8 +397,9 @@ addFixItHintsForLiteralCastToBool(Diagnostic, CastExpression, EquivalentLiteralExpression); } else { - addFixItHintsForGenericExpressionCastToBool(Diagnostic, CastExpression, - ParentStatement, Context); + addFixItHintsForGenericExpressionCastToBool(this, Diagnostic, + CastExpression, ParentStatement, + Context); } } Index: clang-tidy/readability/SimplifyBooleanExprCheck.h =================================================================== --- clang-tidy/readability/SimplifyBooleanExprCheck.h +++ clang-tidy/readability/SimplifyBooleanExprCheck.h @@ -96,6 +96,10 @@ void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + StringRef getNullPointerLiteral() const { + return NullPointerLiteral; + } + private: void matchBoolBinOpExpr(ast_matchers::MatchFinder *Finder, bool Value, StringRef OperatorName, StringRef BooleanId); @@ -160,6 +164,7 @@ const bool ChainedConditionalReturn; const bool ChainedConditionalAssignment; + const std::string NullPointerLiteral; }; } // namespace readability Index: clang-tidy/readability/SimplifyBooleanExprCheck.cpp =================================================================== --- clang-tidy/readability/SimplifyBooleanExprCheck.cpp +++ clang-tidy/readability/SimplifyBooleanExprCheck.cpp @@ -172,7 +172,8 @@ return !E->getType()->isBooleanType(); } -std::string replacementExpression(const MatchFinder::MatchResult &Result, +std::string replacementExpression(SimplifyBooleanExprCheck *Check, + const MatchFinder::MatchResult &Result, bool Negated, const Expr *E) { E = E->ignoreParenBaseCasts(); const bool NeedsStaticCast = needsStaticCast(E); @@ -180,14 +181,16 @@ if (const auto *UnOp = dyn_cast(E)) { if (UnOp->getOpcode() == UO_LNot) { if (needsNullPtrComparison(UnOp->getSubExpr())) - return (getText(Result, *UnOp->getSubExpr()) + " != nullptr").str(); + return (getText(Result, *UnOp->getSubExpr()) + " != " + + Check->getNullPointerLiteral()).str(); - return replacementExpression(Result, false, UnOp->getSubExpr()); + return replacementExpression(Check, Result, false, UnOp->getSubExpr()); } } if (needsNullPtrComparison(E)) - return (getText(Result, *E) + " == nullptr").str(); + return (getText(Result, *E) + " == " + + Check->getNullPointerLiteral()).str(); StringRef NegatedOperator; const Expr *LHS = nullptr; @@ -214,7 +217,8 @@ return ("!(" + Text + ")").str(); if (needsNullPtrComparison(E)) - return (getText(Result, *E) + " == nullptr").str(); + return (getText(Result, *E) + " == " + + Check->getNullPointerLiteral()).str(); return ("!" + asBool(Text, NeedsStaticCast)); } @@ -222,12 +226,14 @@ if (const auto *UnOp = dyn_cast(E)) { if (UnOp->getOpcode() == UO_LNot) { if (needsNullPtrComparison(UnOp->getSubExpr())) - return (getText(Result, *UnOp->getSubExpr()) + " == nullptr").str(); + return (getText(Result, *UnOp->getSubExpr()) + " == " + + Check->getNullPointerLiteral()).str(); } } if (needsNullPtrComparison(E)) - return (getText(Result, *E) + " != nullptr").str(); + return (getText(Result, *E) + " != " + + Check->getNullPointerLiteral()).str(); return asBool(getText(Result, *E), NeedsStaticCast); } @@ -265,7 +271,10 @@ : ClangTidyCheck(Name, Context), ChainedConditionalReturn(Options.get("ChainedConditionalReturn", 0U)), ChainedConditionalAssignment( - Options.get("ChainedConditionalAssignment", 0U)) {} + Options.get("ChainedConditionalAssignment", 0U)), + NullPointerLiteral( + Options.get("NullPointerLiteral", + Context->getLangOpts().CPlusPlus11 ? "nullptr" : "0")) {} void SimplifyBooleanExprCheck::matchBoolBinOpExpr(MatchFinder *Finder, bool Value, @@ -528,7 +537,7 @@ const auto *LHS = Result.Nodes.getNodeAs(LHSId); const auto *RHS = Result.Nodes.getNodeAs(RHSId); std::string Replacement = - replacementExpression(Result, Negated, UseLHS ? LHS : RHS); + replacementExpression(this, Result, Negated, UseLHS ? LHS : RHS); SourceRange Range(LHS->getLocStart(), RHS->getLocEnd()); issueDiag(Result, BoolLiteral->getLocStart(), SimplifyOperatorDiagnostic, Range, Replacement); @@ -557,7 +566,7 @@ const MatchFinder::MatchResult &Result, const ConditionalOperator *Ternary, bool Negated) { std::string Replacement = - replacementExpression(Result, Negated, Ternary->getCond()); + replacementExpression(this, Result, Negated, Ternary->getCond()); issueDiag(Result, Ternary->getTrueExpr()->getLocStart(), "redundant boolean literal in ternary expression result", Ternary->getSourceRange(), Replacement); @@ -566,7 +575,8 @@ void SimplifyBooleanExprCheck::replaceWithReturnCondition( const MatchFinder::MatchResult &Result, const IfStmt *If, bool Negated) { StringRef Terminator = isa(If->getElse()) ? ";" : ""; - std::string Condition = replacementExpression(Result, Negated, If->getCond()); + std::string Condition = + replacementExpression(this, Result, Negated, If->getCond()); std::string Replacement = ("return " + Condition + Terminator).str(); SourceLocation Start = Result.Nodes.getNodeAs(ThenLiteralId)->getLocStart(); @@ -599,7 +609,8 @@ const Expr *Condition = If->getCond(); std::string Replacement = - "return " + replacementExpression(Result, Negated, Condition); + "return " + replacementExpression(this, Result, Negated, + Condition); issueDiag( Result, Lit->getLocStart(), SimplifyConditionalReturnDiagnostic, SourceRange(If->getLocStart(), Ret->getLocEnd()), Replacement); @@ -622,7 +633,7 @@ getText(Result, *Result.Nodes.getNodeAs(IfAssignVariableId)); StringRef Terminator = isa(IfAssign->getElse()) ? ";" : ""; std::string Condition = - replacementExpression(Result, Negated, IfAssign->getCond()); + replacementExpression(this, Result, Negated, IfAssign->getCond()); std::string Replacement = (VariableName + " = " + Condition + Terminator).str(); SourceLocation Location = Index: docs/clang-tidy/checks/readability-implicit-bool-cast.rst =================================================================== --- docs/clang-tidy/checks/readability-implicit-bool-cast.rst +++ docs/clang-tidy/checks/readability-implicit-bool-cast.rst @@ -97,3 +97,7 @@ Occurences of implicit casts inside macros and template instantiations are deliberately ignored, as it is not clear how to deal with such cases. + +Null pointer literal for fixes could be changed with option +``NullPointerLiteral``. The default value for C++11 or later is ``nullptr``, for + C++98/C++03 - ``0``. Index: docs/clang-tidy/checks/readability-simplify-boolean-expr.rst =================================================================== --- docs/clang-tidy/checks/readability-simplify-boolean-expr.rst +++ docs/clang-tidy/checks/readability-simplify-boolean-expr.rst @@ -76,3 +76,6 @@ ``ChainedConditionalAssignment``, respectively, is specified as non-zero. The default value for both options is zero. +Null pointer literal for fixes could be changed with option +``NullPointerLiteral``. The default value for C++11 or later is ``nullptr``, for + C++98/C++03 - ``0``.