trixirt updated this revision to Diff 300830. trixirt added a comment. Comment on the matcher Comment explaining need to look for empty macro Add test for normal switch Add test for switch with empty macro Fix formatting
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D90180/new/ 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,37 @@ +// 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; +} + +// A normal switch, should not produce a warning +int p1(int a) { + switch (a) { + case 1: + return 0; + default: + break; + } + return 0; +} + +#define EMPTY_MACRO() +// A corner case, do not fix an empty macro +int p2(int a) { + switch (a) { + case 1: + return 0; + default: + break; + } + EMPTY_MACRO(); + 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,76 @@ +//===--- 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) { + // From the reproducer + // void foo (int a) { + // switch (a) {}; + // } + // The AST + // `-FunctionDecl + // |-ParmVarDecl + // `-CompoundStmt <--- "comp", 'C' + // |-SwitchStmt <-- "switch", 'S' + // | |-ImplicitCastExpr + // | | `-DeclRefExpr + // | `-CompoundStmt + // `-NullStmt <-------------- 'N' + 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)) { + // This code has the same AST as the reproducer + // + // #define EMPTY() + // void foo (int a) { + // switch (a) {} EMPTY(); + // } + // + // But we do not want to remove the ; because the + // macro may only be conditionally empty. + // ex/ the release version of a debug macro + // + // So check that the NullStmt does not have a + // leading empty macro. + 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,7 @@ 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