nullptr.cpp created this revision.
nullptr.cpp added reviewers: alexfh, aaron.ballman, njames93, balazske.
Herald added subscribers: xazax.hun, mgorny.
nullptr.cpp requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Finds redundant `using` declarations and directives.

Example:

  namespace n {
  void func();
  }
  
  namespace  {
  using n::func; // redundant using declaration, already in namespace 'n'.
  }



  namespace n {
  using namespace n; // redundant using directive, already in namespace 'n'.
  }


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D97361

Files:
  clang-tools-extra/clang-tidy/misc/CMakeLists.txt
  clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
  clang-tools-extra/clang-tidy/misc/RedundantUsingCheck.cpp
  clang-tools-extra/clang-tidy/misc/RedundantUsingCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/docs/clang-tidy/checks/misc-redundant-using.rst
  clang-tools-extra/test/clang-tidy/checkers/misc-redundant-using.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc-redundant-using.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/misc-redundant-using.cpp
@@ -0,0 +1,114 @@
+// RUN: %check_clang_tidy %s misc-redundant-using %t
+
+namespace n1 {
+using namespace n1;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: using directive 'n1' is redundant, already in namespace 'n1' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:17: note: remove the using directive
+// CHECK-FIXES: {{^}}
+} // namespace n1
+
+namespace n2 {
+using namespace n1; // ok
+}
+
+namespace n3 {
+namespace n = n3;
+using namespace n;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: using directive 'n' is redundant, already in namespace 'n3' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:17: note: remove the using directive
+// CHECK-FIXES: {{^}}
+} // namespace n3
+
+namespace n4 {
+namespace inner {
+using namespace n4;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: using directive 'n4' is redundant, already in namespace 'n4' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:17: note: remove the using directive
+// CHECK-FIXES: {{^}}
+
+using namespace n4::inner;
+// CHECK-MESSAGES: :[[@LINE-1]]:21: warning: using directive 'inner' is redundant, already in namespace 'inner' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:21: note: remove the using directive
+// CHECK-FIXES: {{^}}
+
+namespace n = n4::inner;
+using namespace n;
+// CHECK-MESSAGES: :[[@LINE-1]]:17: warning: using directive 'n' is redundant, already in namespace 'inner' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:17: note: remove the using directive
+// CHECK-FIXES: {{^}}
+} // namespace inner
+} // namespace n4
+
+namespace n5 {
+namespace inner {
+using namespace n4::inner; // ok
+}
+} // namespace n5
+
+namespace n6 {
+void func();
+
+using n6::func;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: using declaration 'func' is redundant, already in namespace 'n6' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:11: note: remove the using declaration
+// CHECK-FIXES: {{^}}
+} // namespace n6
+
+namespace n7 {
+using n6::func; // ok
+}
+
+namespace n8 {
+void func();
+
+namespace n = n8;
+using n::func;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using declaration 'func' is redundant, already in namespace 'n8' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:10: note: remove the using declaration
+// CHECK-FIXES: {{^}}
+} // namespace n8
+
+namespace n9 {
+void outerFunc();
+
+namespace inner {
+using n9::outerFunc;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: using declaration 'outerFunc' is redundant, already in namespace 'n9' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:11: note: remove the using declaration
+// CHECK-FIXES: {{^}}
+
+void innerFunc();
+using inner::innerFunc;
+// CHECK-MESSAGES: :[[@LINE-1]]:14: warning: using declaration 'innerFunc' is redundant, already in namespace 'inner' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:14: note: remove the using declaration
+// CHECK-FIXES: {{^}}
+
+using n9::inner::innerFunc;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: using declaration 'innerFunc' is redundant, already in namespace 'inner' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:18: note: remove the using declaration
+// CHECK-FIXES: {{^}}
+
+namespace n = n9::inner;
+using n::innerFunc;
+// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: using declaration 'innerFunc' is redundant, already in namespace 'inner' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:10: note: remove the using declaration
+// CHECK-FIXES: {{^}}
+} // namespace inner
+} // namespace n9
+
+namespace n10 {
+namespace inner {
+using n9::inner::innerFunc; // ok
+}
+} // namespace n10
+
+namespace n11 {
+void func();
+}
+
+namespace n11 {
+using n11::func;
+// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: using declaration 'func' is redundant, already in namespace 'n11' [misc-redundant-using]
+// CHECK-MESSAGES: :[[@LINE-2]]:12: note: remove the using declaration
+// CHECK-FIXES: {{^}}
+} // namespace n11
Index: clang-tools-extra/docs/clang-tidy/checks/misc-redundant-using.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/misc-redundant-using.rst
@@ -0,0 +1,25 @@
+.. title:: clang-tidy - misc-redundant-using
+
+misc-redundant-using
+====================
+
+Finds redundant ``using`` declarations and directives.
+
+Example:
+
+.. code-block:: c++
+
+  namespace n {
+  void func();
+  }
+
+  namespace  {
+  using n::func; // redundant using declaration, already in namespace 'n'.
+  }
+
+.. code-block:: c++
+
+  namespace n {
+  using namespace n; // redundant using directive, already in namespace 'n'.
+  }
+
Index: clang-tools-extra/docs/clang-tidy/checks/list.rst
===================================================================
--- clang-tools-extra/docs/clang-tidy/checks/list.rst
+++ clang-tools-extra/docs/clang-tidy/checks/list.rst
@@ -208,6 +208,7 @@
    `misc-non-copyable-objects <misc-non-copyable-objects.html>`_,
    `misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_,
    `misc-redundant-expression <misc-redundant-expression.html>`_, "Yes"
+   `misc-redundant-using <misc-redundant-using.html>`_, "Yes"
    `misc-static-assert <misc-static-assert.html>`_, "Yes"
    `misc-throw-by-value-catch-by-reference <misc-throw-by-value-catch-by-reference.html>`_,
    `misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_,
