11 #include "clang/AST/ASTContext.h"
12 #include "clang/Lex/Lexer.h"
14 using namespace clang::ast_matchers;
18 AST_MATCHER(CXXRecordDecl, hasNonTrivialDestructor) {
20 return Node.hasDefinition() && Node.hasNonTrivialDestructor();
27 void UnusedRAIICheck::registerMatchers(MatchFinder *
Finder) {
30 if (!getLangOpts().CPlusPlus)
36 auto BindTemp = cxxBindTemporaryExpr(unless(has(callExpr()))).bind(
"temp");
39 unless(isInTemplateInstantiation()),
40 hasParent(compoundStmt().bind(
"compound")),
41 hasType(cxxRecordDecl(hasNonTrivialDestructor())),
42 anyOf(has(BindTemp), has(cxxFunctionalCastExpr(has(BindTemp)))))
47 void UnusedRAIICheck::check(
const MatchFinder::MatchResult &
Result) {
48 const auto *E = Result.Nodes.getStmtAs<Expr>(
"expr");
52 if (E->getLocStart().isMacroID())
57 const auto *CS = Result.Nodes.getStmtAs<CompoundStmt>(
"compound");
58 if (E == CS->body_back())
62 auto D = diag(E->getLocStart(),
"object destroyed immediately after "
63 "creation; did you mean to name the object?");
64 const char *Replacement =
" give_me_a_name";
68 const auto *BTE = Result.Nodes.getStmtAs<CXXBindTemporaryExpr>(
"temp");
69 if (
const auto *TOE = dyn_cast<CXXTemporaryObjectExpr>(BTE->getSubExpr()))
70 if (TOE->getNumArgs() == 0) {
71 D << FixItHint::CreateReplacement(
72 CharSourceRange::getTokenRange(TOE->getParenOrBraceRange()),
81 match(expr(hasDescendant(typeLoc().bind(
"t"))), *E, *Result.Context);
82 const auto *TL = selectFirst<TypeLoc>(
"t", Matches);
83 D << FixItHint::CreateInsertion(
84 Lexer::getLocForEndOfToken(TL->getLocEnd(), 0, *Result.SourceManager,
85 Result.Context->getLangOpts()),
std::unique_ptr< ast_matchers::MatchFinder > Finder
AST_MATCHER(Stmt, isInsideOfRangeBeginEndStmt)