baloghadamsoftware created this revision.
baloghadamsoftware added reviewers: alexfh, hokein.
baloghadamsoftware added subscribers: cfe-commits, xazax.hun.

Finds return statements in assign operator bodies where the return value is 
different from '*this'. Only assignment operators with correct return value 
Class& are checked.

http://reviews.llvm.org/D18265

Files:
  clang-tidy/misc/AssignOperatorReturnCheck.cpp
  clang-tidy/misc/AssignOperatorReturnCheck.h
  clang-tidy/misc/CMakeLists.txt
  clang-tidy/misc/MiscTidyModule.cpp
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/misc-assign-operator-return.rst
  test/clang-tidy/misc-assign-operator-return.cpp

Index: test/clang-tidy/misc-assign-operator-return.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/misc-assign-operator-return.cpp
@@ -0,0 +1,23 @@
+// RUN: %check_clang_tidy %s misc-assign-operator-return %t -- -- -std=c++11 =isystem %S/Inputs/Headers
+
+#include <utility>
+
+struct S {
+  int n;
+
+  S& operator=(const S& rhs) {
+    n = rhs.n;
+    return *this;
+  }
+
+  S& operator=(S&& rhs) {
+    n = std::move(rhs.n);
+    return rhs;
+// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: operator=() should always return '*this'
+  }
+
+  int operator=(int i) {
+    n = i;
+    return n;
+  }
+};
Index: docs/clang-tidy/checks/misc-assign-operator-return.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/misc-assign-operator-return.rst
@@ -0,0 +1,7 @@
+.. title:: clang-tidy - misc-assign-operator-return
+
+misc-assign-operator-return
+===========================
+
+Finds return statements in assign operator bodies where the return value is
+different from '*this'.
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -48,6 +48,7 @@
    llvm-twine-local
    misc-argument-comment
    misc-assert-side-effect
+   misc-assign-operator-return
    misc-assign-operator-signature
    misc-bool-pointer-implicit-conversion
    misc-definitions-in-headers
Index: clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tidy/misc/MiscTidyModule.cpp
@@ -12,6 +12,7 @@
 #include "../ClangTidyModuleRegistry.h"
 #include "ArgumentCommentCheck.h"
 #include "AssertSideEffectCheck.h"
+#include "AssignOperatorReturnCheck.h"
 #include "AssignOperatorSignatureCheck.h"
 #include "BoolPointerImplicitConversionCheck.h"
 #include "DefinitionsInHeadersCheck.h"
@@ -50,6 +51,8 @@
     CheckFactories.registerCheck<ArgumentCommentCheck>("misc-argument-comment");
     CheckFactories.registerCheck<AssertSideEffectCheck>(
         "misc-assert-side-effect");
+    CheckFactories.registerCheck<AssignOperatorReturnCheck>(
+        "misc-assign-operator-return");
     CheckFactories.registerCheck<AssignOperatorSignatureCheck>(
         "misc-assign-operator-signature");
     CheckFactories.registerCheck<BoolPointerImplicitConversionCheck>(
Index: clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tidy/misc/CMakeLists.txt
+++ clang-tidy/misc/CMakeLists.txt
@@ -3,6 +3,7 @@
 add_clang_library(clangTidyMiscModule
   ArgumentCommentCheck.cpp
   AssertSideEffectCheck.cpp
+  AssignOperatorReturnCheck.cpp
   AssignOperatorSignatureCheck.cpp
   BoolPointerImplicitConversionCheck.cpp
   DefinitionsInHeadersCheck.cpp
Index: clang-tidy/misc/AssignOperatorReturnCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/misc/AssignOperatorReturnCheck.h
@@ -0,0 +1,33 @@
+//===--- AssignOperatorReturnCheck.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_ASSIGN_OPERATOR_RETURN_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSIGN_OPERATOR_RETURN_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds return statements in assign operator bodies where the return value is
+/// different from '*this'.
+class AssignOperatorReturnCheck : public ClangTidyCheck {
+public:
+  AssignOperatorReturnCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_ASSIGN_OPERATOR_RETURN_H
Index: clang-tidy/misc/AssignOperatorReturnCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/misc/AssignOperatorReturnCheck.cpp
@@ -0,0 +1,47 @@
+//===--- AssignOperatorReturnCheck.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 "AssignOperatorReturnCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void AssignOperatorReturnCheck::registerMatchers(MatchFinder *Finder) {
+  // Only register the matchers for C++; the functionality currently does not
+  // provide any benefit to other languages, despite being benign.
+  if (!getLangOpts().CPlusPlus)
+    return;
+
+  const auto IsAssign =
+    cxxMethodDecl(hasName("operator="), ofClass(recordDecl().bind("class")));
+  const auto HasGoodReturnType = cxxMethodDecl(returns(
+      lValueReferenceType(pointee(hasDeclaration(equalsBoundNode("class"))))));
+  const auto IsGoodAssign = cxxMethodDecl(IsAssign, HasGoodReturnType);
+  const auto IsBadReturn =
+    returnStmt(unless(has(unaryOperator(hasOperatorName("*"),
+                                        hasUnaryOperand(cxxThisExpr())))));
+  Finder->addMatcher(
+      returnStmt(IsBadReturn, hasAncestor(IsGoodAssign)).bind("returnStmt"),
+      this);
+}
+
+void AssignOperatorReturnCheck::check(const MatchFinder::MatchResult &Result) {
+  // FIXME: Add callback implementation.
+  const auto *RetStmt = Result.Nodes.getNodeAs<ReturnStmt>("returnStmt");
+  diag(RetStmt->getLocStart(), "operator=() should always return '*this'");
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to