Index: clang-tools-extra/clang-tidy/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/CMakeLists.txt +++ clang-tools-extra/clang-tidy/CMakeLists.txt @@ -38,4 +38,5 @@ add_subdirectory(mpi) add_subdirectory(performance) add_subdirectory(readability) +add_subdirectory(safety) add_subdirectory(utils) Index: clang-tools-extra/clang-tidy/safety/CMakeLists.txt =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/CMakeLists.txt @@ -0,0 +1,14 @@ +set(LLVM_LINK_COMPONENTS support) + +add_clang_library(clangTidySafetyModule + NoAssemblerCheck.cpp + SafetyTidyModule.cpp + + LINK_LIBS + clangAST + clangASTMatchers + clangBasic + clangLex + clangTidy + clangTidyUtils + ) Index: clang-tools-extra/clang-tidy/safety/NoAssemblerCheck.h =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/NoAssemblerCheck.h @@ -0,0 +1,35 @@ +//===--- NoAssemblerCheck.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_SAFETY_NO_ASSEMBLER_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SAFETY_NO_ASSEMBLER_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace safety { + +/// Find assembler statements. No fix is offered. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/safety-no-assembler.html +class NoAssemblerCheck : public ClangTidyCheck { +public: + NoAssemblerCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace safety +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_SAFETY_NO_ASSEMBLER_H Index: clang-tools-extra/clang-tidy/safety/NoAssemblerCheck.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/NoAssemblerCheck.cpp @@ -0,0 +1,52 @@ +//===--- NoAssemblerCheck.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 "NoAssemblerCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace ast_matchers { +AST_MATCHER(VarDecl, isAsm) { return Node.hasAttr(); } +const internal::VariadicDynCastAllOfMatcher + fileScopeAsmDecl; +} +} + +namespace clang { +namespace tidy { +namespace safety { + +void NoAssemblerCheck::registerMatchers(MatchFinder *Finder) { + Finder->addMatcher(asmStmt().bind("asm-stmt"), this); + Finder->addMatcher(fileScopeAsmDecl().bind("asm-file-scope"), this); + Finder->addMatcher(varDecl(isAsm()).bind("asm-var"), this); +} + +void NoAssemblerCheck::check(const MatchFinder::MatchResult &Result) { + Optional ASMLocation; + if (const auto *ASM = Result.Nodes.getNodeAs("asm-stmt")) + ASMLocation = ASM->getAsmLoc(); + else if (const auto *ASM = + Result.Nodes.getNodeAs("asm-file-scope")) + ASMLocation = ASM->getAsmLoc(); + else if (const auto *ASM = Result.Nodes.getNodeAs("asm-var")) + ASMLocation = ASM->getLocation(); + else + llvm_unreachable("Unhandled case in matcher."); + + diag(*ASMLocation, "do not use inline assembler in safety-critical code"); +} + +} // namespace safety +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/safety/SafetyTidyModule.cpp =================================================================== --- /dev/null +++ clang-tools-extra/clang-tidy/safety/SafetyTidyModule.cpp @@ -0,0 +1,38 @@ +//===------- SafetyTidyModule.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 "../ClangTidy.h" +#include "../ClangTidyModule.h" +#include "../ClangTidyModuleRegistry.h" +#include "NoAssemblerCheck.h" + +namespace clang { +namespace tidy { +namespace safety { + +class SafetyModule : public ClangTidyModule { +public: + void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override { + CheckFactories.registerCheck( + "safety-no-assembler"); + } +}; + +// Register the SafetyModule using this statically initialized variable. +static ClangTidyModuleRegistry::Add + X("safety-module", "Adds safety-critical checks."); + +} // namespace safety + +// This anchor is used to force the linker to link in the generated object file +// and thus register the SafetyModule. +volatile int SafetyModuleAnchorSource = 0; + +} // namespace tidy +} // namespace clang Index: clang-tools-extra/clang-tidy/tool/CMakeLists.txt =================================================================== --- clang-tools-extra/clang-tidy/tool/CMakeLists.txt +++ clang-tools-extra/clang-tidy/tool/CMakeLists.txt @@ -23,6 +23,7 @@ clangTidyMPIModule clangTidyPerformanceModule clangTidyReadabilityModule + clangTidySafetyModule clangTooling ) Index: clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp =================================================================== --- clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp +++ clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp @@ -475,6 +475,11 @@ static int LLVM_ATTRIBUTE_UNUSED ReadabilityModuleAnchorDestination = ReadabilityModuleAnchorSource; +// This anchor is used to force the linker to link the SafetyModule. +extern volatile int SafetyModuleAnchorSource; +static int LLVM_ATTRIBUTE_UNUSED SafetyModuleAnchorDestination = + SafetyModuleAnchorSource; + } // namespace tidy } // namespace clang Index: clang-tools-extra/docs/ReleaseNotes.rst =================================================================== --- clang-tools-extra/docs/ReleaseNotes.rst +++ clang-tools-extra/docs/ReleaseNotes.rst @@ -57,7 +57,10 @@ Improvements to clang-tidy -------------------------- -The improvements are... +- New `safety-no-assembler + `_ check + + Finds uses of inline assembler. Improvements to include-fixer ----------------------------- 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 @@ -152,3 +152,4 @@ readability-simplify-boolean-expr readability-static-definition-in-anonymous-namespace readability-uniqueptr-delete-release + safety-no-assembler Index: clang-tools-extra/docs/clang-tidy/checks/safety-no-assembler.rst =================================================================== --- /dev/null +++ clang-tools-extra/docs/clang-tidy/checks/safety-no-assembler.rst @@ -0,0 +1,10 @@ +.. title:: clang-tidy - safety-no-assembler + +safety-no-assembler +=================== + +Check for assembler statements. No fix is offered. + +Inline assembler is forbidden by safety-critical C++ standards like `High +Intergrity C++ `_ as it restricts the +portability of code. Index: clang-tools-extra/test/clang-tidy/safety-no-assembler.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-tidy/safety-no-assembler.cpp @@ -0,0 +1,13 @@ +// RUN: %check_clang_tidy %s safety-no-assembler %t + +__asm__(".symver foo, bar@v"); +// CHECK-MESSAGES: :[[@LINE-1]]:1: warning: do not use inline assembler in safety-critical code [safety-no-assembler] + +static int s asm("spam"); +// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: do not use inline assembler in safety-critical code [safety-no-assembler] + +void f() { + __asm("mov al, 2"); + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: do not use inline assembler in safety-critical code [safety-no-assembler] +} +