diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/bugprone')
103 files changed, 1167 insertions, 509 deletions
diff --git a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp index c0a778a..ed30d01 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ArgumentCommentCheck.cpp @@ -81,14 +81,16 @@ static std::vector<std::pair<SourceLocation, StringRef>> getCommentsInRange(ASTContext *Ctx, CharSourceRange Range) { std::vector<std::pair<SourceLocation, StringRef>> Comments; auto &SM = Ctx->getSourceManager(); - std::pair<FileID, unsigned> BeginLoc = SM.getDecomposedLoc(Range.getBegin()), - EndLoc = SM.getDecomposedLoc(Range.getEnd()); + const std::pair<FileID, unsigned> BeginLoc = + SM.getDecomposedLoc(Range.getBegin()), + EndLoc = + SM.getDecomposedLoc(Range.getEnd()); if (BeginLoc.first != EndLoc.first) return Comments; bool Invalid = false; - StringRef Buffer = SM.getBufferData(BeginLoc.first, &Invalid); + const StringRef Buffer = SM.getBufferData(BeginLoc.first, &Invalid); if (Invalid) return Comments; @@ -106,7 +108,7 @@ getCommentsInRange(ASTContext *Ctx, CharSourceRange Range) { break; if (Tok.is(tok::comment)) { - std::pair<FileID, unsigned> CommentLoc = + const std::pair<FileID, unsigned> CommentLoc = SM.getDecomposedLoc(Tok.getLocation()); assert(CommentLoc.first == BeginLoc.first); Comments.emplace_back( @@ -125,7 +127,7 @@ static std::vector<std::pair<SourceLocation, StringRef>> getCommentsBeforeLoc(ASTContext *Ctx, SourceLocation Loc) { std::vector<std::pair<SourceLocation, StringRef>> Comments; while (Loc.isValid()) { - clang::Token Tok = utils::lexer::getPreviousToken( + const clang::Token Tok = utils::lexer::getPreviousToken( Loc, Ctx->getSourceManager(), Ctx->getLangOpts(), /*SkipComments=*/false); if (Tok.isNot(tok::comment)) @@ -142,11 +144,11 @@ getCommentsBeforeLoc(ASTContext *Ctx, SourceLocation Loc) { static bool isLikelyTypo(llvm::ArrayRef<ParmVarDecl *> Params, StringRef ArgName, unsigned ArgIndex) { - std::string ArgNameLowerStr = ArgName.lower(); - StringRef ArgNameLower = ArgNameLowerStr; + const std::string ArgNameLowerStr = ArgName.lower(); + const StringRef ArgNameLower = ArgNameLowerStr; // The threshold is arbitrary. - unsigned UpperBound = ((ArgName.size() + 2) / 3) + 1; - unsigned ThisED = ArgNameLower.edit_distance( + const unsigned UpperBound = ((ArgName.size() + 2) / 3) + 1; + const unsigned ThisED = ArgNameLower.edit_distance( Params[ArgIndex]->getIdentifier()->getName().lower(), /*AllowReplacements=*/true, UpperBound); if (ThisED >= UpperBound) @@ -155,7 +157,7 @@ static bool isLikelyTypo(llvm::ArrayRef<ParmVarDecl *> Params, for (unsigned I = 0, E = Params.size(); I != E; ++I) { if (I == ArgIndex) continue; - IdentifierInfo *II = Params[I]->getIdentifier(); + const IdentifierInfo *II = Params[I]->getIdentifier(); if (!II) continue; @@ -163,9 +165,9 @@ static bool isLikelyTypo(llvm::ArrayRef<ParmVarDecl *> Params, // Other parameters must be an edit distance at least Threshold more away // from this parameter. This gives us greater confidence that this is a // typo of this parameter and not one with a similar name. - unsigned OtherED = ArgNameLower.edit_distance(II->getName().lower(), - /*AllowReplacements=*/true, - ThisED + Threshold); + const unsigned OtherED = ArgNameLower.edit_distance( + II->getName().lower(), + /*AllowReplacements=*/true, ThisED + Threshold); if (OtherED < ThisED + Threshold) return false; } @@ -267,7 +269,8 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx, return; Callee = Callee->getFirstDecl(); - unsigned NumArgs = std::min<unsigned>(Args.size(), Callee->getNumParams()); + const unsigned NumArgs = + std::min<unsigned>(Args.size(), Callee->getNumParams()); if ((NumArgs == 0) || (IgnoreSingleArgument && NumArgs == 1)) return; @@ -279,7 +282,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx, for (unsigned I = 0; I < NumArgs; ++I) { const ParmVarDecl *PVD = Callee->getParamDecl(I); - IdentifierInfo *II = PVD->getIdentifier(); + const IdentifierInfo *II = PVD->getIdentifier(); if (!II) continue; if (FunctionDecl *Template = Callee->getTemplateInstantiationPattern()) { @@ -293,7 +296,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx, } } - CharSourceRange BeforeArgument = + const CharSourceRange BeforeArgument = MakeFileCharRange(ArgBeginLoc, Args[I]->getBeginLoc()); ArgBeginLoc = Args[I]->getEndLoc(); @@ -302,7 +305,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx, Comments = getCommentsInRange(Ctx, BeforeArgument); } else { // Fall back to parsing back from the start of the argument. - CharSourceRange ArgsRange = + const CharSourceRange ArgsRange = MakeFileCharRange(Args[I]->getBeginLoc(), Args[I]->getEndLoc()); Comments = getCommentsBeforeLoc(Ctx, ArgsRange.getBegin()); } @@ -312,7 +315,7 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx, if (IdentRE.match(Comment.second, &Matches) && !sameName(Matches[2], II->getName(), StrictMode)) { { - DiagnosticBuilder Diag = + const DiagnosticBuilder Diag = diag(Comment.first, "argument name '%0' in comment does not " "match parameter name %1") << Matches[2] << II; @@ -332,9 +335,9 @@ void ArgumentCommentCheck::checkCallArgs(ASTContext *Ctx, // If the argument comments are missing for literals add them. if (Comments.empty() && shouldAddComment(Args[I])) { - std::string ArgComment = + const std::string ArgComment = (llvm::Twine("/*") + II->getName() + "=*/").str(); - DiagnosticBuilder Diag = + const DiagnosticBuilder Diag = diag(Args[I]->getBeginLoc(), "argument comment missing for literal argument %0") << II diff --git a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp index 1700502..a29aa55 100644 --- a/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssertSideEffectCheck.cpp @@ -29,7 +29,7 @@ AST_MATCHER_P2(Expr, hasSideEffect, bool, CheckFunctionCalls, const Expr *E = &Node; if (const auto *Op = dyn_cast<UnaryOperator>(E)) { - UnaryOperator::Opcode OC = Op->getOpcode(); + const UnaryOperator::Opcode OC = Op->getOpcode(); return OC == UO_PostInc || OC == UO_PostDec || OC == UO_PreInc || OC == UO_PreDec; } @@ -44,7 +44,7 @@ AST_MATCHER_P2(Expr, hasSideEffect, bool, CheckFunctionCalls, if (MethodDecl->isConst()) return false; - OverloadedOperatorKind OpKind = OpCallExpr->getOperator(); + const OverloadedOperatorKind OpKind = OpCallExpr->getOperator(); return OpKind == OO_Equal || OpKind == OO_PlusEqual || OpKind == OO_MinusEqual || OpKind == OO_StarEqual || OpKind == OO_SlashEqual || OpKind == OO_AmpEqual || @@ -130,7 +130,7 @@ void AssertSideEffectCheck::check(const MatchFinder::MatchResult &Result) { StringRef AssertMacroName; while (Loc.isValid() && Loc.isMacroID()) { - StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LangOpts); + const StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LangOpts); Loc = SM.getImmediateMacroCallerLoc(Loc); // Check if this macro is an assert. diff --git a/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp index 2c88562..d5d8a29 100644 --- a/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/AssignmentInIfConditionCheck.cpp @@ -66,7 +66,7 @@ void AssignmentInIfConditionCheck::check( } void AssignmentInIfConditionCheck::report(const Expr *AssignmentExpr) { - SourceLocation OpLoc = + const SourceLocation OpLoc = isa<BinaryOperator>(AssignmentExpr) ? cast<BinaryOperator>(AssignmentExpr)->getOperatorLoc() : cast<CXXOperatorCallExpr>(AssignmentExpr)->getOperatorLoc(); diff --git a/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp index e1d0538a..3e1188d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BadSignalToKillThreadCheck.cpp @@ -40,7 +40,7 @@ void BadSignalToKillThreadCheck::check(const MatchFinder::MatchResult &Result) { const Token &T = MI->tokens().back(); if (!T.isLiteral() || !T.getLiteralData()) return std::nullopt; - StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength()); + const StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength()); llvm::APInt IntValue; constexpr unsigned AutoSenseRadix = 0; diff --git a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp index 07bb081..4f33670 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BranchCloneCheck.cpp @@ -75,12 +75,9 @@ static bool isFallthroughSwitchBranch(const SwitchBranch &Branch) { if (!S) return true; - for (const Attr *A : S->getAttrs()) { - if (isa<FallThroughAttr>(A)) - return false; - } - - return true; + return llvm::all_of(S->getAttrs(), [](const Attr *A) { + return !isa<FallThroughAttr>(A); + }); } } Visitor; @@ -117,7 +114,6 @@ void BranchCloneCheck::registerMatchers(MatchFinder *Finder) { /// static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, const Stmt *Stmt2, bool IgnoreSideEffects) { - if (!Stmt1 || !Stmt2) return !Stmt1 && !Stmt2; @@ -281,8 +277,8 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1, const auto *IntLit1 = cast<IntegerLiteral>(Stmt1); const auto *IntLit2 = cast<IntegerLiteral>(Stmt2); - llvm::APInt I1 = IntLit1->getValue(); - llvm::APInt I2 = IntLit2->getValue(); + const llvm::APInt I1 = IntLit1->getValue(); + const llvm::APInt I2 = IntLit2->getValue(); if (I1.getBitWidth() != I2.getBitWidth()) return false; return I1 == I2; @@ -352,7 +348,7 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) { } } - size_t N = Branches.size(); + const size_t N = Branches.size(); llvm::BitVector KnownAsClone(N); for (size_t I = 0; I + 1 < N; I++) { @@ -375,7 +371,7 @@ void BranchCloneCheck::check(const MatchFinder::MatchResult &Result) { // We report the first occurrence only when we find the second one. diag(Branches[I]->getBeginLoc(), "repeated branch body in conditional chain"); - SourceLocation End = + const SourceLocation End = Lexer::getLocForEndOfToken(Branches[I]->getEndLoc(), 0, *Result.SourceManager, getLangOpts()); if (End.isValid()) { diff --git a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp index 2e21a4c4..6859dc9 100644 --- a/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/BugproneTidyModule.cpp @@ -22,6 +22,7 @@ #include "CommandProcessorCheck.h" #include "ComparePointerToMemberVirtualFunctionCheck.h" #include "CopyConstructorInitCheck.h" +#include "CopyConstructorMutatesArgumentCheck.h" #include "CrtpConstructorAccessibilityCheck.h" #include "DanglingHandleCheck.h" #include "DefaultOperatorNewOnOveralignedTypeCheck.h" @@ -29,7 +30,9 @@ #include "DynamicStaticInitializersCheck.h" #include "EasilySwappableParametersCheck.h" #include "EmptyCatchCheck.h" +#include "ExceptionCopyConstructorThrowsCheck.h" #include "ExceptionEscapeCheck.h" +#include "FloatLoopCounterCheck.h" #include "FoldInitTypeCheck.h" #include "ForwardDeclarationNamespaceCheck.h" #include "ForwardingReferenceOverloadCheck.h" @@ -62,6 +65,7 @@ #include "ParentVirtualCallCheck.h" #include "PointerArithmeticOnPolymorphicObjectCheck.h" #include "PosixReturnCheck.h" +#include "RandomGeneratorSeedCheck.h" #include "RawMemoryCallOnNonTrivialTypeCheck.h" #include "RedundantBranchConditionCheck.h" #include "ReservedIdentifierCheck.h" @@ -73,6 +77,7 @@ #include "SizeofExpressionCheck.h" #include "SpuriouslyWakeUpFunctionsCheck.h" #include "StandaloneEmptyCheck.h" +#include "StdNamespaceModificationCheck.h" #include "StringConstructorCheck.h" #include "StringIntegerAssignmentCheck.h" #include "StringLiteralWithEmbeddedNulCheck.h" @@ -139,6 +144,8 @@ public: "bugprone-compare-pointer-to-member-virtual-function"); CheckFactories.registerCheck<CopyConstructorInitCheck>( "bugprone-copy-constructor-init"); + CheckFactories.registerCheck<CopyConstructorMutatesArgumentCheck>( + "bugprone-copy-constructor-mutates-argument"); CheckFactories.registerCheck<DanglingHandleCheck>( "bugprone-dangling-handle"); CheckFactories.registerCheck<DefaultOperatorNewOnOveralignedTypeCheck>( @@ -150,8 +157,12 @@ public: CheckFactories.registerCheck<EasilySwappableParametersCheck>( "bugprone-easily-swappable-parameters"); CheckFactories.registerCheck<EmptyCatchCheck>("bugprone-empty-catch"); + CheckFactories.registerCheck<ExceptionCopyConstructorThrowsCheck>( + "bugprone-exception-copy-constructor-throws"); CheckFactories.registerCheck<ExceptionEscapeCheck>( "bugprone-exception-escape"); + CheckFactories.registerCheck<FloatLoopCounterCheck>( + "bugprone-float-loop-counter"); CheckFactories.registerCheck<FoldInitTypeCheck>("bugprone-fold-init-type"); CheckFactories.registerCheck<ForwardDeclarationNamespaceCheck>( "bugprone-forward-declaration-namespace"); @@ -220,6 +231,8 @@ public: CheckFactories.registerCheck<ParentVirtualCallCheck>( "bugprone-parent-virtual-call"); CheckFactories.registerCheck<PosixReturnCheck>("bugprone-posix-return"); + CheckFactories.registerCheck<RandomGeneratorSeedCheck>( + "bugprone-random-generator-seed"); CheckFactories.registerCheck<RawMemoryCallOnNonTrivialTypeCheck>( "bugprone-raw-memory-call-on-non-trivial-type"); CheckFactories.registerCheck<ReservedIdentifierCheck>( @@ -237,6 +250,8 @@ public: "bugprone-spuriously-wake-up-functions"); CheckFactories.registerCheck<StandaloneEmptyCheck>( "bugprone-standalone-empty"); + CheckFactories.registerCheck<StdNamespaceModificationCheck>( + "bugprone-std-namespace-modification"); CheckFactories.registerCheck<StringConstructorCheck>( "bugprone-string-constructor"); CheckFactories.registerCheck<StringIntegerAssignmentCheck>( diff --git a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt index 31a0e69..db1256d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/bugprone/CMakeLists.txt @@ -18,6 +18,7 @@ add_clang_library(clangTidyBugproneModule STATIC CommandProcessorCheck.cpp ComparePointerToMemberVirtualFunctionCheck.cpp CopyConstructorInitCheck.cpp + CopyConstructorMutatesArgumentCheck.cpp CrtpConstructorAccessibilityCheck.cpp DanglingHandleCheck.cpp DefaultOperatorNewOnOveralignedTypeCheck.cpp @@ -25,7 +26,9 @@ add_clang_library(clangTidyBugproneModule STATIC DynamicStaticInitializersCheck.cpp EasilySwappableParametersCheck.cpp EmptyCatchCheck.cpp + ExceptionCopyConstructorThrowsCheck.cpp ExceptionEscapeCheck.cpp + FloatLoopCounterCheck.cpp FoldInitTypeCheck.cpp ForwardDeclarationNamespaceCheck.cpp ForwardingReferenceOverloadCheck.cpp @@ -63,6 +66,7 @@ add_clang_library(clangTidyBugproneModule STATIC ParentVirtualCallCheck.cpp PointerArithmeticOnPolymorphicObjectCheck.cpp PosixReturnCheck.cpp + RandomGeneratorSeedCheck.cpp RawMemoryCallOnNonTrivialTypeCheck.cpp RedundantBranchConditionCheck.cpp ReservedIdentifierCheck.cpp @@ -75,6 +79,7 @@ add_clang_library(clangTidyBugproneModule STATIC SmartPtrArrayMismatchCheck.cpp SpuriouslyWakeUpFunctionsCheck.cpp StandaloneEmptyCheck.cpp + StdNamespaceModificationCheck.cpp StringConstructorCheck.cpp StringIntegerAssignmentCheck.cpp StringLiteralWithEmbeddedNulCheck.cpp diff --git a/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp index a376de5..6aed454 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/CapturingThisInMemberVariableCheck.cpp @@ -44,18 +44,17 @@ AST_MATCHER(CXXRecordDecl, correctHandleCaptureThisLambda) { if (Node.hasSimpleMoveAssignment()) return false; - for (const CXXConstructorDecl *C : Node.ctors()) { - if (C->isCopyOrMoveConstructor() && C->isDefaulted() && !C->isDeleted()) - return false; - } - for (const CXXMethodDecl *M : Node.methods()) { - if (M->isCopyAssignmentOperator()) - llvm::errs() << M->isDeleted() << "\n"; - if (M->isCopyAssignmentOperator() && M->isDefaulted() && !M->isDeleted()) - return false; - if (M->isMoveAssignmentOperator() && M->isDefaulted() && !M->isDeleted()) - return false; - } + if (llvm::any_of(Node.ctors(), [](const CXXConstructorDecl *C) { + return C->isCopyOrMoveConstructor() && C->isDefaulted() && + !C->isDeleted(); + })) + return false; + if (llvm::any_of(Node.methods(), [](const CXXMethodDecl *M) { + return (M->isCopyAssignmentOperator() || + M->isMoveAssignmentOperator()) && + M->isDefaulted() && !M->isDeleted(); + })) + return false; // FIXME: find ways to identifier correct handle capture this lambda return true; } diff --git a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp index 3d3fc78..47acc21 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ChainedComparisonCheck.cpp @@ -11,7 +11,6 @@ #include "clang/ASTMatchers/ASTMatchFinder.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" -#include <algorithm> using namespace clang::ast_matchers; diff --git a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp index 602b63e..9067f43 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ComparePointerToMemberVirtualFunctionCheck.cpp @@ -34,7 +34,6 @@ static constexpr llvm::StringLiteral ErrorMsg = void ComparePointerToMemberVirtualFunctionCheck::registerMatchers( MatchFinder *Finder) { - auto DirectMemberVirtualFunctionPointer = unaryOperator( allOf(hasOperatorName("&"), hasUnaryOperand(declRefExpr(to(cxxMethodDecl(isVirtual())))))); diff --git a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp index 76bcbbb..ccbc86a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.cpp @@ -31,7 +31,7 @@ void CopyConstructorInitCheck::registerMatchers(MatchFinder *Finder) { void CopyConstructorInitCheck::check(const MatchFinder::MatchResult &Result) { const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructorDecl>("ctor"); - std::string ParamName = Ctor->getParamDecl(0)->getNameAsString(); + const std::string ParamName = Ctor->getParamDecl(0)->getNameAsString(); // We want only one warning (and FixIt) for each ctor. std::string FixItInitList; @@ -40,7 +40,7 @@ void CopyConstructorInitCheck::check(const MatchFinder::MatchResult &Result) { bool HasWrittenInitializer = false; SmallVector<FixItHint, 2> SafeFixIts; for (const auto *Init : Ctor->inits()) { - bool CtorInitIsWritten = Init->isWritten(); + const bool CtorInitIsWritten = Init->isWritten(); HasWrittenInitializer = HasWrittenInitializer || CtorInitIsWritten; if (!Init->isBaseInitializer()) continue; diff --git a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.h b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.h index cba1a25..e977bc2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorInitCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPYCONSTRUCTORINITCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPYCONSTRUCTORINITCHECK_H #include "../ClangTidyCheck.h" @@ -31,4 +31,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPY_CONSTRUCTOR_INIT_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPYCONSTRUCTORINITCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorMutatesArgumentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorMutatesArgumentCheck.cpp new file mode 100644 index 0000000..cbbb1a0 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorMutatesArgumentCheck.cpp @@ -0,0 +1,74 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "CopyConstructorMutatesArgumentCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +static constexpr llvm::StringLiteral SourceDeclName = "ChangedPVD"; +static constexpr llvm::StringLiteral MutatingOperatorName = "MutatingOp"; +static constexpr llvm::StringLiteral MutatingCallName = "MutatingCall"; + +void CopyConstructorMutatesArgumentCheck::registerMatchers( + MatchFinder *Finder) { + const auto MemberExprOrSourceObject = anyOf( + memberExpr(), + declRefExpr(to(decl(equalsBoundNode(std::string(SourceDeclName)))))); + + const auto IsPartOfSource = + allOf(unless(hasDescendant(expr(unless(MemberExprOrSourceObject)))), + MemberExprOrSourceObject); + + const auto IsSourceMutatingAssignment = traverse( + TK_AsIs, binaryOperation(hasOperatorName("="), hasLHS(IsPartOfSource)) + .bind(MutatingOperatorName)); + + const auto MemberExprOrSelf = anyOf(memberExpr(), cxxThisExpr()); + + const auto IsPartOfSelf = allOf( + unless(hasDescendant(expr(unless(MemberExprOrSelf)))), MemberExprOrSelf); + + const auto IsSelfMutatingAssignment = + binaryOperation(isAssignmentOperator(), hasLHS(IsPartOfSelf)); + + const auto IsSelfMutatingMemberFunction = + functionDecl(hasBody(hasDescendant(IsSelfMutatingAssignment))); + + const auto IsSourceMutatingMemberCall = + cxxMemberCallExpr(on(IsPartOfSource), + callee(IsSelfMutatingMemberFunction)) + .bind(MutatingCallName); + + const auto MutatesSource = allOf( + hasParameter( + 0, parmVarDecl(hasType(lValueReferenceType())).bind(SourceDeclName)), + anyOf(forEachDescendant(IsSourceMutatingAssignment), + forEachDescendant(IsSourceMutatingMemberCall))); + + Finder->addMatcher(cxxConstructorDecl(isCopyConstructor(), MutatesSource), + this); + + Finder->addMatcher(cxxMethodDecl(isCopyAssignmentOperator(), MutatesSource), + this); +} + +void CopyConstructorMutatesArgumentCheck::check( + const MatchFinder::MatchResult &Result) { + if (const auto *MemberCall = + Result.Nodes.getNodeAs<CXXMemberCallExpr>(MutatingCallName)) + diag(MemberCall->getBeginLoc(), "call mutates copied object"); + else if (const auto *Assignment = + Result.Nodes.getNodeAs<Expr>(MutatingOperatorName)) + diag(Assignment->getBeginLoc(), "mutating copied object"); +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/CopyConstructorMutatesArgumentCheck.h b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorMutatesArgumentCheck.h new file mode 100644 index 0000000..0fed572 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/CopyConstructorMutatesArgumentCheck.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPYCONSTRUCTORMUTATESARGUMENTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPYCONSTRUCTORMUTATESARGUMENTCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// Finds assignments to the copied object and its direct or indirect members +/// in copy constructors and copy assignment operators. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/copy-constructor-mutates-argument.html +class CopyConstructorMutatesArgumentCheck : public ClangTidyCheck { +public: + CopyConstructorMutatesArgumentCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_COPYCONSTRUCTORMUTATESARGUMENTCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp index 60f7be8..5ef72ea 100644 --- a/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/CrtpConstructorAccessibilityCheck.cpp @@ -116,9 +116,10 @@ void CrtpConstructorAccessibilityCheck::check( assert(DerivedTemplateParameter && "No template parameter corresponds to the derived class of the CRTP."); - bool NeedsFriend = !isDerivedParameterBefriended(CRTPDeclaration, - DerivedTemplateParameter) && - !isDerivedClassBefriended(CRTPDeclaration, DerivedRecord); + const bool NeedsFriend = + !isDerivedParameterBefriended(CRTPDeclaration, + DerivedTemplateParameter) && + !isDerivedClassBefriended(CRTPDeclaration, DerivedRecord); const FixItHint HintFriend = FixItHint::CreateInsertion( CRTPDeclaration->getBraceRange().getEnd(), diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp index 9f8e885..c95ad2b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.cpp @@ -7,13 +7,11 @@ //===----------------------------------------------------------------------===// #include "DanglingHandleCheck.h" -#include "../utils/Matchers.h" #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" using namespace clang::ast_matchers; -using namespace clang::tidy::matchers; namespace clang::tidy::bugprone { @@ -31,7 +29,6 @@ handleFrom(const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle, static ast_matchers::internal::Matcher<Stmt> handleFromTemporaryValue( const ast_matchers::internal::Matcher<RecordDecl> &IsAHandle) { - const auto TemporaryExpr = anyOf( cxxBindTemporaryExpr(), cxxFunctionalCastExpr( diff --git a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.h b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.h index 486562c..0b71bc4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/DanglingHandleCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLING_HANDLE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLING_HANDLE_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLINGHANDLECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLINGHANDLECHECK_H #include "../ClangTidyCheck.h" @@ -37,4 +37,4 @@ private: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLING_HANDLE_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DANGLINGHANDLECHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/DefaultOperatorNewOnOveralignedTypeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DefaultOperatorNewOnOveralignedTypeCheck.cpp index 0aafdfd..cb4f69a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DefaultOperatorNewOnOveralignedTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DefaultOperatorNewOnOveralignedTypeCheck.cpp @@ -26,7 +26,7 @@ void DefaultOperatorNewOnOveralignedTypeCheck::check( // Get the found 'new' expression. const auto *NewExpr = Result.Nodes.getNodeAs<CXXNewExpr>("new"); - QualType T = NewExpr->getAllocatedType(); + const QualType T = NewExpr->getAllocatedType(); // Dependent types do not have fixed alignment. if (T->isDependentType()) return; @@ -35,25 +35,25 @@ void DefaultOperatorNewOnOveralignedTypeCheck::check( if (!D || !D->isCompleteDefinition()) return; - ASTContext &Context = D->getASTContext(); + const ASTContext &Context = D->getASTContext(); // Check if no alignment was specified for the type. if (!Context.isAlignmentRequired(T)) return; // The user-specified alignment (in bits). - unsigned SpecifiedAlignment = D->getMaxAlignment(); + const unsigned SpecifiedAlignment = D->getMaxAlignment(); // Double-check if no alignment was specified. if (!SpecifiedAlignment) return; // The alignment used by default 'operator new' (in bits). - unsigned DefaultNewAlignment = Context.getTargetInfo().getNewAlign(); + const unsigned DefaultNewAlignment = Context.getTargetInfo().getNewAlign(); - bool OverAligned = SpecifiedAlignment > DefaultNewAlignment; - bool HasDefaultOperatorNew = + const bool OverAligned = SpecifiedAlignment > DefaultNewAlignment; + const bool HasDefaultOperatorNew = !NewExpr->getOperatorNew() || NewExpr->getOperatorNew()->isImplicit(); - unsigned CharWidth = Context.getTargetInfo().getCharWidth(); + const unsigned CharWidth = Context.getTargetInfo().getCharWidth(); if (HasDefaultOperatorNew && OverAligned) diag(NewExpr->getBeginLoc(), "allocation function returns a pointer with alignment %0 but the " diff --git a/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp index 743e6cd..7c58676 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DerivedMethodShadowingBaseMethodCheck.cpp @@ -65,7 +65,7 @@ AST_MATCHER(CXXMethodDecl, nameCollidesWithMethodInBase) { for (const auto &BaseMethod : CurrentRecord->methods()) { if (namesCollide(*BaseMethod, Node)) { - ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder); + const ast_matchers::internal::BoundNodesTreeBuilder Result(*Builder); Builder->setBinding("base_method", clang::DynTypedNode::create(*BaseMethod)); return true; diff --git a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp index 4d0428e..48de7fb 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.cpp @@ -43,7 +43,7 @@ void DynamicStaticInitializersCheck::registerMatchers(MatchFinder *Finder) { void DynamicStaticInitializersCheck::check( const MatchFinder::MatchResult &Result) { const auto *Var = Result.Nodes.getNodeAs<VarDecl>("var"); - SourceLocation Loc = Var->getLocation(); + const SourceLocation Loc = Var->getLocation(); if (!Loc.isValid() || !utils::isPresumedLocInHeaderFile( Loc, *Result.SourceManager, HeaderFileExtensions)) return; diff --git a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.h b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.h index e02c62a..00e4bb1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/DynamicStaticInitializersCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DYNAMIC_STATIC_INITIALIZERS_CHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DYNAMIC_STATIC_INITIALIZERS_CHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DYNAMICSTATICINITIALIZERSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DYNAMICSTATICINITIALIZERSCHECK_H #include "../ClangTidyCheck.h" #include "../FileExtensionsSet.h" @@ -30,4 +30,4 @@ private: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DYNAMIC_STATIC_INITIALIZERS_CHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_DYNAMICSTATICINITIALIZERSCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp index b4ee351..496f3e5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/EasilySwappableParametersCheck.cpp @@ -417,7 +417,7 @@ struct MixData { void sanitize() { assert(Flags != MixFlags::Invalid && "sanitize() called on invalid bitvec"); - MixFlags CanonicalAndWorkaround = + const MixFlags CanonicalAndWorkaround = MixFlags::Canonical | MixFlags::WorkaroundDisableCanonicalEquivalence; if ((Flags & CanonicalAndWorkaround) == CanonicalAndWorkaround) { // A workaround for too eagerly equivalent canonical types was requested, @@ -483,7 +483,7 @@ struct MixData { if (CommonType.isNull()) return *this; - QualType NewCommonType = Func(CommonType); + const QualType NewCommonType = Func(CommonType); if (CreatedFromOneWayConversion) { MixData M{Flags, Conversion}; @@ -761,7 +761,7 @@ calculateMixability(const TheCheck &Check, QualType LType, QualType RType, return {MixFlags::None}; } - MixData UnqualifiedMixability = + const MixData UnqualifiedMixability = calculateMixability(Check, LType.getLocalUnqualifiedType(), RType.getLocalUnqualifiedType(), Ctx, ImplicitMode) .withCommonTypeTransformed([&AdditionalQuals, &Ctx](QualType QT) { @@ -813,7 +813,7 @@ calculateMixability(const TheCheck &Check, QualType LType, QualType RType, if (ImplicitMode > ImplicitConversionModellingMode::None) { LLVM_DEBUG(llvm::dbgs() << "--- calculateMixability. Start implicit...\n"); - MixData MixLTR = + const MixData MixLTR = approximateImplicitConversion(Check, LType, RType, Ctx, ImplicitMode); LLVM_DEBUG( if (hasFlag(MixLTR.Flags, MixFlags::ImplicitConversion)) llvm::dbgs() @@ -833,7 +833,7 @@ calculateMixability(const TheCheck &Check, QualType LType, QualType RType, // Otherwise if the invoker requested a full modelling, do the other // direction as well. - MixData MixRTL = + const MixData MixRTL = approximateImplicitConversion(Check, RType, LType, Ctx, ImplicitMode); LLVM_DEBUG( if (hasFlag(MixRTL.Flags, MixFlags::ImplicitConversion)) llvm::dbgs() @@ -868,7 +868,7 @@ calculateMixability(const TheCheck &Check, QualType LType, QualType RType, // If none of the previous logic found a match, try if Clang otherwise // believes the types to be the same. - QualType LCanonical = LType.getCanonicalType(); + const QualType LCanonical = LType.getCanonicalType(); if (LCanonical == RType.getCanonicalType()) { LLVM_DEBUG(llvm::dbgs() << "<<< calculateMixability. Same CanonicalType.\n"); @@ -983,9 +983,9 @@ approximateStandardConversionSequence(const TheCheck &Check, QualType From, // Numeric promotions and conversions. const auto *FromBuiltin = WorkType->getAs<BuiltinType>(); const auto *ToBuiltin = To->getAs<BuiltinType>(); - bool FromNumeric = FromBuiltin && (FromBuiltin->isIntegerType() || - FromBuiltin->isFloatingType()); - bool ToNumeric = + const bool FromNumeric = FromBuiltin && (FromBuiltin->isIntegerType() || + FromBuiltin->isFloatingType()); + const bool ToNumeric = ToBuiltin && (ToBuiltin->isIntegerType() || ToBuiltin->isFloatingType()); if (FromNumeric && ToNumeric) { // If both are integral types, the numeric conversion is performed. @@ -1150,9 +1150,9 @@ public: continue; } - bool BestConversionHasImplicit = + const bool BestConversionHasImplicit = hasFlag(BestConversion->Flags, MixFlags::ImplicitConversion); - bool ThisConversionHasImplicit = + const bool ThisConversionHasImplicit = hasFlag(Prepared.Flags, MixFlags::ImplicitConversion); if (!BestConversionHasImplicit && ThisConversionHasImplicit) // This is a worse conversion, because a better one was found earlier. @@ -1221,7 +1221,7 @@ tryConversionOperators(const TheCheck &Check, const CXXRecordDecl *RD, if (std::optional<UserDefinedConversionSelector::PreparedConversion> SelectedConversion = ConversionSet()) { - CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD); + const CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD); ConversionSequence Result{RecordType, ToType}; // The conversion from the operator call's return type to ToType was @@ -1272,7 +1272,7 @@ tryConvertingConstructors(const TheCheck &Check, QualType FromType, if (std::optional<UserDefinedConversionSelector::PreparedConversion> SelectedConversion = ConversionSet()) { - CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD); + const CanQualType RecordType = RD->getASTContext().getCanonicalTagType(RD); ConversionSequence Result{FromType, RecordType}; Result.AfterFirstStandard = SelectedConversion->Seq.AfterFirstStandard; @@ -1385,7 +1385,7 @@ approximateImplicitConversion(const TheCheck &Check, QualType LType, LLVM_DEBUG( llvm::dbgs() << "--- approximateImplicitConversion. Try to find post-conversion.\n"); - MixData SecondStdConv = approximateImplicitConversion( + const MixData SecondStdConv = approximateImplicitConversion( Check, WorkType, RType, Ctx, ImplicitConversionModellingMode::OneWaySingleStandardOnly); if (SecondStdConv.indicatesMixability()) { @@ -1414,7 +1414,7 @@ approximateImplicitConversion(const TheCheck &Check, QualType LType, static MixableParameterRange modelMixingRange( const TheCheck &Check, const FunctionDecl *FD, std::size_t StartIndex, const filter::SimilarlyUsedParameterPairSuppressor &UsageBasedSuppressor) { - std::size_t NumParams = FD->getNumParams(); + const std::size_t NumParams = FD->getNumParams(); assert(StartIndex < NumParams && "out of bounds for start"); const ASTContext &Ctx = FD->getASTContext(); @@ -1424,7 +1424,7 @@ static MixableParameterRange modelMixingRange( for (std::size_t I = StartIndex + 1; I < NumParams; ++I) { const ParmVarDecl *Ith = FD->getParamDecl(I); - StringRef ParamName = Ith->getName(); + const StringRef ParamName = Ith->getName(); LLVM_DEBUG(llvm::dbgs() << "Check param #" << I << " '" << ParamName << "'...\n"); if (filter::isIgnoredParameter(Check, Ith)) { @@ -1432,7 +1432,7 @@ static MixableParameterRange modelMixingRange( break; } - StringRef PrevParamName = FD->getParamDecl(I - 1)->getName(); + const StringRef PrevParamName = FD->getParamDecl(I - 1)->getName(); if (!ParamName.empty() && !PrevParamName.empty() && filter::prefixSuffixCoverUnderThreshold( Check.NamePrefixSuffixSilenceDissimilarityThreshold, PrevParamName, @@ -1518,18 +1518,18 @@ static bool isIgnoredParameter(const TheCheck &Check, const ParmVarDecl *Node) { if (!Node->getIdentifier()) return llvm::is_contained(Check.IgnoredParameterNames, "\"\""); - StringRef NodeName = Node->getName(); + const StringRef NodeName = Node->getName(); if (llvm::is_contained(Check.IgnoredParameterNames, NodeName)) { LLVM_DEBUG(llvm::dbgs() << "\tName ignored.\n"); return true; } - StringRef NodeTypeName = [Node] { + const StringRef NodeTypeName = [Node] { const ASTContext &Ctx = Node->getASTContext(); const SourceManager &SM = Ctx.getSourceManager(); SourceLocation B = Node->getTypeSpecStartLoc(); SourceLocation E = Node->getTypeSpecEndLoc(); - LangOptions LO; + const LangOptions LO; LLVM_DEBUG(llvm::dbgs() << "\tType name code is '" << Lexer::getSourceText( @@ -1589,11 +1589,9 @@ static bool lazyMapOfSetsIntersectionExists(const MapTy &Map, const ElemTy &E1, if (E1Iterator == Map.end() || E2Iterator == Map.end()) return false; - for (const auto &E1SetElem : E1Iterator->second) - if (E2Iterator->second.contains(E1SetElem)) - return true; - - return false; + return llvm::any_of(E1Iterator->second, [&E2Iterator](const auto &E1SetElem) { + return E2Iterator->second.contains(E1SetElem); + }); } /// Implements the heuristic that marks two parameters related if there is @@ -1633,7 +1631,7 @@ public: RootSetInCurrentStackFrame = true; } - bool Ret = Base::TraverseStmt(S); + const bool Ret = Base::TraverseStmt(S); if (RootSetInCurrentStackFrame) CurrentExprOnlyTreeRoot = nullptr; @@ -1684,7 +1682,7 @@ public: continue; std::optional<unsigned> TargetIdx; - unsigned NumFnParams = CalledFn->getNumParams(); + const unsigned NumFnParams = CalledFn->getNumParams(); for (unsigned Idx = 0; Idx < NumFnParams; ++Idx) if (CalledFn->getParamDecl(Idx) == PassedToParam) TargetIdx.emplace(Idx); @@ -1837,16 +1835,16 @@ static void padStringAtBegin(SmallVectorImpl<char> &Str, std::size_t ToLen) { static bool isCommonPrefixWithoutSomeCharacters(std::size_t N, StringRef S1, StringRef S2) { assert(S1.size() >= N && S2.size() >= N); - StringRef S1Prefix = S1.take_front(S1.size() - N), - S2Prefix = S2.take_front(S2.size() - N); + const StringRef S1Prefix = S1.take_front(S1.size() - N), + S2Prefix = S2.take_front(S2.size() - N); return S1Prefix == S2Prefix && !S1Prefix.empty(); } static bool isCommonSuffixWithoutSomeCharacters(std::size_t N, StringRef S1, StringRef S2) { assert(S1.size() >= N && S2.size() >= N); - StringRef S1Suffix = S1.take_back(S1.size() - N), - S2Suffix = S2.take_back(S2.size() - N); + const StringRef S1Suffix = S1.take_back(S1.size() - N), + S2Suffix = S2.take_back(S2.size() - N); return S1Suffix == S2Suffix && !S1Suffix.empty(); } @@ -1858,7 +1856,7 @@ static bool prefixSuffixCoverUnderThreshold(std::size_t Threshold, return false; // Pad the two strings to the longer length. - std::size_t BiggerLength = std::max(Str1.size(), Str2.size()); + const std::size_t BiggerLength = std::max(Str1.size(), Str2.size()); if (BiggerLength <= Threshold) // If the length of the strings is still smaller than the threshold, they @@ -1980,7 +1978,7 @@ struct FormattedConversionSequence { // However, the parameter's defined type might not be what the implicit // conversion started with, e.g. if a typedef is found to convert. - std::string SeqBeginTypeStr = Conv.Begin.getAsString(PP); + const std::string SeqBeginTypeStr = Conv.Begin.getAsString(PP); std::string SeqEndTypeStr = Conv.End.getAsString(PP); if (StartTypeAsDiagnosed != SeqBeginTypeStr) { OS << " (as '" << SeqBeginTypeStr << "')"; @@ -1995,7 +1993,7 @@ struct FormattedConversionSequence { ++NumElementsAdded; } }; - for (QualType InvolvedType : Conv.getInvolvedTypesInSequence()) + for (const QualType InvolvedType : Conv.getInvolvedTypesInSequence()) // Print every type that's unique in the sequence into the diagnosis. AddType(InvolvedType.getAsString(PP)); @@ -2073,12 +2071,14 @@ public: if (CommonType.isNull() || CommonType == LHSType || CommonType == RHSType) return Base::operator()({LHSType, RHSType, {}}); - TypeAliasDiagnosticTuple ThreeTuple{LHSType, RHSType, CommonType}; + const TypeAliasDiagnosticTuple ThreeTuple{LHSType, RHSType, CommonType}; if (!Base::operator()(ThreeTuple)) return false; - bool AlreadySaidLHSAndCommonIsSame = calledWith({LHSType, CommonType, {}}); - bool AlreadySaidRHSAndCommonIsSame = calledWith({RHSType, CommonType, {}}); + const bool AlreadySaidLHSAndCommonIsSame = + calledWith({LHSType, CommonType, {}}); + const bool AlreadySaidRHSAndCommonIsSame = + calledWith({RHSType, CommonType, {}}); if (AlreadySaidLHSAndCommonIsSame && AlreadySaidRHSAndCommonIsSame) { // "SomeInt == int" && "SomeOtherInt == int" => "Common(SomeInt, // SomeOtherInt) == int", no need to diagnose it. Save the 3-tuple only @@ -2154,12 +2154,12 @@ void EasilySwappableParametersCheck::check( assert(FD); const PrintingPolicy &PP = FD->getASTContext().getPrintingPolicy(); - std::size_t NumParams = FD->getNumParams(); + const std::size_t NumParams = FD->getNumParams(); std::size_t MixableRangeStartIndex = 0; // Spawn one suppressor and if the user requested, gather information from // the AST for the parameters' usages. - filter::SimilarlyUsedParameterPairSuppressor UsageBasedSuppressor{ + const filter::SimilarlyUsedParameterPairSuppressor UsageBasedSuppressor{ FD, SuppressParametersUsedTogether}; LLVM_DEBUG(llvm::dbgs() << "Begin analysis of " << getName(FD) << " with " @@ -2182,11 +2182,13 @@ void EasilySwappableParametersCheck::check( continue; } - bool NeedsAnyTypeNote = llvm::any_of(R.Mixes, needsToPrintTypeInDiagnostic); - bool HasAnyImplicits = + const bool NeedsAnyTypeNote = + llvm::any_of(R.Mixes, needsToPrintTypeInDiagnostic); + const bool HasAnyImplicits = llvm::any_of(R.Mixes, needsToElaborateImplicitConversion); const ParmVarDecl *First = R.getFirstParam(), *Last = R.getLastParam(); - std::string FirstParamTypeAsWritten = First->getType().getAsString(PP); + const std::string FirstParamTypeAsWritten = + First->getType().getAsString(PP); { StringRef DiagText; @@ -2205,7 +2207,7 @@ void EasilySwappableParametersCheck::check( if (!NeedsAnyTypeNote) Diag << FirstParamTypeAsWritten; - CharSourceRange HighlightRange = CharSourceRange::getTokenRange( + const CharSourceRange HighlightRange = CharSourceRange::getTokenRange( First->getBeginLoc(), Last->getEndLoc()); Diag << HighlightRange; } @@ -2240,12 +2242,12 @@ void EasilySwappableParametersCheck::check( // emitted to a note diagnostic, so prepare it. const ParmVarDecl *LVar = M.First; const ParmVarDecl *RVar = M.Second; - QualType LType = LVar->getType(); - QualType RType = RVar->getType(); - QualType CommonType = M.commonUnderlyingType(); - std::string LTypeStr = LType.getAsString(PP); - std::string RTypeStr = RType.getAsString(PP); - std::string CommonTypeStr = CommonType.getAsString(PP); + const QualType LType = LVar->getType(); + const QualType RType = RVar->getType(); + const QualType CommonType = M.commonUnderlyingType(); + const std::string LTypeStr = LType.getAsString(PP); + const std::string RTypeStr = RType.getAsString(PP); + const std::string CommonTypeStr = CommonType.getAsString(PP); if (hasFlag(M.flags(), MixFlags::TypeAlias) && UniqueTypeAlias(LType, RType, CommonType)) { @@ -2274,8 +2276,9 @@ void EasilySwappableParametersCheck::check( if ((hasFlag(M.flags(), MixFlags::ReferenceBind) || hasFlag(M.flags(), MixFlags::Qualifiers)) && UniqueBindPower({LType, RType})) { - StringRef DiagText = "'%0' and '%1' parameters accept and bind the " - "same kind of values"; + const StringRef DiagText = + "'%0' and '%1' parameters accept and bind the " + "same kind of values"; diag(RVar->getOuterLocStart(), DiagText, DiagnosticIDs::Note) << LTypeStr << RTypeStr; } @@ -2286,8 +2289,8 @@ void EasilySwappableParametersCheck::check( M.leftToRightConversionSequence(); const model::ConversionSequence &RTL = M.rightToLeftConversionSequence(); - FormattedConversionSequence LTRFmt{PP, LTypeStr, LTR, RTypeStr}; - FormattedConversionSequence RTLFmt{PP, RTypeStr, RTL, LTypeStr}; + const FormattedConversionSequence LTRFmt{PP, LTypeStr, LTR, RTypeStr}; + const FormattedConversionSequence RTLFmt{PP, RTypeStr, RTL, LTypeStr}; StringRef DiagText = "'%0' and '%1' may be implicitly converted"; if (!LTRFmt.Trivial || !RTLFmt.Trivial) @@ -2302,7 +2305,7 @@ void EasilySwappableParametersCheck::check( Diag << LTRFmt.DiagnosticText << RTLFmt.DiagnosticText; } - StringRef ConversionFunctionDiagText = + const StringRef ConversionFunctionDiagText = "the implicit conversion involves the " "%select{|converting constructor|conversion operator}0 " "declared here"; diff --git a/clang-tools-extra/clang-tidy/bugprone/EmptyCatchCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/EmptyCatchCheck.cpp index eebab84..5dd2f62 100644 --- a/clang-tools-extra/clang-tidy/bugprone/EmptyCatchCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/EmptyCatchCheck.cpp @@ -25,7 +25,7 @@ AST_MATCHER(CXXCatchStmt, isInMacro) { } AST_MATCHER_P(CXXCatchStmt, hasHandler, Matcher<Stmt>, InnerMatcher) { - Stmt *Handler = Node.getHandlerBlock(); + const Stmt *Handler = Node.getHandlerBlock(); if (!Handler) return false; return InnerMatcher.matches(*Handler, Finder, Builder); @@ -41,7 +41,7 @@ AST_MATCHER_P(CompoundStmt, hasAnyTextFromList, std::vector<llvm::StringRef>, return false; ASTContext &Context = Finder->getASTContext(); - SourceManager &SM = Context.getSourceManager(); + const SourceManager &SM = Context.getSourceManager(); StringRef Text = Lexer::getSourceText( CharSourceRange::getTokenRange(Node.getSourceRange()), SM, Context.getLangOpts()); diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp new file mode 100644 index 0000000..7365845 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.cpp @@ -0,0 +1,36 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "ExceptionCopyConstructorThrowsCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +void ExceptionCopyConstructorThrowsCheck::registerMatchers( + MatchFinder *Finder) { + Finder->addMatcher( + traverse( + TK_AsIs, + cxxThrowExpr(has(ignoringParenImpCasts( + cxxConstructExpr(hasDeclaration(cxxConstructorDecl( + isCopyConstructor(), unless(isNoThrow())))) + .bind("expr"))))), + this); +} + +void ExceptionCopyConstructorThrowsCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *E = Result.Nodes.getNodeAs<Expr>("expr"); + diag(E->getExprLoc(), + "thrown exception type is not nothrow copy constructible"); +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h new file mode 100644 index 0000000..f1d7cca --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionCopyConstructorThrowsCheck.h @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// Checks whether a thrown object is nothrow copy constructible. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/exception-copy-constructor-throws.html +class ExceptionCopyConstructorThrowsCheck : public ClangTidyCheck { +public: + ExceptionCopyConstructorThrowsCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONCOPYCONSTRUCTORTHROWSCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp index 837a86f..1cfb151 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.cpp @@ -36,13 +36,22 @@ ExceptionEscapeCheck::ExceptionEscapeCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), RawFunctionsThatShouldNotThrow(Options.get( "FunctionsThatShouldNotThrow", "")), - RawIgnoredExceptions(Options.get("IgnoredExceptions", "")) { + RawIgnoredExceptions(Options.get("IgnoredExceptions", "")), + RawCheckedSwapFunctions( + Options.get("CheckedSwapFunctions", "swap,iter_swap,iter_move")), + CheckDestructors(Options.get("CheckDestructors", true)), + CheckMoveMemberFunctions(Options.get("CheckMoveMemberFunctions", true)), + CheckMain(Options.get("CheckMain", true)), + CheckNothrowFunctions(Options.get("CheckNothrowFunctions", true)) { llvm::SmallVector<StringRef, 8> FunctionsThatShouldNotThrowVec, - IgnoredExceptionsVec; + IgnoredExceptionsVec, CheckedSwapFunctionsVec; RawFunctionsThatShouldNotThrow.split(FunctionsThatShouldNotThrowVec, ",", -1, false); FunctionsThatShouldNotThrow.insert_range(FunctionsThatShouldNotThrowVec); + RawCheckedSwapFunctions.split(CheckedSwapFunctionsVec, ",", -1, false); + CheckedSwapFunctions.insert_range(CheckedSwapFunctionsVec); + llvm::StringSet<> IgnoredExceptions; RawIgnoredExceptions.split(IgnoredExceptionsVec, ",", -1, false); IgnoredExceptions.insert_range(IgnoredExceptionsVec); @@ -54,20 +63,34 @@ void ExceptionEscapeCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "FunctionsThatShouldNotThrow", RawFunctionsThatShouldNotThrow); Options.store(Opts, "IgnoredExceptions", RawIgnoredExceptions); + Options.store(Opts, "CheckedSwapFunctions", RawCheckedSwapFunctions); + Options.store(Opts, "CheckDestructors", CheckDestructors); + Options.store(Opts, "CheckMoveMemberFunctions", CheckMoveMemberFunctions); + Options.store(Opts, "CheckMain", CheckMain); + Options.store(Opts, "CheckNothrowFunctions", CheckNothrowFunctions); } void ExceptionEscapeCheck::registerMatchers(MatchFinder *Finder) { + auto MatchIf = [](bool Enabled, const auto &Matcher) { + const ast_matchers::internal::Matcher<FunctionDecl> Nothing = + unless(anything()); + return Enabled ? Matcher : Nothing; + }; Finder->addMatcher( functionDecl( isDefinition(), - anyOf(isNoThrow(), - allOf(anyOf(cxxDestructorDecl(), - cxxConstructorDecl(isMoveConstructor()), - cxxMethodDecl(isMoveAssignmentOperator()), isMain(), - allOf(hasAnyName("swap", "iter_swap", "iter_move"), - hasAtLeastOneParameter())), - unless(isExplicitThrow())), - isEnabled(FunctionsThatShouldNotThrow))) + anyOf( + MatchIf(CheckNothrowFunctions, isNoThrow()), + allOf(anyOf(MatchIf(CheckDestructors, cxxDestructorDecl()), + MatchIf( + CheckMoveMemberFunctions, + anyOf(cxxConstructorDecl(isMoveConstructor()), + cxxMethodDecl(isMoveAssignmentOperator()))), + MatchIf(CheckMain, isMain()), + allOf(isEnabled(CheckedSwapFunctions), + hasAtLeastOneParameter())), + unless(isExplicitThrow())), + isEnabled(FunctionsThatShouldNotThrow))) .bind("thrower"), this); } diff --git a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h index bd1e7ba..c3bf4a4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/ExceptionEscapeCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTION_ESCAPE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTION_ESCAPE_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONESCAPECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONESCAPECHECK_H #include "../ClangTidyCheck.h" #include "../utils/ExceptionAnalyzer.h" @@ -35,11 +35,18 @@ public: private: StringRef RawFunctionsThatShouldNotThrow; StringRef RawIgnoredExceptions; + StringRef RawCheckedSwapFunctions; + + const bool CheckDestructors; + const bool CheckMoveMemberFunctions; + const bool CheckMain; + const bool CheckNothrowFunctions; llvm::StringSet<> FunctionsThatShouldNotThrow; + llvm::StringSet<> CheckedSwapFunctions; utils::ExceptionAnalyzer Tracer; }; } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTION_ESCAPE_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_EXCEPTIONESCAPECHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.cpp new file mode 100644 index 0000000..38a0234 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.cpp @@ -0,0 +1,47 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "FloatLoopCounterCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchers.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +void FloatLoopCounterCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher( + forStmt(hasIncrement(forEachDescendant( + declRefExpr(hasType(realFloatingPointType()), + to(varDecl().bind("var"))) + .bind("inc"))), + hasCondition(forEachDescendant( + declRefExpr(hasType(realFloatingPointType()), + to(varDecl(equalsBoundNode("var")))) + .bind("cond")))) + .bind("for"), + this); +} + +void FloatLoopCounterCheck::check(const MatchFinder::MatchResult &Result) { + const auto *FS = Result.Nodes.getNodeAs<ForStmt>("for"); + assert(FS && "FS should not be null"); + + diag(FS->getInc()->getBeginLoc(), "loop induction expression should not have " + "floating-point type") + << Result.Nodes.getNodeAs<DeclRefExpr>("inc")->getSourceRange() + << Result.Nodes.getNodeAs<DeclRefExpr>("cond")->getSourceRange(); + + if (!FS->getInc()->getType()->isRealFloatingType()) + if (const auto *V = Result.Nodes.getNodeAs<VarDecl>("var")) + diag(V->getBeginLoc(), "floating-point type loop induction variable", + DiagnosticIDs::Note); +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.h b/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.h new file mode 100644 index 0000000..43dd9c2 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/FloatLoopCounterCheck.h @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FLOATLOOPCOUNTERCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FLOATLOOPCOUNTERCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// This check diagnoses when the loop induction expression of a for loop has +/// floating-point type. The check corresponds to: +/// https://www.securecoding.cert.org/confluence/display/c/FLP30-C.+Do+not+use+floating-point+variables+as+loop+counters +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/float-loop-counter.html +class FloatLoopCounterCheck : public ClangTidyCheck { +public: + FloatLoopCounterCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FLOATLOOPCOUNTERCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h b/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h index 119728d..ef8b4d1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/FoldInitTypeCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLDINITTYPECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLDINITTYPECHECK_H #include "../ClangTidyCheck.h" @@ -39,4 +39,4 @@ private: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLD_INIT_TYPE_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_FOLDINITTYPECHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp index c3db8fa..11270e7 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp @@ -46,7 +46,7 @@ void ForwardDeclarationNamespaceCheck::check( const MatchFinder::MatchResult &Result) { if (const auto *RecordDecl = Result.Nodes.getNodeAs<CXXRecordDecl>("record_decl")) { - StringRef DeclName = RecordDecl->getName(); + const StringRef DeclName = RecordDecl->getName(); if (RecordDecl->isThisDeclarationADefinition()) { DeclNameToDefinitions[DeclName].push_back(RecordDecl); } else { diff --git a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp index d372cbd..c1e66f2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp @@ -40,7 +40,7 @@ AST_MATCHER(QualType, isEnableIf) { if (CheckTemplate(BaseType->getAs<TemplateSpecializationType>())) return true; // Case: enable_if_t< >. if (const auto *TT = BaseType->getAs<TypedefType>()) - if (NestedNameSpecifier Q = TT->getQualifier(); + if (const NestedNameSpecifier Q = TT->getQualifier(); Q.getKind() == NestedNameSpecifier::Kind::Type) if (CheckTemplate(Q.getAsType()->getAs<TemplateSpecializationType>())) return true; // Case: enable_if< >::type. @@ -67,7 +67,7 @@ void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) { unless(references(isConstQualified()))))) .bind("parm-var"); - DeclarationMatcher FindOverload = + const DeclarationMatcher FindOverload = cxxConstructorDecl( hasParameter(0, ForwardingRefParm), unless(isDeleted()), unless(hasAnyParameter( @@ -128,8 +128,9 @@ void ForwardingReferenceOverloadCheck::check( (OtherCtor->isCopyConstructor() ? EnabledCopy : EnabledMove) = true; } } - bool Copy = (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy; - bool Move = !DisabledMove || EnabledMove; + const bool Copy = + (!EnabledMove && !DisabledMove && !DisabledCopy) || EnabledCopy; + const bool Move = !DisabledMove || EnabledMove; if (!Copy && !Move) return; diag(Ctor->getLocation(), diff --git a/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp index 2211a0b..634d54c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ImplicitWideningOfMultiplicationResultCheck.cpp @@ -71,18 +71,18 @@ ImplicitWideningOfMultiplicationResultCheck::includeStddefHeader( void ImplicitWideningOfMultiplicationResultCheck::handleImplicitCastExpr( const ImplicitCastExpr *ICE) { - ASTContext *Context = Result->Context; + const ASTContext *Context = Result->Context; const Expr *E = ICE->getSubExpr()->IgnoreParens(); - QualType Ty = ICE->getType(); - QualType ETy = E->getType(); + const QualType Ty = ICE->getType(); + const QualType ETy = E->getType(); assert(!ETy->isDependentType() && !Ty->isDependentType() && "Don't expect to ever get here in template Context."); // This must be a widening cast. Else we do not care. - unsigned SrcWidth = Context->getIntWidth(ETy); - unsigned TgtWidth = Context->getIntWidth(Ty); + const unsigned SrcWidth = Context->getIntWidth(ETy); + const unsigned TgtWidth = Context->getIntWidth(Ty); if (TgtWidth <= SrcWidth) return; @@ -92,7 +92,7 @@ void ImplicitWideningOfMultiplicationResultCheck::handleImplicitCastExpr( !ETy->isUnsignedIntegerType()) { if (const auto ConstExprResult = E->getIntegerConstantExpr(*Context)) { const auto TypeSize = Context->getTypeSize(ETy); - llvm::APSInt WidenedResult = ConstExprResult->extOrTrunc(TypeSize); + const llvm::APSInt WidenedResult = ConstExprResult->extOrTrunc(TypeSize); if (WidenedResult <= llvm::APSInt::getMaxValue(TypeSize, false) && WidenedResult >= llvm::APSInt::getMinValue(TypeSize, false)) return; @@ -168,7 +168,7 @@ void ImplicitWideningOfMultiplicationResultCheck::handleImplicitCastExpr( void ImplicitWideningOfMultiplicationResultCheck::handlePointerOffsetting( const Expr *E) { - ASTContext *Context = Result->Context; + const ASTContext *Context = Result->Context; // We are looking for a pointer offset operation, // with one hand being a pointer, and another one being an offset. @@ -191,19 +191,20 @@ void ImplicitWideningOfMultiplicationResultCheck::handlePointerOffsetting( IndexExpr = IndexExpr->IgnoreParens(); - QualType IndexExprType = IndexExpr->getType(); + const QualType IndexExprType = IndexExpr->getType(); // If the index expression's type is not known (i.e. we are in a template), // we can't do anything here. if (IndexExprType->isDependentType()) return; - QualType SSizeTy = Context->getPointerDiffType(); - QualType USizeTy = Context->getSizeType(); - QualType SizeTy = IndexExprType->isSignedIntegerType() ? SSizeTy : USizeTy; + const QualType SSizeTy = Context->getPointerDiffType(); + const QualType USizeTy = Context->getSizeType(); + const QualType SizeTy = + IndexExprType->isSignedIntegerType() ? SSizeTy : USizeTy; // FIXME: is there a way to actually get the QualType for size_t/ptrdiff_t? // Note that SizeTy.getAsString() will be unsigned long/..., NOT size_t! - StringRef TyAsString = + const StringRef TyAsString = IndexExprType->isSignedIntegerType() ? "ptrdiff_t" : "size_t"; // So, is size_t actually wider than the result of the multiplication? diff --git a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp index b0dd901..12fa365 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InaccurateEraseCheck.cpp @@ -43,7 +43,7 @@ void InaccurateEraseCheck::check(const MatchFinder::MatchResult &Result) { if (!Loc.isMacroID() && EndExpr) { const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("alg"); - std::string ReplacementText = std::string(Lexer::getSourceText( + const std::string ReplacementText = std::string(Lexer::getSourceText( CharSourceRange::getTokenRange(EndExpr->getSourceRange()), *Result.SourceManager, getLangOpts())); const SourceLocation EndLoc = Lexer::getLocForEndOfToken( diff --git a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp index 9ce6d42..553c45c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncDecInConditionsCheck.cpp @@ -64,7 +64,6 @@ void IncDecInConditionsCheck::registerMatchers(MatchFinder *Finder) { } void IncDecInConditionsCheck::check(const MatchFinder::MatchResult &Result) { - SourceLocation ExprLoc; bool IsIncrementOp = false; diff --git a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp index 84a99c3..6181ac8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/IncorrectEnableIfCheck.cpp @@ -22,7 +22,7 @@ AST_MATCHER_P(TemplateTypeParmDecl, hasUnnamedDefaultArgument, Node.getDefaultArgument().getArgument().isNull()) return false; - TypeLoc DefaultArgTypeLoc = + const TypeLoc DefaultArgTypeLoc = Node.getDefaultArgument().getTypeSourceInfo()->getTypeLoc(); return InnerMatcher.matches(DefaultArgTypeLoc, Finder, Builder); } @@ -51,7 +51,7 @@ void IncorrectEnableIfCheck::check(const MatchFinder::MatchResult &Result) { return; const SourceManager &SM = *Result.SourceManager; - SourceLocation RAngleLoc = + const SourceLocation RAngleLoc = SM.getExpansionLoc(EnableIfSpecializationLoc->getRAngleLoc()); auto Diag = diag(EnableIf->getBeginLoc(), diff --git a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp index 1e516c1..6749c59 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InfiniteLoopCheck.cpp @@ -34,7 +34,7 @@ AST_MATCHER(FunctionType, typeHasNoReturnAttr) { } // namespace static Matcher<Stmt> loopEndingStmt(Matcher<Stmt> Internal) { - Matcher<QualType> IsNoReturnFunType = + const Matcher<QualType> IsNoReturnFunType = ignoringParens(functionType(typeHasNoReturnAttr())); Matcher<Decl> IsNoReturnDecl = anyOf(declHasNoReturnAttr(), functionDecl(hasType(IsNoReturnFunType)), @@ -119,14 +119,9 @@ static bool isAtLeastOneCondVarChanged(const Decl *Func, const Stmt *LoopStmt, if (isVarThatIsPossiblyChanged(Func, LoopStmt, Cond, Context)) return true; - for (const Stmt *Child : Cond->children()) { - if (!Child) - continue; - - if (isAtLeastOneCondVarChanged(Func, LoopStmt, Child, Context)) - return true; - } - return false; + return llvm::any_of(Cond->children(), [&](const Stmt *Child) { + return Child && isAtLeastOneCondVarChanged(Func, LoopStmt, Child, Context); + }); } /// Return the variable names in `Cond`. @@ -145,7 +140,7 @@ static std::string getCondVarNames(const Stmt *Cond) { if (!Child) continue; - std::string NewNames = getCondVarNames(Child); + const std::string NewNames = getCondVarNames(Child); if (!Result.empty() && !NewNames.empty()) Result += ", "; Result += NewNames; @@ -240,10 +235,9 @@ static bool hasStaticLocalVariable(const Stmt *Cond) { return true; } - for (const Stmt *Child : Cond->children()) - if (Child && hasStaticLocalVariable(Child)) - return true; - return false; + return llvm::any_of(Cond->children(), [](const Stmt *Child) { + return Child && hasStaticLocalVariable(Child); + }); } /// Tests if the loop condition `Cond` involves static local variables and @@ -332,7 +326,7 @@ void InfiniteLoopCheck::check(const MatchFinder::MatchResult &Result) { Result.Context)) return; - std::string CondVarNames = getCondVarNames(Cond); + const std::string CondVarNames = getCondVarNames(Cond); if (ShouldHaveConditionVariables && CondVarNames.empty()) return; diff --git a/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.h b/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.h index 777e3186..acab7be 100644 --- a/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/IntegerDivisionCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGERDIVISIONCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGERDIVISIONCHECK_H #include "../ClangTidyCheck.h" @@ -28,4 +28,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGER_DIVISION_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_INTEGERDIVISIONCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp index 18eb40f..f3e94b6 100644 --- a/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/InvalidEnumDefaultInitializationCheck.cpp @@ -151,7 +151,7 @@ void InvalidEnumDefaultInitializationCheck::check( SourceLocation Loc = InitExpr->getExprLoc(); if (Loc.isInvalid()) { if (isa<ImplicitValueInitExpr, InitListExpr>(InitExpr)) { - DynTypedNodeList Parents = ACtx.getParents(*InitExpr); + const DynTypedNodeList Parents = ACtx.getParents(*InitExpr); if (Parents.empty()) return; @@ -170,7 +170,7 @@ void InvalidEnumDefaultInitializationCheck::check( // The expression may be implicitly generated for an initialization. // Search for a parent initialization list with valid source location. while (InitList->getExprLoc().isInvalid()) { - DynTypedNodeList Parents = ACtx.getParents(*InitList); + const DynTypedNodeList Parents = ACtx.getParents(*InitList); if (Parents.empty()) return; InitList = Parents[0].get<InitListExpr>(); diff --git a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp index fb73e89..1f666d2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/LambdaFunctionNameCheck.cpp @@ -40,7 +40,7 @@ public: bool HasLine = false; for (const Token &T : MD.getMacroInfo()->tokens()) { if (T.is(tok::identifier)) { - StringRef IdentName = T.getIdentifierInfo()->getName(); + const StringRef IdentName = T.getIdentifierInfo()->getName(); if (IdentName == "__FILE__") { HasFile = true; } else if (IdentName == "__LINE__") { diff --git a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp index b16119d..6467fb5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MacroParenthesesCheck.cpp @@ -152,7 +152,6 @@ void MacroParenthesesPPCallbacks::replacementList(const Token &MacroNameTok, void MacroParenthesesPPCallbacks::argument(const Token &MacroNameTok, const MacroInfo *MI) { - // Skip variable declaration. bool VarDecl = possibleVarDecl(MI, MI->tokens_begin()); diff --git a/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp index 78a53d1..c79320f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MacroRepeatedSideEffectsCheck.cpp @@ -127,7 +127,7 @@ unsigned MacroRepeatedPPCallbacks::countArgumentExpansions( continue; } - IdentifierInfo *TII = T.getIdentifierInfo(); + const IdentifierInfo *TII = T.getIdentifierInfo(); // If not existent, skip it. if (TII == nullptr) continue; diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h index f650145..c40aef3 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedOperatorInStrlenInAllocCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDOPERATORINSTRLENINALLOCCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDOPERATORINSTRLENINALLOCCHECK_H #include "../ClangTidyCheck.h" @@ -30,4 +30,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_STRLEN_IN_ALLOC_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDOPERATORINSTRLENINALLOCCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h index e78c30cb..9f6504f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedPointerArithmeticInAllocCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_ALLOC_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_ALLOC_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDPOINTERARITHMETICINALLOCCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDPOINTERARITHMETICINALLOCCHECK_H #include "../ClangTidyCheck.h" @@ -29,4 +29,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACED_OPERATOR_IN_ALLOC_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MISPLACEDPOINTERARITHMETICINALLOCCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp index d508e2a..f040235 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MisplacedWideningCastCheck.cpp @@ -52,8 +52,8 @@ static unsigned getMaxCalculationWidth(const ASTContext &Context, E = E->IgnoreParenImpCasts(); if (const auto *Bop = dyn_cast<BinaryOperator>(E)) { - unsigned LHSWidth = getMaxCalculationWidth(Context, Bop->getLHS()); - unsigned RHSWidth = getMaxCalculationWidth(Context, Bop->getRHS()); + const unsigned LHSWidth = getMaxCalculationWidth(Context, Bop->getLHS()); + const unsigned RHSWidth = getMaxCalculationWidth(Context, Bop->getRHS()); if (Bop->getOpcode() == BO_Mul) return LHSWidth + RHSWidth; if (Bop->getOpcode() == BO_Add) @@ -79,7 +79,7 @@ static unsigned getMaxCalculationWidth(const ASTContext &Context, if (Uop->getOpcode() == UO_Not) return 1024U; - QualType T = Uop->getType(); + const QualType T = Uop->getType(); return T->isIntegerType() ? Context.getIntWidth(T) : 1024U; } else if (const auto *I = dyn_cast<IntegerLiteral>(E)) { return I->getValue().getActiveBits(); @@ -190,10 +190,10 @@ void MisplacedWideningCastCheck::check(const MatchFinder::MatchResult &Result) { Calc->isTypeDependent() || Calc->isValueDependent()) return; - ASTContext &Context = *Result.Context; + const ASTContext &Context = *Result.Context; - QualType CastType = Cast->getType(); - QualType CalcType = Calc->getType(); + const QualType CastType = Cast->getType(); + const QualType CalcType = Calc->getType(); // Explicit truncation using cast. if (Context.getIntWidth(CastType) < Context.getIntWidth(CalcType)) diff --git a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp index 66559a0..e182df7 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MoveForwardingReferenceCheck.cpp @@ -21,7 +21,7 @@ static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee, const SourceManager &SM = Context.getSourceManager(); const LangOptions &LangOpts = Context.getLangOpts(); - CharSourceRange CallRange = + const CharSourceRange CallRange = Lexer::makeFileCharRange(CharSourceRange::getTokenRange( Callee->getBeginLoc(), Callee->getEndLoc()), SM, LangOpts); @@ -39,7 +39,7 @@ static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee, // std::move(). This will hopefully prevent erroneous replacements if the // code does unusual things (e.g. create an alias for std::move() in // another namespace). - NestedNameSpecifier NNS = Callee->getQualifier(); + const NestedNameSpecifier NNS = Callee->getQualifier(); switch (NNS.getKind()) { case NestedNameSpecifier::Kind::Null: // Called as "move" (i.e. presumably the code had a "using std::move;"). diff --git a/clang-tools-extra/clang-tidy/bugprone/MultiLevelImplicitPointerConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MultiLevelImplicitPointerConversionCheck.cpp index 2eff013..78f2017 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MultiLevelImplicitPointerConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MultiLevelImplicitPointerConversionCheck.cpp @@ -86,8 +86,9 @@ MultiLevelImplicitPointerConversionCheck::getCheckTraversalKind() const { void MultiLevelImplicitPointerConversionCheck::check( const MatchFinder::MatchResult &Result) { const auto *MatchedExpr = Result.Nodes.getNodeAs<ImplicitCastExpr>("expr"); - QualType Target = MatchedExpr->getType().getDesugaredType(*Result.Context); - QualType Source = + const QualType Target = + MatchedExpr->getType().getDesugaredType(*Result.Context); + const QualType Source = MatchedExpr->getSubExpr()->getType().getDesugaredType(*Result.Context); diag(MatchedExpr->getExprLoc(), "multilevel pointer conversion from %0 to " diff --git a/clang-tools-extra/clang-tidy/bugprone/MultipleNewInOneExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/MultipleNewInOneExpressionCheck.cpp index 17aea93..b81d2b4 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MultipleNewInOneExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/MultipleNewInOneExpressionCheck.cpp @@ -51,7 +51,8 @@ namespace { AST_MATCHER_P(CXXTryStmt, hasHandlerFor, ast_matchers::internal::Matcher<QualType>, InnerMatcher) { - for (unsigned NH = Node.getNumHandlers(), I = 0; I < NH; ++I) { + const unsigned NH = Node.getNumHandlers(); + for (unsigned I = 0; I < NH; ++I) { const CXXCatchStmt *CatchS = Node.getHandler(I); // Check for generic catch handler (match anything). if (CatchS->getCaughtType().isNull()) @@ -66,7 +67,7 @@ AST_MATCHER_P(CXXTryStmt, hasHandlerFor, } AST_MATCHER(CXXNewExpr, mayThrow) { - FunctionDecl *OperatorNew = Node.getOperatorNew(); + const FunctionDecl *OperatorNew = Node.getOperatorNew(); if (!OperatorNew) return false; return !OperatorNew->getType()->castAs<FunctionProtoType>()->isNothrow(); diff --git a/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h b/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h index 1a2d4a4..1c3679a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/MultipleStatementMacroCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLESTATEMENTMACROCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLESTATEMENTMACROCHECK_H #include "../ClangTidyCheck.h" @@ -29,4 +29,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLE_STATEMENT_MACRO_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_MULTIPLESTATEMENTMACROCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp index 287ee95..501a82d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.cpp @@ -29,15 +29,15 @@ AST_MATCHER_P(QualType, hasAnyType, std::vector<StringRef>, Names) { if (Names.empty()) return false; - std::string Name = Node.getLocalUnqualifiedType().getAsString(); + const std::string Name = Node.getLocalUnqualifiedType().getAsString(); return llvm::is_contained(Names, Name); } AST_MATCHER(FieldDecl, hasIntBitwidth) { assert(Node.isBitField()); const ASTContext &Ctx = Node.getASTContext(); - unsigned IntBitWidth = Ctx.getIntWidth(Ctx.IntTy); - unsigned CurrentBitWidth = Node.getBitWidthValue(); + const unsigned IntBitWidth = Ctx.getIntWidth(Ctx.IntTy); + const unsigned CurrentBitWidth = Node.getBitWidthValue(); return IntBitWidth == CurrentBitWidth; } @@ -79,7 +79,7 @@ void NarrowingConversionsCheck::registerMatchers(MatchFinder *Finder) { const auto IsCeilFloorCallExpr = expr(callExpr(callee(functionDecl( hasAnyName("::ceil", "::std::ceil", "::floor", "::std::floor"))))); - std::vector<StringRef> IgnoreConversionFromTypesVec = + const std::vector<StringRef> IgnoreConversionFromTypesVec = utils::options::parseStringList(IgnoreConversionFromTypes); // We may want to exclude other types from the checks, such as `size_type` @@ -243,7 +243,7 @@ struct IntegerRange { static IntegerRange createFromType(const ASTContext &Context, const BuiltinType &T) { if (T.isFloatingPoint()) { - unsigned PrecisionBits = llvm::APFloatBase::semanticsPrecision( + const unsigned PrecisionBits = llvm::APFloatBase::semanticsPrecision( Context.getFloatTypeSemantics(T.desugar())); // Contrary to two's complement integer, floating point values are // symmetric and have the same number of positive and negative values. @@ -262,8 +262,8 @@ static IntegerRange createFromType(const ASTContext &Context, return {LowerValue, UpperValue}; } assert(T.isInteger() && "Unexpected builtin type"); - uint64_t TypeSize = Context.getTypeSize(&T); - bool IsUnsignedInteger = T.isUnsignedInteger(); + const uint64_t TypeSize = Context.getTypeSize(&T); + const bool IsUnsignedInteger = T.isUnsignedInteger(); return {llvm::APSInt::getMinValue(TypeSize, IsUnsignedInteger), llvm::APSInt::getMaxValue(TypeSize, IsUnsignedInteger)}; } @@ -271,15 +271,15 @@ static IntegerRange createFromType(const ASTContext &Context, static bool isWideEnoughToHold(const ASTContext &Context, const BuiltinType &FromType, const BuiltinType &ToType) { - IntegerRange FromIntegerRange = createFromType(Context, FromType); - IntegerRange ToIntegerRange = createFromType(Context, ToType); + const IntegerRange FromIntegerRange = createFromType(Context, FromType); + const IntegerRange ToIntegerRange = createFromType(Context, ToType); return ToIntegerRange.contains(FromIntegerRange); } static bool isWideEnoughToHold(const ASTContext &Context, const llvm::APSInt &IntegerConstant, const BuiltinType &ToType) { - IntegerRange ToIntegerRange = createFromType(Context, ToType); + const IntegerRange ToIntegerRange = createFromType(Context, ToType); return ToIntegerRange.contains(IntegerConstant); } @@ -289,13 +289,13 @@ static bool isWideEnoughToHold(const ASTContext &Context, static bool isFloatExactlyRepresentable(const ASTContext &Context, const llvm::APFloat &FloatConstant, const QualType &DestType) { - unsigned DestWidth = Context.getIntWidth(DestType); - bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); + const unsigned DestWidth = Context.getIntWidth(DestType); + const bool DestSigned = DestType->isSignedIntegerOrEnumerationType(); llvm::APSInt Result = llvm::APSInt(DestWidth, !DestSigned); bool IsExact = false; - bool Overflows = FloatConstant.convertToInteger( - Result, llvm::APFloat::rmTowardZero, &IsExact) & - llvm::APFloat::opInvalidOp; + const bool Overflows = FloatConstant.convertToInteger( + Result, llvm::APFloat::rmTowardZero, &IsExact) & + llvm::APFloat::opInvalidOp; return !Overflows && IsExact; } @@ -321,8 +321,8 @@ bool NarrowingConversionsCheck::isWarningInhibitedByEquivalentSize( // With this option, we don't warn on conversions that have equivalent width // in bits. eg. uint32 <-> int32. if (!WarnOnEquivalentBitWidth) { - uint64_t FromTypeSize = Context.getTypeSize(&FromType); - uint64_t ToTypeSize = Context.getTypeSize(&ToType); + const uint64_t FromTypeSize = Context.getTypeSize(&FromType); + const uint64_t ToTypeSize = Context.getTypeSize(&ToType); if (FromTypeSize == ToTypeSize) { return true; } @@ -406,8 +406,8 @@ void NarrowingConversionsCheck::handleIntegralCast(const ASTContext &Context, // With this option, we don't warn on conversions that have equivalent width // in bits. eg. uint32 <-> int32. if (!WarnOnEquivalentBitWidth) { - uint64_t FromTypeSize = Context.getTypeSize(FromType); - uint64_t ToTypeSize = Context.getTypeSize(ToType); + const uint64_t FromTypeSize = Context.getTypeSize(FromType); + const uint64_t ToTypeSize = Context.getTypeSize(ToType); if (FromTypeSize == ToTypeSize) return; } @@ -583,7 +583,7 @@ void NarrowingConversionsCheck::handleImplicitCast( return; if (handleConditionalOperator(Context, Lhs, Rhs)) return; - SourceLocation SourceLoc = Lhs.getExprLoc(); + const SourceLocation SourceLoc = Lhs.getExprLoc(); switch (Cast.getCastKind()) { case CK_BooleanToSignedIntegral: handleBooleanToSignedIntegral(Context, SourceLoc, Lhs, Rhs); diff --git a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h index 9631c71..e506e5b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/NarrowingConversionsCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWING_CONVERSIONS_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWING_CONVERSIONS_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWINGCONVERSIONSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWINGCONVERSIONSCHECK_H #include "../ClangTidyCheck.h" @@ -108,4 +108,4 @@ private: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWING_CONVERSIONS_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NARROWINGCONVERSIONSCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp index 067577f..127af27 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NonZeroEnumToBoolConversionCheck.cpp @@ -11,7 +11,6 @@ #include "../utils/OptionsUtils.h" #include "clang/AST/ASTContext.h" #include "clang/ASTMatchers/ASTMatchFinder.h" -#include <algorithm> using namespace clang::ast_matchers; diff --git a/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp index abde115..fdb903a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.cpp @@ -15,7 +15,6 @@ namespace clang::tidy::bugprone { void NondeterministicPointerIterationOrderCheck::registerMatchers( MatchFinder *Finder) { - auto LoopVariable = varDecl(hasType( qualType(hasCanonicalType(anyOf(referenceType(), pointerType()))))); @@ -60,7 +59,7 @@ void NondeterministicPointerIterationOrderCheck::check( TemplateArgs[0].getAsType()->isPointerType(); if (IsAlgoArgPointer) { - SourceRange R = RangeInit->getSourceRange(); + const SourceRange R = RangeInit->getSourceRange(); diag(R.getBegin(), "iteration of pointers is nondeterministic") << R; } } @@ -69,7 +68,7 @@ void NondeterministicPointerIterationOrderCheck::check( const auto *SortPointers = Result.Nodes.getNodeAs<Stmt>("sortsemantic"); if ((SortPointers) && !(SortPointers->getBeginLoc().isMacroID())) { - SourceRange R = SortPointers->getSourceRange(); + const SourceRange R = SortPointers->getSourceRange(); diag(R.getBegin(), "sorting pointers is nondeterministic") << R; } } diff --git a/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.h b/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.h index 054d580..46b4e12 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/NondeterministicPointerIterationOrderCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NONDETERMINISTIC_POINTER_ITERATION_ORDER_CHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NONDETERMINISTIC_POINTER_ITERATION_ORDER_CHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NONDETERMINISTICPOINTERITERATIONORDERCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NONDETERMINISTICPOINTERITERATIONORDERCHECK_H #include "../ClangTidyCheck.h" @@ -36,4 +36,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NONDETERMINISTIC_POINTER_ITERATION_ORDER_CHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NONDETERMINISTICPOINTERITERATIONORDERCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp index 08fae7b..7198c1b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.cpp @@ -120,18 +120,18 @@ static int getGivenLength(const MatchFinder::MatchResult &Result) { if (Result.Nodes.getNodeAs<Expr>(UnknownLengthName)) return 0; - if (int Length = + if (const int Length = getLength(Result.Nodes.getNodeAs<Expr>(WrongLengthExprName), Result)) return Length; - if (int Length = + if (const int Length = getLength(Result.Nodes.getNodeAs<Expr>(LengthExprName), Result)) return Length; // Special case, for example 'strlen("foo")'. if (const CallExpr *StrlenCE = getStrlenExpr(Result)) if (const Expr *Arg = StrlenCE->getArg(0)->IgnoreImpCasts()) - if (int ArgLength = getLength(Arg, Result)) + if (const int ArgLength = getLength(Arg, Result)) return ArgLength; return 0; @@ -174,9 +174,9 @@ static bool isKnownDest(const MatchFinder::MatchResult &Result) { // True if the capacity of the destination array is based on the given length, // therefore we assume that it cannot overflow (e.g. 'malloc(given_length + 1)' static bool isDestBasedOnGivenLength(const MatchFinder::MatchResult &Result) { - StringRef DestCapacityExprStr = + const StringRef DestCapacityExprStr = exprToStr(getDestCapacityExpr(Result), Result).trim(); - StringRef LengthExprStr = + const StringRef LengthExprStr = exprToStr(Result.Nodes.getNodeAs<Expr>(LengthExprName), Result).trim(); return !DestCapacityExprStr.empty() && !LengthExprStr.empty() && @@ -226,8 +226,9 @@ isGivenLengthEqualToSrcLength(const MatchFinder::MatchResult &Result) { if (isStringDataAndLength(Result)) return true; - int GivenLength = getGivenLength(Result); - int SrcLength = getLength(Result.Nodes.getNodeAs<Expr>(SrcExprName), Result); + const int GivenLength = getGivenLength(Result); + const int SrcLength = + getLength(Result.Nodes.getNodeAs<Expr>(SrcExprName), Result); if (GivenLength != 0 && SrcLength != 0 && GivenLength == SrcLength) return true; @@ -261,15 +262,15 @@ static bool isDestCapacityOverflows(const MatchFinder::MatchResult &Result) { return true; const Expr *DestCapacityExpr = getDestCapacityExpr(Result); - int DestCapacity = getLength(DestCapacityExpr, Result); - int GivenLength = getGivenLength(Result); + const int DestCapacity = getLength(DestCapacityExpr, Result); + const int GivenLength = getGivenLength(Result); if (GivenLength != 0 && DestCapacity != 0) return isGivenLengthEqualToSrcLength(Result) && DestCapacity == GivenLength; // Assume that the destination array's capacity cannot overflow if the // expression of the memory allocation contains '+ 1'. - StringRef DestCapacityExprStr = exprToStr(DestCapacityExpr, Result); + const StringRef DestCapacityExprStr = exprToStr(DestCapacityExpr, Result); if (DestCapacityExprStr.contains("+1") || DestCapacityExprStr.contains("+ 1")) return false; @@ -297,7 +298,7 @@ static void lengthExprHandle(const Expr *LengthExpr, // See whether we work with a macro. bool IsMacroDefinition = false; - StringRef LengthExprStr = exprToStr(LengthExpr, Result); + const StringRef LengthExprStr = exprToStr(LengthExpr, Result); Preprocessor::macro_iterator It = PP->macro_begin(); while (It != PP->macro_end() && !IsMacroDefinition) { if (It->first->getName() == LengthExprStr) @@ -309,7 +310,7 @@ static void lengthExprHandle(const Expr *LengthExpr, // Try to obtain an 'IntegerLiteral' and adjust it. if (!IsMacroDefinition) { if (const auto *LengthIL = dyn_cast<IntegerLiteral>(LengthExpr)) { - uint64_t NewLength = + const uint64_t NewLength = LengthIL->getValue().getZExtValue() + (LengthHandle == LengthHandleKind::Increase ? 1 : -1); @@ -347,7 +348,7 @@ static void lengthExprHandle(const Expr *LengthExpr, } // Try to inject the '+ 1'/'- 1' string. - bool NeedInnerParen = BO && BO->getOpcode() != BO_Add; + const bool NeedInnerParen = BO && BO->getOpcode() != BO_Add; if (NeedInnerParen) Diag << FixItHint::CreateInsertion(LengthExpr->getBeginLoc(), "("); @@ -384,8 +385,8 @@ static bool isDestExprFix(const MatchFinder::MatchResult &Result, if (!Dest) return false; - std::string TempTyStr = Dest->getType().getAsString(); - StringRef TyStr = TempTyStr; + const std::string TempTyStr = Dest->getType().getAsString(); + const StringRef TyStr = TempTyStr; if (TyStr.starts_with("char") || TyStr.starts_with("wchar_t")) return false; @@ -397,7 +398,7 @@ static bool isDestExprFix(const MatchFinder::MatchResult &Result, // increase the capacity by one to create space for the null terminator. static bool isDestCapacityFix(const MatchFinder::MatchResult &Result, DiagnosticBuilder &Diag) { - bool IsOverflows = isDestCapacityOverflows(Result); + const bool IsOverflows = isDestCapacityOverflows(Result); if (IsOverflows) if (const Expr *CapacityExpr = getDestCapacityExpr(Result)) lengthExprHandle(CapacityExpr, LengthHandleKind::Increase, Result, Diag); @@ -424,9 +425,9 @@ static void renameFunc(StringRef NewFuncName, const MatchFinder::MatchResult &Result, DiagnosticBuilder &Diag) { const auto *FunctionExpr = Result.Nodes.getNodeAs<CallExpr>(FunctionExprName); - int FuncNameLength = + const int FuncNameLength = FunctionExpr->getDirectCallee()->getIdentifier()->getLength(); - SourceRange FuncNameRange( + const SourceRange FuncNameRange( FunctionExpr->getBeginLoc(), FunctionExpr->getBeginLoc().getLocWithOffset(FuncNameLength - 1)); @@ -451,7 +452,7 @@ static void insertDestCapacityArg(bool IsOverflows, StringRef Name, const auto *FunctionExpr = Result.Nodes.getNodeAs<CallExpr>(FunctionExprName); SmallString<64> NewSecondArg; - if (int DestLength = getDestCapacity(Result)) { + if (const int DestLength = getDestCapacity(Result)) { NewSecondArg = Twine(IsOverflows ? DestLength + 1 : DestLength).str(); } else { NewSecondArg = @@ -470,12 +471,12 @@ static void insertNullTerminatorExpr(StringRef Name, const MatchFinder::MatchResult &Result, DiagnosticBuilder &Diag) { const auto *FunctionExpr = Result.Nodes.getNodeAs<CallExpr>(FunctionExprName); - int FuncLocStartColumn = Result.SourceManager->getPresumedColumnNumber( + const int FuncLocStartColumn = Result.SourceManager->getPresumedColumnNumber( FunctionExpr->getBeginLoc()); - SourceRange SpaceRange( + const SourceRange SpaceRange( FunctionExpr->getBeginLoc().getLocWithOffset(-FuncLocStartColumn + 1), FunctionExpr->getBeginLoc()); - StringRef SpaceBeforeStmtStr = Lexer::getSourceText( + const StringRef SpaceBeforeStmtStr = Lexer::getSourceText( CharSourceRange::getCharRange(SpaceRange), *Result.SourceManager, Result.Context->getLangOpts(), nullptr); @@ -717,10 +718,10 @@ void NotNullTerminatedResultCheck::registerMatchers(MatchFinder *Finder) { }; auto MatchCall = [=](CallContext CC) { - std::string CharHandlerFuncName = "::" + CC.Name.str(); + const std::string CharHandlerFuncName = "::" + CC.Name.str(); // Try to match with 'wchar_t' based function calls. - std::string WcharHandlerFuncName = + const std::string WcharHandlerFuncName = "::" + (CC.Name.starts_with("mem") ? "w" + CC.Name.str() : "wcs" + CC.Name.substr(3).str()); @@ -804,7 +805,8 @@ void NotNullTerminatedResultCheck::check( if (MI) { const auto &T = MI->tokens().back(); if (T.isLiteral() && T.getLiteralData()) { - StringRef ValueStr = StringRef(T.getLiteralData(), T.getLength()); + const StringRef ValueStr = + StringRef(T.getLiteralData(), T.getLength()); llvm::APInt IntValue; ValueStr.getAsInteger(10, IntValue); AreSafeFunctionsWanted = IntValue.getZExtValue(); @@ -819,7 +821,7 @@ void NotNullTerminatedResultCheck::check( UseSafeFunctions = *AreSafeFunctionsWanted; } - StringRef Name = FunctionExpr->getDirectCallee()->getName(); + const StringRef Name = FunctionExpr->getDirectCallee()->getName(); if (Name.starts_with("mem") || Name.starts_with("wmem")) memoryHandlerFunctionFix(Name, Result); else if (Name == "strerror_s") @@ -864,16 +866,16 @@ void NotNullTerminatedResultCheck::memoryHandlerFunctionFix( void NotNullTerminatedResultCheck::memcpyFix( StringRef Name, const MatchFinder::MatchResult &Result, DiagnosticBuilder &Diag) { - bool IsOverflows = isDestCapacityFix(Result, Diag); - bool IsDestFixed = isDestExprFix(Result, Diag); + const bool IsOverflows = isDestCapacityFix(Result, Diag); + const bool IsDestFixed = isDestExprFix(Result, Diag); - bool IsCopy = + const bool IsCopy = isGivenLengthEqualToSrcLength(Result) || isDestBasedOnGivenLength(Result); - bool IsSafe = UseSafeFunctions && IsOverflows && isKnownDest(Result) && - !isDestBasedOnGivenLength(Result); + const bool IsSafe = UseSafeFunctions && IsOverflows && isKnownDest(Result) && + !isDestBasedOnGivenLength(Result); - bool IsDestLengthNotRequired = + const bool IsDestLengthNotRequired = IsSafe && getLangOpts().CPlusPlus && Result.Nodes.getNodeAs<ArrayType>(DestArrayTyName) && !IsDestFixed; @@ -892,14 +894,14 @@ void NotNullTerminatedResultCheck::memcpyFix( void NotNullTerminatedResultCheck::memcpySFix( StringRef Name, const MatchFinder::MatchResult &Result, DiagnosticBuilder &Diag) { - bool IsOverflows = isDestCapacityFix(Result, Diag); - bool IsDestFixed = isDestExprFix(Result, Diag); + const bool IsOverflows = isDestCapacityFix(Result, Diag); + const bool IsDestFixed = isDestExprFix(Result, Diag); - bool RemoveDestLength = getLangOpts().CPlusPlus && - Result.Nodes.getNodeAs<ArrayType>(DestArrayTyName) && - !IsDestFixed; - bool IsCopy = isGivenLengthEqualToSrcLength(Result); - bool IsSafe = IsOverflows; + const bool RemoveDestLength = + getLangOpts().CPlusPlus && + Result.Nodes.getNodeAs<ArrayType>(DestArrayTyName) && !IsDestFixed; + const bool IsCopy = isGivenLengthEqualToSrcLength(Result); + const bool IsSafe = IsOverflows; renameMemcpy(Name, IsCopy, IsSafe, Result, Diag); @@ -932,7 +934,7 @@ void NotNullTerminatedResultCheck::memchrFix( Diag << CastRemoveFix; } - StringRef NewFuncName = (Name[0] != 'w') ? "strchr" : "wcschr"; + const StringRef NewFuncName = (Name[0] != 'w') ? "strchr" : "wcschr"; renameFunc(NewFuncName, Result, Diag); removeArg(2, Result, Diag); } @@ -940,7 +942,7 @@ void NotNullTerminatedResultCheck::memchrFix( void NotNullTerminatedResultCheck::memmoveFix( StringRef Name, const MatchFinder::MatchResult &Result, DiagnosticBuilder &Diag) const { - bool IsOverflows = isDestCapacityFix(Result, Diag); + const bool IsOverflows = isDestCapacityFix(Result, Diag); if (UseSafeFunctions && isKnownDest(Result)) { renameFunc((Name[0] != 'w') ? "memmove_s" : "wmemmove_s", Result, Diag); @@ -970,15 +972,15 @@ void NotNullTerminatedResultCheck::ncmpFix( if (const CallExpr *StrlenExpr = getStrlenExpr(Result)) { const Expr *LengthExprArg = StrlenExpr->getArg(0); - StringRef FirstExprStr = exprToStr(FirstArgExpr, Result).trim(); - StringRef SecondExprStr = exprToStr(SecondArgExpr, Result).trim(); - StringRef LengthArgStr = exprToStr(LengthExprArg, Result).trim(); + const StringRef FirstExprStr = exprToStr(FirstArgExpr, Result).trim(); + const StringRef SecondExprStr = exprToStr(SecondArgExpr, Result).trim(); + const StringRef LengthArgStr = exprToStr(LengthExprArg, Result).trim(); IsLengthTooLong = LengthArgStr == FirstExprStr || LengthArgStr == SecondExprStr; } else { - int SrcLength = + const int SrcLength = getLength(Result.Nodes.getNodeAs<Expr>(SrcExprName), Result); - int GivenLength = getGivenLength(Result); + const int GivenLength = getGivenLength(Result); if (SrcLength != 0 && GivenLength != 0) IsLengthTooLong = GivenLength > SrcLength; } diff --git a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.h b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.h index a8f4ca3..cf61eb5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/NotNullTerminatedResultCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NOT_NULL_TERMINATED_RESULT_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NOT_NULL_TERMINATED_RESULT_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NOTNULLTERMINATEDRESULTCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NOTNULLTERMINATEDRESULTCHECK_H #include "../ClangTidyCheck.h" @@ -60,4 +60,4 @@ private: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NOT_NULL_TERMINATED_RESULT_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_NOTNULLTERMINATEDRESULTCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp index 1b1e0401..19b4fc1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/OptionalValueConversionCheck.cpp @@ -101,11 +101,9 @@ void OptionalValueConversionCheck::registerMatchers(MatchFinder *Finder) { hasName(MakeOptional), returns(BindOptionalType)))), hasArgument(0, OptionalDerefMatcher)), - callExpr( - - argumentCountIs(1), + callExpr(argumentCountIs(1), - hasArgument(0, OptionalDerefMatcher))), + hasArgument(0, OptionalDerefMatcher))), unless(anyOf(hasAncestor(typeLoc()), hasAncestor(expr(matchers::hasUnevaluatedContext()))))) .bind("expr"), diff --git a/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.cpp index 57196ad..0084ace 100644 --- a/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.cpp @@ -66,8 +66,8 @@ void PosixReturnCheck::registerMatchers(MatchFinder *Finder) { void PosixReturnCheck::check(const MatchFinder::MatchResult &Result) { if (const auto *LessThanZeroOp = Result.Nodes.getNodeAs<BinaryOperator>("ltzop")) { - SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc(); - StringRef NewBinOp = + const SourceLocation OperatorLoc = LessThanZeroOp->getOperatorLoc(); + const StringRef NewBinOp = LessThanZeroOp->getOpcode() == BinaryOperator::Opcode::BO_LT ? ">" : "<"; diag(OperatorLoc, "the comparison always evaluates to false because %0 " diff --git a/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.h b/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.h index d72c86c..a9cb7a6 100644 --- a/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/PosixReturnCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POSIX_RETURN_CHECK_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POSIX_RETURN_CHECK_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POSIXRETURNCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POSIXRETURNCHECK_H #include "../ClangTidyCheck.h" @@ -23,4 +23,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POSIX_RETURN_CHECK_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_POSIXRETURNCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.cpp new file mode 100644 index 0000000..3e32e9b --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.cpp @@ -0,0 +1,119 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "RandomGeneratorSeedCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "llvm/ADT/STLExtras.h" + +using namespace clang::ast_matchers; + +namespace clang::tidy::bugprone { + +RandomGeneratorSeedCheck::RandomGeneratorSeedCheck(StringRef Name, + ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + RawDisallowedSeedTypes( + Options.get("DisallowedSeedTypes", "time_t,std::time_t")) { + RawDisallowedSeedTypes.split(DisallowedSeedTypes, ','); +} + +void RandomGeneratorSeedCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "DisallowedSeedTypes", RawDisallowedSeedTypes); +} + +void RandomGeneratorSeedCheck::registerMatchers(MatchFinder *Finder) { + auto RandomGeneratorEngineDecl = cxxRecordDecl(hasAnyName( + "::std::linear_congruential_engine", "::std::mersenne_twister_engine", + "::std::subtract_with_carry_engine", "::std::discard_block_engine", + "::std::independent_bits_engine", "::std::shuffle_order_engine")); + auto RandomGeneratorEngineTypeMatcher = hasType(hasUnqualifiedDesugaredType( + recordType(hasDeclaration(RandomGeneratorEngineDecl)))); + + // std::mt19937 engine; + // engine.seed(); + // ^ + // engine.seed(1); + // ^ + // const int x = 1; + // engine.seed(x); + // ^ + Finder->addMatcher( + cxxMemberCallExpr( + has(memberExpr(has(declRefExpr(RandomGeneratorEngineTypeMatcher)), + member(hasName("seed")), + unless(hasDescendant(cxxThisExpr()))))) + .bind("seed"), + this); + + // std::mt19937 engine; + // ^ + // std::mt19937 engine(1); + // ^ + // const int x = 1; + // std::mt19937 engine(x); + // ^ + Finder->addMatcher( + traverse(TK_AsIs, + cxxConstructExpr(RandomGeneratorEngineTypeMatcher).bind("ctor")), + this); + + // srand(); + // ^ + // const int x = 1; + // srand(x); + // ^ + Finder->addMatcher( + callExpr(callee(functionDecl(hasAnyName("::srand", "::std::srand")))) + .bind("srand"), + this); +} + +void RandomGeneratorSeedCheck::check(const MatchFinder::MatchResult &Result) { + const auto *Ctor = Result.Nodes.getNodeAs<CXXConstructExpr>("ctor"); + if (Ctor) + checkSeed(Result, Ctor); + + const auto *Func = Result.Nodes.getNodeAs<CXXMemberCallExpr>("seed"); + if (Func) + checkSeed(Result, Func); + + const auto *Srand = Result.Nodes.getNodeAs<CallExpr>("srand"); + if (Srand) + checkSeed(Result, Srand); +} + +template <class T> +void RandomGeneratorSeedCheck::checkSeed(const MatchFinder::MatchResult &Result, + const T *Func) { + if (Func->getNumArgs() == 0 || Func->getArg(0)->isDefaultArgument()) { + diag(Func->getExprLoc(), + "random number generator seeded with a default argument will generate " + "a predictable sequence of values"); + return; + } + + Expr::EvalResult EVResult; + if (Func->getArg(0)->EvaluateAsInt(EVResult, *Result.Context)) { + diag(Func->getExprLoc(), + "random number generator seeded with a constant value will generate a " + "predictable sequence of values"); + return; + } + + const std::string SeedType( + Func->getArg(0)->IgnoreCasts()->getType().getAsString()); + if (llvm::is_contained(DisallowedSeedTypes, SeedType)) { + diag(Func->getExprLoc(), + "random number generator seeded with a disallowed source of seed " + "value will generate a predictable sequence of values"); + return; + } +} + +} // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.h b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.h new file mode 100644 index 0000000..c9c54ea --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/RandomGeneratorSeedCheck.h @@ -0,0 +1,42 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RANDOMGENERATORSEEDCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RANDOMGENERATORSEEDCHECK_H + +#include "../ClangTidyCheck.h" +#include <string> + +namespace clang::tidy::bugprone { + +/// Random number generator must be seeded properly. +/// +/// A random number generator initialized with default value or a +/// constant expression is a security vulnerability. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/random-generator-seed.html +class RandomGeneratorSeedCheck : public ClangTidyCheck { +public: + RandomGeneratorSeedCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + template <class T> + void checkSeed(const ast_matchers::MatchFinder::MatchResult &Result, + const T *Func); + + StringRef RawDisallowedSeedTypes; + SmallVector<StringRef, 5> DisallowedSeedTypes; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_RANDOMGENERATORSEEDCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp index f7f7ccb..e212301 100644 --- a/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/RawMemoryCallOnNonTrivialTypeCheck.cpp @@ -64,7 +64,8 @@ void RawMemoryCallOnNonTrivialTypeCheck::storeOptions( void RawMemoryCallOnNonTrivialTypeCheck::registerMatchers(MatchFinder *Finder) { using namespace ast_matchers::internal; - auto IsStructPointer = [](Matcher<CXXRecordDecl> Constraint = anything(), + auto IsStructPointer = [](const Matcher<CXXRecordDecl> &Constraint = + anything(), bool Bind = false) { return expr(unaryOperator( hasOperatorName("&"), @@ -74,8 +75,8 @@ void RawMemoryCallOnNonTrivialTypeCheck::registerMatchers(MatchFinder *Finder) { }; auto IsRecordSizeOf = expr(sizeOfExpr(hasArgumentOfType(equalsBoundNode("Record")))); - auto ArgChecker = [&](Matcher<CXXRecordDecl> RecordConstraint, - BindableMatcher<Stmt> SecondArg = expr()) { + auto ArgChecker = [&](const Matcher<CXXRecordDecl> &RecordConstraint, + const BindableMatcher<Stmt> &SecondArg = expr()) { return allOf(argumentCountIs(3), hasArgument(0, IsStructPointer(RecordConstraint, true)), hasArgument(1, SecondArg), hasArgument(2, IsRecordSizeOf)); diff --git a/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp index 6abe53f..528c254 100644 --- a/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/RedundantBranchConditionCheck.cpp @@ -112,7 +112,7 @@ void RedundantBranchConditionCheck::check( if (isa<DeclRefExpr>(InnerIf->getCond()->IgnoreParenImpCasts()) || (BinOpCond && BinOpCond->getOpcode() == BO_LOr)) { - SourceLocation IfBegin = InnerIf->getBeginLoc(); + const SourceLocation IfBegin = InnerIf->getBeginLoc(); const Stmt *Body = InnerIf->getThen(); const Expr *OtherSide = nullptr; if (BinOpCond) { @@ -132,9 +132,9 @@ void RedundantBranchConditionCheck::check( // If the other side has side effects then keep it. if (OtherSide && OtherSide->HasSideEffects(*Result.Context)) { - SourceLocation BeforeOtherSide = + const SourceLocation BeforeOtherSide = OtherSide->getBeginLoc().getLocWithOffset(-1); - SourceLocation AfterOtherSide = + const SourceLocation AfterOtherSide = Lexer::findNextToken(OtherSide->getEndLoc(), *Result.SourceManager, getLangOpts()) ->getLocation(); @@ -161,12 +161,12 @@ void RedundantBranchConditionCheck::check( const auto *LeftDRE = dyn_cast<DeclRefExpr>(CondOp->getLHS()->IgnoreParenImpCasts()); if (LeftDRE && LeftDRE->getDecl() == CondVar) { - SourceLocation BeforeRHS = + const SourceLocation BeforeRHS = CondOp->getRHS()->getBeginLoc().getLocWithOffset(-1); Diag << FixItHint::CreateRemoval(CharSourceRange::getTokenRange( CondOp->getLHS()->getBeginLoc(), BeforeRHS)); } else { - SourceLocation AfterLHS = + const SourceLocation AfterLHS = Lexer::findNextToken(CondOp->getLHS()->getEndLoc(), *Result.SourceManager, getLangOpts()) ->getLocation(); diff --git a/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp index a3265293..1107cef 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ReturnConstRefFromParameterCheck.cpp @@ -83,7 +83,7 @@ static const Decl *findRVRefOverload(const FunctionDecl &FD, // FIXME: // 1. overload in anonymous namespace // 2. forward reference - DeclContext::lookup_result LookupResult = + const DeclContext::lookup_result LookupResult = FD.getParent()->lookup(FD.getNameInfo().getName()); if (LookupResult.isSingleResult()) { return nullptr; diff --git a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp index c262b1c..282a3b2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.cpp @@ -283,7 +283,7 @@ static bool isStandardFunction(const FunctionDecl *FD) { /// This includes all statements that have a class name with "CXX" prefix /// and every other statement that is declared in file ExprCXX.h. static bool isCXXOnlyStmt(const Stmt *S) { - StringRef Name = S->getStmtClassName(); + const StringRef Name = S->getStmtClassName(); if (Name.starts_with("CXX")) return true; // Check for all other class names in ExprCXX.h that have no 'CXX' prefix. @@ -317,7 +317,7 @@ static SourceRange getSourceRangeOfStmt(const Stmt *S, ASTContext &Ctx) { ParentMapContext &PM = Ctx.getParentMapContext(); DynTypedNode P = DynTypedNode::create(*S); while (P.getSourceRange().isInvalid()) { - DynTypedNodeList PL = PM.getParents(P); + const DynTypedNodeList PL = PM.getParents(P); if (PL.size() != 1) return {}; P = PL[0]; @@ -401,14 +401,15 @@ void SignalHandlerCheck::check(const MatchFinder::MatchResult &Result) { } // FIXME: Update CallGraph::getNode to use canonical decl? - CallGraphNode *HandlerNode = CG.getNode(HandlerDecl->getCanonicalDecl()); + const CallGraphNode *HandlerNode = + CG.getNode(HandlerDecl->getCanonicalDecl()); assert(HandlerNode && "Handler with body should be present in the call graph."); // Start from signal handler and visit every function call. auto Itr = llvm::df_begin(HandlerNode), ItrE = llvm::df_end(HandlerNode); while (Itr != ItrE) { const auto *CallF = dyn_cast<FunctionDecl>((*Itr)->getDecl()); - unsigned int PathL = Itr.getPathLength(); + const unsigned int PathL = Itr.getPathLength(); if (CallF) { // A signal handler or a function transitively reachable from the signal // handler was found to be unsafe. @@ -434,8 +435,8 @@ void SignalHandlerCheck::check(const MatchFinder::MatchResult &Result) { bool SignalHandlerCheck::checkFunction( const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter) { - bool FunctionIsCalled = isa<CallExpr>(CallOrRef); + llvm::function_ref<void(bool)> ChainReporter) { + const bool FunctionIsCalled = isa<CallExpr>(CallOrRef); if (isStandardFunction(FD)) { if (!isStandardFunctionAsyncSafe(FD)) { @@ -470,7 +471,7 @@ bool SignalHandlerCheck::checkFunction( bool SignalHandlerCheck::checkFunctionCPP14( const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter) { + llvm::function_ref<void(bool)> ChainReporter) { if (!FD->isExternC()) { diag(CallOrRef->getBeginLoc(), "functions without C linkage are not allowed as signal " @@ -492,7 +493,7 @@ bool SignalHandlerCheck::checkFunctionCPP14( for (const auto &Match : Matches) { const auto *FoundS = Match.getNodeAs<Stmt>("stmt"); if (isCXXOnlyStmt(FoundS)) { - SourceRange R = getSourceRangeOfStmt(FoundS, Ctx); + const SourceRange R = getSourceRangeOfStmt(FoundS, Ctx); if (R.isInvalid()) continue; diag(R.getBegin(), @@ -531,7 +532,7 @@ bool SignalHandlerCheck::isStandardFunctionAsyncSafe( } void SignalHandlerCheck::reportHandlerChain( - const llvm::df_iterator<clang::CallGraphNode *> &Itr, + const llvm::df_iterator<const clang::CallGraphNode *> &Itr, const DeclRefExpr *HandlerRef, bool SkipPathEnd) { int CallLevel = Itr.getPathLength() - 2; assert(CallLevel >= -1 && "Empty iterator?"); diff --git a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h index b5317793..324b2c8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/SignalHandlerCheck.h @@ -48,10 +48,10 @@ private: /// The bool parameter is used like \c SkipPathEnd in \c reportHandlerChain . /// \return Returns true if a diagnostic was emitted for this function. bool checkFunction(const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter); + llvm::function_ref<void(bool)> ChainReporter); /// Similar as \c checkFunction but only check for C++14 rules. bool checkFunctionCPP14(const FunctionDecl *FD, const Expr *CallOrRef, - std::function<void(bool)> ChainReporter); + llvm::function_ref<void(bool)> ChainReporter); /// Returns true if a standard library function is considered /// asynchronous-safe. bool isStandardFunctionAsyncSafe(const FunctionDecl *FD) const; @@ -65,8 +65,9 @@ private: /// registered as signal handler. /// @param SkipPathEnd If true the last item of the call chain (farthest away /// from the \c signal call) is omitted from note generation. - void reportHandlerChain(const llvm::df_iterator<clang::CallGraphNode *> &Itr, - const DeclRefExpr *HandlerRef, bool SkipPathEnd); + void + reportHandlerChain(const llvm::df_iterator<const clang::CallGraphNode *> &Itr, + const DeclRefExpr *HandlerRef, bool SkipPathEnd); clang::CallGraph CG; diff --git a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp index 742d85b..31c5413 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SignedCharMisuseCheck.cpp @@ -140,7 +140,7 @@ void SignedCharMisuseCheck::check(const MatchFinder::MatchResult &Result) { if (!SignedCastExpression->isValueDependent() && SignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult, *Result.Context)) { - llvm::APSInt Value = EVResult.Val.getInt(); + const llvm::APSInt Value = EVResult.Val.getInt(); if (Value.isNonNegative()) return; } @@ -154,7 +154,7 @@ void SignedCharMisuseCheck::check(const MatchFinder::MatchResult &Result) { if (!UnSignedCastExpression->isValueDependent() && UnSignedCastExpression->getSubExpr()->EvaluateAsInt(EVResult, *Result.Context)) { - llvm::APSInt Value = EVResult.Val.getInt(); + const llvm::APSInt Value = EVResult.Val.getInt(); if (Value <= UnsignedASCIIUpperBound) return; } diff --git a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp index 2672dc7..49ba3b8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SizeofExpressionCheck.cpp @@ -407,9 +407,9 @@ void SizeofExpressionCheck::check(const MatchFinder::MatchResult &Result) { const auto *ElementTy = Result.Nodes.getNodeAs<Type>("elem-type"); const auto *PointedTy = Result.Nodes.getNodeAs<Type>("elem-ptr-type"); - CharUnits NumeratorSize = getSizeOfType(Ctx, NumTy); - CharUnits DenominatorSize = getSizeOfType(Ctx, DenomTy); - CharUnits ElementSize = getSizeOfType(Ctx, ElementTy); + const CharUnits NumeratorSize = getSizeOfType(Ctx, NumTy); + const CharUnits DenominatorSize = getSizeOfType(Ctx, DenomTy); + const CharUnits ElementSize = getSizeOfType(Ctx, ElementTy); if (DenominatorSize > CharUnits::Zero() && !NumeratorSize.isMultipleOf(DenominatorSize)) { diff --git a/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp index f76e4a7..af478b1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SmartPtrArrayMismatchCheck.cpp @@ -93,10 +93,10 @@ void SmartPtrArrayMismatchCheck::check(const MatchFinder::MatchResult &Result) { assert(TSTypeLoc.getNumArgs() >= 1 && "Matched type should have at least 1 template argument."); - SourceRange TemplateArgumentRange = TSTypeLoc.getArgLoc(0) - .getTypeSourceInfo() - ->getTypeLoc() - .getSourceRange(); + const SourceRange TemplateArgumentRange = TSTypeLoc.getArgLoc(0) + .getTypeSourceInfo() + ->getTypeLoc() + .getSourceRange(); D << TemplateArgumentRange; if (isInSingleDeclStmt(VarOrField)) { @@ -104,7 +104,7 @@ void SmartPtrArrayMismatchCheck::check(const MatchFinder::MatchResult &Result) { if (!utils::rangeCanBeFixed(TemplateArgumentRange, &SM)) return; - SourceLocation InsertLoc = Lexer::getLocForEndOfToken( + const SourceLocation InsertLoc = Lexer::getLocForEndOfToken( TemplateArgumentRange.getEnd(), 0, SM, Ctx.getLangOpts()); D << FixItHint::CreateInsertion(InsertLoc, "[]"); } diff --git a/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp index 1e8058b..fd82b1c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SpuriouslyWakeUpFunctionsCheck.cpp @@ -15,7 +15,6 @@ using namespace clang::ast_matchers; namespace clang::tidy::bugprone { void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) { - auto HasUniqueLock = hasDescendant(declRefExpr( hasDeclaration(varDecl(hasType(recordDecl(classTemplateSpecializationDecl( hasName("::std::unique_lock"), @@ -45,9 +44,7 @@ void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) { onImplicitObjectArgument( declRefExpr(to(varDecl(hasType(references(recordDecl( hasName("::std::condition_variable")))))))), - HasUniqueLock) - - )) + HasUniqueLock))) .bind("wait")); auto HasWaitDescendantC = hasDescendant( @@ -77,7 +74,7 @@ void SpuriouslyWakeUpFunctionsCheck::registerMatchers(MatchFinder *Finder) { void SpuriouslyWakeUpFunctionsCheck::check( const MatchFinder::MatchResult &Result) { const auto *MatchedWait = Result.Nodes.getNodeAs<CallExpr>("wait"); - StringRef WaitName = MatchedWait->getDirectCallee()->getName(); + const StringRef WaitName = MatchedWait->getDirectCallee()->getName(); diag(MatchedWait->getExprLoc(), "'%0' should be placed inside a while statement %select{|or used with a " "conditional parameter}1") diff --git a/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp index a7958cc..056ae4b8 100644 --- a/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/StandaloneEmptyCheck.cpp @@ -117,12 +117,13 @@ void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) { if (ParentReturnStmt) return; - SourceLocation MemberLoc = MemberCall->getBeginLoc(); - SourceLocation ReplacementLoc = MemberCall->getExprLoc(); - SourceRange ReplacementRange = SourceRange(ReplacementLoc, ReplacementLoc); + const SourceLocation MemberLoc = MemberCall->getBeginLoc(); + const SourceLocation ReplacementLoc = MemberCall->getExprLoc(); + const SourceRange ReplacementRange = + SourceRange(ReplacementLoc, ReplacementLoc); ASTContext &Context = MemberCall->getRecordDecl()->getASTContext(); - DeclarationName Name = + const DeclarationName Name = Context.DeclarationNames.getIdentifier(&Context.Idents.get("clear")); auto Candidates = HeuristicResolver(Context).lookupDependentName( @@ -133,11 +134,12 @@ void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) { !llvm::cast<CXXMethodDecl>(ND)->isConst(); }); - bool HasClear = !Candidates.empty(); + const bool HasClear = !Candidates.empty(); if (HasClear) { const auto *Clear = llvm::cast<CXXMethodDecl>(Candidates.at(0)); - QualType RangeType = MemberCall->getImplicitObjectArgument()->getType(); - bool QualifierIncompatible = + const QualType RangeType = + MemberCall->getImplicitObjectArgument()->getType(); + const bool QualifierIncompatible = (!Clear->isVolatile() && RangeType.isVolatileQualified()) || RangeType.isConstQualified(); if (!QualifierIncompatible) { @@ -162,8 +164,8 @@ void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) { if (NonMemberCall->getNumArgs() != 1) return; - SourceLocation NonMemberLoc = NonMemberCall->getExprLoc(); - SourceLocation NonMemberEndLoc = NonMemberCall->getEndLoc(); + const SourceLocation NonMemberLoc = NonMemberCall->getExprLoc(); + const SourceLocation NonMemberEndLoc = NonMemberCall->getEndLoc(); const Expr *Arg = NonMemberCall->getArg(0); CXXRecordDecl *ArgRecordDecl = Arg->getType()->getAsCXXRecordDecl(); @@ -171,7 +173,7 @@ void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) { return; ASTContext &Context = ArgRecordDecl->getASTContext(); - DeclarationName Name = + const DeclarationName Name = Context.DeclarationNames.getIdentifier(&Context.Idents.get("clear")); auto Candidates = HeuristicResolver(Context).lookupDependentName( @@ -182,20 +184,20 @@ void StandaloneEmptyCheck::check(const MatchFinder::MatchResult &Result) { !llvm::cast<CXXMethodDecl>(ND)->isConst(); }); - bool HasClear = !Candidates.empty(); + const bool HasClear = !Candidates.empty(); if (HasClear) { const auto *Clear = llvm::cast<CXXMethodDecl>(Candidates.at(0)); - bool QualifierIncompatible = + const bool QualifierIncompatible = (!Clear->isVolatile() && Arg->getType().isVolatileQualified()) || Arg->getType().isConstQualified(); if (!QualifierIncompatible) { - std::string ReplacementText = + const std::string ReplacementText = std::string(Lexer::getSourceText( CharSourceRange::getTokenRange(Arg->getSourceRange()), *Result.SourceManager, getLangOpts())) + ".clear()"; - SourceRange ReplacementRange = + const SourceRange ReplacementRange = SourceRange(NonMemberLoc, NonMemberEndLoc); diag(NonMemberLoc, "ignoring the result of '%0'; did you mean 'clear()'?") diff --git a/clang-tools-extra/clang-tidy/bugprone/StdNamespaceModificationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StdNamespaceModificationCheck.cpp new file mode 100644 index 0000000..1dff741 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/StdNamespaceModificationCheck.cpp @@ -0,0 +1,129 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "StdNamespaceModificationCheck.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/ASTMatchers/ASTMatchersInternal.h" + +using namespace clang; +using namespace clang::ast_matchers; + +namespace { + +AST_POLYMORPHIC_MATCHER_P( + hasAnyTemplateArgumentIncludingPack, + AST_POLYMORPHIC_SUPPORTED_TYPES(ClassTemplateSpecializationDecl, + TemplateSpecializationType, FunctionDecl), + clang::ast_matchers::internal::Matcher<TemplateArgument>, InnerMatcher) { + const ArrayRef<TemplateArgument> Args = + clang::ast_matchers::internal::getTemplateSpecializationArgs(Node); + for (const auto &Arg : Args) { + if (Arg.getKind() != TemplateArgument::Pack) + continue; + const ArrayRef<TemplateArgument> PackArgs = Arg.getPackAsArray(); + if (matchesFirstInRange(InnerMatcher, PackArgs.begin(), PackArgs.end(), + Finder, Builder) != PackArgs.end()) + return true; + } + return matchesFirstInRange(InnerMatcher, Args.begin(), Args.end(), Finder, + Builder) != Args.end(); +} + +} // namespace + +namespace clang::tidy::bugprone { + +void StdNamespaceModificationCheck::registerMatchers(MatchFinder *Finder) { + auto HasStdParent = + hasDeclContext(namespaceDecl(hasAnyName("std", "posix"), + unless(hasParent(namespaceDecl()))) + .bind("nmspc")); + auto UserDefinedType = qualType( + hasUnqualifiedDesugaredType(tagType(unless(hasDeclaration(tagDecl( + hasAncestor(namespaceDecl(hasAnyName("std", "posix"), + unless(hasParent(namespaceDecl())))))))))); + auto HasNoProgramDefinedTemplateArgument = unless( + hasAnyTemplateArgumentIncludingPack(refersToType(UserDefinedType))); + auto InsideStdClassOrClassTemplateSpecialization = hasDeclContext( + anyOf(cxxRecordDecl(HasStdParent), + classTemplateSpecializationDecl( + HasStdParent, HasNoProgramDefinedTemplateArgument))); + + // Try to follow exactly CERT rule DCL58-CPP (this text is taken from C++ + // standard into the CERT rule): + // " + // 1 The behavior of a C++ program is undefined if it adds declarations or + // definitions to namespace std or to a namespace within namespace std unless + // otherwise specified. A program may add a template specialization for any + // standard library template to namespace std only if the declaration depends + // on a user-defined type and the specialization meets the standard library + // requirements for the original template and is not explicitly prohibited. 2 + // The behavior of a C++ program is undefined if it declares — an explicit + // specialization of any member function of a standard library class template, + // or — an explicit specialization of any member function template of a + // standard library class or class template, or — an explicit or partial + // specialization of any member class template of a standard library class or + // class template. + // " + // The "standard library requirements" and explicit prohibition are not + // checked. + + auto BadNonTemplateSpecializationDecl = + decl(unless(anyOf(functionDecl(isExplicitTemplateSpecialization()), + varDecl(isExplicitTemplateSpecialization()), + cxxRecordDecl(isExplicitTemplateSpecialization()))), + HasStdParent); + auto BadClassTemplateSpec = classTemplateSpecializationDecl( + HasNoProgramDefinedTemplateArgument, HasStdParent); + auto BadInnerClassTemplateSpec = classTemplateSpecializationDecl( + InsideStdClassOrClassTemplateSpecialization); + auto BadFunctionTemplateSpec = + functionDecl(unless(cxxMethodDecl()), isExplicitTemplateSpecialization(), + HasNoProgramDefinedTemplateArgument, HasStdParent); + auto BadMemberFunctionSpec = + cxxMethodDecl(isExplicitTemplateSpecialization(), + InsideStdClassOrClassTemplateSpecialization); + + Finder->addMatcher(decl(anyOf(BadNonTemplateSpecializationDecl, + BadClassTemplateSpec, BadInnerClassTemplateSpec, + BadFunctionTemplateSpec, BadMemberFunctionSpec), + unless(isExpansionInSystemHeader())) + .bind("decl"), + this); +} +} // namespace clang::tidy::bugprone + +static const NamespaceDecl *getTopLevelLexicalNamespaceDecl(const Decl *D) { + const NamespaceDecl *LastNS = nullptr; + while (D) { + if (const auto *NS = dyn_cast<NamespaceDecl>(D)) + LastNS = NS; + D = dyn_cast_or_null<Decl>(D->getLexicalDeclContext()); + } + return LastNS; +} + +void clang::tidy::bugprone::StdNamespaceModificationCheck::check( + const MatchFinder::MatchResult &Result) { + const auto *D = Result.Nodes.getNodeAs<Decl>("decl"); + const auto *NS = Result.Nodes.getNodeAs<NamespaceDecl>("nmspc"); + if (!D || !NS) + return; + + diag(D->getLocation(), + "modification of %0 namespace can result in undefined behavior") + << NS; + // 'NS' is not always the namespace declaration that lexically contains 'D', + // try to find such a namespace. + if (const NamespaceDecl *LexNS = getTopLevelLexicalNamespaceDecl(D)) { + assert(NS->getCanonicalDecl() == LexNS->getCanonicalDecl() && + "Mismatch in found namespace"); + diag(LexNS->getLocation(), "%0 namespace opened here", DiagnosticIDs::Note) + << LexNS; + } +} diff --git a/clang-tools-extra/clang-tidy/bugprone/StdNamespaceModificationCheck.h b/clang-tools-extra/clang-tidy/bugprone/StdNamespaceModificationCheck.h new file mode 100644 index 0000000..0f62dc3 --- /dev/null +++ b/clang-tools-extra/clang-tidy/bugprone/StdNamespaceModificationCheck.h @@ -0,0 +1,34 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STDNAMESPACEMODIFICATIONCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STDNAMESPACEMODIFICATIONCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang::tidy::bugprone { + +/// Modification of the std or posix namespace can result in undefined behavior. +/// This check warns for such modifications. +/// +/// For the user-facing documentation see: +/// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/std-namespace-modification.html +class StdNamespaceModificationCheck : public ClangTidyCheck { +public: + StdNamespaceModificationCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { + return LangOpts.CPlusPlus; + } + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace clang::tidy::bugprone + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STDNAMESPACEMODIFICATIONCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp index 832377e..d2e631e 100644 --- a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.cpp @@ -29,8 +29,8 @@ static std::vector<StringRef> removeNamespaces(const std::vector<StringRef> &Names) { std::vector<StringRef> Result; Result.reserve(Names.size()); - for (StringRef Name : Names) { - std::string::size_type ColonPos = Name.rfind(':'); + for (const StringRef Name : Names) { + const std::string::size_type ColonPos = Name.rfind(':'); Result.push_back( Name.substr(ColonPos == std::string::npos ? 0 : ColonPos + 1)); } @@ -168,7 +168,7 @@ void StringConstructorCheck::check(const MatchFinder::MatchResult &Result) { const ASTContext &Ctx = *Result.Context; const auto *E = Result.Nodes.getNodeAs<CXXConstructExpr>("constructor"); assert(E && "missing constructor expression"); - SourceLocation Loc = E->getBeginLoc(); + const SourceLocation Loc = E->getBeginLoc(); if (Result.Nodes.getNodeAs<Expr>("swapped-parameter")) { const Expr *P0 = E->getArg(0); diff --git a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.h b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.h index 0d7a203..9c08e4b 100644 --- a/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/StringConstructorCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRINGCONSTRUCTORCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRINGCONSTRUCTORCHECK_H #include "../ClangTidyCheck.h" @@ -36,4 +36,4 @@ private: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRING_CONSTRUCTOR_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_STRINGCONSTRUCTORCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp index 93a55ef54..8454fd1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/StringIntegerAssignmentCheck.cpp @@ -129,7 +129,7 @@ void StringIntegerAssignmentCheck::check( const auto *Argument = Result.Nodes.getNodeAs<Expr>("expr"); const auto CharType = Result.Nodes.getNodeAs<QualType>("type")->getCanonicalType(); - SourceLocation Loc = Argument->getBeginLoc(); + const SourceLocation Loc = Argument->getBeginLoc(); // Try to detect a few common expressions to reduce false positives. if (CharExpressionDetector(CharType, *Result.Context) @@ -145,7 +145,7 @@ void StringIntegerAssignmentCheck::check( if (Loc.isMacroID()) return; - bool IsWideCharType = CharType->isWideCharType(); + const bool IsWideCharType = CharType->isWideCharType(); if (!CharType->isCharType() && !IsWideCharType) return; bool IsOneDigit = false; @@ -155,7 +155,7 @@ void StringIntegerAssignmentCheck::check( IsLiteral = true; } - SourceLocation EndLoc = Lexer::getLocForEndOfToken( + const SourceLocation EndLoc = Lexer::getLocForEndOfToken( Argument->getEndLoc(), 0, *Result.SourceManager, getLangOpts()); if (IsOneDigit) { Diag << FixItHint::CreateInsertion(Loc, IsWideCharType ? "L'" : "'") diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp index 8dbe1c0..ef7f0b5 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousEnumUsageCheck.cpp @@ -54,7 +54,7 @@ static int enumLength(const EnumDecl *EnumDec) { static bool hasDisjointValueRange(const EnumDecl *Enum1, const EnumDecl *Enum2) { - ValueRange Range1(Enum1), Range2(Enum2); + const ValueRange Range1(Enum1), Range2(Enum2); return llvm::APSInt::compareValues(Range1.MaxVal, Range2.MinVal) < 0 || llvm::APSInt::compareValues(Range2.MaxVal, Range1.MinVal) < 0; } @@ -94,9 +94,9 @@ static int countNonPowOfTwoLiteralNum(const EnumDecl *EnumDec) { /// last enumerator is the sum of the lesser values (and initialized by a /// literal) or when it could contain consecutive values. static bool isPossiblyBitMask(const EnumDecl *EnumDec) { - ValueRange VR(EnumDec); - int EnumLen = enumLength(EnumDec); - int NonPowOfTwoCounter = countNonPowOfTwoLiteralNum(EnumDec); + const ValueRange VR(EnumDec); + const int EnumLen = enumLength(EnumDec); + const int NonPowOfTwoCounter = countNonPowOfTwoLiteralNum(EnumDec); return NonPowOfTwoCounter >= 1 && NonPowOfTwoCounter <= 2 && NonPowOfTwoCounter < EnumLen / 2 && (VR.MaxVal - VR.MinVal != EnumLen - 1) && diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp index aaf0594..5abbada 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousIncludeCheck.cpp @@ -66,7 +66,7 @@ void SuspiciousIncludePPCallbacks::InclusionDirective( if (!Check.IgnoredRegexString.empty() && Check.IgnoredRegex.match(FileName)) return; - SourceLocation DiagLoc = FilenameRange.getBegin().getLocWithOffset(1); + const SourceLocation DiagLoc = FilenameRange.getBegin().getLocWithOffset(1); const std::optional<StringRef> IFE = utils::getFileExtension(FileName, Check.ImplementationFileExtensions); @@ -81,7 +81,7 @@ void SuspiciousIncludePPCallbacks::InclusionDirective( llvm::sys::path::replace_extension(GuessedFileName, (!HFE.empty() ? "." : "") + HFE); - OptionalFileEntryRef File = + const OptionalFileEntryRef File = PP->LookupFile(DiagLoc, GuessedFileName, IsAngled, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr); if (File) { diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemoryComparisonCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemoryComparisonCheck.cpp index d1df2a8..7890afb 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemoryComparisonCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemoryComparisonCheck.cpp @@ -44,10 +44,10 @@ void SuspiciousMemoryComparisonCheck::check( for (unsigned int ArgIndex = 0; ArgIndex < 2; ++ArgIndex) { const Expr *ArgExpr = CE->getArg(ArgIndex); - QualType ArgType = ArgExpr->IgnoreImplicit()->getType(); + const QualType ArgType = ArgExpr->IgnoreImplicit()->getType(); const Type *PointeeType = ArgType->getPointeeOrArrayElementType(); assert(PointeeType != nullptr && "PointeeType should always be available."); - QualType PointeeQualifiedType(PointeeType, 0); + const QualType PointeeQualifiedType(PointeeType, 0); if (PointeeType->isRecordType()) { if (const RecordDecl *RD = @@ -65,7 +65,7 @@ void SuspiciousMemoryComparisonCheck::check( } if (!PointeeType->isIncompleteType()) { - uint64_t PointeeSize = Ctx.getTypeSize(PointeeType); + const uint64_t PointeeSize = Ctx.getTypeSize(PointeeType); if (ComparedBits && *ComparedBits >= PointeeSize && !Ctx.hasUniqueObjectRepresentations(PointeeQualifiedType)) { diag(CE->getBeginLoc(), diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp index b1d12ba..63ba2ed 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.cpp @@ -60,7 +60,7 @@ void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) { // Case 1: fill_char of memset() is a character '0'. Probably an // integer zero was intended. - SourceRange CharRange = CharZeroFill->getSourceRange(); + const SourceRange CharRange = CharZeroFill->getSourceRange(); auto Diag = diag(CharZeroFill->getBeginLoc(), "memset fill value is char '0', " "potentially mistaken for int 0"); @@ -70,10 +70,8 @@ void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) { return; Diag << FixItHint::CreateReplacement( CharSourceRange::getTokenRange(CharRange), "0"); - } - - else if (const auto *NumFill = - Result.Nodes.getNodeAs<IntegerLiteral>("num-fill")) { + } else if (const auto *NumFill = + Result.Nodes.getNodeAs<IntegerLiteral>("num-fill")) { // Case 2: fill_char of memset() is larger in size than an unsigned char // so it gets truncated during conversion. @@ -82,15 +80,13 @@ void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) { if (!NumFill->EvaluateAsInt(EVResult, *Result.Context)) return; - llvm::APSInt NumValue = EVResult.Val.getInt(); + const llvm::APSInt NumValue = EVResult.Val.getInt(); if (NumValue >= 0 && NumValue <= UCharMax) return; diag(NumFill->getBeginLoc(), "memset fill value is out of unsigned " "character range, gets truncated"); - } - - else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call")) { + } else if (const auto *Call = Result.Nodes.getNodeAs<CallExpr>("call")) { // Case 3: byte_count of memset() is zero. This is most likely an // argument swap. @@ -110,7 +106,7 @@ void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) { Expr::EvalResult EVResult; if (!FillChar->isValueDependent() && FillChar->EvaluateAsInt(EVResult, *Result.Context)) { - llvm::APSInt Value1 = EVResult.Val.getInt(); + const llvm::APSInt Value1 = EVResult.Val.getInt(); if (Value1 == 0 || Value1.isNegative()) return; } @@ -120,8 +116,10 @@ void SuspiciousMemsetUsageCheck::check(const MatchFinder::MatchResult &Result) { // and fix-its to swap the arguments. auto D = diag(Call->getBeginLoc(), "memset of size zero, potentially swapped arguments"); - StringRef RHSString = tooling::fixit::getText(*ByteCount, *Result.Context); - StringRef LHSString = tooling::fixit::getText(*FillChar, *Result.Context); + const StringRef RHSString = + tooling::fixit::getText(*ByteCount, *Result.Context); + const StringRef LHSString = + tooling::fixit::getText(*FillChar, *Result.Context); if (LHSString.empty() || RHSString.empty()) return; diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h index a1f5f2b..c45f332 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMemsetUsageCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSMEMSETUSAGECHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSMEMSETUSAGECHECK_H #include "../ClangTidyCheck.h" @@ -30,4 +30,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUS_MEMSET_USAGE_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_SUSPICIOUSMEMSETUSAGECHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp index a41f650..4f0d819 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousMissingCommaCheck.cpp @@ -19,7 +19,7 @@ static bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx, // String literals surrounded by parentheses are assumed to be on purpose. // i.e.: const char* Array[] = { ("a" "b" "c"), "d", [...] }; - TraversalKindScope RAII(*Ctx, TK_AsIs); + const TraversalKindScope RAII(*Ctx, TK_AsIs); auto Parents = Ctx->getParents(*Lit); if (Parents.size() == 1 && Parents[0].get<ParenExpr>() != nullptr) return true; @@ -35,15 +35,15 @@ static bool isConcatenatedLiteralsOnPurpose(ASTContext *Ctx, // }; const SourceManager &SM = Ctx->getSourceManager(); bool IndentedCorrectly = true; - SourceLocation FirstToken = Lit->getStrTokenLoc(0); - FileID BaseFID = SM.getFileID(FirstToken); - unsigned int BaseIndent = SM.getSpellingColumnNumber(FirstToken); - unsigned int BaseLine = SM.getSpellingLineNumber(FirstToken); + const SourceLocation FirstToken = Lit->getStrTokenLoc(0); + const FileID BaseFID = SM.getFileID(FirstToken); + const unsigned int BaseIndent = SM.getSpellingColumnNumber(FirstToken); + const unsigned int BaseLine = SM.getSpellingLineNumber(FirstToken); for (unsigned int TokNum = 1; TokNum < Lit->getNumConcatenated(); ++TokNum) { - SourceLocation Token = Lit->getStrTokenLoc(TokNum); - FileID FID = SM.getFileID(Token); - unsigned int Indent = SM.getSpellingColumnNumber(Token); - unsigned int Line = SM.getSpellingLineNumber(Token); + const SourceLocation Token = Lit->getStrTokenLoc(TokNum); + const FileID FID = SM.getFileID(Token); + const unsigned int Indent = SM.getSpellingColumnNumber(Token); + const unsigned int Line = SM.getSpellingLineNumber(Token); if (FID != BaseFID || Line != BaseLine + TokNum || Indent <= BaseIndent) { IndentedCorrectly = false; break; @@ -100,7 +100,7 @@ void SuspiciousMissingCommaCheck::check( assert(InitializerList && ConcatenatedLiteral); // Skip small arrays as they often generate false-positive. - unsigned int Size = InitializerList->getNumInits(); + const unsigned int Size = InitializerList->getNumInits(); if (Size < SizeThreshold) return; @@ -116,7 +116,7 @@ void SuspiciousMissingCommaCheck::check( // Warn only when concatenation is not common in this initializer list. // The current threshold is set to less than 1/5 of the string literals. - if (double(Count) / Size > RatioThreshold) + if (static_cast<double>(Count) / Size > RatioThreshold) return; diag(ConcatenatedLiteral->getBeginLoc(), diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp index b5da801..bf31218 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousReallocUsageCheck.cpp @@ -44,7 +44,7 @@ public: return false; if (!check(E1->getBase(), E2->getBase())) return false; - DeclAccessPair FD = E1->getFoundDecl(); + const DeclAccessPair FD = E1->getFoundDecl(); return isa<FieldDecl>(FD.getDecl()) && FD == E2->getFoundDecl(); } @@ -92,10 +92,9 @@ public: return false; } bool VisitStmt(const Stmt *S) { - for (const Stmt *Child : S->children()) - if (Child && Visit(Child)) - return true; - return false; + return llvm::any_of(S->children(), [this](const Stmt *Child) { + return Child && Visit(Child); + }); } }; @@ -145,7 +144,7 @@ void SuspiciousReallocUsageCheck::check( if (FindAssignToVarBefore{Var, DeclRef, SM}.Visit(Func->getBody())) return; - StringRef CodeOfAssignedExpr = Lexer::getSourceText( + const StringRef CodeOfAssignedExpr = Lexer::getSourceText( CharSourceRange::getTokenRange(PtrResultExpr->getSourceRange()), SM, getLangOpts()); diag(Call->getBeginLoc(), "'%0' may be set to null if 'realloc' fails, which " diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp index 543d312..9d37fc1 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousSemicolonCheck.cpp @@ -31,7 +31,7 @@ void SuspiciousSemicolonCheck::check(const MatchFinder::MatchResult &Result) { return; const auto *Semicolon = Result.Nodes.getNodeAs<NullStmt>("semi"); - SourceLocation LocStart = Semicolon->getBeginLoc(); + const SourceLocation LocStart = Semicolon->getBeginLoc(); if (LocStart.isMacroID()) return; @@ -40,7 +40,7 @@ void SuspiciousSemicolonCheck::check(const MatchFinder::MatchResult &Result) { auto Token = utils::lexer::getPreviousToken(LocStart, Ctxt.getSourceManager(), Ctxt.getLangOpts()); auto &SM = *Result.SourceManager; - unsigned SemicolonLine = SM.getSpellingLineNumber(LocStart); + const unsigned SemicolonLine = SM.getSpellingLineNumber(LocStart); const auto *Statement = Result.Nodes.getNodeAs<Stmt>("stmt"); const bool IsIfStmt = isa<IfStmt>(Statement); @@ -49,18 +49,20 @@ void SuspiciousSemicolonCheck::check(const MatchFinder::MatchResult &Result) { SM.getSpellingLineNumber(Token.getLocation()) != SemicolonLine) return; - SourceLocation LocEnd = Semicolon->getEndLoc(); - FileID FID = SM.getFileID(LocEnd); - llvm::MemoryBufferRef Buffer = SM.getBufferOrFake(FID, LocEnd); + const SourceLocation LocEnd = Semicolon->getEndLoc(); + const FileID FID = SM.getFileID(LocEnd); + const llvm::MemoryBufferRef Buffer = SM.getBufferOrFake(FID, LocEnd); Lexer Lexer(SM.getLocForStartOfFile(FID), Ctxt.getLangOpts(), Buffer.getBufferStart(), SM.getCharacterData(LocEnd) + 1, Buffer.getBufferEnd()); if (Lexer.LexFromRawLexer(Token)) return; - unsigned BaseIndent = SM.getSpellingColumnNumber(Statement->getBeginLoc()); - unsigned NewTokenIndent = SM.getSpellingColumnNumber(Token.getLocation()); - unsigned NewTokenLine = SM.getSpellingLineNumber(Token.getLocation()); + const unsigned BaseIndent = + SM.getSpellingColumnNumber(Statement->getBeginLoc()); + const unsigned NewTokenIndent = + SM.getSpellingColumnNumber(Token.getLocation()); + const unsigned NewTokenLine = SM.getSpellingLineNumber(Token.getLocation()); if (!IsIfStmt && NewTokenIndent <= BaseIndent && Token.getKind() != tok::l_brace && NewTokenLine != SemicolonLine) diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp index 7519685..5da9240 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringCompareCheck.cpp @@ -88,7 +88,7 @@ void SuspiciousStringCompareCheck::registerMatchers(MatchFinder *Finder) { // Add the list of known string compare-like functions and add user-defined // functions. - std::vector<StringRef> FunctionNames = utils::options::parseListPair( + const std::vector<StringRef> FunctionNames = utils::options::parseListPair( KnownStringCompareFunctions, StringCompareLikeFunctions); // Match a call to a string compare functions. @@ -163,7 +163,7 @@ void SuspiciousStringCompareCheck::check( assert(Decl != nullptr && Call != nullptr); if (Result.Nodes.getNodeAs<Stmt>("missing-comparison")) { - SourceLocation EndLoc = Lexer::getLocForEndOfToken( + const SourceLocation EndLoc = Lexer::getLocForEndOfToken( Call->getRParenLoc(), 0, Result.Context->getSourceManager(), getLangOpts()); @@ -173,10 +173,10 @@ void SuspiciousStringCompareCheck::check( } if (const auto *E = Result.Nodes.getNodeAs<Expr>("logical-not-comparison")) { - SourceLocation EndLoc = Lexer::getLocForEndOfToken( + const SourceLocation EndLoc = Lexer::getLocForEndOfToken( Call->getRParenLoc(), 0, Result.Context->getSourceManager(), getLangOpts()); - SourceLocation NotLoc = E->getBeginLoc(); + const SourceLocation NotLoc = E->getBeginLoc(); diag(Call->getBeginLoc(), "function %0 is compared using logical not operator") diff --git a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp index d239cbe..cb37976 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SuspiciousStringviewDataUsageCheck.cpp @@ -43,7 +43,6 @@ SuspiciousStringviewDataUsageCheck::getCheckTraversalKind() const { } void SuspiciousStringviewDataUsageCheck::registerMatchers(MatchFinder *Finder) { - auto AncestorCall = anyOf( cxxConstructExpr(), callExpr(unless(cxxOperatorCallExpr())), lambdaExpr(), initListExpr( diff --git a/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp index bcedff5..152c0cb 100644 --- a/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/SwappedArgumentsCheck.cpp @@ -70,7 +70,7 @@ static bool areArgumentsPotentiallySwapped(const QualType LTo, if (LTo == RFrom && REq) return true; - bool LEq = areTypesSemiEqual(LTo, RFrom); + const bool LEq = areTypesSemiEqual(LTo, RFrom); if (RTo == LFrom && LEq) return true; diff --git a/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp index a85a136..c0d38dc 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TaggedUnionMemberCountCheck.cpp @@ -104,7 +104,6 @@ void TaggedUnionMemberCountCheck::storeOptions( } void TaggedUnionMemberCountCheck::registerMatchers(MatchFinder *Finder) { - auto NotFromSystemHeaderOrStdNamespace = unless(anyOf(isExpansionInSystemHeader(), isInStdNamespace())); diff --git a/clang-tools-extra/clang-tidy/bugprone/ThrowingStaticInitializationCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/ThrowingStaticInitializationCheck.cpp index 56ec5a5..80905e2 100644 --- a/clang-tools-extra/clang-tidy/bugprone/ThrowingStaticInitializationCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/ThrowingStaticInitializationCheck.cpp @@ -44,7 +44,7 @@ void ThrowingStaticInitializationCheck::check( "duration may throw an exception that cannot be caught") << VD << (VD->getStorageDuration() == SD_Static ? 0 : 1); - SourceLocation FuncLocation = Func->getLocation(); + const SourceLocation FuncLocation = Func->getLocation(); if (FuncLocation.isValid()) { diag(FuncLocation, "possibly throwing %select{constructor|function}0 declared here", diff --git a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp index 536b680..71b785f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/TooSmallLoopVariableCheck.cpp @@ -67,21 +67,21 @@ void TooSmallLoopVariableCheck::storeOptions( /// LoopName: The entire for loop (as a ForStmt) /// void TooSmallLoopVariableCheck::registerMatchers(MatchFinder *Finder) { - StatementMatcher LoopVarMatcher = + const StatementMatcher LoopVarMatcher = expr(ignoringParenImpCasts( anyOf(declRefExpr(to(varDecl(hasType(isInteger())))), memberExpr(member(fieldDecl(hasType(isInteger()))))))) .bind(LoopVarName); // We need to catch only those comparisons which contain any integer cast. - StatementMatcher LoopVarConversionMatcher = traverse( + const StatementMatcher LoopVarConversionMatcher = traverse( TK_AsIs, implicitCastExpr(hasImplicitDestinationType(isInteger()), has(ignoringParenImpCasts(LoopVarMatcher))) .bind(LoopVarCastName)); // We are interested in only those cases when the loop bound is a variable // value (not const, enum, etc.). - StatementMatcher LoopBoundMatcher = + const StatementMatcher LoopBoundMatcher = expr(ignoringParenImpCasts(allOf( hasType(isInteger()), unless(integerLiteral()), unless(allOf( @@ -94,7 +94,7 @@ void TooSmallLoopVariableCheck::registerMatchers(MatchFinder *Finder) { // We use the loop increment expression only to make sure we found the right // loop variable. - StatementMatcher IncrementMatcher = + const StatementMatcher IncrementMatcher = expr(ignoringParenImpCasts(hasType(isInteger()))).bind(LoopIncrementName); Finder->addMatcher( @@ -121,14 +121,14 @@ static MagnitudeBits calcMagnitudeBits(const ASTContext &Context, const Expr *IntExpr) { assert(IntExprType->isIntegerType()); - unsigned SignedBits = IntExprType->isUnsignedIntegerType() ? 0U : 1U; + const unsigned SignedBits = IntExprType->isUnsignedIntegerType() ? 0U : 1U; if (const auto *BitField = IntExpr->getSourceBitField()) { - unsigned BitFieldWidth = BitField->getBitWidthValue(); + const unsigned BitFieldWidth = BitField->getBitWidthValue(); return {BitFieldWidth - SignedBits, BitFieldWidth}; } - unsigned IntWidth = Context.getIntWidth(IntExprType); + const unsigned IntWidth = Context.getIntWidth(IntExprType); return {IntWidth - SignedBits, 0U}; } @@ -143,18 +143,18 @@ calcUpperBoundMagnitudeBits(const ASTContext &Context, const Expr *UpperBound, const Expr *RHSE = BinOperator->getRHS()->IgnoreParenImpCasts(); const Expr *LHSE = BinOperator->getLHS()->IgnoreParenImpCasts(); - QualType RHSEType = RHSE->getType(); - QualType LHSEType = LHSE->getType(); + const QualType RHSEType = RHSE->getType(); + const QualType LHSEType = LHSE->getType(); if (!RHSEType->isIntegerType() || !LHSEType->isIntegerType()) return {}; - bool RHSEIsConstantValue = RHSEType->isEnumeralType() || - RHSEType.isConstQualified() || - isa<IntegerLiteral>(RHSE); - bool LHSEIsConstantValue = LHSEType->isEnumeralType() || - LHSEType.isConstQualified() || - isa<IntegerLiteral>(LHSE); + const bool RHSEIsConstantValue = RHSEType->isEnumeralType() || + RHSEType.isConstQualified() || + isa<IntegerLiteral>(RHSE); + const bool LHSEIsConstantValue = LHSEType->isEnumeralType() || + LHSEType.isConstQualified() || + isa<IntegerLiteral>(LHSE); // Avoid false positives produced by two constant values. if (RHSEIsConstantValue && LHSEIsConstantValue) @@ -193,7 +193,7 @@ void TooSmallLoopVariableCheck::check(const MatchFinder::MatchResult &Result) { if (LoopVar->getType() != LoopIncrement->getType()) return; - ASTContext &Context = *Result.Context; + const ASTContext &Context = *Result.Context; const QualType LoopVarType = LoopVar->getType(); const MagnitudeBits LoopVarMagnitudeBits = diff --git a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h index 11086fb..62bf42d 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UncheckedOptionalAccessCheck.h @@ -25,7 +25,8 @@ class UncheckedOptionalAccessCheck : public ClangTidyCheck { public: UncheckedOptionalAccessCheck(StringRef Name, ClangTidyContext *Context) : ClangTidyCheck(Name, Context), - ModelOptions{Options.get("IgnoreSmartPointerDereference", false)} {} + ModelOptions{Options.get("IgnoreSmartPointerDereference", false), + Options.get("IgnoreValueCalls", false)} {} void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { @@ -34,6 +35,7 @@ public: void storeOptions(ClangTidyOptions::OptionMap &Opts) override { Options.store(Opts, "IgnoreSmartPointerDereference", ModelOptions.IgnoreSmartPointerDereference); + Options.store(Opts, "IgnoreValueCalls", ModelOptions.IgnoreValueCalls); } private: diff --git a/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp index d0bf72b..b82c9d3 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UncheckedStringToNumberConversionCheck.cpp @@ -76,7 +76,8 @@ static ConversionKind classifyFormatString(StringRef Fmt, const LangOptions &LO, // Get the conversion specifier and use it to determine the conversion // kind. - analyze_scanf::ScanfConversionSpecifier SCS = FS.getConversionSpecifier(); + const analyze_scanf::ScanfConversionSpecifier SCS = + FS.getConversionSpecifier(); if (SCS.isIntArg()) { switch (FS.getLengthModifier().getKind()) { case analyze_scanf::LengthModifier::AsLongLong: @@ -194,7 +195,7 @@ void UncheckedStringToNumberConversionCheck::check( // The format string comes from the call expression and depends on which // flavor of scanf is called. // Index 0: scanf, vscanf, Index 1: fscanf, sscanf, vfscanf, vsscanf. - unsigned Idx = + const unsigned Idx = (FFD->getName() == "scanf" || FFD->getName() == "vscanf") ? 0 : 1; // Given the index, see if the call expression argument at that index is diff --git a/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h b/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h index c9a232a..409122f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UndefinedMemoryManipulationCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINEDMEMORYMANIPULATIONCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINEDMEMORYMANIPULATIONCHECK_H #include "../ClangTidyCheck.h" @@ -29,4 +29,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINED_MEMORY_MANIPULATION_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDEFINEDMEMORYMANIPULATIONCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.h b/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.h index 18465f7..c7cadbf6 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UndelegatedConstructorCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNDELEGATEDCONSTRUCTOR_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNDELEGATEDCONSTRUCTOR_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDELEGATEDCONSTRUCTORCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDELEGATEDCONSTRUCTORCHECK_H #include "../ClangTidyCheck.h" @@ -31,4 +31,4 @@ public: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNDELEGATEDCONSTRUCTOR_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNDELEGATEDCONSTRUCTORCHECK_H diff --git a/clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp index bf30753..340b136 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnhandledExceptionAtNewCheck.cpp @@ -16,7 +16,8 @@ namespace { AST_MATCHER_P(CXXTryStmt, hasHandlerFor, ast_matchers::internal::Matcher<QualType>, InnerMatcher) { - for (unsigned NH = Node.getNumHandlers(), I = 0; I < NH; ++I) { + const unsigned NH = Node.getNumHandlers(); + for (unsigned I = 0; I < NH; ++I) { const CXXCatchStmt *CatchS = Node.getHandler(I); // Check for generic catch handler (match anything). if (CatchS->getCaughtType().isNull()) @@ -31,7 +32,7 @@ AST_MATCHER_P(CXXTryStmt, hasHandlerFor, } AST_MATCHER(CXXNewExpr, mayThrow) { - FunctionDecl *OperatorNew = Node.getOperatorNew(); + const FunctionDecl *OperatorNew = Node.getOperatorNew(); if (!OperatorNew) return false; return !OperatorNew->getType()->castAs<FunctionProtoType>()->isNothrow(); diff --git a/clang-tools-extra/clang-tidy/bugprone/UnintendedCharOstreamOutputCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnintendedCharOstreamOutputCheck.cpp index bce4657..e10b17c 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnintendedCharOstreamOutputCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnintendedCharOstreamOutputCheck.cpp @@ -80,17 +80,17 @@ void UnintendedCharOstreamOutputCheck::check( const Expr *Value = Call->getArg(1); const SourceRange SourceRange = Value->getSourceRange(); - DiagnosticBuilder Builder = + const DiagnosticBuilder Builder = diag(Call->getOperatorLoc(), "%0 passed to 'operator<<' outputs as character instead of integer. " "cast to 'unsigned int' to print numeric value or cast to 'char' to " "print as character") << Value->getType() << SourceRange; - QualType T = Value->getType(); + const QualType T = Value->getType(); const Type *UnqualifiedDesugaredType = T->getUnqualifiedDesugaredType(); - llvm::StringRef CastType = CastTypeName.value_or( + const llvm::StringRef CastType = CastTypeName.value_or( UnqualifiedDesugaredType->isSpecificBuiltinType(BuiltinType::SChar) ? "int" : "unsigned int"); diff --git a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp index 61ccd26..0a7467a 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnsafeFunctionsCheck.cpp @@ -141,7 +141,7 @@ parseCheckedFunctions(StringRef Option, ClangTidyContext *Context) { std::vector<UnsafeFunctionsCheck::CheckedFunction> Result; Result.reserve(Functions.size()); - for (StringRef Function : Functions) { + for (const StringRef Function : Functions) { if (Function.empty()) continue; @@ -266,8 +266,8 @@ void UnsafeFunctionsCheck::registerMatchers(MatchFinder *Finder) { } void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) { - const Expr *SourceExpr; - const FunctionDecl *FuncDecl; + const Expr *SourceExpr = nullptr; + const FunctionDecl *FuncDecl = nullptr; if (const auto *DeclRef = Result.Nodes.getNodeAs<DeclRefExpr>(DeclRefId)) { SourceExpr = DeclRef; @@ -304,11 +304,17 @@ void UnsafeFunctionsCheck::check(const MatchFinder::MatchResult &Result) { StringRef Reason = Entry.Reason.empty() ? "is marked as unsafe" : Entry.Reason.c_str(); - if (Entry.Replacement.empty()) { + // Omit the replacement, when a fully-custom reason is given. + if (Reason.consume_front(">")) { + diag(SourceExpr->getExprLoc(), "function %0 %1") + << FuncDecl << Reason.trim() << SourceExpr->getSourceRange(); + // Do not recommend a replacement when it is not present. + } else if (Entry.Replacement.empty()) { diag(SourceExpr->getExprLoc(), "function %0 %1; it should not be used") << FuncDecl << Reason << Entry.Replacement << SourceExpr->getSourceRange(); + // Otherwise, emit the replacement. } else { diag(SourceExpr->getExprLoc(), "function %0 %1; '%2' should be used instead") diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp index dae679b..6502fc9 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedRaiiCheck.cpp @@ -37,8 +37,8 @@ void UnusedRaiiCheck::registerMatchers(MatchFinder *Finder) { } template <typename T> -static void reportDiagnostic(DiagnosticBuilder D, const T *Node, SourceRange SR, - bool DefaultConstruction) { +static void reportDiagnostic(const DiagnosticBuilder &D, const T *Node, + SourceRange SR, bool DefaultConstruction) { const char *Replacement = " give_me_a_name"; // If this is a default ctor we have to remove the parens or we'll introduce a diff --git a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp index c2fc4af..6fbd392 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UnusedReturnValueCheck.cpp @@ -25,7 +25,8 @@ namespace { // member function are matched directly with InnerMatcher. AST_MATCHER_P(FunctionDecl, isInstantiatedFrom, Matcher<FunctionDecl>, InnerMatcher) { - FunctionDecl *InstantiatedFrom = Node.getInstantiatedFromMemberFunction(); + const FunctionDecl *InstantiatedFrom = + Node.getInstantiatedFromMemberFunction(); return InnerMatcher.matches(InstantiatedFrom ? *InstantiatedFrom : Node, Finder, Builder); } diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp index efb5ec6..b2e08fe 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp @@ -19,6 +19,7 @@ #include "../utils/ExprSequence.h" #include "../utils/Matchers.h" +#include "../utils/OptionsUtils.h" #include <optional> using namespace clang::ast_matchers; @@ -48,7 +49,8 @@ struct UseAfterMove { /// various internal helper functions). class UseAfterMoveFinder { public: - UseAfterMoveFinder(ASTContext *TheContext); + UseAfterMoveFinder(ASTContext *TheContext, + llvm::ArrayRef<StringRef> InvalidationFunctions); // Within the given code block, finds the first use of 'MovedVariable' that // occurs after 'MovingCall' (the expression that performs the move). If a @@ -71,6 +73,7 @@ private: llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs); ASTContext *Context; + llvm::ArrayRef<StringRef> InvalidationFunctions; std::unique_ptr<ExprSequence> Sequence; std::unique_ptr<StmtToBlockMap> BlockMap; llvm::SmallPtrSet<const CFGBlock *, 8> Visited; @@ -78,6 +81,11 @@ private: } // namespace +static auto getNameMatcher(llvm::ArrayRef<StringRef> InvalidationFunctions) { + return anyOf(hasAnyName("::std::move", "::std::forward"), + matchers::matchesAnyListedName(InvalidationFunctions)); +} + // Matches nodes that are // - Part of a decltype argument or class template argument (we check this by // seeing if they are children of a TypeLoc), or @@ -92,8 +100,9 @@ static StatementMatcher inDecltypeOrTemplateArg() { hasAncestor(expr(hasUnevaluatedContext()))); } -UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext) - : Context(TheContext) {} +UseAfterMoveFinder::UseAfterMoveFinder( + ASTContext *TheContext, llvm::ArrayRef<StringRef> InvalidationFunctions) + : Context(TheContext), InvalidationFunctions(InvalidationFunctions) {} std::optional<UseAfterMove> UseAfterMoveFinder::find(Stmt *CodeBlock, const Expr *MovingCall, @@ -255,7 +264,7 @@ static bool isStandardSmartPointer(const ValueDecl *VD) { if (!ID) return false; - StringRef Name = ID->getName(); + const StringRef Name = ID->getName(); if (Name != "unique_ptr" && Name != "shared_ptr" && Name != "weak_ptr") return false; @@ -359,7 +368,7 @@ void UseAfterMoveFinder::getReinits( unless(parmVarDecl(hasType( references(qualType(isConstQualified())))))), unless(callee(functionDecl( - hasAnyName("::std::move", "::std::forward"))))))) + getNameMatcher(InvalidationFunctions))))))) .bind("reinit"); Stmts->clear(); @@ -369,7 +378,7 @@ void UseAfterMoveFinder::getReinits( if (!S) continue; - SmallVector<BoundNodes, 1> Matches = + const SmallVector<BoundNodes, 1> Matches = match(findAll(ReinitMatcher), *S->getStmt(), *Context); for (const auto &Match : Matches) { @@ -388,18 +397,21 @@ void UseAfterMoveFinder::getReinits( } } -enum class MoveType { - Move, // std::move - Forward, // std::forward +enum MoveType { + Forward = 0, // std::forward + Move = 1, // std::move + Invalidation = 2, // other }; static MoveType determineMoveType(const FunctionDecl *FuncDecl) { - if (FuncDecl->getName() == "move") - return MoveType::Move; - if (FuncDecl->getName() == "forward") - return MoveType::Forward; + if (FuncDecl->isInStdNamespace()) { + if (FuncDecl->getName() == "move") + return MoveType::Move; + if (FuncDecl->getName() == "forward") + return MoveType::Forward; + } - llvm_unreachable("Invalid move type"); + return MoveType::Invalidation; } static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg, @@ -408,29 +420,38 @@ static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg, const SourceLocation UseLoc = Use.DeclRef->getExprLoc(); const SourceLocation MoveLoc = MovingCall->getExprLoc(); - const bool IsMove = (Type == MoveType::Move); - - Check->diag(UseLoc, "'%0' used after it was %select{forwarded|moved}1") - << MoveArg->getDecl()->getName() << IsMove; - Check->diag(MoveLoc, "%select{forward|move}0 occurred here", + Check->diag(UseLoc, + "'%0' used after it was %select{forwarded|moved|invalidated}1") + << MoveArg->getDecl()->getName() << Type; + Check->diag(MoveLoc, "%select{forward|move|invalidation}0 occurred here", DiagnosticIDs::Note) - << IsMove; + << Type; if (Use.EvaluationOrderUndefined) { Check->diag( UseLoc, - "the use and %select{forward|move}0 are unsequenced, i.e. " + "the use and %select{forward|move|invalidation}0 are unsequenced, i.e. " "there is no guarantee about the order in which they are evaluated", DiagnosticIDs::Note) - << IsMove; + << Type; } else if (Use.UseHappensInLaterLoopIteration) { Check->diag(UseLoc, "the use happens in a later loop iteration than the " - "%select{forward|move}0", + "%select{forward|move|invalidation}0", DiagnosticIDs::Note) - << IsMove; + << Type; } } +UseAfterMoveCheck::UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + InvalidationFunctions(utils::options::parseStringList( + Options.get("InvalidationFunctions", ""))) {} + +void UseAfterMoveCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "InvalidationFunctions", + utils::options::serializeStringList(InvalidationFunctions)); +} + void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) { // try_emplace is a common maybe-moving function that returns a // bool to tell callers whether it moved. Ignore std::move inside @@ -438,11 +459,14 @@ void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) { // the bool. auto TryEmplaceMatcher = cxxMemberCallExpr(callee(cxxMethodDecl(hasName("try_emplace")))); + auto Arg = declRefExpr().bind("arg"); + auto IsMemberCallee = callee(functionDecl(unless(isStaticStorageClass()))); auto CallMoveMatcher = - callExpr(argumentCountIs(1), - callee(functionDecl(hasAnyName("::std::move", "::std::forward")) + callExpr(callee(functionDecl(getNameMatcher(InvalidationFunctions)) .bind("move-decl")), - hasArgument(0, declRefExpr().bind("arg")), + anyOf(cxxMemberCallExpr(IsMemberCallee, on(Arg)), + callExpr(unless(cxxMemberCallExpr(IsMemberCallee)), + hasArgument(0, Arg))), unless(inDecltypeOrTemplateArg()), unless(hasParent(TryEmplaceMatcher)), expr().bind("call-move"), anyOf(hasAncestor(compoundStmt( @@ -506,7 +530,7 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) { if (ContainingCtorInit) { // Collect the constructor initializer expressions. bool BeforeMove{true}; - for (CXXCtorInitializer *Init : ContainingCtor->inits()) { + for (const CXXCtorInitializer *Init : ContainingCtor->inits()) { if (BeforeMove && Init->getInit()->IgnoreImplicit() == ContainingCtorInit->IgnoreImplicit()) BeforeMove = false; @@ -521,7 +545,7 @@ void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) { } for (Stmt *CodeBlock : CodeBlocks) { - UseAfterMoveFinder Finder(Result.Context); + UseAfterMoveFinder Finder(Result.Context, InvalidationFunctions); if (auto Use = Finder.find(CodeBlock, MovingCall, Arg)) emitDiagnostic(MovingCall, Arg, *Use, this, Result.Context, determineMoveType(MoveDecl)); diff --git a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h index d38b29e..1bbf5c0 100644 --- a/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.h @@ -20,13 +20,16 @@ namespace clang::tidy::bugprone { /// https://clang.llvm.org/extra/clang-tidy/checks/bugprone/use-after-move.html class UseAfterMoveCheck : public ClangTidyCheck { public: - UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context) - : ClangTidyCheck(Name, Context) {} + UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; bool isLanguageVersionSupported(const LangOptions &LangOpts) const override { return LangOpts.CPlusPlus11; } void registerMatchers(ast_matchers::MatchFinder *Finder) override; void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + std::vector<StringRef> InvalidationFunctions; }; } // namespace clang::tidy::bugprone diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp index cef8b4d..0d69b9f 100644 --- a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp +++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.cpp @@ -37,14 +37,14 @@ static bool isOverrideMethod(const CXXMethodDecl *MD) { static bool checkOverridingFunctionReturnType(const ASTContext *Context, const CXXMethodDecl *BaseMD, const CXXMethodDecl *DerivedMD) { - QualType BaseReturnTy = BaseMD->getType() - ->castAs<FunctionType>() - ->getReturnType() - .getCanonicalType(); - QualType DerivedReturnTy = DerivedMD->getType() - ->castAs<FunctionType>() - ->getReturnType() - .getCanonicalType(); + const QualType BaseReturnTy = BaseMD->getType() + ->castAs<FunctionType>() + ->getReturnType() + .getCanonicalType(); + const QualType DerivedReturnTy = DerivedMD->getType() + ->castAs<FunctionType>() + ->getReturnType() + .getCanonicalType(); if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType()) return false; @@ -63,8 +63,8 @@ static bool checkOverridingFunctionReturnType(const ASTContext *Context, /// BTy is the class type in return type of BaseMD. For example, /// B* Base::md() /// While BRD is the declaration of B. - QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType(); - QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType(); + const QualType DTy = DerivedReturnTy->getPointeeType().getCanonicalType(); + const QualType BTy = BaseReturnTy->getPointeeType().getCanonicalType(); const CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl(); const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl(); @@ -94,7 +94,7 @@ static bool checkOverridingFunctionReturnType(const ASTContext *Context, // Check accessibility. // FIXME: We currently only support checking if B is accessible base class // of D, or D is the same class which DerivedMD is in. - bool IsItself = + const bool IsItself = DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl(); bool HasPublicAccess = false; for (const auto &Path : Paths) { @@ -129,8 +129,8 @@ static QualType getDecayedType(QualType Type) { /// \returns true if the param types are the same. static bool checkParamTypes(const CXXMethodDecl *BaseMD, const CXXMethodDecl *DerivedMD) { - unsigned NumParamA = BaseMD->getNumParams(); - unsigned NumParamB = DerivedMD->getNumParams(); + const unsigned NumParamA = BaseMD->getNumParams(); + const unsigned NumParamB = DerivedMD->getNumParams(); if (NumParamA != NumParamB) return false; @@ -184,10 +184,10 @@ bool VirtualNearMissCheck::isPossibleToBeOverridden( if (!Inserted) return Iter->second; - bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) && - !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() && - !BaseMD->isOverloadedOperator() && - !isa<CXXConversionDecl>(BaseMD); + const bool IsPossible = + !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) && + !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() && + !BaseMD->isOverloadedOperator() && !isa<CXXConversionDecl>(BaseMD); Iter->second = IsPossible; return IsPossible; } @@ -241,7 +241,7 @@ void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) { if (isOverriddenByDerivedClass(BaseMD, DerivedRD)) continue; - unsigned EditDistance = BaseMD->getName().edit_distance( + const unsigned EditDistance = BaseMD->getName().edit_distance( DerivedMD->getName(), EditDistanceThreshold); if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) { if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) { @@ -249,8 +249,8 @@ void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) { auto Range = CharSourceRange::getTokenRange( SourceRange(DerivedMD->getLocation())); - bool ApplyFix = !BaseMD->isTemplateInstantiation() && - !DerivedMD->isTemplateInstantiation(); + const bool ApplyFix = !BaseMD->isTemplateInstantiation() && + !DerivedMD->isTemplateInstantiation(); auto Diag = diag(DerivedMD->getBeginLoc(), "method '%0' has a similar name and the same signature as " diff --git a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h index 71d302f4..2278817 100644 --- a/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h +++ b/clang-tools-extra/clang-tidy/bugprone/VirtualNearMissCheck.h @@ -6,8 +6,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H -#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUALNEARMISSCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUALNEARMISSCHECK_H #include "../ClangTidyCheck.h" #include "llvm/ADT/DenseMap.h" @@ -60,4 +60,4 @@ private: } // namespace clang::tidy::bugprone -#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUAL_NEAR_MISS_H +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_VIRTUALNEARMISSCHECK_H |
