aboutsummaryrefslogtreecommitdiff
path: root/clang-tidy/bugprone
diff options
context:
space:
mode:
authorAlexander Kornienko <alexfh@google.com>2018-03-15 08:27:42 +0000
committerAlexander Kornienko <alexfh@google.com>2018-03-15 08:27:42 +0000
commit32a44d6e3a088d33b2e7a93d7cfc428ec946ae4c (patch)
treef87f08f4c1709019887b40858064b528803e852c /clang-tidy/bugprone
parent8c06718c3910e60534bb55dd0a521a882cee7ce1 (diff)
[clang-tidy] rename_check.py misc-unused-raii bugprone-unused-raii --check_class_name=UnusedRAIICheck
git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@327610 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'clang-tidy/bugprone')
-rw-r--r--clang-tidy/bugprone/BugproneTidyModule.cpp3
-rw-r--r--clang-tidy/bugprone/CMakeLists.txt1
-rw-r--r--clang-tidy/bugprone/UnusedRaiiCheck.cpp94
-rw-r--r--clang-tidy/bugprone/UnusedRaiiCheck.h35
4 files changed, 133 insertions, 0 deletions
diff --git a/clang-tidy/bugprone/BugproneTidyModule.cpp b/clang-tidy/bugprone/BugproneTidyModule.cpp
index ac218d7c..5849da24 100644
--- a/clang-tidy/bugprone/BugproneTidyModule.cpp
+++ b/clang-tidy/bugprone/BugproneTidyModule.cpp
@@ -42,6 +42,7 @@
#include "ThrowKeywordMissingCheck.h"
#include "UndefinedMemoryManipulationCheck.h"
#include "UndelegatedConstructorCheck.h"
+#include "UnusedRaiiCheck.h"
#include "UseAfterMoveCheck.h"
#include "VirtualNearMissCheck.h"
@@ -116,6 +117,8 @@ public:
"bugprone-undefined-memory-manipulation");
CheckFactories.registerCheck<UndelegatedConstructorCheck>(
"bugprone-undelegated-constructor");
+ CheckFactories.registerCheck<UnusedRaiiCheck>(
+ "bugprone-unused-raii");
CheckFactories.registerCheck<UseAfterMoveCheck>(
"bugprone-use-after-move");
CheckFactories.registerCheck<VirtualNearMissCheck>(
diff --git a/clang-tidy/bugprone/CMakeLists.txt b/clang-tidy/bugprone/CMakeLists.txt
index 1c8b9b46..9d52852d 100644
--- a/clang-tidy/bugprone/CMakeLists.txt
+++ b/clang-tidy/bugprone/CMakeLists.txt
@@ -34,6 +34,7 @@ add_clang_library(clangTidyBugproneModule
ThrowKeywordMissingCheck.cpp
UndefinedMemoryManipulationCheck.cpp
UndelegatedConstructorCheck.cpp
+ UnusedRaiiCheck.cpp
UseAfterMoveCheck.cpp
VirtualNearMissCheck.cpp
diff --git a/clang-tidy/bugprone/UnusedRaiiCheck.cpp b/clang-tidy/bugprone/UnusedRaiiCheck.cpp
new file mode 100644
index 00000000..e2882f37
--- /dev/null
+++ b/clang-tidy/bugprone/UnusedRaiiCheck.cpp
@@ -0,0 +1,94 @@
+//===--- UnusedRaiiCheck.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 "UnusedRaiiCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+namespace {
+AST_MATCHER(CXXRecordDecl, hasNonTrivialDestructor) {
+ // TODO: If the dtor is there but empty we don't want to warn either.
+ return Node.hasDefinition() && Node.hasNonTrivialDestructor();
+}
+} // namespace
+
+void UnusedRaiiCheck::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;
+
+ // Look for temporaries that are constructed in-place and immediately
+ // destroyed. Look for temporaries created by a functional cast but not for
+ // those returned from a call.
+ auto BindTemp =
+ cxxBindTemporaryExpr(unless(has(ignoringParenImpCasts(callExpr()))))
+ .bind("temp");
+ Finder->addMatcher(
+ exprWithCleanups(unless(isInTemplateInstantiation()),
+ hasParent(compoundStmt().bind("compound")),
+ hasType(cxxRecordDecl(hasNonTrivialDestructor())),
+ anyOf(has(ignoringParenImpCasts(BindTemp)),
+ has(ignoringParenImpCasts(cxxFunctionalCastExpr(
+ has(ignoringParenImpCasts(BindTemp)))))))
+ .bind("expr"),
+ this);
+}
+
+void UnusedRaiiCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
+
+ // We ignore code expanded from macros to reduce the number of false
+ // positives.
+ if (E->getLocStart().isMacroID())
+ return;
+
+ // Don't emit a warning for the last statement in the surrounding compund
+ // statement.
+ const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>("compound");
+ if (E == CS->body_back())
+ return;
+
+ // Emit a warning.
+ auto D = diag(E->getLocStart(), "object destroyed immediately after "
+ "creation; did you mean to name the object?");
+ const char *Replacement = " give_me_a_name";
+
+ // If this is a default ctor we have to remove the parens or we'll introduce a
+ // most vexing parse.
+ const auto *BTE = Result.Nodes.getNodeAs<CXXBindTemporaryExpr>("temp");
+ if (const auto *TOE = dyn_cast<CXXTemporaryObjectExpr>(BTE->getSubExpr()))
+ if (TOE->getNumArgs() == 0) {
+ D << FixItHint::CreateReplacement(
+ CharSourceRange::getTokenRange(TOE->getParenOrBraceRange()),
+ Replacement);
+ return;
+ }
+
+ // Otherwise just suggest adding a name. To find the place to insert the name
+ // find the first TypeLoc in the children of E, which always points to the
+ // written type.
+ auto Matches =
+ match(expr(hasDescendant(typeLoc().bind("t"))), *E, *Result.Context);
+ const auto *TL = selectFirst<TypeLoc>("t", Matches);
+ D << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(TL->getLocEnd(), 0, *Result.SourceManager,
+ getLangOpts()),
+ Replacement);
+}
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tidy/bugprone/UnusedRaiiCheck.h b/clang-tidy/bugprone/UnusedRaiiCheck.h
new file mode 100644
index 00000000..34190ece
--- /dev/null
+++ b/clang-tidy/bugprone/UnusedRaiiCheck.h
@@ -0,0 +1,35 @@
+//===--- UnusedRaiiCheck.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_BUGPRONE_UNUSEDRAIICHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDRAIICHECK_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace bugprone {
+
+/// Finds temporaries that look like RAII objects.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/bugprone-unused-raii.html
+class UnusedRaiiCheck : public ClangTidyCheck {
+public:
+ UnusedRaiiCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace bugprone
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_BUGPRONE_UNUSEDRAIICHECK_H