From fcb676e0863a057fc323875301b5c59df08eca32 Mon Sep 17 00:00:00 2001 From: daquexian <daquexian566@gmail.com> Date: Thu, 15 Jul 2021 12:06:44 +0800 Subject: [PATCH] new static check based on clang-tidy (#5476) * new static check based on clang-tidy Signed-off-by: daquexian <daquexian566@gmail.com> * set compiler as clang to generate right compile_commands.json, skip build Signed-off-by: daquexian <daquexian566@gmail.com> * include clang headers Signed-off-by: daquexian <daquexian566@gmail.com> * build third party Signed-off-by: daquexian <daquexian566@gmail.com> * install deps Signed-off-by: daquexian <daquexian566@gmail.com> * build third party by gcc, generate compile_commands.json by clang Signed-off-by: daquexian <daquexian566@gmail.com> * rm CMakeCache.txt Signed-off-by: daquexian <daquexian566@gmail.com> * run of_git_version Signed-off-by: daquexian <daquexian566@gmail.com> * download clang-tidy from oneflow-inc/llvm-project repo Signed-off-by: daquexian <daquexian566@gmail.com> * rename check name Signed-off-by: daquexian <daquexian566@gmail.com> * remove old clang plugin Signed-off-by: daquexian <daquexian566@gmail.com> Co-authored-by: oneflow-ci-bot <69100618+oneflow-ci-bot@users.noreply.github.com> --- .clang-tidy | 4 + .github/workflows/test.yml | 52 +++---- tools/clang-plugin/.clang-format | 1 - tools/clang-plugin/.gitignore | 4 - tools/clang-plugin/CMakeLists.txt | 66 --------- .../CheckUnusedMaybe/CMakeLists.txt | 18 --- .../CheckUnusedMaybe/CheckUnusedMaybe.cpp | 134 ------------------ .../CheckUnusedMaybe/unused_maybe_example.cpp | 8 -- 8 files changed, 24 insertions(+), 263 deletions(-) create mode 100644 .clang-tidy delete mode 100644 tools/clang-plugin/.clang-format delete mode 100644 tools/clang-plugin/.gitignore delete mode 100644 tools/clang-plugin/CMakeLists.txt delete mode 100644 tools/clang-plugin/CheckUnusedMaybe/CMakeLists.txt delete mode 100644 tools/clang-plugin/CheckUnusedMaybe/CheckUnusedMaybe.cpp delete mode 100644 tools/clang-plugin/CheckUnusedMaybe/unused_maybe_example.cpp diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 000000000..d5935e488 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,4 @@ +# maybe-* checks are only available on OneFlow custom clang-tidy and clangd +Checks: '-*, maybe-*' +# TODO: treat all maybe warnings as errors when existing warnings are all fixed +WarningsAsErrors: 'maybe-unused' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a45142400..78f718010 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -92,8 +92,8 @@ jobs: run: | exit 1 - static_analysis_with_clang_plug_in: - name: Static analysis with Clang plug-in + static_analysis_with_clang: + name: Static analysis with clang runs-on: ubuntu-20.04 if: github.event.pull_request.draft == false && contains(github.event.pull_request.requested_reviewers.*.login, 'oneflow-ci-bot') steps: @@ -104,48 +104,36 @@ jobs: repository: ${{github.event.pull_request.head.repo.full_name}} - name: Install dependencies run: | - wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | sudo apt-key add - - sudo apt-add-repository "deb http://apt.llvm.org/focal/ llvm-toolchain-focal-12 main" sudo apt-get update - sudo apt-get install -y llvm-12 llvm-12-dev llvm-12-tools clang-12 libclang-common-12-dev libclang-12-dev \ - libopenblas-dev nasm python3-pip ninja-build - - name: Set environment variables - run: | - set -x - echo "CC=clang-12" >> $GITHUB_ENV - echo "CXX=clang++-12" >> $GITHUB_ENV - - name: Build Clang plug-in + sudo apt-get install -y libopenblas-dev nasm python3-pip ninja-build + - name: Download OneFlow custom clang-tidy run: | - cd tools/clang-plugin - mkdir build - cd build - cmake .. -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCP_LLVM_INSTALL_DIR=/usr/lib/llvm-12 - make -j$(nproc) - clang_plugin_path="${PWD}/lib/libCheckUnusedMaybe.so" - ldd ${clang_plugin_path} - echo "clang_plugin_path=${clang_plugin_path}" >> $GITHUB_ENV - - name: Build (third party) + wget https://github.com/oneflow-inc/llvm-project/releases/download/latest/clang-tidy + wget https://raw.githubusercontent.com/oneflow-inc/llvm-project/maybe/clang-tools-extra/clang-tidy/tool/run-clang-tidy.py + chmod +x clang-tidy run-clang-tidy.py + - name: Build third party libs and generate files run: | mkdir build cd build - # clang-12 produces many warnings on oneflow, -w to suppress them + # clang-tidy has builtin includes, but doesn't work here + # https://clang.llvm.org/docs/LibTooling.html#builtin-includes cmake .. -C ../cmake/caches/international/cpu.cmake \ -DCMAKE_BUILD_TYPE=Release \ - -DBUILD_TESTING=ON \ - -DTHIRD_PARTY=ON \ - -DONEFLOW=OFF \ - -DCMAKE_CXX_FLAGS="-w" - cmake --build . -j$(nproc) - - name: Check unused Maybe (by building OneFlow with Clang plug-in) + -DBUILD_TESTING=ON + cmake --build . -j$(nproc) --target of_git_version oneflow_deps generate_functional of_cfgobj generate_py_cfg + - name: Run Maybe-related checks by clang-tidy run: | cd build + rm CMakeCache.txt cmake .. -C ../cmake/caches/international/cpu.cmake \ + -DCMAKE_C_COMPILER=clang-12 \ + -DCMAKE_CXX_COMPILER=clang++-12 \ + -DCMAKE_CXX_FLAGS="-isystem /usr/lib/llvm-12/lib/clang/12.0.1/include/" \ -DCMAKE_BUILD_TYPE=Release \ -DBUILD_TESTING=ON \ - -DTHIRD_PARTY=OFF \ - -DONEFLOW=ON \ - -DCMAKE_CXX_FLAGS="-w -fplugin=${{ env.clang_plugin_path }}" - cmake --build . -j$(nproc) + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + cd .. + ./run-clang-tidy.py -clang-tidy-binary ./clang-tidy -p build -quiet wait_for_gpu_slot: name: Wait for GPU slots diff --git a/tools/clang-plugin/.clang-format b/tools/clang-plugin/.clang-format deleted file mode 100644 index 9b3aa8b72..000000000 --- a/tools/clang-plugin/.clang-format +++ /dev/null @@ -1 +0,0 @@ -BasedOnStyle: LLVM diff --git a/tools/clang-plugin/.gitignore b/tools/clang-plugin/.gitignore deleted file mode 100644 index 413e45698..000000000 --- a/tools/clang-plugin/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -build/ -build-*/ -.cache/ -compile_commands.json diff --git a/tools/clang-plugin/CMakeLists.txt b/tools/clang-plugin/CMakeLists.txt deleted file mode 100644 index 7e5b98a2c..000000000 --- a/tools/clang-plugin/CMakeLists.txt +++ /dev/null @@ -1,66 +0,0 @@ -cmake_minimum_required(VERSION 3.10) -project(clang-plugins CXX) - -set(CP_LLVM_INSTALL_DIR "" CACHE PATH "LLVM installation directory") - -# A bit of a sanity checking -set(CP_LLVM_INCLUDE_DIR "${CP_LLVM_INSTALL_DIR}/include/llvm") -if(NOT EXISTS "${CP_LLVM_INCLUDE_DIR}") -message(FATAL_ERROR - "${CP_LLVM_INCLUDE_DIR} does not exist, CP_LLVM_INSTALL_DIR (${CP_LLVM_INSTALL_DIR}) is invalid") -endif() - -set(CP_LLVM_CMAKE_FILE "${CP_LLVM_INSTALL_DIR}/lib/cmake/clang/ClangConfig.cmake") -if(NOT EXISTS "${CP_LLVM_CMAKE_FILE}") -message(FATAL_ERROR - " CP_LLVM_CMAKE_FILE (${CP_LLVM_CMAKE_FILE}) is invalid.") -endif() - -#=============================================================================== -# 2. LOAD CLANG CONFIGURATION -# For more: http://llvm.org/docs/CMake.html#embedding-llvm-in-your-project -#=============================================================================== -list(APPEND CMAKE_PREFIX_PATH "${CP_LLVM_INSTALL_DIR}/lib/cmake/llvm/") -list(APPEND CMAKE_PREFIX_PATH "${CP_LLVM_INSTALL_DIR}/lib/cmake/clang/") - -find_package(Clang REQUIRED CONFIG) - -# Sanity check. As Clang does not expose e.g. `CLANG_VERSION_MAJOR` through -# AddClang.cmake, we have to use LLVM_VERSION_MAJOR instead. -# TODO: Revisit when next version is released. -if(NOT "12" VERSION_EQUAL "${LLVM_VERSION_MAJOR}") - message(FATAL_ERROR "Found LLVM ${LLVM_VERSION_MAJOR}, but need LLVM 12") -endif() - -message(STATUS "Found Clang ${LLVM_PACKAGE_VERSION}") -message(STATUS "Using ClangConfig.cmake in: ${CP_LLVM_INSTALL_DIR}") - -message("CLANG STATUS: - Includes (clang) ${CLANG_INCLUDE_DIRS} - Includes (llvm) ${LLVM_INCLUDE_DIRS}" -) - -# Set the LLVM and Clang header and library paths -include_directories(SYSTEM "${LLVM_INCLUDE_DIRS};${CLANG_INCLUDE_DIRS}") - -#=============================================================================== -# 3. BUILD CONFIGURATION -#=============================================================================== -# Use the same C++ standard as LLVM does -set(CMAKE_CXX_STANDARD 14 CACHE STRING "") - -# -fvisibility-inlines-hidden is set when building LLVM and on Darwin warnings -# are triggered if llvm-tutor is built without this flag (though otherwise it -# builds fine). For consistency, add it here too. -include(CheckCXXCompilerFlag) -check_cxx_compiler_flag("-fvisibility-inlines-hidden" SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG) -if (${SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG} EQUAL "1") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility-inlines-hidden") -endif() - -# Set the build directories -set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/bin") -set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/lib") - -add_subdirectory(CheckUnusedMaybe) - diff --git a/tools/clang-plugin/CheckUnusedMaybe/CMakeLists.txt b/tools/clang-plugin/CheckUnusedMaybe/CMakeLists.txt deleted file mode 100644 index 15a321fa4..000000000 --- a/tools/clang-plugin/CheckUnusedMaybe/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -add_library(CheckUnusedMaybe SHARED CheckUnusedMaybe.cpp) - -# On Darwin (unlike on Linux), undefined symbols in shared objects are not -# allowed at the end of the link-edit. The plugins defined here: -# - _are_ shared objects -# - reference symbols from LLVM shared libraries, i.e. symbols which are -# undefined until those shared objects are loaded in memory (and hence -# _undefined_ during static linking) -# The build will fail with errors like this: -# "Undefined symbols for architecture x86_64" -# with various LLVM symbols being undefined. Since those symbols are later -# loaded and resolved at runtime, these errors are false positives. -# This behaviour can be modified via the '-undefined' OS X linker flag as -# follows. -target_link_libraries( - CheckUnusedMaybe - "$<$<PLATFORM_ID:Darwin>:-undefined dynamic_lookup>" - ) diff --git a/tools/clang-plugin/CheckUnusedMaybe/CheckUnusedMaybe.cpp b/tools/clang-plugin/CheckUnusedMaybe/CheckUnusedMaybe.cpp deleted file mode 100644 index 899e185f8..000000000 --- a/tools/clang-plugin/CheckUnusedMaybe/CheckUnusedMaybe.cpp +++ /dev/null @@ -1,134 +0,0 @@ -#include "clang/AST/ASTConsumer.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/RecursiveASTVisitor.h" -#include "clang/AST/Stmt.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/FrontendAction.h" -#include "clang/Frontend/FrontendPluginRegistry.h" -#include "clang/Tooling/Tooling.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/CrashRecoveryContext.h" - -using namespace clang; - -class CheckUnusedMaybeVisitor - : public RecursiveASTVisitor<CheckUnusedMaybeVisitor> { -public: - explicit CheckUnusedMaybeVisitor(ASTContext *Context) : Context(Context) { - { - auto skip_filenames_env = - llvm::StringRef(std::getenv("ONEFLOW_MAYBE_CHECK_SKIP_FN")); - if (!skip_filenames_env.empty()) { - skip_filenames_env.split(skip_filenames, ";"); - for (const auto &x : skip_filenames) { - llvm::outs() << "skip: " << x << "\n"; - } - } - } - { - auto only_filenames_env = - llvm::StringRef(std::getenv("ONEFLOW_MAYBE_CHECK_ONLY_FN")); - if (!only_filenames_env.empty()) { - only_filenames_env.split(only_filenames, ";"); - for (const auto &x : only_filenames) { - llvm::outs() << "only: " << x << "\n"; - } - } - } - } - - virtual bool VisitCompoundStmt(CompoundStmt *stmt) { - if (!only_filenames.empty()) { - bool skip = true; - for (const auto &x : only_filenames) { - if (Context->getSourceManager() - .getFilename(stmt->getBeginLoc()) - .contains(x)) { - skip = false; - } - } - if (skip) { - return true; - } - } - - for (const auto &x : skip_filenames) { - if (Context->getSourceManager() - .getFilename(stmt->getBeginLoc()) - .contains(x)) { - return true; - } - } - - for (const auto &x : stmt->children()) { - std::string typeStr; - if (ExprWithCleanups *expr = dyn_cast<ExprWithCleanups>(x)) { - typeStr = expr->getType().getAsString(); - } - if (CallExpr *call = dyn_cast<CallExpr>(x)) { - llvm::CrashRecoveryContext CRC; - CRC.RunSafely([&call, &typeStr, this]() { - QualType returnType; - if (auto *callee = call->getDirectCallee()) { - returnType = callee->getReturnType(); - } else { - returnType = call->getCallReturnType(*this->Context); - } - if (!returnType.isNull() && returnType->isClassType()) { - typeStr = returnType.getAsString(); - } - }); - } - if (typeStr.substr(0, 12) == "class Maybe<" || - typeStr.substr(0, 6) == "Maybe<") { - DiagnosticsEngine &DE = Context->getDiagnostics(); - unsigned DiagID = - DE.getCustomDiagID(DiagnosticsEngine::Error, - "This function returns Maybe but the return " - "value is ignored. Wrap it with JUST(..)?"); - auto DB = DE.Report(x->getBeginLoc(), DiagID); - DB.AddSourceRange( - clang::CharSourceRange::getCharRange(x->getSourceRange())); - } - } - return true; - } - -private: - ASTContext *Context; - llvm::SmallVector<llvm::StringRef, 10> skip_filenames; - llvm::SmallVector<llvm::StringRef, 10> only_filenames; -}; - -class CheckUnusedMaybeConsumer : public clang::ASTConsumer { -public: - explicit CheckUnusedMaybeConsumer(ASTContext *Context) : Visitor(Context) {} - - void HandleTranslationUnit(clang::ASTContext &Context) override { - Visitor.TraverseDecl(Context.getTranslationUnitDecl()); - } - -private: - CheckUnusedMaybeVisitor Visitor; -}; - -class CheckUnusedMaybeAction : public clang::PluginASTAction { -public: - virtual std::unique_ptr<clang::ASTConsumer> - CreateASTConsumer(clang::CompilerInstance &Compiler, - llvm::StringRef InFile) override { - return std::make_unique<CheckUnusedMaybeConsumer>( - &Compiler.getASTContext()); - } - - bool ParseArgs(const CompilerInstance &CI, - const std::vector<std::string> &args) override { - return true; - } - - // Automatically run the plugin after the main AST action - ActionType getActionType() override { return AddAfterMainAction; } -}; - -static FrontendPluginRegistry::Add<CheckUnusedMaybeAction> - X("check-unused-maybe", "Check unused maybe"); diff --git a/tools/clang-plugin/CheckUnusedMaybe/unused_maybe_example.cpp b/tools/clang-plugin/CheckUnusedMaybe/unused_maybe_example.cpp deleted file mode 100644 index f61664629..000000000 --- a/tools/clang-plugin/CheckUnusedMaybe/unused_maybe_example.cpp +++ /dev/null @@ -1,8 +0,0 @@ -template <class T> class Maybe {}; - -Maybe<void> a() { return Maybe<void>(); } - -int main() { - a(); - return 0; -} -- GitLab