Index: clang-tools-extra/docs/ReleaseNotes.rst
===================================================================
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -85,6 +85,11 @@
   Finds member initializations in the constructor body which can be placed into
   the initialization list instead.
 
+- New :doc:`misc-redundant-using
+  <clang-tidy/checks/misc-redundant-using>` check.
+
+  Finds redundant ``using`` declarations and directives.
+
 New check aliases
 ^^^^^^^^^^^^^^^^^
 
Index: clang-tools-extra/clang-tidy/misc/RedundantUsingCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/RedundantUsingCheck.h
@@ -0,0 +1,44 @@
+//===--- RedundantUsingCheck.h - clang-tidy ---------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANTUSINGCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANTUSINGCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+/// Finds redundant using declarations and directives.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/misc-redundant-using.html
+class RedundantUsingCheck : public ClangTidyCheck {
+public:
+  RedundantUsingCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+
+private:
+  void checkUsingDecl(const UsingDecl *Declaration,
+                      const ast_matchers::MatchFinder::MatchResult &Result);
+  void
+  checkUsingDirective(const UsingDirectiveDecl *Directive,
+                      const ast_matchers::MatchFinder::MatchResult &Result);
+  void diagUsing(const char *Type, const Decl *Using, const NamedDecl *ND,
+                 const NamespaceDecl *NSD,
+                 const ast_matchers::MatchFinder::MatchResult &Result);
+};
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MISC_REDUNDANTUSINGCHECK_H
Index: clang-tools-extra/clang-tidy/misc/RedundantUsingCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/misc/RedundantUsingCheck.cpp
@@ -0,0 +1,86 @@
+//===--- RedundantUsingCheck.cpp - clang-tidy
+//--------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "RedundantUsingCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace misc {
+
+void RedundantUsingCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      usingDecl(isExpansionInMainFile()).bind("using-declaration"), this);
+  Finder->addMatcher(
+      usingDirectiveDecl(isExpansionInMainFile()).bind("using-directive"),
+      this);
+}
+
+void RedundantUsingCheck::check(const MatchFinder::MatchResult &Result) {
+  if (const auto *Declaration =
+          Result.Nodes.getNodeAs<UsingDecl>("using-declaration")) {
+    checkUsingDecl(Declaration, Result);
+  }
+
+  if (const auto *Directive =
+          Result.Nodes.getNodeAs<UsingDirectiveDecl>("using-directive")) {
+    checkUsingDirective(Directive, Result);
+  }
+}
+
+void RedundantUsingCheck::checkUsingDecl(
+    const UsingDecl *Declaration, const MatchFinder::MatchResult &Result) {
+  const DeclContext *DC = Declaration->getDeclContext();
+
+  for (const auto *UsingShadow : Declaration->shadows()) {
+    const Decl *TargetDecl = UsingShadow->getTargetDecl()->getCanonicalDecl();
+
+    if (TargetDecl->getDeclContext()->Encloses(DC)) {
+      const auto *NSD = cast<NamespaceDecl>(TargetDecl->getDeclContext());
+      diagUsing("declaration", Declaration, Declaration, NSD, Result);
+    }
+  }
+}
+
+void RedundantUsingCheck::checkUsingDirective(
+    const UsingDirectiveDecl *Directive,
+    const MatchFinder::MatchResult &Result) {
+  const NamespaceDecl *NDNominated = Directive->getNominatedNamespace();
+  const DeclContext *DC = Directive->getDeclContext();
+
+  if (NDNominated->Encloses(DC)) {
+    const NamedDecl *NDAsWritten = Directive->getNominatedNamespaceAsWritten();
+
+    diagUsing("directive", Directive, NDAsWritten, NDNominated, Result);
+  }
+}
+void RedundantUsingCheck::diagUsing(const char *Type, const Decl *Using,
+                                    const NamedDecl *ND,
+                                    const NamespaceDecl *NSD,
+                                    const MatchFinder::MatchResult &Result) {
+  SourceLocation End =
+      Lexer::findLocationAfterToken(Using->getEndLoc(), tok::semi,
+                                    *Result.SourceManager, getLangOpts(), true);
+  CharSourceRange RemoveRange =
+      CharSourceRange::getCharRange(Using->getBeginLoc(), End);
+
+  diag(Using->getLocation(),
+       "using %0 %1 is redundant, already in namespace %2")
+      << Type << ND << NSD;
+  diag(Using->getLocation(), "remove the using %0", DiagnosticIDs::Note)
+      << Type << FixItHint::CreateRemoval(RemoveRange);
+}
+
+} // namespace misc
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
+++ clang-tools-extra/clang-tidy/misc/MiscTidyModule.cpp
@@ -16,6 +16,7 @@
 #include "NonCopyableObjects.h"
 #include "NonPrivateMemberVariablesInClassesCheck.h"
 #include "RedundantExpressionCheck.h"
+#include "RedundantUsingCheck.h"
 #include "StaticAssertCheck.h"
 #include "ThrowByValueCatchByReferenceCheck.h"
 #include "UnconventionalAssignOperatorCheck.h"
@@ -43,6 +44,7 @@
         "misc-non-private-member-variables-in-classes");
     CheckFactories.registerCheck<RedundantExpressionCheck>(
         "misc-redundant-expression");
+    CheckFactories.registerCheck<RedundantUsingCheck>("misc-redundant-using");
     CheckFactories.registerCheck<StaticAssertCheck>("misc-static-assert");
     CheckFactories.registerCheck<ThrowByValueCatchByReferenceCheck>(
         "misc-throw-by-value-catch-by-reference");
Index: clang-tools-extra/clang-tidy/misc/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/misc/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/misc/CMakeLists.txt
@@ -12,6 +12,7 @@
   NonCopyableObjects.cpp
   NonPrivateMemberVariablesInClassesCheck.cpp
   RedundantExpressionCheck.cpp
+  RedundantUsingCheck.cpp
   StaticAssertCheck.cpp
   ThrowByValueCatchByReferenceCheck.cpp
   UnconventionalAssignOperatorCheck.cpp
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to