blob: 0a648e208de863d7cbcd61c82030bf657c769417 [file] [log] [blame]
//===--- UniqueptrResetRelease.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 "UniqueptrResetRelease.h"
#include "clang/ASTMatchers/ASTMatchFinder.h"
#include "clang/Lex/Lexer.h"
using namespace clang::ast_matchers;
namespace clang {
namespace tidy {
void UniqueptrResetRelease::registerMatchers(MatchFinder *Finder) {
Finder->addMatcher(
memberCallExpr(
on(expr().bind("left")), callee(memberExpr().bind("reset_member")),
callee(methodDecl(hasName("reset"),
ofClass(hasName("::std::unique_ptr")))),
has(memberCallExpr(
on(expr().bind("right")),
callee(memberExpr().bind("release_member")),
callee(methodDecl(hasName("release"),
ofClass(hasName("::std::unique_ptr")))))))
.bind("reset_call"),
this);
}
void UniqueptrResetRelease::check(const MatchFinder::MatchResult &Result) {
const auto *ResetMember = Result.Nodes.getNodeAs<MemberExpr>("reset_member");
const auto *ReleaseMember =
Result.Nodes.getNodeAs<MemberExpr>("release_member");
const auto *Right = Result.Nodes.getNodeAs<Expr>("right");
const auto *Left = Result.Nodes.getNodeAs<Expr>("left");
const auto *ResetCall =
Result.Nodes.getNodeAs<CXXMemberCallExpr>("reset_call");
std::string LeftText = clang::Lexer::getSourceText(
CharSourceRange::getTokenRange(Left->getSourceRange()),
*Result.SourceManager, Result.Context->getLangOpts());
std::string RightText = clang::Lexer::getSourceText(
CharSourceRange::getTokenRange(Right->getSourceRange()),
*Result.SourceManager, Result.Context->getLangOpts());
if (ResetMember->isArrow())
LeftText = "*" + LeftText;
if (ReleaseMember->isArrow())
RightText = "*" + RightText;
// Even if x was rvalue, *x is not rvalue anymore.
if (!Right->isRValue() || ReleaseMember->isArrow())
RightText = "std::move(" + RightText + ")";
std::string NewText = LeftText + " = " + RightText;
diag(ResetMember->getExprLoc(),
"prefer ptr1 = std::move(ptr2) over ptr1.reset(ptr2.release())")
<< FixItHint::CreateReplacement(
CharSourceRange::getTokenRange(ResetCall->getSourceRange()), NewText);
}
} // namespace tidy
} // namespace clang