trixirt created this revision.
trixirt added reviewers: alexfh, nickdesaulniers.
trixirt added projects: clang, clang-tools-extra.
Herald added subscribers: cfe-commits, xazax.hun, mgorny.
trixirt requested review of this revision.

Cleaning up -Wextra-semi-stmt in the linux kernel shows a high
incidence of 'switch() {} ;' The ';' is not needed.

This is special case of the Parser::ConsumeExtraSemi() fixer.
This fixer allows the fixes to be batched and takes care of the
formatting issue of having an empty line when the ';' is removed.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D90180

Files:
  clang-tools-extra/clang-tidy/linuxkernel/CMakeLists.txt
  clang-tools-extra/clang-tidy/linuxkernel/LinuxKernelTidyModule.cpp
  clang-tools-extra/clang-tidy/linuxkernel/SwitchSemiCheck.cpp
  clang-tools-extra/clang-tidy/linuxkernel/SwitchSemiCheck.h
  clang-tools-extra/test/clang-tidy/checkers/linuxkernel-switch-semi.c

Index: clang-tools-extra/test/clang-tidy/checkers/linuxkernel-switch-semi.c
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/linuxkernel-switch-semi.c
@@ -0,0 +1,13 @@
+// RUN: %check_clang_tidy %s linuxkernel-switch-semi %t
+
+int f(int a) {
+  switch (a) {
+  case 1:
+    return 0;
+  default:
+    break;
+  };
+  // CHECK-MESSAGES: warning: unneeded semicolon
+  // CHECK-MESSAGES: note: FIX-IT applied suggested code changes
+  return 0;
+}
Index: clang-tools-extra/clang-tidy/linuxkernel/SwitchSemiCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/linuxkernel/SwitchSemiCheck.h
@@ -0,0 +1,30 @@
+//===--- SwitchSemiCheck.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_LINUXKERNEL_SWITCHSEMICHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LINUXKERNEL_SWITCHSEMICHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace linuxkernel {
+
+class SwitchSemiCheck : public ClangTidyCheck {
+public:
+  SwitchSemiCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace linuxkernel
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_LINUXKERNEL_SWITCHSEMICHECK_H
Index: clang-tools-extra/clang-tidy/linuxkernel/SwitchSemiCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/linuxkernel/SwitchSemiCheck.cpp
@@ -0,0 +1,50 @@
+//===--- SwitchSemiCheck.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 "SwitchSemiCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace linuxkernel {
+
+void SwitchSemiCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+      compoundStmt(has(switchStmt().bind("switch"))).bind("comp"), this);
+}
+
+void SwitchSemiCheck::check(const MatchFinder::MatchResult &Result) {
+  auto *C = Result.Nodes.getNodeAs<CompoundStmt>("comp");
+  auto *S = Result.Nodes.getNodeAs<SwitchStmt>("switch");
+
+  auto Current = C->body_begin();
+  auto Next = Current;
+  Next++;
+  while (Next != C->body_end()) {
+    if (*Current == S) {
+      if (const auto *N = dyn_cast<NullStmt>(*Next)) {
+        if (!N->hasLeadingEmptyMacro() && S->getBody()->getEndLoc().isValid() &&
+            N->getSemiLoc().isValid()) {
+          auto H = FixItHint::CreateReplacement(
+              SourceRange(S->getBody()->getEndLoc(), N->getSemiLoc()), "}");
+          diag(N->getSemiLoc(), "unneeded semicolon") << H;
+          break;
+        }
+      }
+    }
+    Current = Next;
+    Next++;
+  }
+}
+
+} // namespace linuxkernel
+} // namespace tidy
+} // namespace clang
Index: clang-tools-extra/clang-tidy/linuxkernel/LinuxKernelTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/linuxkernel/LinuxKernelTidyModule.cpp
+++ clang-tools-extra/clang-tidy/linuxkernel/LinuxKernelTidyModule.cpp
@@ -10,6 +10,7 @@
 #include "../ClangTidyModule.h"
 #include "../ClangTidyModuleRegistry.h"
 #include "MustCheckErrsCheck.h"
+#include "SwitchSemiCheck.h"
 
 namespace clang {
 namespace tidy {
@@ -21,6 +22,8 @@
   void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
     CheckFactories.registerCheck<MustCheckErrsCheck>(
         "linuxkernel-must-check-errs");
+    CheckFactories.registerCheck<SwitchSemiCheck>(
+        "linuxkernel-switch-semi");
   }
 };
 // Register the LinuxKernelTidyModule using this statically initialized
Index: clang-tools-extra/clang-tidy/linuxkernel/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/linuxkernel/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/linuxkernel/CMakeLists.txt
@@ -6,6 +6,7 @@
 add_clang_library(clangTidyLinuxKernelModule
   LinuxKernelTidyModule.cpp
   MustCheckErrsCheck.cpp
+  SwitchSemiCheck.cpp
 
   LINK_LIBS
   clangTidy
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to