diff options
author | Alexander Kornienko <alexfh@google.com> | 2018-03-15 08:27:42 +0000 |
---|---|---|
committer | Alexander Kornienko <alexfh@google.com> | 2018-03-15 08:27:42 +0000 |
commit | 32a44d6e3a088d33b2e7a93d7cfc428ec946ae4c (patch) | |
tree | f87f08f4c1709019887b40858064b528803e852c /clang-tidy/bugprone | |
parent | 8c06718c3910e60534bb55dd0a521a882cee7ce1 (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.cpp | 3 | ||||
-rw-r--r-- | clang-tidy/bugprone/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang-tidy/bugprone/UnusedRaiiCheck.cpp | 94 | ||||
-rw-r--r-- | clang-tidy/bugprone/UnusedRaiiCheck.h | 35 |
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 |