barancsuk created this revision.
barancsuk added a project: clang-tools-extra.
Herald added subscribers: baloghadamsoftware, xazax.hun, whisperity, 
JDevlieghere, mgorny.

Checks for member expressions that access static members through instances, and
replaces them with the corresponding expressions that use a more readable `::` 
operator.

Example:

The following code:

  struct C {
    static void foo();
    static int x;
  };
  
  C *c1=new C();
  c1->foo();
  c1->x;

is changed to:

  C::foo();
  C::x;


Repository:
  rL LLVM

https://reviews.llvm.org/D35937

Files:
  clang-tidy/readability/CMakeLists.txt
  clang-tidy/readability/ReadabilityTidyModule.cpp
  clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
  clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
  docs/ReleaseNotes.rst
  docs/clang-tidy/checks/list.rst
  docs/clang-tidy/checks/readability-static-accessed-through-instance.rst
  test/clang-tidy/readability-static-accessed-through-instance.cpp

Index: test/clang-tidy/readability-static-accessed-through-instance.cpp
===================================================================
--- /dev/null
+++ test/clang-tidy/readability-static-accessed-through-instance.cpp
@@ -0,0 +1,137 @@
+// RUN: %check_clang_tidy %s readability-static-accessed-through-instance %t
+
+struct C {
+  static void foo();
+  static int x;
+  int nsx;
+  void mf() {
+    (void)&x;    // OK, x is accessed inside the struct.
+    (void)&C::x; // OK, x is accessed using the scope operator.
+    foo();       // OK, foo() is accessed inside the struct.
+  }
+};
+
+struct CC {
+  void foo();
+  int x;
+};
+
+template <typename T> struct CT {
+  static T foo();
+  static T x;
+  int nsx;
+  void mf() {
+    (void)&x;    // OK, x is accessed inside the struct.
+    (void)&C::x; // OK, x is accessed using the scope operator.
+    foo();       // OK, foo() is accessed inside the struct.
+  }
+};
+
+C &f(int, int, int, int);
+void g() {
+  f(1, 2, 3, 4).x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  C::x;{{$}}
+}
+
+template <typename T> T CT<T>::x;
+
+template <typename T> struct CCT {
+  T foo();
+  T x;
+};
+
+typedef C D;
+
+using E = D;
+
+#define FOO(c) c.foo()
+#define X(c) c.x
+
+template <typename T> void f(T t, C c) {
+  t.x; // OK, t is a template parameter.
+  c.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  C::x;{{$}}
+}
+
+template <int N> struct S { static int x; };
+
+template <> struct S<0> { int x; };
+
+template <int N> void h() {
+  S<N> sN;
+  sN.x; // OK, value of N affects whether x is static or not.
+
+  S<2> s2;
+  s2.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  S<2>::x;{{$}}
+}
+
+void static_through_instance() {
+  C *c1 = new C();
+  c1->foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  C::foo();{{$}}
+  c1->x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  C::x;{{$}}
+  c1->nsx; // OK, nsx is a non-static member.
+
+  C::foo(); // OK, foo() is accessed using the scope operator.
+  C::x;     // OK, x is accessed using the scope operator.
+
+  D d;
+  d.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  D::foo();{{$}}
+  d.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  D::x;{{$}}
+
+  E e;
+  e.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  E::foo();{{$}}
+  e.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  E::x;{{$}}
+
+  CC *cc = new CC;
+
+  f(*c1, *c1);
+  f(*cc, *c1);
+
+  // Macros: OK, macros are not checked.
+  FOO((*c1));
+  X((*c1));
+  FOO((*cc));
+  X((*cc));
+
+  // Templates
+  CT<int> ct;
+  ct.foo();
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  CT<int>::foo();{{$}}
+  ct.x;
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: static member accessed through
+  // instance  [readability-static-accessed-through-instance]
+  // CHECK-FIXES: {{^}}  CT<int>::x;{{$}}
+  ct.nsx; // OK, nsx is a non-static member
+
+  CCT<int> cct;
+  cct.foo(); // OK, CCT has no static members.
+  cct.x;     // OK, CCT has no static members.
+
+  h<4>();
+}
Index: docs/clang-tidy/checks/readability-static-accessed-through-instance.rst
===================================================================
--- /dev/null
+++ docs/clang-tidy/checks/readability-static-accessed-through-instance.rst
@@ -0,0 +1,30 @@
+.. title:: clang-tidy - readability-static-accessed-through-instance
+
+readability-static-accessed-through-instance
+============================================
+
+Checks for member expressions that access static members through instances, and
+replaces them with the corresponding expressions that use a more readable `::` operator.
+
+Example:
+
+Thefollowing code:
+
+.. code-block:: c++
+
+  struct C {
+    static void foo();
+    static int x;
+  };
+
+  C *c1=new C();
+  c1->foo();
+  c1->x;
+
+is changed to:
+
+.. code-block:: c++
+
+  C::foo();
+  C::x;
+
Index: docs/clang-tidy/checks/list.rst
===================================================================
--- docs/clang-tidy/checks/list.rst
+++ docs/clang-tidy/checks/list.rst
@@ -175,5 +175,6 @@
    readability-redundant-string-cstr
    readability-redundant-string-init
    readability-simplify-boolean-expr
