Hi alexfh,
Replace `x.reset(y.release());` with `x = std::move(y);`
If y is rvalue, replace with `x = y;` instead
http://reviews.llvm.org/D6485
Files:
clang-tidy/misc/CMakeLists.txt
clang-tidy/misc/MiscTidyModule.cpp
clang-tidy/misc/UniqueptrResetRelease.cpp
clang-tidy/misc/UniqueptrResetRelease.h
test/clang-tidy/uniqueptr-reset-release.cpp
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -7,6 +7,7 @@
SwappedArgumentsCheck.cpp
UndelegatedConstructor.cpp
UnusedRAII.cpp
+ UniqueptrResetRelease.cpp
UseOverride.cpp
LINK_LIBS
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -15,6 +15,7 @@
#include "SwappedArgumentsCheck.h"
#include "UndelegatedConstructor.h"
#include "UnusedRAII.h"
+#include "UniqueptrResetRelease.h"
#include "UseOverride.h"
namespace clang {
@@ -30,6 +31,8 @@
"misc-swapped-arguments");
CheckFactories.registerCheck<UndelegatedConstructorCheck>(
"misc-undelegated-constructor");
+ CheckFactories.registerCheck<UniqueptrResetRelease>(
+ "misc-uniqueptr-reset-release");
CheckFactories.registerCheck<UnusedRAIICheck>("misc-unused-raii");
CheckFactories.registerCheck<UseOverride>("misc-use-override");
}
Index: clang-tidy/misc/UniqueptrResetRelease.cpp
===================================================================
--- clang-tidy/misc/UniqueptrResetRelease.cpp
+++ clang-tidy/misc/UniqueptrResetRelease.cpp
@@ -0,0 +1,75 @@
+//===--- 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"
+
+// #include "clang/AST/ASTContext.h"
+// #include "clang/AST/Decl.h"
+// #include "clang/Basic/CharInfo.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 ast_matchers::MatchFinder::MatchResult &result) {
+ const auto* reset_member = result.Nodes.getNodeAs<MemberExpr>("reset_member");
+ const auto* release_member =
+ result.Nodes.getNodeAs<MemberExpr>("release_member");
+ const auto* right = result.Nodes.getNodeAs<Expr>("right");
+ const auto* left = result.Nodes.getNodeAs<Expr>("left");
+ const auto* reset_call =
+ result.Nodes.getNodeAs<CXXMemberCallExpr>("reset_call");
+
+ std::string left_text = clang::Lexer::getSourceText(
+ CharSourceRange::getTokenRange(left->getSourceRange()),
+ *result.SourceManager, result.Context->getLangOpts());
+ std::string right_text = clang::Lexer::getSourceText(
+ CharSourceRange::getTokenRange(right->getSourceRange()),
+ *result.SourceManager, result.Context->getLangOpts());
+
+ if (reset_member->isArrow()) {
+ left_text = "*" + left_text;
+ }
+ if (release_member->isArrow()) {
+ right_text = "*" + right_text;
+ }
+ // Even if x was rvalue, *x is not rvalue anymore
+ if (!right->isRValue() || release_member->isArrow()) {
+ right_text = "std::move(" + right_text + ")";
+ }
+ std::string new_text = left_text + " = " + right_text;
+
+ diag(reset_member->getExprLoc(),
+ "Prefer std::move over ptr1.reset(ptr2.release())")
+ << FixItHint::CreateReplacement(
+ CharSourceRange::getTokenRange(reset_call->getSourceRange()),
+ new_text);
+}
+
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/misc/UniqueptrResetRelease.h
===================================================================
--- clang-tidy/misc/UniqueptrResetRelease.h
+++ clang-tidy/misc/UniqueptrResetRelease.h
@@ -0,0 +1,36 @@
+//===--- UniqueptrResetRelease.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_MISC_UNIQUEPTR_RESET_RELEASE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNIQUEPTR_RESET_RELEASE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+/// \brief Find and replace unique_ptr::reset(release()) with std::move
+///
+/// Example:
+/// std::unique_ptr<Foo> x, y;
+/// x.reset(y.release()); -> x = std::move(y);
+///
+/// If "y" is already rvalue, std::move is not added.
+/// "x" and "y" can also be std::unique_ptr<Foo>*.
+class UniqueptrResetRelease : public ClangTidyCheck {
+public:
+ using ClangTidyCheck::ClangTidyCheck;
+ void registerMatchers(ast_matchers::MatchFinder *finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &result) override;
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_UNIQUEPTR_RESET_RELEASE_H
Index: test/clang-tidy/uniqueptr-reset-release.cpp
===================================================================
--- test/clang-tidy/uniqueptr-reset-release.cpp
+++ test/clang-tidy/uniqueptr-reset-release.cpp
@@ -0,0 +1,50 @@
+// RUN: $(dirname %s)/check_clang_tidy.sh %s misc-uniqueptr-reset-release %t
+// REQUIRES: shell
+
+// CHECK-NOT: warning
+
+namespace std {
+template <typename T>
+struct unique_ptr {
+ unique_ptr<T>();
+ explicit unique_ptr<T>(T*);
+ template <typename U>
+ unique_ptr<T>(unique_ptr<U>&&);
+ void reset(T*);
+ T* release();
+};
+} // namespace std
+
+struct Foo {};
+struct Bar : Foo {};
+
+std::unique_ptr<Foo> Create();
+std::unique_ptr<Foo>& Look();
+std::unique_ptr<Foo>* Get();
+
+void f() {
+ std::unique_ptr<Foo> a, b;
+ std::unique_ptr<Bar> c;
+ std::unique_ptr<Foo>* x = &a;
+ std::unique_ptr<Foo>* y = &b;
+
+ a.reset(b.release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Prefer std::move over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: a = std::move(b);
+ a.reset(c.release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Prefer std::move over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: a = std::move(c);
+ a.reset(Create().release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: Prefer std::move over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: a = Create();
+ x->reset(y->release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: Prefer std::move over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: *x = std::move(*y);
+ Look().reset(Look().release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Prefer std::move over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: Look() = std::move(Look());
+ Get()->reset(Get()->release());
+ // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: Prefer std::move over ptr1.reset(ptr2.release()) [misc-uniqueptr-reset-release]
+ // CHECK-FIXES: *Get() = std::move(*Get());
+}
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits