clang-tools  14.0.0git
UnusedRaiiCheck.cpp
Go to the documentation of this file.
1 //===--- UnusedRaiiCheck.cpp - clang-tidy ---------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "UnusedRaiiCheck.h"
10 #include "clang/AST/ASTContext.h"
11 #include "clang/Lex/Lexer.h"
12 
13 using namespace clang::ast_matchers;
14 
15 namespace clang {
16 namespace tidy {
17 namespace bugprone {
18 
19 namespace {
20 AST_MATCHER(CXXRecordDecl, hasNonTrivialDestructor) {
21  // TODO: If the dtor is there but empty we don't want to warn either.
22  return Node.hasDefinition() && Node.hasNonTrivialDestructor();
23 }
24 } // namespace
25 
26 void UnusedRaiiCheck::registerMatchers(MatchFinder *Finder) {
27  // Look for temporaries that are constructed in-place and immediately
28  // destroyed.
29  Finder->addMatcher(
30  mapAnyOf(cxxConstructExpr, cxxUnresolvedConstructExpr)
31  .with(hasParent(compoundStmt().bind("compound")),
32  anyOf(hasType(cxxRecordDecl(hasNonTrivialDestructor())),
33  hasType(templateSpecializationType(
34  hasDeclaration(classTemplateDecl(has(
35  cxxRecordDecl(hasNonTrivialDestructor()))))))))
36  .bind("expr"),
37  this);
38 }
39 
40 template <typename T>
41 void reportDiagnostic(DiagnosticBuilder D, const T *Node, SourceRange SR,
42  bool DefaultConstruction) {
43  const char *Replacement = " give_me_a_name";
44 
45  // If this is a default ctor we have to remove the parens or we'll introduce a
46  // most vexing parse.
47  if (DefaultConstruction) {
48  D << FixItHint::CreateReplacement(CharSourceRange::getTokenRange(SR),
49  Replacement);
50  return;
51  }
52 
53  // Otherwise just suggest adding a name. To find the place to insert the name
54  // find the first TypeLoc in the children of E, which always points to the
55  // written type.
56  D << FixItHint::CreateInsertion(SR.getBegin(), Replacement);
57 }
58 
59 void UnusedRaiiCheck::check(const MatchFinder::MatchResult &Result) {
60  const auto *E = Result.Nodes.getNodeAs<Expr>("expr");
61 
62  // We ignore code expanded from macros to reduce the number of false
63  // positives.
64  if (E->getBeginLoc().isMacroID())
65  return;
66 
67  // Don't emit a warning for the last statement in the surrounding compound
68  // statement.
69  const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>("compound");
70  const auto *LastExpr = dyn_cast<Expr>(CS->body_back());
71 
72  if (LastExpr && E == LastExpr->IgnoreUnlessSpelledInSource())
73  return;
74 
75  // Emit a warning.
76  auto D = diag(E->getBeginLoc(), "object destroyed immediately after "
77  "creation; did you mean to name the object?");
78 
79  if (const auto *Node = dyn_cast<CXXConstructExpr>(E))
80  reportDiagnostic(D, Node, Node->getParenOrBraceRange(),
81  Node->getNumArgs() == 0 ||
82  isa<CXXDefaultArgExpr>(Node->getArg(0)));
83  if (const auto *Node = dyn_cast<CXXUnresolvedConstructExpr>(E)) {
84  auto SR = SourceRange(Node->getLParenLoc(), Node->getRParenLoc());
85  auto DefaultConstruction = Node->getNumArgs() == 0;
86  if (!DefaultConstruction) {
87  auto *FirstArg = Node->getArg(0);
88  DefaultConstruction = isa<CXXDefaultArgExpr>(FirstArg);
89  if (auto *ILE = dyn_cast<InitListExpr>(FirstArg)) {
90  DefaultConstruction = ILE->getNumInits() == 0;
91  SR = SourceRange(ILE->getLBraceLoc(), ILE->getRBraceLoc());
92  }
93  }
94  reportDiagnostic(D, Node, SR, DefaultConstruction);
95  }
96 }
97 
98 } // namespace bugprone
99 } // namespace tidy
100 } // namespace clang
E
const Expr * E
Definition: AvoidBindCheck.cpp:88
clang::ast_matchers
Definition: AbseilMatcher.h:14
ns1::ns2::D
@ D
Definition: CategoricalFeature.h:3
clang::ast_matchers::AST_MATCHER
AST_MATCHER(Expr, isMacroID)
Definition: PreferIsaOrDynCastInConditionalsCheck.cpp:19
clang::clangd::check
bool check(llvm::StringRef File, llvm::function_ref< bool(const Position &)> ShouldCheckLine, const ThreadsafeFS &TFS, const ClangdLSPServer::Options &Opts, bool EnableCodeCompletion)
Definition: Check.cpp:259
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
UnusedRaiiCheck.h
clang::tidy::bugprone::reportDiagnostic
void reportDiagnostic(DiagnosticBuilder D, const T *Node, SourceRange SR, bool DefaultConstruction)
Definition: UnusedRaiiCheck.cpp:41