+   readability-static-accessed-through-instance
    readability-static-definition-in-anonymous-namespace
    readability-uniqueptr-delete-release
Index: docs/ReleaseNotes.rst
===================================================================
--- docs/ReleaseNotes.rst
+++ docs/ReleaseNotes.rst
@@ -142,6 +142,12 @@
 
   Finds misleading indentation where braces should be introduced or the code should be reformatted.
 
+- New `readability-static-accessed-through-instance
+  <http://clang.llvm.org/extra/clang-tidy/checks/readability-static-accessed-through-instance.html>`_ check
+
+  Finds member expressions that access static members through instances and
+  replaces them with the corresponding expressions that use a more readable scope operator.
+
 - Support clang-formatting of the code around applied fixes (``-format-style``
   command-line option).
 
Index: clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
===================================================================
--- /dev/null
+++ clang-tidy/readability/StaticAccessedThroughInstanceCheck.h
@@ -0,0 +1,36 @@
+//===--- StaticAccessedThroughInstanceCheck.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_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+/// \@brief Checks for member expressions that access static members through instances
+/// and replaces them with calls to the preferred, more readable `::` operator.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/readability-static-accessed-through-instance.html
+class StaticAccessedThroughInstanceCheck : public ClangTidyCheck {
+public:
+  StaticAccessedThroughInstanceCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_READABILITY_STATIC_ACCESSED_THROUGH_INSTANCE_H
Index: clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
===================================================================
--- /dev/null
+++ clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -0,0 +1,59 @@
+//===--- StaticAccessedThroughInstanceCheck.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 "StaticAccessedThroughInstanceCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace readability {
+
+void StaticAccessedThroughInstanceCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      memberExpr(hasDeclaration(anyOf(cxxMethodDecl(isStaticStorageClass()),
+                                      varDecl(hasStaticStorageDuration()))),
+                 unless(isInTemplateInstantiation()))
+          .bind("memberExpression"),
+      this);
+}
+
+void StaticAccessedThroughInstanceCheck::check(
+    const MatchFinder::MatchResult &Result) {
+  const auto *MemberExpression =
+      Result.Nodes.getNodeAs<MemberExpr>("memberExpression");
+
+  if (MemberExpression->getLocStart().isMacroID())
+    return;
+
+  const Expr *BaseExpr = MemberExpression->getBase();
+
+  QualType BaseType =
+      BaseExpr->getType()->isPointerType()
+          ? BaseExpr->getType().getUnqualifiedType()->getPointeeType()
+          : BaseExpr->getType().getUnqualifiedType();
+
+  PrintingPolicy PrintingPolicyWithSupressedTag(Result.Context->getLangOpts());
+  PrintingPolicyWithSupressedTag.SuppressTagKeyword = true;
+  std::string BaseTypeName =
+      BaseType.getAsString(PrintingPolicyWithSupressedTag);
+
+  diag(MemberExpression->getLocStart(),
+       "static member accessed through instance")
+      << FixItHint::CreateReplacement(
+          CharSourceRange::getCharRange(MemberExpression->getLocStart(),
+                                        MemberExpression->getMemberLoc()),
+          BaseTypeName + "::");
+}
+
+} // namespace readability
+} // namespace tidy
+} // namespace clang
Index: clang-tidy/readability/ReadabilityTidyModule.cpp
===================================================================
--- clang-tidy/readability/ReadabilityTidyModule.cpp
+++ clang-tidy/readability/ReadabilityTidyModule.cpp
@@ -32,6 +32,7 @@
 #include "RedundantStringCStrCheck.h"
 #include "RedundantStringInitCheck.h"
 #include "SimplifyBooleanExprCheck.h"
+#include "StaticAccessedThroughInstanceCheck.h"
 #include "StaticDefinitionInAnonymousNamespaceCheck.h"
 #include "UniqueptrDeleteReleaseCheck.h"
 
@@ -70,6 +71,8 @@
         "readability-redundant-function-ptr-dereference");
     CheckFactories.registerCheck<RedundantMemberInitCheck>(
         "readability-redundant-member-init");
+    CheckFactories.registerCheck<StaticAccessedThroughInstanceCheck>(
+        "readability-static-accessed-through-instance");
     CheckFactories.registerCheck<StaticDefinitionInAnonymousNamespaceCheck>(
         "readability-static-definition-in-anonymous-namespace");
     CheckFactories.registerCheck<readability::NamedParameterCheck>(
Index: clang-tidy/readability/CMakeLists.txt
===================================================================
--- clang-tidy/readability/CMakeLists.txt
+++ clang-tidy/readability/CMakeLists.txt
@@ -25,6 +25,7 @@
   RedundantSmartptrGetCheck.cpp
   RedundantStringInitCheck.cpp
   SimplifyBooleanExprCheck.cpp
+  StaticAccessedThroughInstanceCheck.cpp
   StaticDefinitionInAnonymousNamespaceCheck.cpp
   UniqueptrDeleteReleaseCheck.cpp
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to