summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/misc
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2017-11-24 14:16:29 +0000
committerAlexander Kornienko <alexfh@google.com>2017-11-24 14:16:29 +0000
commitd4ac4afda75c9ef174e85eea7f40a6ae6cc50ab4 (patch)
treec43c0be034454ea297f0ccdc84302e9636abed63 /clang-tools-extra/clang-tidy/misc
parent70cdb5b3914803ca89a96a867a47936d049a4b32 (diff)
downloadbcm5719-llvm-d4ac4afda75c9ef174e85eea7f40a6ae6cc50ab4.tar.gz
bcm5719-llvm-d4ac4afda75c9ef174e85eea7f40a6ae6cc50ab4.zip
[clang-tidy] Move a few more checks from misc to bugprone.
Summary: clang_tidy/rename_check.py misc-assert-side-effect bugprone-assert-side-effect clang_tidy/rename_check.py misc-bool-pointer-implicit-conversion bugprone-bool-pointer-implicit-conversion clang_tidy/rename_check.py misc-fold-init-type bugprone-fold-init-type clang_tidy/rename_check.py misc-forward-declaration-namespace bugprone-forward-declaration-namespace clang_tidy/rename_check.py misc-inaccurate-erase bugprone-inaccurate-erase clang_tidy/rename_check.py misc-move-forwarding-reference bugprone-move-forwarding-reference clang_tidy/rename_check.py misc-multiple-statement-macro bugprone-multiple-statement-macro clang_tidy/rename_check.py misc-use-after-move bugprone-use-after-move clang_tidy/rename_check.py misc-virtual-near-miss bugprone-virtual-near-miss Manually fixed a reference to UseAfterMoveCheck in the hicpp module. Manually fixed header guards. Reviewers: hokein Reviewed By: hokein Subscribers: nemanjai, mgorny, javed.absar, xazax.hun, kbarton, cfe-commits Differential Revision: https://reviews.llvm.org/D40426 llvm-svn: 318950
Diffstat (limited to 'clang-tools-extra/clang-tidy/misc')
-rw-r--r--clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.cpp127
-rw-r--r--clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.h52
-rw-r--r--clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.cpp73
-rw-r--r--clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.h42
-rw-r--r--clang-tools-extra/clang-tidy/misc/CMakeLists.txt9
-rw-r--r--clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.cpp140
-rw-r--r--clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.h44
-rw-r--r--clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp174
-rw-r--r--clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h59
-rw-r--r--clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.cpp81
-rw-r--r--clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.h38
-rw-r--r--clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp24
-rw-r--r--clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.cpp133
-rw-r--r--clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.h49
-rw-r--r--clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.cpp106
-rw-r--r--clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.h37
-rw-r--r--clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp434
-rw-r--r--clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.h36
-rw-r--r--clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp274
-rw-r--r--clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.h65
20 files changed, 0 insertions, 1997 deletions
diff --git a/clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.cpp b/clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.cpp
deleted file mode 100644
index 0b63c0d33a4..00000000000
--- a/clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
-//===--- AssertSideEffectCheck.cpp - clang-tidy ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "AssertSideEffectCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Lex/Lexer.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Casting.h"
-#include <algorithm>
-#include <string>
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-namespace {
-
-AST_MATCHER_P(Expr, hasSideEffect, bool, CheckFunctionCalls) {
- const Expr *E = &Node;
-
- if (const auto *Op = dyn_cast<UnaryOperator>(E)) {
- UnaryOperator::Opcode OC = Op->getOpcode();
- return OC == UO_PostInc || OC == UO_PostDec || OC == UO_PreInc ||
- OC == UO_PreDec;
- }
-
- if (const auto *Op = dyn_cast<BinaryOperator>(E)) {
- return Op->isAssignmentOp();
- }
-
- if (const auto *OpCallExpr = dyn_cast<CXXOperatorCallExpr>(E)) {
- OverloadedOperatorKind OpKind = OpCallExpr->getOperator();
- return OpKind == OO_Equal || OpKind == OO_PlusEqual ||
- OpKind == OO_MinusEqual || OpKind == OO_StarEqual ||
- OpKind == OO_SlashEqual || OpKind == OO_AmpEqual ||
- OpKind == OO_PipeEqual || OpKind == OO_CaretEqual ||
- OpKind == OO_LessLessEqual || OpKind == OO_GreaterGreaterEqual ||
- OpKind == OO_PlusPlus || OpKind == OO_MinusMinus ||
- OpKind == OO_PercentEqual || OpKind == OO_New ||
- OpKind == OO_Delete || OpKind == OO_Array_New ||
- OpKind == OO_Array_Delete;
- }
-
- if (const auto *CExpr = dyn_cast<CallExpr>(E)) {
- bool Result = CheckFunctionCalls;
- if (const auto *FuncDecl = CExpr->getDirectCallee()) {
- if (FuncDecl->getDeclName().isIdentifier() &&
- FuncDecl->getName() == "__builtin_expect") // exceptions come here
- Result = false;
- else if (const auto *MethodDecl = dyn_cast<CXXMethodDecl>(FuncDecl))
- Result &= !MethodDecl->isConst();
- }
- return Result;
- }
-
- return isa<CXXNewExpr>(E) || isa<CXXDeleteExpr>(E) || isa<CXXThrowExpr>(E);
-}
-
-} // namespace
-
-AssertSideEffectCheck::AssertSideEffectCheck(StringRef Name,
- ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context),
- CheckFunctionCalls(Options.get("CheckFunctionCalls", false)),
- RawAssertList(Options.get("AssertMacros", "assert")) {
- StringRef(RawAssertList).split(AssertMacros, ",", -1, false);
-}
-
-// The options are explained in AssertSideEffectCheck.h.
-void AssertSideEffectCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
- Options.store(Opts, "CheckFunctionCalls", CheckFunctionCalls);
- Options.store(Opts, "AssertMacros", RawAssertList);
-}
-
-void AssertSideEffectCheck::registerMatchers(MatchFinder *Finder) {
- auto DescendantWithSideEffect =
- hasDescendant(expr(hasSideEffect(CheckFunctionCalls)));
- auto ConditionWithSideEffect = hasCondition(DescendantWithSideEffect);
- Finder->addMatcher(
- stmt(
- anyOf(conditionalOperator(ConditionWithSideEffect),
- ifStmt(ConditionWithSideEffect),
- unaryOperator(hasOperatorName("!"),
- hasUnaryOperand(unaryOperator(
- hasOperatorName("!"),
- hasUnaryOperand(DescendantWithSideEffect))))))
- .bind("condStmt"),
- this);
-}
-
-void AssertSideEffectCheck::check(const MatchFinder::MatchResult &Result) {
- const SourceManager &SM = *Result.SourceManager;
- const LangOptions LangOpts = getLangOpts();
- SourceLocation Loc = Result.Nodes.getNodeAs<Stmt>("condStmt")->getLocStart();
-
- StringRef AssertMacroName;
- while (Loc.isValid() && Loc.isMacroID()) {
- StringRef MacroName = Lexer::getImmediateMacroName(Loc, SM, LangOpts);
-
- // Check if this macro is an assert.
- if (std::find(AssertMacros.begin(), AssertMacros.end(), MacroName) !=
- AssertMacros.end()) {
- AssertMacroName = MacroName;
- break;
- }
- Loc = SM.getImmediateMacroCallerLoc(Loc);
- }
- if (AssertMacroName.empty())
- return;
-
- diag(Loc, "found %0() with side effect") << AssertMacroName;
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.h b/clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.h
deleted file mode 100644
index 2bb25e2d4a4..00000000000
--- a/clang-tools-extra/clang-tidy/misc/AssertSideEffectCheck.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//===--- AssertSideEffectCheck.h - clang-tidy -------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSERTSIDEEFFECTCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSERTSIDEEFFECTCHECK_H
-
-#include "../ClangTidy.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
-#include <string>
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// Finds `assert()` with side effect.
-///
-/// The condition of `assert()` is evaluated only in debug builds so a
-/// condition with side effect can cause different behavior in debug / release
-/// builds.
-///
-/// There are two options:
-///
-/// - `AssertMacros`: A comma-separated list of the names of assert macros to
-/// be checked.
-/// - `CheckFunctionCalls`: Whether to treat non-const member and non-member
-/// functions as they produce side effects. Disabled by default because it
-/// can increase the number of false positive warnings.
-class AssertSideEffectCheck : public ClangTidyCheck {
-public:
- AssertSideEffectCheck(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:
- const bool CheckFunctionCalls;
- const std::string RawAssertList;
- SmallVector<StringRef, 5> AssertMacros;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSERTSIDEEFFECTCHECK_H
diff --git a/clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.cpp b/clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.cpp
deleted file mode 100644
index f831125838d..00000000000
--- a/clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.cpp
+++ /dev/null
@@ -1,73 +0,0 @@
-//===--- BoolPointerImplicitConversionCheck.cpp - clang-tidy --------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "BoolPointerImplicitConversionCheck.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-void BoolPointerImplicitConversionCheck::registerMatchers(MatchFinder *Finder) {
- // Look for ifs that have an implicit bool* to bool conversion in the
- // condition. Filter negations.
- Finder->addMatcher(
- ifStmt(hasCondition(findAll(implicitCastExpr(
- allOf(unless(hasParent(unaryOperator(hasOperatorName("!")))),
- hasSourceExpression(expr(
- hasType(pointerType(pointee(booleanType()))),
- ignoringParenImpCasts(declRefExpr().bind("expr")))),
- hasCastKind(CK_PointerToBoolean))))),
- unless(isInTemplateInstantiation()))
- .bind("if"),
- this);
-}
-
-void BoolPointerImplicitConversionCheck::check(
- const MatchFinder::MatchResult &Result) {
- auto *If = Result.Nodes.getNodeAs<IfStmt>("if");
- auto *Var = Result.Nodes.getNodeAs<DeclRefExpr>("expr");
-
- // Ignore macros.
- if (Var->getLocStart().isMacroID())
- return;
-
- // Only allow variable accesses for now, no function calls or member exprs.
- // Check that we don't dereference the variable anywhere within the if. This
- // avoids false positives for checks of the pointer for nullptr before it is
- // dereferenced. If there is a dereferencing operator on this variable don't
- // emit a diagnostic. Also ignore array subscripts.
- const Decl *D = Var->getDecl();
- auto DeclRef = ignoringParenImpCasts(declRefExpr(to(equalsNode(D))));
- if (!match(findAll(
- unaryOperator(hasOperatorName("*"), hasUnaryOperand(DeclRef))),
- *If, *Result.Context)
- .empty() ||
- !match(findAll(arraySubscriptExpr(hasBase(DeclRef))), *If,
- *Result.Context)
- .empty() ||
- // FIXME: We should still warn if the paremater is implicitly converted to
- // bool.
- !match(findAll(callExpr(hasAnyArgument(ignoringParenImpCasts(DeclRef)))),
- *If, *Result.Context)
- .empty() ||
- !match(findAll(cxxDeleteExpr(has(ignoringParenImpCasts(expr(DeclRef))))),
- *If, *Result.Context)
- .empty())
- return;
-
- diag(Var->getLocStart(), "dubious check of 'bool *' against 'nullptr', did "
- "you mean to dereference it?")
- << FixItHint::CreateInsertion(Var->getLocStart(), "*");
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.h b/clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.h
deleted file mode 100644
index d8a90f35729..00000000000
--- a/clang-tools-extra/clang-tidy/misc/BoolPointerImplicitConversionCheck.h
+++ /dev/null
@@ -1,42 +0,0 @@
-//===--- BoolPointerImplicitConversionCheck.h - clang-tidy ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
-
-#include "../ClangTidy.h"
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// Checks for conditions based on implicit conversion from a bool pointer to
-/// bool.
-///
-/// Example:
-///
-/// \code
-/// bool *p;
-/// if (p) {
-/// // Never used in a pointer-specific way.
-/// }
-/// \endcode
-class BoolPointerImplicitConversionCheck : public ClangTidyCheck {
-public:
- BoolPointerImplicitConversionCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_BOOLPOINTERIMPLICITCONVERSIONCHECK_H
diff --git a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
index f67c1365949..8a4dcbd5638 100644
--- a/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -1,16 +1,11 @@
set(LLVM_LINK_COMPONENTS support)
add_clang_library(clangTidyMiscModule
- AssertSideEffectCheck.cpp
ForwardingReferenceOverloadCheck.cpp
LambdaFunctionNameCheck.cpp
MisplacedConstCheck.cpp
UnconventionalAssignOperatorCheck.cpp
- BoolPointerImplicitConversionCheck.cpp
DefinitionsInHeadersCheck.cpp
- FoldInitTypeCheck.cpp
- ForwardDeclarationNamespaceCheck.cpp
- InaccurateEraseCheck.cpp
IncorrectRoundings.cpp
InefficientAlgorithmCheck.cpp
MacroParenthesesCheck.cpp
@@ -19,8 +14,6 @@ add_clang_library(clangTidyMiscModule
MisplacedWideningCastCheck.cpp
MoveConstantArgumentCheck.cpp
MoveConstructorInitCheck.cpp
- MoveForwardingReferenceCheck.cpp
- MultipleStatementMacroCheck.cpp
NewDeleteOverloadsCheck.cpp
NoexceptMoveConstructorCheck.cpp
NonCopyableObjects.cpp
@@ -43,8 +36,6 @@ add_clang_library(clangTidyMiscModule
UnusedParametersCheck.cpp
UnusedRAIICheck.cpp
UnusedUsingDeclsCheck.cpp
- UseAfterMoveCheck.cpp
- VirtualNearMissCheck.cpp
LINK_LIBS
clangAnalysis
diff --git a/clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.cpp b/clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.cpp
deleted file mode 100644
index c5d27201b8b..00000000000
--- a/clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-//===--- FoldInitTypeCheck.cpp - clang-tidy--------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "FoldInitTypeCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-void FoldInitTypeCheck::registerMatchers(MatchFinder *Finder) {
- // We match functions of interest and bind the iterator and init value types.
- // Note: Right now we check only builtin types.
- const auto BuiltinTypeWithId = [](const char *ID) {
- return hasCanonicalType(builtinType().bind(ID));
- };
- const auto IteratorWithValueType = [&BuiltinTypeWithId](const char *ID) {
- return anyOf(
- // Pointer types.
- pointsTo(BuiltinTypeWithId(ID)),
- // Iterator types.
- recordType(hasDeclaration(has(typedefNameDecl(
- hasName("value_type"), hasType(BuiltinTypeWithId(ID)))))));
- };
-
- const auto IteratorParam = parmVarDecl(
- hasType(hasCanonicalType(IteratorWithValueType("IterValueType"))));
- const auto Iterator2Param = parmVarDecl(
- hasType(hasCanonicalType(IteratorWithValueType("Iter2ValueType"))));
- const auto InitParam = parmVarDecl(hasType(BuiltinTypeWithId("InitType")));
-
- // std::accumulate, std::reduce.
- Finder->addMatcher(
- callExpr(callee(functionDecl(
- hasAnyName("::std::accumulate", "::std::reduce"),
- hasParameter(0, IteratorParam), hasParameter(2, InitParam))),
- argumentCountIs(3))
- .bind("Call"),
- this);
- // std::inner_product.
- Finder->addMatcher(
- callExpr(callee(functionDecl(hasName("::std::inner_product"),
- hasParameter(0, IteratorParam),
- hasParameter(2, Iterator2Param),
- hasParameter(3, InitParam))),
- argumentCountIs(4))
- .bind("Call"),
- this);
- // std::reduce with a policy.
- Finder->addMatcher(
- callExpr(callee(functionDecl(hasName("::std::reduce"),
- hasParameter(1, IteratorParam),
- hasParameter(3, InitParam))),
- argumentCountIs(4))
- .bind("Call"),
- this);
- // std::inner_product with a policy.
- Finder->addMatcher(
- callExpr(callee(functionDecl(hasName("::std::inner_product"),
- hasParameter(1, IteratorParam),
- hasParameter(3, Iterator2Param),
- hasParameter(4, InitParam))),
- argumentCountIs(5))
- .bind("Call"),
- this);
-}
-
-/// Returns true if ValueType is allowed to fold into InitType, i.e. if:
-/// static_cast<InitType>(ValueType{some_value})
-/// does not result in trucation.
-static bool isValidBuiltinFold(const BuiltinType &ValueType,
- const BuiltinType &InitType,
- const ASTContext &Context) {
- const auto ValueTypeSize = Context.getTypeSize(&ValueType);
- const auto InitTypeSize = Context.getTypeSize(&InitType);
- // It's OK to fold a float into a float of bigger or equal size, but not OK to
- // fold into an int.
- if (ValueType.isFloatingPoint())
- return InitType.isFloatingPoint() && InitTypeSize >= ValueTypeSize;
- // It's OK to fold an int into:
- // - an int of the same size and signedness.
- // - a bigger int, regardless of signedness.
- // - FIXME: should it be a warning to fold into floating point?
- if (ValueType.isInteger()) {
- if (InitType.isInteger()) {
- if (InitType.isSignedInteger() == ValueType.isSignedInteger())
- return InitTypeSize >= ValueTypeSize;
- return InitTypeSize > ValueTypeSize;
- }
- if (InitType.isFloatingPoint())
- return InitTypeSize >= ValueTypeSize;
- }
- return false;
-}
-
-/// Prints a diagnostic if IterValueType doe snot fold into IterValueType (see
-// isValidBuiltinFold for details).
-void FoldInitTypeCheck::doCheck(const BuiltinType &IterValueType,
- const BuiltinType &InitType,
- const ASTContext &Context,
- const CallExpr &CallNode) {
- if (!isValidBuiltinFold(IterValueType, InitType, Context)) {
- diag(CallNode.getExprLoc(), "folding type %0 into type %1 might result in "
- "loss of precision")
- << IterValueType.desugar() << InitType.desugar();
- }
-}
-
-void FoldInitTypeCheck::check(const MatchFinder::MatchResult &Result) {
- // Given the iterator and init value type retreived by the matchers,
- // we check that the ::value_type of the iterator is compatible with
- // the init value type.
- const auto *InitType = Result.Nodes.getNodeAs<BuiltinType>("InitType");
- const auto *IterValueType =
- Result.Nodes.getNodeAs<BuiltinType>("IterValueType");
- assert(InitType != nullptr);
- assert(IterValueType != nullptr);
-
- const auto *CallNode = Result.Nodes.getNodeAs<CallExpr>("Call");
- assert(CallNode != nullptr);
-
- doCheck(*IterValueType, *InitType, *Result.Context, *CallNode);
-
- if (const auto *Iter2ValueType =
- Result.Nodes.getNodeAs<BuiltinType>("Iter2ValueType"))
- doCheck(*Iter2ValueType, *InitType, *Result.Context, *CallNode);
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.h b/clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.h
deleted file mode 100644
index df4ec88fa04..00000000000
--- a/clang-tools-extra/clang-tidy/misc/FoldInitTypeCheck.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//===--- FoldInitTypeCheck.h - clang-tidy------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FOLD_INIT_TYPE_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FOLD_INIT_TYPE_H
-
-#include "../ClangTidy.h"
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// Find and flag invalid initializer values in folds, e.g. std::accumulate.
-/// Example:
-/// \code
-/// auto v = {65536L * 65536 * 65536};
-/// std::accumulate(begin(v), end(v), 0 /* int type is too small */);
-/// \endcode
-///
-/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/misc-fold-init-type.html
-class FoldInitTypeCheck : public ClangTidyCheck {
-public:
- FoldInitTypeCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-
-private:
- void doCheck(const BuiltinType &IterValueType, const BuiltinType &InitType,
- const ASTContext &Context, const CallExpr &CallNode);
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FOLD_INIT_TYPE_H
diff --git a/clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp b/clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp
deleted file mode 100644
index 1487e8f1861..00000000000
--- a/clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
-//===--- ForwardDeclarationNamespaceCheck.cpp - clang-tidy ------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "ForwardDeclarationNamespaceCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/ASTMatchers/ASTMatchers.h"
-#include <stack>
-#include <string>
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-void ForwardDeclarationNamespaceCheck::registerMatchers(MatchFinder *Finder) {
- // Match all class declarations/definitions *EXCEPT*
- // 1. implicit classes, e.g. `class A {};` has implicit `class A` inside `A`.
- // 2. nested classes declared/defined inside another class.
- // 3. template class declaration, template instantiation or
- // specialization (NOTE: extern specialization is filtered out by
- // `unless(hasAncestor(cxxRecordDecl()))`).
- auto IsInSpecialization = hasAncestor(
- decl(anyOf(cxxRecordDecl(isExplicitTemplateSpecialization()),
- functionDecl(isExplicitTemplateSpecialization()))));
- Finder->addMatcher(
- cxxRecordDecl(
- hasParent(decl(anyOf(namespaceDecl(), translationUnitDecl()))),
- unless(isImplicit()), unless(hasAncestor(cxxRecordDecl())),
- unless(isInstantiated()), unless(IsInSpecialization),
- unless(classTemplateSpecializationDecl()))
- .bind("record_decl"),
- this);
-
- // Match all friend declarations. Classes used in friend declarations are not
- // marked as referenced in AST. We need to record all record classes used in
- // friend declarations.
- Finder->addMatcher(friendDecl().bind("friend_decl"), this);
-}
-
-void ForwardDeclarationNamespaceCheck::check(
- const MatchFinder::MatchResult &Result) {
- if (const auto *RecordDecl =
- Result.Nodes.getNodeAs<CXXRecordDecl>("record_decl")) {
- StringRef DeclName = RecordDecl->getName();
- if (RecordDecl->isThisDeclarationADefinition()) {
- DeclNameToDefinitions[DeclName].push_back(RecordDecl);
- } else {
- // If a declaration has no definition, the definition could be in another
- // namespace (a wrong namespace).
- // NOTE: even a declaration does have definition, we still need it to
- // compare with other declarations.
- DeclNameToDeclarations[DeclName].push_back(RecordDecl);
- }
- } else {
- const auto *Decl = Result.Nodes.getNodeAs<FriendDecl>("friend_decl");
- assert(Decl && "Decl is neither record_decl nor friend decl!");
-
- // Classes used in friend delarations are not marked referenced in AST,
- // so we need to check classes used in friend declarations manually to
- // reduce the rate of false positive.
- // For example, in
- // \code
- // struct A;
- // struct B { friend A; };
- // \endcode
- // `A` will not be marked as "referenced" in the AST.
- if (const TypeSourceInfo *Tsi = Decl->getFriendType()) {
- QualType Desugared = Tsi->getType().getDesugaredType(*Result.Context);
- FriendTypes.insert(Desugared.getTypePtr());
- }
- }
-}
-
-static bool haveSameNamespaceOrTranslationUnit(const CXXRecordDecl *Decl1,
- const CXXRecordDecl *Decl2) {
- const DeclContext *ParentDecl1 = Decl1->getLexicalParent();
- const DeclContext *ParentDecl2 = Decl2->getLexicalParent();
-
- // Since we only matched declarations whose parent is Namespace or
- // TranslationUnit declaration, the parent should be either a translation unit
- // or namespace.
- if (ParentDecl1->getDeclKind() == Decl::TranslationUnit ||
- ParentDecl2->getDeclKind() == Decl::TranslationUnit) {
- return ParentDecl1 == ParentDecl2;
- }
- assert(ParentDecl1->getDeclKind() == Decl::Namespace &&
- "ParentDecl1 declaration must be a namespace");
- assert(ParentDecl2->getDeclKind() == Decl::Namespace &&
- "ParentDecl2 declaration must be a namespace");
- auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);
- auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);
- return Ns1->getOriginalNamespace() == Ns2->getOriginalNamespace();
-}
-
-static std::string getNameOfNamespace(const CXXRecordDecl *Decl) {
- const auto *ParentDecl = Decl->getLexicalParent();
- if (ParentDecl->getDeclKind() == Decl::TranslationUnit) {
- return "(global)";
- }
- const auto *NsDecl = cast<NamespaceDecl>(ParentDecl);
- std::string Ns;
- llvm::raw_string_ostream OStream(Ns);
- NsDecl->printQualifiedName(OStream);
- OStream.flush();
- return Ns.empty() ? "(global)" : Ns;
-}
-
-void ForwardDeclarationNamespaceCheck::onEndOfTranslationUnit() {
- // Iterate each group of declarations by name.
- for (const auto &KeyValuePair : DeclNameToDeclarations) {
- const auto &Declarations = KeyValuePair.second;
- // If more than 1 declaration exists, we check if all are in the same
- // namespace.
- for (const auto *CurDecl : Declarations) {
- if (CurDecl->hasDefinition() || CurDecl->isReferenced()) {
- continue; // Skip forward declarations that are used/referenced.
- }
- if (FriendTypes.count(CurDecl->getTypeForDecl()) != 0) {
- continue; // Skip forward declarations referenced as friend.
- }
- if (CurDecl->getLocation().isMacroID() ||
- CurDecl->getLocation().isInvalid()) {
- continue;
- }
- // Compare with all other declarations with the same name.
- for (const auto *Decl : Declarations) {
- if (Decl == CurDecl) {
- continue; // Don't compare with self.
- }
- if (!CurDecl->hasDefinition() &&
- !haveSameNamespaceOrTranslationUnit(CurDecl, Decl)) {
- diag(CurDecl->getLocation(),
- "declaration %0 is never referenced, but a declaration with "
- "the same name found in another namespace '%1'")
- << CurDecl << getNameOfNamespace(Decl);
- diag(Decl->getLocation(), "a declaration of %0 is found here",
- DiagnosticIDs::Note)
- << Decl;
- break; // FIXME: We only generate one warning for each declaration.
- }
- }
- // Check if a definition in another namespace exists.
- const auto DeclName = CurDecl->getName();
- if (DeclNameToDefinitions.find(DeclName) == DeclNameToDefinitions.end()) {
- continue; // No definition in this translation unit, we can skip it.
- }
- // Make a warning for each definition with the same name (in other
- // namespaces).
- const auto &Definitions = DeclNameToDefinitions[DeclName];
- for (const auto *Def : Definitions) {
- diag(CurDecl->getLocation(),
- "no definition found for %0, but a definition with "
- "the same name %1 found in another namespace '%2'")
- << CurDecl << Def << getNameOfNamespace(Def);
- diag(Def->getLocation(), "a definition of %0 is found here",
- DiagnosticIDs::Note)
- << Def;
- }
- }
- }
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h b/clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h
deleted file mode 100644
index dd7042d3691..00000000000
--- a/clang-tools-extra/clang-tidy/misc/ForwardDeclarationNamespaceCheck.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===--- ForwardDeclarationNamespaceCheck.h - clang-tidy --------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FORWARDDECLARATIONNAMESPACECHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FORWARDDECLARATIONNAMESPACECHECK_H
-
-#include "../ClangTidy.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include <set>
-#include <vector>
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// Checks if an unused forward declaration is in a wrong namespace.
-///
-/// The check inspects all unused forward declarations and checks if there is
-/// any declaration/definition with the same name, which could indicate
-/// that the forward declaration is potentially in a wrong namespace.
-///
-/// \code
-/// namespace na { struct A; }
-/// namespace nb { struct A {} };
-/// nb::A a;
-/// // warning : no definition found for 'A', but a definition with the same
-/// name 'A' found in another namespace 'nb::'
-/// \endcode
-///
-/// This check can only generate warnings, but it can't suggest fixes at this
-/// point.
-///
-/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/misc-forward-declaration-namespace.html
-class ForwardDeclarationNamespaceCheck : public ClangTidyCheck {
-public:
- ForwardDeclarationNamespaceCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
- void onEndOfTranslationUnit() override;
-
-private:
- llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDefinitions;
- llvm::StringMap<std::vector<const CXXRecordDecl *>> DeclNameToDeclarations;
- llvm::SmallPtrSet<const Type *, 16> FriendTypes;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_FORWARDDECLARATIONNAMESPACECHECK_H
diff --git a/clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.cpp b/clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.cpp
deleted file mode 100644
index fd86d1723e3..00000000000
--- a/clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.cpp
+++ /dev/null
@@ -1,81 +0,0 @@
-//===--- InaccurateEraseCheck.cpp - clang-tidy-----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "InaccurateEraseCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Lex/Lexer.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-namespace {
-AST_MATCHER(Decl, isInStdNamespace) { return Node.isInStdNamespace(); }
-}
-
-void InaccurateEraseCheck::registerMatchers(MatchFinder *Finder) {
- // Only register the matchers for C++; the functionality currently does not
- // provide any benefit to other languages, despite being benign.
- if (!getLangOpts().CPlusPlus)
- return;
-
- const auto EndCall =
- callExpr(
- callee(functionDecl(hasAnyName("remove", "remove_if", "unique"))),
- hasArgument(
- 1,
- anyOf(cxxConstructExpr(has(ignoringImplicit(
- cxxMemberCallExpr(callee(cxxMethodDecl(hasName("end"))))
- .bind("end")))),
- anything())))
- .bind("alg");
-
- const auto DeclInStd = type(hasUnqualifiedDesugaredType(
- tagType(hasDeclaration(decl(isInStdNamespace())))));
- Finder->addMatcher(
- cxxMemberCallExpr(
- on(anyOf(hasType(DeclInStd), hasType(pointsTo(DeclInStd)))),
- callee(cxxMethodDecl(hasName("erase"))), argumentCountIs(1),
- hasArgument(0, has(ignoringImplicit(
- anyOf(EndCall, has(ignoringImplicit(EndCall)))))),
- unless(isInTemplateInstantiation()))
- .bind("erase"),
- this);
-}
-
-void InaccurateEraseCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *MemberCall =
- Result.Nodes.getNodeAs<CXXMemberCallExpr>("erase");
- const auto *EndExpr =
- Result.Nodes.getNodeAs<CXXMemberCallExpr>("end");
- const SourceLocation Loc = MemberCall->getLocStart();
-
- FixItHint Hint;
-
- if (!Loc.isMacroID() && EndExpr) {
- const auto *AlgCall = Result.Nodes.getNodeAs<CallExpr>("alg");
- std::string ReplacementText = Lexer::getSourceText(
- CharSourceRange::getTokenRange(EndExpr->getSourceRange()),
- *Result.SourceManager, getLangOpts());
- const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
- AlgCall->getLocEnd(), 0, *Result.SourceManager, getLangOpts());
- Hint = FixItHint::CreateInsertion(EndLoc, ", " + ReplacementText);
- }
-
- diag(Loc, "this call will remove at most one item even when multiple items "
- "should be removed")
- << Hint;
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.h b/clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.h
deleted file mode 100644
index 623e1c236eb..00000000000
--- a/clang-tools-extra/clang-tidy/misc/InaccurateEraseCheck.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===--- InaccurateEraseCheck.h - clang-tidy---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INACCURATEERASECHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INACCURATEERASECHECK_H
-
-#include "../ClangTidy.h"
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// Checks for inaccurate use of the `erase()` method.
-///
-/// Algorithms like `remove()` do not actually remove any element from the
-/// container but return an iterator to the first redundant element at the end
-/// of the container. These redundant elements must be removed using the
-/// `erase()` method. This check warns when not all of the elements will be
-/// removed due to using an inappropriate overload.
-class InaccurateEraseCheck : public ClangTidyCheck {
-public:
- InaccurateEraseCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_INACCURATEERASECHECK_H
diff --git a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
index fbc999f2a0a..1dddd4e2832 100644
--- a/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -10,13 +10,8 @@
#include "../ClangTidy.h"
#include "../ClangTidyModule.h"
#include "../ClangTidyModuleRegistry.h"
-#include "AssertSideEffectCheck.h"
-#include "BoolPointerImplicitConversionCheck.h"
#include "DefinitionsInHeadersCheck.h"
-#include "FoldInitTypeCheck.h"
-#include "ForwardDeclarationNamespaceCheck.h"
#include "ForwardingReferenceOverloadCheck.h"
-#include "InaccurateEraseCheck.h"
#include "IncorrectRoundings.h"
#include "InefficientAlgorithmCheck.h"
#include "LambdaFunctionNameCheck.h"
@@ -26,8 +21,6 @@
#include "MisplacedWideningCastCheck.h"
#include "MoveConstantArgumentCheck.h"
#include "MoveConstructorInitCheck.h"
-#include "MoveForwardingReferenceCheck.h"
-#include "MultipleStatementMacroCheck.h"
#include "NewDeleteOverloadsCheck.h"
#include "NoexceptMoveConstructorCheck.h"
#include "NonCopyableObjects.h"
@@ -51,8 +44,6 @@
#include "UnusedParametersCheck.h"
#include "UnusedRAIICheck.h"
#include "UnusedUsingDeclsCheck.h"
-#include "UseAfterMoveCheck.h"
-#include "VirtualNearMissCheck.h"
namespace clang {
namespace tidy {
@@ -61,8 +52,6 @@ namespace misc {
class MiscModule : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
- CheckFactories.registerCheck<AssertSideEffectCheck>(
- "misc-assert-side-effect");
CheckFactories.registerCheck<ForwardingReferenceOverloadCheck>(
"misc-forwarding-reference-overload");
CheckFactories.registerCheck<LambdaFunctionNameCheck>(
@@ -70,14 +59,8 @@ public:
CheckFactories.registerCheck<MisplacedConstCheck>("misc-misplaced-const");
CheckFactories.registerCheck<UnconventionalAssignOperatorCheck>(
"misc-unconventional-assign-operator");
- CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
- "misc-bool-pointer-implicit-conversion");
CheckFactories.registerCheck<DefinitionsInHeadersCheck>(
"misc-definitions-in-headers");
- CheckFactories.registerCheck<FoldInitTypeCheck>("misc-fold-init-type");
- CheckFactories.registerCheck<ForwardDeclarationNamespaceCheck>(
- "misc-forward-declaration-namespace");
- CheckFactories.registerCheck<InaccurateEraseCheck>("misc-inaccurate-erase");
CheckFactories.registerCheck<IncorrectRoundings>(
"misc-incorrect-roundings");
CheckFactories.registerCheck<InefficientAlgorithmCheck>(
@@ -92,10 +75,6 @@ public:
"misc-move-const-arg");
CheckFactories.registerCheck<MoveConstructorInitCheck>(
"misc-move-constructor-init");
- CheckFactories.registerCheck<MoveForwardingReferenceCheck>(
- "misc-move-forwarding-reference");
- CheckFactories.registerCheck<MultipleStatementMacroCheck>(
- "misc-multiple-statement-macro");
CheckFactories.registerCheck<NewDeleteOverloadsCheck>(
"misc-new-delete-overloads");
CheckFactories.registerCheck<NoexceptMoveConstructorCheck>(
@@ -136,9 +115,6 @@ public:
CheckFactories.registerCheck<UnusedRAIICheck>("misc-unused-raii");
CheckFactories.registerCheck<UnusedUsingDeclsCheck>(
"misc-unused-using-decls");
- CheckFactories.registerCheck<UseAfterMoveCheck>("misc-use-after-move");
- CheckFactories.registerCheck<VirtualNearMissCheck>(
- "misc-virtual-near-miss");
}
};
diff --git a/clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.cpp b/clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.cpp
deleted file mode 100644
index 12c19dd9c20..00000000000
--- a/clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.cpp
+++ /dev/null
@@ -1,133 +0,0 @@
-//===--- MoveForwardingReferenceCheck.cpp - clang-tidy --------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MoveForwardingReferenceCheck.h"
-#include "clang/Lex/Lexer.h"
-#include "llvm/Support/raw_ostream.h"
-
-#include <algorithm>
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-static void replaceMoveWithForward(const UnresolvedLookupExpr *Callee,
- const ParmVarDecl *ParmVar,
- const TemplateTypeParmDecl *TypeParmDecl,
- DiagnosticBuilder &Diag,
- const ASTContext &Context) {
- const SourceManager &SM = Context.getSourceManager();
- const LangOptions &LangOpts = Context.getLangOpts();
-
- CharSourceRange CallRange =
- Lexer::makeFileCharRange(CharSourceRange::getTokenRange(
- Callee->getLocStart(), Callee->getLocEnd()),
- SM, LangOpts);
-
- if (CallRange.isValid()) {
- const std::string TypeName =
- TypeParmDecl->getIdentifier()
- ? TypeParmDecl->getName().str()
- : (llvm::Twine("decltype(") + ParmVar->getName() + ")").str();
-
- const std::string ForwardName =
- (llvm::Twine("forward<") + TypeName + ">").str();
-
- // Create a replacement only if we see a "standard" way of calling
- // 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();
- if (!NNS) {
- // Called as "move" (i.e. presumably the code had a "using std::move;").
- // We still conservatively put a "std::" in front of the forward because
- // we don't know whether the code also had a "using std::forward;".
- Diag << FixItHint::CreateReplacement(CallRange, "std::" + ForwardName);
- } else if (const NamespaceDecl *Namespace = NNS->getAsNamespace()) {
- if (Namespace->getName() == "std") {
- if (!NNS->getPrefix()) {
- // Called as "std::move".
- Diag << FixItHint::CreateReplacement(CallRange,
- "std::" + ForwardName);
- } else if (NNS->getPrefix()->getKind() == NestedNameSpecifier::Global) {
- // Called as "::std::move".
- Diag << FixItHint::CreateReplacement(CallRange,
- "::std::" + ForwardName);
- }
- }
- }
- }
-}
-
-void MoveForwardingReferenceCheck::registerMatchers(MatchFinder *Finder) {
- if (!getLangOpts().CPlusPlus11)
- return;
-
- // Matches a ParmVarDecl for a forwarding reference, i.e. a non-const rvalue
- // reference of a function template parameter type.
- auto ForwardingReferenceParmMatcher =
- parmVarDecl(
- hasType(qualType(rValueReferenceType(),
- references(templateTypeParmType(hasDeclaration(
- templateTypeParmDecl().bind("type-parm-decl")))),
- unless(references(qualType(isConstQualified()))))))
- .bind("parm-var");
-
- Finder->addMatcher(
- callExpr(callee(unresolvedLookupExpr(
- hasAnyDeclaration(namedDecl(
- hasUnderlyingDecl(hasName("::std::move")))))
- .bind("lookup")),
- argumentCountIs(1),
- hasArgument(0, ignoringParenImpCasts(declRefExpr(
- to(ForwardingReferenceParmMatcher)))))
- .bind("call-move"),
- this);
-}
-
-void MoveForwardingReferenceCheck::check(
- const MatchFinder::MatchResult &Result) {
- const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
- const auto *UnresolvedLookup =
- Result.Nodes.getNodeAs<UnresolvedLookupExpr>("lookup");
- const auto *ParmVar = Result.Nodes.getNodeAs<ParmVarDecl>("parm-var");
- const auto *TypeParmDecl =
- Result.Nodes.getNodeAs<TemplateTypeParmDecl>("type-parm-decl");
-
- // Get the FunctionDecl and FunctionTemplateDecl containing the function
- // parameter.
- const auto *FuncForParam = dyn_cast<FunctionDecl>(ParmVar->getDeclContext());
- if (!FuncForParam)
- return;
- const FunctionTemplateDecl *FuncTemplate =
- FuncForParam->getDescribedFunctionTemplate();
- if (!FuncTemplate)
- return;
-
- // Check that the template type parameter belongs to the same function
- // template as the function parameter of that type. (This implies that type
- // deduction will happen on the type.)
- const TemplateParameterList *Params = FuncTemplate->getTemplateParameters();
- if (!std::count(Params->begin(), Params->end(), TypeParmDecl))
- return;
-
- auto Diag = diag(CallMove->getExprLoc(),
- "forwarding reference passed to std::move(), which may "
- "unexpectedly cause lvalues to be moved; use "
- "std::forward() instead");
-
- replaceMoveWithForward(UnresolvedLookup, ParmVar, TypeParmDecl, Diag,
- *Result.Context);
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.h b/clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.h
deleted file mode 100644
index 2e6ec363488..00000000000
--- a/clang-tools-extra/clang-tidy/misc/MoveForwardingReferenceCheck.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===--- MoveForwardingReferenceCheck.h - clang-tidy ----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MOVEFORWARDINGREFERENCECHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MOVEFORWARDINGREFERENCECHECK_H
-
-#include "../ClangTidy.h"
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// The check warns if std::move is applied to a forwarding reference (i.e. an
-/// rvalue reference of a function template argument type).
-///
-/// If a developer is unaware of the special rules for template argument
-/// deduction on forwarding references, it will seem reasonable to apply
-/// std::move to the forwarding reference, in the same way that this would be
-/// done for a "normal" rvalue reference.
-///
-/// This has a consequence that is usually unwanted and possibly surprising: if
-/// the function that takes the forwarding reference as its parameter is called
-/// with an lvalue, that lvalue will be moved from (and hence placed into an
-/// indeterminate state) even though no std::move was applied to the lvalue at
-/// the call site.
-//
-/// The check suggests replacing the std::move with a std::forward.
-///
-/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/misc-move-forwarding-reference.html
-class MoveForwardingReferenceCheck : public ClangTidyCheck {
-public:
- MoveForwardingReferenceCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MOVEFORWARDINGREFERENCECHECK_H
diff --git a/clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.cpp b/clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.cpp
deleted file mode 100644
index 9d485fd211b..00000000000
--- a/clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-//===--- MultipleStatementMacroCheck.cpp - clang-tidy----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MultipleStatementMacroCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-namespace {
-
-AST_MATCHER(Expr, isInMacro) { return Node.getLocStart().isMacroID(); }
-
-/// \brief Find the next statement after `S`.
-const Stmt *nextStmt(const MatchFinder::MatchResult &Result, const Stmt *S) {
- auto Parents = Result.Context->getParents(*S);
- if (Parents.empty())
- return nullptr;
- const auto *Parent = Parents[0].get<Stmt>();
- if (!Parent)
- return nullptr;
- const Stmt *Prev = nullptr;
- for (const Stmt *Child : Parent->children()) {
- if (Prev == S)
- return Child;
- Prev = Child;
- }
- return nextStmt(Result, Parent);
-}
-
-using ExpansionRanges = std::vector<std::pair<SourceLocation, SourceLocation>>;
-
-/// \bried Get all the macro expansion ranges related to `Loc`.
-///
-/// The result is ordered from most inner to most outer.
-ExpansionRanges getExpansionRanges(SourceLocation Loc,
- const MatchFinder::MatchResult &Result) {
- ExpansionRanges Locs;
- while (Loc.isMacroID()) {
- Locs.push_back(Result.SourceManager->getImmediateExpansionRange(Loc));
- Loc = Locs.back().first;
- }
- return Locs;
-}
-
-} // namespace
-
-void MultipleStatementMacroCheck::registerMatchers(MatchFinder *Finder) {
- const auto Inner = expr(isInMacro(), unless(compoundStmt())).bind("inner");
- Finder->addMatcher(
- stmt(anyOf(ifStmt(hasThen(Inner)), ifStmt(hasElse(Inner)).bind("else"),
- whileStmt(hasBody(Inner)), forStmt(hasBody(Inner))))
- .bind("outer"),
- this);
-}
-
-void MultipleStatementMacroCheck::check(
- const MatchFinder::MatchResult &Result) {
- const auto *Inner = Result.Nodes.getNodeAs<Expr>("inner");
- const auto *Outer = Result.Nodes.getNodeAs<Stmt>("outer");
- const auto *Next = nextStmt(Result, Outer);
- if (!Next)
- return;
-
- SourceLocation OuterLoc = Outer->getLocStart();
- if (Result.Nodes.getNodeAs<Stmt>("else"))
- OuterLoc = cast<IfStmt>(Outer)->getElseLoc();
-
- auto InnerRanges = getExpansionRanges(Inner->getLocStart(), Result);
- auto OuterRanges = getExpansionRanges(OuterLoc, Result);
- auto NextRanges = getExpansionRanges(Next->getLocStart(), Result);
-
- // Remove all the common ranges, starting from the top (the last ones in the
- // list).
- while (!InnerRanges.empty() && !OuterRanges.empty() && !NextRanges.empty() &&
- InnerRanges.back() == OuterRanges.back() &&
- InnerRanges.back() == NextRanges.back()) {
- InnerRanges.pop_back();
- OuterRanges.pop_back();
- NextRanges.pop_back();
- }
-
- // Inner and Next must have at least one more macro that Outer doesn't have,
- // and that range must be common to both.
- if (InnerRanges.empty() || NextRanges.empty() ||
- InnerRanges.back() != NextRanges.back())
- return;
-
- diag(InnerRanges.back().first, "multiple statement macro used without "
- "braces; some statements will be "
- "unconditionally executed");
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.h b/clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.h
deleted file mode 100644
index 77a6b27dcde..00000000000
--- a/clang-tools-extra/clang-tidy/misc/MultipleStatementMacroCheck.h
+++ /dev/null
@@ -1,37 +0,0 @@
-//===--- MultipleStatementMacroCheck.h - clang-tidy--------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MULTIPLE_STATEMENT_MACRO_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MULTIPLE_STATEMENT_MACRO_H
-
-#include "../ClangTidy.h"
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// Detect multiple statement macros that are used in unbraced conditionals.
-/// Only the first statement of the macro will be inside the conditional and the
-/// other ones will be executed unconditionally.
-///
-/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/misc-multiple-statement-macro.html
-class MultipleStatementMacroCheck : public ClangTidyCheck {
-public:
- MultipleStatementMacroCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_MULTIPLE_STATEMENT_MACRO_H
diff --git a/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp b/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp
deleted file mode 100644
index 99673766a53..00000000000
--- a/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.cpp
+++ /dev/null
@@ -1,434 +0,0 @@
-//===--- UseAfterMoveCheck.cpp - clang-tidy -------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "UseAfterMoveCheck.h"
-
-#include "clang/Analysis/CFG.h"
-#include "clang/Lex/Lexer.h"
-
-#include "../utils/ExprSequence.h"
-
-using namespace clang::ast_matchers;
-using namespace clang::tidy::utils;
-
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-namespace {
-
-/// Contains information about a use-after-move.
-struct UseAfterMove {
- // The DeclRefExpr that constituted the use of the object.
- const DeclRefExpr *DeclRef;
-
- // Is the order in which the move and the use are evaluated undefined?
- bool EvaluationOrderUndefined;
-};
-
-/// Finds uses of a variable after a move (and maintains state required by the
-/// various internal helper functions).
-class UseAfterMoveFinder {
-public:
- UseAfterMoveFinder(ASTContext *TheContext);
-
- // Within the given function body, finds the first use of 'MovedVariable' that
- // occurs after 'MovingCall' (the expression that performs the move). If a
- // use-after-move is found, writes information about it to 'TheUseAfterMove'.
- // Returns whether a use-after-move was found.
- bool find(Stmt *FunctionBody, const Expr *MovingCall,
- const ValueDecl *MovedVariable, UseAfterMove *TheUseAfterMove);
-
-private:
- bool findInternal(const CFGBlock *Block, const Expr *MovingCall,
- const ValueDecl *MovedVariable,
- UseAfterMove *TheUseAfterMove);
- void getUsesAndReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
- llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
- llvm::SmallPtrSetImpl<const Stmt *> *Reinits);
- void getDeclRefs(const CFGBlock *Block, const Decl *MovedVariable,
- llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
- void getReinits(const CFGBlock *Block, const ValueDecl *MovedVariable,
- llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
- llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs);
-
- ASTContext *Context;
- std::unique_ptr<ExprSequence> Sequence;
- std::unique_ptr<StmtToBlockMap> BlockMap;
- llvm::SmallPtrSet<const CFGBlock *, 8> Visited;
-};
-
-} // namespace
-
-
-// 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
-// - Part of a function template argument (we check this by seeing if they are
-// children of a DeclRefExpr that references a function template).
-// DeclRefExprs that fulfill these conditions should not be counted as a use or
-// move.
-static StatementMatcher inDecltypeOrTemplateArg() {
- return anyOf(hasAncestor(typeLoc()),
- hasAncestor(declRefExpr(
- to(functionDecl(ast_matchers::isTemplateInstantiation())))));
-}
-
-UseAfterMoveFinder::UseAfterMoveFinder(ASTContext *TheContext)
- : Context(TheContext) {}
-
-bool UseAfterMoveFinder::find(Stmt *FunctionBody, const Expr *MovingCall,
- const ValueDecl *MovedVariable,
- UseAfterMove *TheUseAfterMove) {
- // Generate the CFG manually instead of through an AnalysisDeclContext because
- // it seems the latter can't be used to generate a CFG for the body of a
- // labmda.
- //
- // We include implicit and temporary destructors in the CFG so that
- // destructors marked [[noreturn]] are handled correctly in the control flow
- // analysis. (These are used in some styles of assertion macros.)
- CFG::BuildOptions Options;
- Options.AddImplicitDtors = true;
- Options.AddTemporaryDtors = true;
- std::unique_ptr<CFG> TheCFG =
- CFG::buildCFG(nullptr, FunctionBody, Context, Options);
- if (!TheCFG)
- return false;
-
- Sequence.reset(new ExprSequence(TheCFG.get(), Context));
- BlockMap.reset(new StmtToBlockMap(TheCFG.get(), Context));
- Visited.clear();
-
- const CFGBlock *Block = BlockMap->blockContainingStmt(MovingCall);
- if (!Block)
- return false;
-
- return findInternal(Block, MovingCall, MovedVariable, TheUseAfterMove);
-}
-
-bool UseAfterMoveFinder::findInternal(const CFGBlock *Block,
- const Expr *MovingCall,
- const ValueDecl *MovedVariable,
- UseAfterMove *TheUseAfterMove) {
- if (Visited.count(Block))
- return false;
-
- // Mark the block as visited (except if this is the block containing the
- // std::move() and it's being visited the first time).
- if (!MovingCall)
- Visited.insert(Block);
-
- // Get all uses and reinits in the block.
- llvm::SmallVector<const DeclRefExpr *, 1> Uses;
- llvm::SmallPtrSet<const Stmt *, 1> Reinits;
- getUsesAndReinits(Block, MovedVariable, &Uses, &Reinits);
-
- // Ignore all reinitializations where the move potentially comes after the
- // reinit.
- llvm::SmallVector<const Stmt *, 1> ReinitsToDelete;
- for (const Stmt *Reinit : Reinits) {
- if (MovingCall && Sequence->potentiallyAfter(MovingCall, Reinit))
- ReinitsToDelete.push_back(Reinit);
- }
- for (const Stmt *Reinit : ReinitsToDelete) {
- Reinits.erase(Reinit);
- }
-
- // Find all uses that potentially come after the move.
- for (const DeclRefExpr *Use : Uses) {
- if (!MovingCall || Sequence->potentiallyAfter(Use, MovingCall)) {
- // Does the use have a saving reinit? A reinit is saving if it definitely
- // comes before the use, i.e. if there's no potential that the reinit is
- // after the use.
- bool HaveSavingReinit = false;
- for (const Stmt *Reinit : Reinits) {
- if (!Sequence->potentiallyAfter(Reinit, Use))
- HaveSavingReinit = true;
- }
-
- if (!HaveSavingReinit) {
- TheUseAfterMove->DeclRef = Use;
-
- // Is this a use-after-move that depends on order of evaluation?
- // This is the case if the move potentially comes after the use (and we
- // already know that use potentially comes after the move, which taken
- // together tells us that the ordering is unclear).
- TheUseAfterMove->EvaluationOrderUndefined =
- MovingCall != nullptr &&
- Sequence->potentiallyAfter(MovingCall, Use);
-
- return true;
- }
- }
- }
-
- // If the object wasn't reinitialized, call ourselves recursively on all
- // successors.
- if (Reinits.empty()) {
- for (const auto &Succ : Block->succs()) {
- if (Succ && findInternal(Succ, nullptr, MovedVariable, TheUseAfterMove))
- return true;
- }
- }
-
- return false;
-}
-
-void UseAfterMoveFinder::getUsesAndReinits(
- const CFGBlock *Block, const ValueDecl *MovedVariable,
- llvm::SmallVectorImpl<const DeclRefExpr *> *Uses,
- llvm::SmallPtrSetImpl<const Stmt *> *Reinits) {
- llvm::SmallPtrSet<const DeclRefExpr *, 1> DeclRefs;
- llvm::SmallPtrSet<const DeclRefExpr *, 1> ReinitDeclRefs;
-
- getDeclRefs(Block, MovedVariable, &DeclRefs);
- getReinits(Block, MovedVariable, Reinits, &ReinitDeclRefs);
-
- // All references to the variable that aren't reinitializations are uses.
- Uses->clear();
- for (const DeclRefExpr *DeclRef : DeclRefs) {
- if (!ReinitDeclRefs.count(DeclRef))
- Uses->push_back(DeclRef);
- }
-
- // Sort the uses by their occurrence in the source code.
- std::sort(Uses->begin(), Uses->end(),
- [](const DeclRefExpr *D1, const DeclRefExpr *D2) {
- return D1->getExprLoc() < D2->getExprLoc();
- });
-}
-
-bool isStandardSmartPointer(const ValueDecl *VD) {
- const Type *TheType = VD->getType().getTypePtrOrNull();
- if (!TheType)
- return false;
-
- const CXXRecordDecl *RecordDecl = TheType->getAsCXXRecordDecl();
- if (!RecordDecl)
- return false;
-
- const IdentifierInfo *ID = RecordDecl->getIdentifier();
- if (!ID)
- return false;
-
- StringRef Name = ID->getName();
- if (Name != "unique_ptr" && Name != "shared_ptr" && Name != "weak_ptr")
- return false;
-
- return RecordDecl->getDeclContext()->isStdNamespace();
-}
-
-void UseAfterMoveFinder::getDeclRefs(
- const CFGBlock *Block, const Decl *MovedVariable,
- llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
- DeclRefs->clear();
- for (const auto &Elem : *Block) {
- Optional<CFGStmt> S = Elem.getAs<CFGStmt>();
- if (!S)
- continue;
-
- auto addDeclRefs = [this, Block,
- DeclRefs](const ArrayRef<BoundNodes> Matches) {
- for (const auto &Match : Matches) {
- const auto *DeclRef = Match.getNodeAs<DeclRefExpr>("declref");
- const auto *Operator = Match.getNodeAs<CXXOperatorCallExpr>("operator");
- if (DeclRef && BlockMap->blockContainingStmt(DeclRef) == Block) {
- // Ignore uses of a standard smart pointer that don't dereference the
- // pointer.
- if (Operator || !isStandardSmartPointer(DeclRef->getDecl())) {
- DeclRefs->insert(DeclRef);
- }
- }
- }
- };
-
- auto DeclRefMatcher = declRefExpr(hasDeclaration(equalsNode(MovedVariable)),
- unless(inDecltypeOrTemplateArg()))
- .bind("declref");
-
- addDeclRefs(match(findAll(DeclRefMatcher), *S->getStmt(), *Context));
- addDeclRefs(match(
- findAll(cxxOperatorCallExpr(anyOf(hasOverloadedOperatorName("*"),
- hasOverloadedOperatorName("->"),
- hasOverloadedOperatorName("[]")),
- hasArgument(0, DeclRefMatcher))
- .bind("operator")),
- *S->getStmt(), *Context));
- }
-}
-
-void UseAfterMoveFinder::getReinits(
- const CFGBlock *Block, const ValueDecl *MovedVariable,
- llvm::SmallPtrSetImpl<const Stmt *> *Stmts,
- llvm::SmallPtrSetImpl<const DeclRefExpr *> *DeclRefs) {
- auto DeclRefMatcher =
- declRefExpr(hasDeclaration(equalsNode(MovedVariable))).bind("declref");
-
- auto StandardContainerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
- "::std::basic_string", "::std::vector", "::std::deque",
- "::std::forward_list", "::std::list", "::std::set", "::std::map",
- "::std::multiset", "::std::multimap", "::std::unordered_set",
- "::std::unordered_map", "::std::unordered_multiset",
- "::std::unordered_multimap"))))));
-
- auto StandardSmartPointerTypeMatcher = hasType(hasUnqualifiedDesugaredType(
- recordType(hasDeclaration(cxxRecordDecl(hasAnyName(
- "::std::unique_ptr", "::std::shared_ptr", "::std::weak_ptr"))))));
-
- // Matches different types of reinitialization.
- auto ReinitMatcher =
- stmt(anyOf(
- // Assignment. In addition to the overloaded assignment operator,
- // test for built-in assignment as well, since template functions
- // may be instantiated to use std::move() on built-in types.
- binaryOperator(hasOperatorName("="), hasLHS(DeclRefMatcher)),
- cxxOperatorCallExpr(hasOverloadedOperatorName("="),
- hasArgument(0, DeclRefMatcher)),
- // Declaration. We treat this as a type of reinitialization too,
- // so we don't need to treat it separately.
- declStmt(hasDescendant(equalsNode(MovedVariable))),
- // clear() and assign() on standard containers.
- cxxMemberCallExpr(
- on(allOf(DeclRefMatcher, StandardContainerTypeMatcher)),
- // To keep the matcher simple, we check for assign() calls
- // on all standard containers, even though only vector,
- // deque, forward_list and list have assign(). If assign()
- // is called on any of the other containers, this will be
- // flagged by a compile error anyway.
- callee(cxxMethodDecl(hasAnyName("clear", "assign")))),
- // reset() on standard smart pointers.
- cxxMemberCallExpr(
- on(allOf(DeclRefMatcher, StandardSmartPointerTypeMatcher)),
- callee(cxxMethodDecl(hasName("reset")))),
- // Passing variable to a function as a non-const pointer.
- callExpr(forEachArgumentWithParam(
- unaryOperator(hasOperatorName("&"),
- hasUnaryOperand(DeclRefMatcher)),
- unless(parmVarDecl(hasType(pointsTo(isConstQualified())))))),
- // Passing variable to a function as a non-const lvalue reference
- // (unless that function is std::move()).
- callExpr(forEachArgumentWithParam(
- DeclRefMatcher,
- unless(parmVarDecl(hasType(
- references(qualType(isConstQualified())))))),
- unless(callee(functionDecl(hasName("::std::move")))))))
- .bind("reinit");
-
- Stmts->clear();
- DeclRefs->clear();
- for (const auto &Elem : *Block) {
- Optional<CFGStmt> S = Elem.getAs<CFGStmt>();
- if (!S)
- continue;
-
- SmallVector<BoundNodes, 1> Matches =
- match(findAll(ReinitMatcher), *S->getStmt(), *Context);
-
- for (const auto &Match : Matches) {
- const auto *TheStmt = Match.getNodeAs<Stmt>("reinit");
- const auto *TheDeclRef = Match.getNodeAs<DeclRefExpr>("declref");
- if (TheStmt && BlockMap->blockContainingStmt(TheStmt) == Block) {
- Stmts->insert(TheStmt);
-
- // We count DeclStmts as reinitializations, but they don't have a
- // DeclRefExpr associated with them -- so we need to check 'TheDeclRef'
- // before adding it to the set.
- if (TheDeclRef)
- DeclRefs->insert(TheDeclRef);
- }
- }
- }
-}
-
-static void emitDiagnostic(const Expr *MovingCall, const DeclRefExpr *MoveArg,
- const UseAfterMove &Use, ClangTidyCheck *Check,
- ASTContext *Context) {
- SourceLocation UseLoc = Use.DeclRef->getExprLoc();
- SourceLocation MoveLoc = MovingCall->getExprLoc();
-
- Check->diag(UseLoc, "'%0' used after it was moved")
- << MoveArg->getDecl()->getName();
- Check->diag(MoveLoc, "move occurred here", DiagnosticIDs::Note);
- if (Use.EvaluationOrderUndefined) {
- Check->diag(UseLoc,
- "the use and move are unsequenced, i.e. there is no guarantee "
- "about the order in which they are evaluated",
- DiagnosticIDs::Note);
- } else if (UseLoc < MoveLoc || Use.DeclRef == MoveArg) {
- Check->diag(UseLoc,
- "the use happens in a later loop iteration than the move",
- DiagnosticIDs::Note);
- }
-}
-
-void UseAfterMoveCheck::registerMatchers(MatchFinder *Finder) {
- if (!getLangOpts().CPlusPlus11)
- return;
-
- auto CallMoveMatcher =
- callExpr(callee(functionDecl(hasName("::std::move"))), argumentCountIs(1),
- hasArgument(0, declRefExpr().bind("arg")),
- anyOf(hasAncestor(lambdaExpr().bind("containing-lambda")),
- hasAncestor(functionDecl().bind("containing-func"))),
- unless(inDecltypeOrTemplateArg()))
- .bind("call-move");
-
- Finder->addMatcher(
- // To find the Stmt that we assume performs the actual move, we look for
- // the direct ancestor of the std::move() that isn't one of the node
- // types ignored by ignoringParenImpCasts().
- stmt(forEach(expr(ignoringParenImpCasts(CallMoveMatcher))),
- // Don't allow an InitListExpr to be the moving call. An InitListExpr
- // has both a syntactic and a semantic form, and the parent-child
- // relationships are different between the two. This could cause an
- // InitListExpr to be analyzed as the moving call in addition to the
- // Expr that we actually want, resulting in two diagnostics with
- // different code locations for the same move.
- unless(initListExpr()),
- unless(expr(ignoringParenImpCasts(equalsBoundNode("call-move")))))
- .bind("moving-call"),
- this);
-}
-
-void UseAfterMoveCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *ContainingLambda =
- Result.Nodes.getNodeAs<LambdaExpr>("containing-lambda");
- const auto *ContainingFunc =
- Result.Nodes.getNodeAs<FunctionDecl>("containing-func");
- const auto *CallMove = Result.Nodes.getNodeAs<CallExpr>("call-move");
- const auto *MovingCall = Result.Nodes.getNodeAs<Expr>("moving-call");
- const auto *Arg = Result.Nodes.getNodeAs<DeclRefExpr>("arg");
-
- if (!MovingCall || !MovingCall->getExprLoc().isValid())
- MovingCall = CallMove;
-
- Stmt *FunctionBody = nullptr;
- if (ContainingLambda)
- FunctionBody = ContainingLambda->getBody();
- else if (ContainingFunc)
- FunctionBody = ContainingFunc->getBody();
- else
- return;
-
- // Ignore the std::move if the variable that was passed to it isn't a local
- // variable.
- if (!Arg->getDecl()->getDeclContext()->isFunctionOrMethod())
- return;
-
- UseAfterMoveFinder finder(Result.Context);
- UseAfterMove Use;
- if (finder.find(FunctionBody, MovingCall, Arg->getDecl(), &Use))
- emitDiagnostic(MovingCall, Arg, Use, this, Result.Context);
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.h b/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.h
deleted file mode 100644
index 2f6be5be300..00000000000
--- a/clang-tools-extra/clang-tidy/misc/UseAfterMoveCheck.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===--- UseAfterMoveCheck.h - clang-tidy ---------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USEAFTERMOVECHECK_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USEAFTERMOVECHECK_H
-
-#include "../ClangTidy.h"
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// The check warns if an object is used after it has been moved, without an
-/// intervening reinitialization.
-///
-/// For details, see the user-facing documentation:
-/// http://clang.llvm.org/extra/clang-tidy/checks/misc-use-after-move.html
-class UseAfterMoveCheck : public ClangTidyCheck {
-public:
- UseAfterMoveCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_USEAFTERMOVECHECK_H
diff --git a/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp b/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp
deleted file mode 100644
index fd74bb6692e..00000000000
--- a/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.cpp
+++ /dev/null
@@ -1,274 +0,0 @@
-//===--- VirtualNearMissCheck.cpp - clang-tidy-----------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "VirtualNearMissCheck.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/CXXInheritance.h"
-#include "clang/ASTMatchers/ASTMatchFinder.h"
-#include "clang/Lex/Lexer.h"
-
-using namespace clang::ast_matchers;
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-AST_MATCHER(CXXMethodDecl, isStatic) { return Node.isStatic(); }
-
-AST_MATCHER(CXXMethodDecl, isOverloadedOperator) {
- return Node.isOverloadedOperator();
-}
-
-/// Finds out if the given method overrides some method.
-static bool isOverrideMethod(const CXXMethodDecl *MD) {
- return MD->size_overridden_methods() > 0 || MD->hasAttr<OverrideAttr>();
-}
-
-/// Checks whether the return types are covariant, according to
-/// C++[class.virtual]p7.
-///
-/// Similar with clang::Sema::CheckOverridingFunctionReturnType.
-/// \returns true if the return types of BaseMD and DerivedMD are covariant.
-static bool checkOverridingFunctionReturnType(const ASTContext *Context,
- const CXXMethodDecl *BaseMD,
- const CXXMethodDecl *DerivedMD) {
- QualType BaseReturnTy = BaseMD->getType()
- ->getAs<FunctionType>()
- ->getReturnType()
- .getCanonicalType();
- QualType DerivedReturnTy = DerivedMD->getType()
- ->getAs<FunctionType>()
- ->getReturnType()
- .getCanonicalType();
-
- if (DerivedReturnTy->isDependentType() || BaseReturnTy->isDependentType())
- return false;
-
- // Check if return types are identical.
- if (Context->hasSameType(DerivedReturnTy, BaseReturnTy))
- return true;
-
- /// Check if the return types are covariant.
-
- // Both types must be pointers or references to classes.
- if (!(BaseReturnTy->isPointerType() && DerivedReturnTy->isPointerType()) &&
- !(BaseReturnTy->isReferenceType() && DerivedReturnTy->isReferenceType()))
- return false;
-
- /// 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 CXXRecordDecl *DRD = DTy->getAsCXXRecordDecl();
- const CXXRecordDecl *BRD = BTy->getAsCXXRecordDecl();
- if (DRD == nullptr || BRD == nullptr)
- return false;
-
- if (!DRD->hasDefinition() || !BRD->hasDefinition())
- return false;
-
- if (DRD == BRD)
- return true;
-
- if (!Context->hasSameUnqualifiedType(DTy, BTy)) {
- // Begin checking whether the conversion from D to B is valid.
- CXXBasePaths Paths(/*FindAmbiguities=*/true, /*RecordPaths=*/true,
- /*DetectVirtual=*/false);
-
- // Check whether D is derived from B, and fill in a CXXBasePaths object.
- if (!DRD->isDerivedFrom(BRD, Paths))
- return false;
-
- // Check ambiguity.
- if (Paths.isAmbiguous(Context->getCanonicalType(BTy).getUnqualifiedType()))
- return false;
-
- // 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 =
- DRD->getCanonicalDecl() == DerivedMD->getParent()->getCanonicalDecl();
- bool HasPublicAccess = false;
- for (const auto &Path : Paths) {
- if (Path.Access == AS_public)
- HasPublicAccess = true;
- }
- if (!HasPublicAccess && !IsItself)
- return false;
- // End checking conversion from D to B.
- }
-
- // Both pointers or references should have the same cv-qualification.
- if (DerivedReturnTy.getLocalCVRQualifiers() !=
- BaseReturnTy.getLocalCVRQualifiers())
- return false;
-
- // The class type D should have the same cv-qualification as or less
- // cv-qualification than the class type B.
- if (DTy.isMoreQualifiedThan(BTy))
- return false;
-
- return true;
-}
-
-/// \returns decayed type for arrays and functions.
-static QualType getDecayedType(QualType Type) {
- if (const auto *Decayed = Type->getAs<DecayedType>())
- return Decayed->getDecayedType();
- return 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();
- if (NumParamA != NumParamB)
- return false;
-
- for (unsigned I = 0; I < NumParamA; I++) {
- if (getDecayedType(BaseMD->getParamDecl(I)->getType().getCanonicalType()) !=
- getDecayedType(
- DerivedMD->getParamDecl(I)->getType().getCanonicalType()))
- return false;
- }
- return true;
-}
-
-/// \returns true if derived method can override base method except for the
-/// name.
-static bool checkOverrideWithoutName(const ASTContext *Context,
- const CXXMethodDecl *BaseMD,
- const CXXMethodDecl *DerivedMD) {
- if (BaseMD->isStatic() != DerivedMD->isStatic())
- return false;
-
- if (BaseMD->getType() == DerivedMD->getType())
- return true;
-
- // Now the function types are not identical. Then check if the return types
- // are covariant and if the param types are the same.
- if (!checkOverridingFunctionReturnType(Context, BaseMD, DerivedMD))
- return false;
- return checkParamTypes(BaseMD, DerivedMD);
-}
-
-/// Check whether BaseMD overrides DerivedMD.
-///
-/// Prerequisite: the class which BaseMD is in should be a base class of that
-/// DerivedMD is in.
-static bool checkOverrideByDerivedMethod(const CXXMethodDecl *BaseMD,
- const CXXMethodDecl *DerivedMD) {
- for (CXXMethodDecl::method_iterator I = DerivedMD->begin_overridden_methods(),
- E = DerivedMD->end_overridden_methods();
- I != E; ++I) {
- const CXXMethodDecl *OverriddenMD = *I;
- if (BaseMD->getCanonicalDecl() == OverriddenMD->getCanonicalDecl())
- return true;
- }
-
- return false;
-}
-
-bool VirtualNearMissCheck::isPossibleToBeOverridden(
- const CXXMethodDecl *BaseMD) {
- auto Iter = PossibleMap.find(BaseMD);
- if (Iter != PossibleMap.end())
- return Iter->second;
-
- bool IsPossible = !BaseMD->isImplicit() && !isa<CXXConstructorDecl>(BaseMD) &&
- !isa<CXXDestructorDecl>(BaseMD) && BaseMD->isVirtual() &&
- !BaseMD->isOverloadedOperator() &&
- !isa<CXXConversionDecl>(BaseMD);
- PossibleMap[BaseMD] = IsPossible;
- return IsPossible;
-}
-
-bool VirtualNearMissCheck::isOverriddenByDerivedClass(
- const CXXMethodDecl *BaseMD, const CXXRecordDecl *DerivedRD) {
- auto Key = std::make_pair(BaseMD, DerivedRD);
- auto Iter = OverriddenMap.find(Key);
- if (Iter != OverriddenMap.end())
- return Iter->second;
-
- bool IsOverridden = false;
- for (const CXXMethodDecl *DerivedMD : DerivedRD->methods()) {
- if (!isOverrideMethod(DerivedMD))
- continue;
-
- if (checkOverrideByDerivedMethod(BaseMD, DerivedMD)) {
- IsOverridden = true;
- break;
- }
- }
- OverriddenMap[Key] = IsOverridden;
- return IsOverridden;
-}
-
-void VirtualNearMissCheck::registerMatchers(MatchFinder *Finder) {
- if (!getLangOpts().CPlusPlus)
- return;
-
- Finder->addMatcher(
- cxxMethodDecl(
- unless(anyOf(isOverride(), isImplicit(), cxxConstructorDecl(),
- cxxDestructorDecl(), cxxConversionDecl(), isStatic(),
- isOverloadedOperator())))
- .bind("method"),
- this);
-}
-
-void VirtualNearMissCheck::check(const MatchFinder::MatchResult &Result) {
- const auto *DerivedMD = Result.Nodes.getNodeAs<CXXMethodDecl>("method");
- assert(DerivedMD);
-
- const ASTContext *Context = Result.Context;
-
- const auto *DerivedRD = DerivedMD->getParent()->getDefinition();
- assert(DerivedRD);
-
- for (const auto &BaseSpec : DerivedRD->bases()) {
- if (const auto *BaseRD = BaseSpec.getType()->getAsCXXRecordDecl()) {
- for (const auto *BaseMD : BaseRD->methods()) {
- if (!isPossibleToBeOverridden(BaseMD))
- continue;
-
- if (isOverriddenByDerivedClass(BaseMD, DerivedRD))
- continue;
-
- unsigned EditDistance = BaseMD->getName().edit_distance(
- DerivedMD->getName(), EditDistanceThreshold);
- if (EditDistance > 0 && EditDistance <= EditDistanceThreshold) {
- if (checkOverrideWithoutName(Context, BaseMD, DerivedMD)) {
- // A "virtual near miss" is found.
- auto Range = CharSourceRange::getTokenRange(
- SourceRange(DerivedMD->getLocation()));
-
- bool ApplyFix = !BaseMD->isTemplateInstantiation() &&
- !DerivedMD->isTemplateInstantiation();
- auto Diag =
- diag(DerivedMD->getLocStart(),
- "method '%0' has a similar name and the same signature as "
- "virtual method '%1'; did you mean to override it?")
- << DerivedMD->getQualifiedNameAsString()
- << BaseMD->getQualifiedNameAsString();
- if (ApplyFix)
- Diag << FixItHint::CreateReplacement(Range, BaseMD->getName());
- }
- }
- }
- }
- }
-}
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.h b/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.h
deleted file mode 100644
index 3d3b9eba762..00000000000
--- a/clang-tools-extra/clang-tidy/misc/VirtualNearMissCheck.h
+++ /dev/null
@@ -1,65 +0,0 @@
-//===--- VirtualNearMissCheck.h - clang-tidy---------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_VIRTUAL_NEAR_MISS_H
-#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_VIRTUAL_NEAR_MISS_H
-
-#include "../ClangTidy.h"
-#include "llvm/ADT/DenseMap.h"
-
-namespace clang {
-namespace tidy {
-namespace misc {
-
-/// \brief Checks for near miss of virtual methods.
-///
-/// For a method in a derived class, this check looks for virtual method with a
-/// very similar name and an identical signature defined in a base class.
-///
-/// For the user-facing documentation see:
-/// http://clang.llvm.org/extra/clang-tidy/checks/misc-virtual-near-miss.html
-class VirtualNearMissCheck : public ClangTidyCheck {
-public:
- VirtualNearMissCheck(StringRef Name, ClangTidyContext *Context)
- : ClangTidyCheck(Name, Context) {}
- void registerMatchers(ast_matchers::MatchFinder *Finder) override;
- void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
-
-private:
- /// Check if the given method is possible to be overridden by some other
- /// method. Operators and destructors are excluded.
- ///
- /// Results are memoized in PossibleMap.
- bool isPossibleToBeOverridden(const CXXMethodDecl *BaseMD);
-
- /// Check if the given base method is overridden by some methods in the given
- /// derived class.
- ///
- /// Results are memoized in OverriddenMap.
- bool isOverriddenByDerivedClass(const CXXMethodDecl *BaseMD,
- const CXXRecordDecl *DerivedRD);
-
- /// Key: the unique ID of a method.
- /// Value: whether the method is possible to be overridden.
- llvm::DenseMap<const CXXMethodDecl *, bool> PossibleMap;
-
- /// Key: <unique ID of base method, name of derived class>
- /// Value: whether the base method is overridden by some method in the derived
- /// class.
- llvm::DenseMap<std::pair<const CXXMethodDecl *, const CXXRecordDecl *>, bool>
- OverriddenMap;
-
- const unsigned EditDistanceThreshold = 1;
-};
-
-} // namespace misc
-} // namespace tidy
-} // namespace clang
-
-#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_VIRTUAL_NEAR_MISS_H
OpenPOWER on IntegriCloud