11 #include "clang/AST/ASTContext.h"
12 #include "clang/Lex/Lexer.h"
14 using namespace clang::ast_matchers;
21 AST_MATCHER(CXXRecordDecl, hasNonTrivialDestructor) {
23 return Node.hasDefinition() && Node.hasNonTrivialDestructor();
27 void UnusedRAIICheck::registerMatchers(MatchFinder *
Finder) {
30 if (!getLangOpts().CPlusPlus)
37 cxxBindTemporaryExpr(unless(has(ignoringParenImpCasts(callExpr()))))
40 exprWithCleanups(unless(isInTemplateInstantiation()),
41 hasParent(compoundStmt().bind(
"compound")),
42 hasType(cxxRecordDecl(hasNonTrivialDestructor())),
43 anyOf(has(ignoringParenImpCasts(BindTemp)),
44 has(ignoringParenImpCasts(cxxFunctionalCastExpr(
45 has(ignoringParenImpCasts(BindTemp)))))))
50 void UnusedRAIICheck::check(
const MatchFinder::MatchResult &Result) {
51 const auto *E = Result.Nodes.getNodeAs<Expr>(
"expr");
55 if (E->getLocStart().isMacroID())
60 const auto *CS = Result.Nodes.getNodeAs<CompoundStmt>(
"compound");
61 if (E == CS->body_back())
65 auto D = diag(E->getLocStart(),
"object destroyed immediately after "
66 "creation; did you mean to name the object?");
67 const char *Replacement =
" give_me_a_name";
71 const auto *BTE = Result.Nodes.getNodeAs<CXXBindTemporaryExpr>(
"temp");
72 if (
const auto *TOE = dyn_cast<CXXTemporaryObjectExpr>(BTE->getSubExpr()))
73 if (TOE->getNumArgs() == 0) {
74 D << FixItHint::CreateReplacement(
75 CharSourceRange::getTokenRange(TOE->getParenOrBraceRange()),
84 match(expr(hasDescendant(typeLoc().bind(
"t"))), *E, *Result.Context);
85 const auto *TL = selectFirst<TypeLoc>(
"t", Matches);
86 D << FixItHint::CreateInsertion(
87 Lexer::getLocForEndOfToken(TL->getLocEnd(), 0, *Result.SourceManager,
std::unique_ptr< ast_matchers::MatchFinder > Finder
AST_MATCHER(VarDecl, isAsm)