balazske created this revision.
Herald added subscribers: cfe-commits, martong, phosek, gamesh411, Szelethus, 
dkrupp, xazax.hun, whisperity, mgorny.
Herald added a project: clang.
balazske requested review of this revision.

SIG30-C. Call only asynchronous-safe functions within signal handlers

First version of this check, only minimal list of functions is allowed
("strictly conforming" case). Later a checker option can be added
to support the POSIX list of allowed functions (taken from the rule's
description).


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D87449

Files:
  clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
  clang-tools-extra/clang-tidy/cert/CMakeLists.txt
  clang-tools-extra/clang-tidy/cert/SignalHandlerCheck.cpp
  clang-tools-extra/clang-tidy/cert/SignalHandlerCheck.h
  clang-tools-extra/docs/clang-tidy/checks/cert-sig30-c.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/signal.h
  clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdlib.h
  clang-tools-extra/test/clang-tidy/checkers/cert-sig30-c.c

Index: clang-tools-extra/test/clang-tidy/checkers/cert-sig30-c.c
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/cert-sig30-c.c
@@ -0,0 +1,72 @@
+// RUN: %check_clang_tidy %s cert-sig30-c %t -- -- -isystem %S/Inputs/Headers
+
+#include "signal.h"
+#include "stdio.h"
+#include "stdlib.h"
+
+void handler_abort(int) {
+  abort();
+}
+
+void handler__Exit(int) {
+  _Exit(0);
+}
+
+void handler_quick_exit(int) {
+  quick_exit(0);
+}
+
+void handler_other(int) {
+  printf("1234");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Signal handler potentially calls non asynchronous-safe function. This may result in undefined behavior. [cert-sig30-c]
+}
+
+void handler_signal(int) {
+  // FIXME: It is only OK to call signal with the current signal number.
+  signal(0, SIG_DFL);
+}
+
+void f_ok() {
+  abort();
+}
+
+void f_bad() {
+  printf("1234");
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: Signal handler potentially calls non asynchronous-safe function. This may result in undefined behavior. [cert-sig30-c]
+}
+
+void f_extern();
+
+void handler_ok(int) {
+  f_ok();
+  f_extern();
+}
+
+void handler_bad(int) {
+  f_bad();
+}
+
+// Function called "signal" that is not to be recognized by the checker.
+typedef void (*callback_t)(int);
+void signal(int, callback_t, int);
+
+void test() {
+  signal(SIGINT, handler_abort);
+  signal(SIGINT, handler__Exit);
+  signal(SIGINT, handler_quick_exit);
+  signal(SIGINT, handler_signal);
+  signal(SIGINT, handler_other);
+
+  signal(SIGINT, handler_ok);
+  signal(SIGINT, handler_bad);
+
+  signal(SIGINT, quick_exit);
+  signal(SIGINT, other_call);
+  // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: Signal handler potentially calls non asynchronous-safe function. This may result in undefined behavior. [cert-sig30-c]
+
+  signal(SIGINT, SIG_IGN);
+  signal(SIGINT, SIG_DFL);
+
+  // Do not find problems here.
+  signal(SIGINT, handler_bad, 1);
+}
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdlib.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/stdlib.h
@@ -0,0 +1,18 @@
+//===--- stdio.h - Stub header for tests ------------------------*- 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 _STDLIB_H_
+#define _STDLIB_H_
+
+void abort(void);
+void _Exit(int __status);
+void quick_exit(int __status);
+
+void other_call(int);
+
+#endif // _STDLIB_H_
Index: clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/signal.h
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/Inputs/Headers/signal.h
@@ -0,0 +1,22 @@
+//===--- stdio.h - Stub header for tests ------------------------*- 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 _SIGNAL_H_
+#define _SIGNAL_H_
+
+void _sig_ign(int);
+void _sig_dfl(int);
+
+#define SIGINT 1
+#define SIG_IGN _sig_ign
+#define SIG_DFL _sig_dfl
+
+typedef void (*sighandler_t)(int);
+sighandler_t signal(int signum, sighandler_t handler);
+
+#endif // _SIGNAL_H_
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
@@ -12,28 +12,28 @@
 .. csv-table::
    :header: "Name", "Offers fixes"
 
-   `abseil-duration-addition <abseil-duration-addition.html>`_, "Yes"
-   `abseil-duration-comparison <abseil-duration-comparison.html>`_, "Yes"
-   `abseil-duration-conversion-cast <abseil-duration-conversion-cast.html>`_, "Yes"
-   `abseil-duration-division <abseil-duration-division.html>`_, "Yes"
-   `abseil-duration-factory-float <abseil-duration-factory-float.html>`_, "Yes"
-   `abseil-duration-factory-scale <abseil-duration-factory-scale.html>`_, "Yes"
-   `abseil-duration-subtraction <abseil-duration-subtraction.html>`_, "Yes"
-   `abseil-duration-unnecessary-conversion <abseil-duration-unnecessary-conversion.html>`_, "Yes"
-   `abseil-faster-strsplit-delimiter <abseil-faster-strsplit-delimiter.html>`_, "Yes"
+   `abseil-duration-addition <abseil-duration-addition.html>`_,
+   `abseil-duration-comparison <abseil-duration-comparison.html>`_,
+   `abseil-duration-conversion-cast <abseil-duration-conversion-cast.html>`_,
+   `abseil-duration-division <abseil-duration-division.html>`_,
+   `abseil-duration-factory-float <abseil-duration-factory-float.html>`_,
+   `abseil-duration-factory-scale <abseil-duration-factory-scale.html>`_,
+   `abseil-duration-subtraction <abseil-duration-subtraction.html>`_,
+   `abseil-duration-unnecessary-conversion <abseil-duration-unnecessary-conversion.html>`_,
+   `abseil-faster-strsplit-delimiter <abseil-faster-strsplit-delimiter.html>`_,
    `abseil-no-internal-dependencies <abseil-no-internal-dependencies.html>`_,
    `abseil-no-namespace <abseil-no-namespace.html>`_,
-   `abseil-redundant-strcat-calls <abseil-redundant-strcat-calls.html>`_, "Yes"
-   `abseil-str-cat-append <abseil-str-cat-append.html>`_, "Yes"
-   `abseil-string-find-startswith <abseil-string-find-startswith.html>`_, "Yes"
-   `abseil-string-find-str-contains <abseil-string-find-str-contains.html>`_, "Yes"
-   `abseil-time-comparison <abseil-time-comparison.html>`_, "Yes"
-   `abseil-time-subtraction <abseil-time-subtraction.html>`_, "Yes"
-   `abseil-upgrade-duration-conversions <abseil-upgrade-duration-conversions.html>`_, "Yes"
-   `android-cloexec-accept <android-cloexec-accept.html>`_, "Yes"
+   `abseil-redundant-strcat-calls <abseil-redundant-strcat-calls.html>`_,
+   `abseil-str-cat-append <abseil-str-cat-append.html>`_,
+   `abseil-string-find-startswith <abseil-string-find-startswith.html>`_,
+   `abseil-string-find-str-contains <abseil-string-find-str-contains.html>`_,
+   `abseil-time-comparison <abseil-time-comparison.html>`_,
+   `abseil-time-subtraction <abseil-time-subtraction.html>`_,
+   `abseil-upgrade-duration-conversions <abseil-upgrade-duration-conversions.html>`_,
+   `android-cloexec-accept <android-cloexec-accept.html>`_,
    `android-cloexec-accept4 <android-cloexec-accept4.html>`_,
-   `android-cloexec-creat <android-cloexec-creat.html>`_, "Yes"
-   `android-cloexec-dup <android-cloexec-dup.html>`_, "Yes"
+   `android-cloexec-creat <android-cloexec-creat.html>`_,
+   `android-cloexec-dup <android-cloexec-dup.html>`_,
    `android-cloexec-epoll-create <android-cloexec-epoll-create.html>`_,
    `android-cloexec-epoll-create1 <android-cloexec-epoll-create1.html>`_,
    `android-cloexec-fopen <android-cloexec-fopen.html>`_,
@@ -41,65 +41,65 @@
    `android-cloexec-inotify-init1 <android-cloexec-inotify-init1.html>`_,
    `android-cloexec-memfd-create <android-cloexec-memfd-create.html>`_,
    `android-cloexec-open <android-cloexec-open.html>`_,
-   `android-cloexec-pipe <android-cloexec-pipe.html>`_, "Yes"
+   `android-cloexec-pipe <android-cloexec-pipe.html>`_,
    `android-cloexec-pipe2 <android-cloexec-pipe2.html>`_,
    `android-cloexec-socket <android-cloexec-socket.html>`_,
    `android-comparison-in-temp-failure-retry <android-comparison-in-temp-failure-retry.html>`_,
-   `boost-use-to-string <boost-use-to-string.html>`_, "Yes"
-   `bugprone-argument-comment <bugprone-argument-comment.html>`_, "Yes"
+   `boost-use-to-string <boost-use-to-string.html>`_,
+   `bugprone-argument-comment <bugprone-argument-comment.html>`_,
    `bugprone-assert-side-effect <bugprone-assert-side-effect.html>`_,
    `bugprone-bad-signal-to-kill-thread <bugprone-bad-signal-to-kill-thread.html>`_,
-   `bugprone-bool-pointer-implicit-conversion <bugprone-bool-pointer-implicit-conversion.html>`_, "Yes"
+   `bugprone-bool-pointer-implicit-conversion <bugprone-bool-pointer-implicit-conversion.html>`_,
    `bugprone-branch-clone <bugprone-branch-clone.html>`_,
-   `bugprone-copy-constructor-init <bugprone-copy-constructor-init.html>`_, "Yes"
+   `bugprone-copy-constructor-init <bugprone-copy-constructor-init.html>`_,
    `bugprone-dangling-handle <bugprone-dangling-handle.html>`_,
    `bugprone-dynamic-static-initializers <bugprone-dynamic-static-initializers.html>`_,
    `bugprone-exception-escape <bugprone-exception-escape.html>`_,
    `bugprone-fold-init-type <bugprone-fold-init-type.html>`_,
    `bugprone-forward-declaration-namespace <bugprone-forward-declaration-namespace.html>`_,
    `bugprone-forwarding-reference-overload <bugprone-forwarding-reference-overload.html>`_,
-   `bugprone-inaccurate-erase <bugprone-inaccurate-erase.html>`_, "Yes"
+   `bugprone-inaccurate-erase <bugprone-inaccurate-erase.html>`_,
    `bugprone-incorrect-roundings <bugprone-incorrect-roundings.html>`_,
    `bugprone-infinite-loop <bugprone-infinite-loop.html>`_,
    `bugprone-integer-division <bugprone-integer-division.html>`_,
    `bugprone-lambda-function-name <bugprone-lambda-function-name.html>`_,
-   `bugprone-macro-parentheses <bugprone-macro-parentheses.html>`_, "Yes"
+   `bugprone-macro-parentheses <bugprone-macro-parentheses.html>`_,
    `bugprone-macro-repeated-side-effects <bugprone-macro-repeated-side-effects.html>`_,
-   `bugprone-misplaced-operator-in-strlen-in-alloc <bugprone-misplaced-operator-in-strlen-in-alloc.html>`_, "Yes"
-   `bugprone-misplaced-pointer-arithmetic-in-alloc <bugprone-misplaced-pointer-arithmetic-in-alloc.html>`_, "Yes"
+   `bugprone-misplaced-operator-in-strlen-in-alloc <bugprone-misplaced-operator-in-strlen-in-alloc.html>`_,
+   `bugprone-misplaced-pointer-arithmetic-in-alloc <bugprone-misplaced-pointer-arithmetic-in-alloc.html>`_,
    `bugprone-misplaced-widening-cast <bugprone-misplaced-widening-cast.html>`_,
-   `bugprone-move-forwarding-reference <bugprone-move-forwarding-reference.html>`_, "Yes"
+   `bugprone-move-forwarding-reference <bugprone-move-forwarding-reference.html>`_,
    `bugprone-multiple-statement-macro <bugprone-multiple-statement-macro.html>`_,
    `bugprone-no-escape <bugprone-no-escape.html>`_,
-   `bugprone-not-null-terminated-result <bugprone-not-null-terminated-result.html>`_, "Yes"
-   `bugprone-parent-virtual-call <bugprone-parent-virtual-call.html>`_, "Yes"
-   `bugprone-posix-return <bugprone-posix-return.html>`_, "Yes"
-   `bugprone-redundant-branch-condition <bugprone-redundant-branch-condition.html>`_, "Yes"
-   `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_, "Yes"
+   `bugprone-not-null-terminated-result <bugprone-not-null-terminated-result.html>`_,
+   `bugprone-parent-virtual-call <bugprone-parent-virtual-call.html>`_,
+   `bugprone-posix-return <bugprone-posix-return.html>`_,
+   `bugprone-redundant-branch-condition <bugprone-redundant-branch-condition.html>`_,
+   `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_,
    `bugprone-signed-char-misuse <bugprone-signed-char-misuse.html>`_,
    `bugprone-sizeof-container <bugprone-sizeof-container.html>`_,
    `bugprone-sizeof-expression <bugprone-sizeof-expression.html>`_,
    `bugprone-spuriously-wake-up-functions <bugprone-spuriously-wake-up-functions.html>`_,
-   `bugprone-string-constructor <bugprone-string-constructor.html>`_, "Yes"
-   `bugprone-string-integer-assignment <bugprone-string-integer-assignment.html>`_, "Yes"
+   `bugprone-string-constructor <bugprone-string-constructor.html>`_,
+   `bugprone-string-integer-assignment <bugprone-string-integer-assignment.html>`_,
    `bugprone-string-literal-with-embedded-nul <bugprone-string-literal-with-embedded-nul.html>`_,
    `bugprone-suspicious-enum-usage <bugprone-suspicious-enum-usage.html>`_,
    `bugprone-suspicious-include <bugprone-suspicious-include.html>`_,
-   `bugprone-suspicious-memset-usage <bugprone-suspicious-memset-usage.html>`_, "Yes"
+   `bugprone-suspicious-memset-usage <bugprone-suspicious-memset-usage.html>`_,
    `bugprone-suspicious-missing-comma <bugprone-suspicious-missing-comma.html>`_,
-   `bugprone-suspicious-semicolon <bugprone-suspicious-semicolon.html>`_, "Yes"
-   `bugprone-suspicious-string-compare <bugprone-suspicious-string-compare.html>`_, "Yes"
-   `bugprone-swapped-arguments <bugprone-swapped-arguments.html>`_, "Yes"
-   `bugprone-terminating-continue <bugprone-terminating-continue.html>`_, "Yes"
+   `bugprone-suspicious-semicolon <bugprone-suspicious-semicolon.html>`_,
+   `bugprone-suspicious-string-compare <bugprone-suspicious-string-compare.html>`_,
+   `bugprone-swapped-arguments <bugprone-swapped-arguments.html>`_,
+   `bugprone-terminating-continue <bugprone-terminating-continue.html>`_,
    `bugprone-throw-keyword-missing <bugprone-throw-keyword-missing.html>`_,
    `bugprone-too-small-loop-variable <bugprone-too-small-loop-variable.html>`_,
    `bugprone-undefined-memory-manipulation <bugprone-undefined-memory-manipulation.html>`_,
    `bugprone-undelegated-constructor <bugprone-undelegated-constructor.html>`_,
    `bugprone-unhandled-self-assignment <bugprone-unhandled-self-assignment.html>`_,
-   `bugprone-unused-raii <bugprone-unused-raii.html>`_, "Yes"
+   `bugprone-unused-raii <bugprone-unused-raii.html>`_,
    `bugprone-unused-return-value <bugprone-unused-return-value.html>`_,
    `bugprone-use-after-move <bugprone-use-after-move.html>`_,
-   `bugprone-virtual-near-miss <bugprone-virtual-near-miss.html>`_, "Yes"
+   `bugprone-virtual-near-miss <bugprone-virtual-near-miss.html>`_,
    `cert-dcl21-cpp <cert-dcl21-cpp.html>`_,
    `cert-dcl50-cpp <cert-dcl50-cpp.html>`_,
    `cert-dcl58-cpp <cert-dcl58-cpp.html>`_,
@@ -114,6 +114,7 @@
    `cert-msc51-cpp <cert-msc51-cpp.html>`_,
    `cert-oop57-cpp <cert-oop57-cpp.html>`_,
    `cert-oop58-cpp <cert-oop58-cpp.html>`_,
+   `cert-sig30-c <cert-sig30-c.html>`_,
    `clang-analyzer-core.DynamicTypePropagation <clang-analyzer-core.DynamicTypePropagation.html>`_,
    `clang-analyzer-core.uninitialized.CapturedBlockVariable <clang-analyzer-core.uninitialized.CapturedBlockVariable.html>`_,
    `clang-analyzer-cplusplus.InnerPointer <clang-analyzer-cplusplus.InnerPointer.html>`_,
@@ -136,7 +137,7 @@
    `clang-analyzer-valist.Unterminated <clang-analyzer-valist.Unterminated.html>`_,
    `cppcoreguidelines-avoid-goto <cppcoreguidelines-avoid-goto.html>`_,
    `cppcoreguidelines-avoid-non-const-global-variables <cppcoreguidelines-avoid-non-const-global-variables.html>`_,
-   `cppcoreguidelines-init-variables <cppcoreguidelines-init-variables.html>`_, "Yes"
+   `cppcoreguidelines-init-variables <cppcoreguidelines-init-variables.html>`_,
    `cppcoreguidelines-interfaces-global-init <cppcoreguidelines-interfaces-global-init.html>`_,
    `cppcoreguidelines-macro-usage <cppcoreguidelines-macro-usage.html>`_,
    `cppcoreguidelines-narrowing-conversions <cppcoreguidelines-narrowing-conversions.html>`_,
@@ -144,21 +145,21 @@
    `cppcoreguidelines-owning-memory <cppcoreguidelines-owning-memory.html>`_,
    `cppcoreguidelines-prefer-member-initializer <cppcoreguidelines-prefer-member-initializer.html>`_,
    `cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines-pro-bounds-array-to-pointer-decay.html>`_,
-   `cppcoreguidelines-pro-bounds-constant-array-index <cppcoreguidelines-pro-bounds-constant-array-index.html>`_, "Yes"
+   `cppcoreguidelines-pro-bounds-constant-array-index <cppcoreguidelines-pro-bounds-constant-array-index.html>`_,
    `cppcoreguidelines-pro-bounds-pointer-arithmetic <cppcoreguidelines-pro-bounds-pointer-arithmetic.html>`_,
    `cppcoreguidelines-pro-type-const-cast <cppcoreguidelines-pro-type-const-cast.html>`_,
-   `cppcoreguidelines-pro-type-cstyle-cast <cppcoreguidelines-pro-type-cstyle-cast.html>`_, "Yes"
-   `cppcoreguidelines-pro-type-member-init <cppcoreguidelines-pro-type-member-init.html>`_, "Yes"
+   `cppcoreguidelines-pro-type-cstyle-cast <cppcoreguidelines-pro-type-cstyle-cast.html>`_,
+   `cppcoreguidelines-pro-type-member-init <cppcoreguidelines-pro-type-member-init.html>`_,
    `cppcoreguidelines-pro-type-reinterpret-cast <cppcoreguidelines-pro-type-reinterpret-cast.html>`_,
-   `cppcoreguidelines-pro-type-static-cast-downcast <cppcoreguidelines-pro-type-static-cast-downcast.html>`_, "Yes"
+   `cppcoreguidelines-pro-type-static-cast-downcast <cppcoreguidelines-pro-type-static-cast-downcast.html>`_,
    `cppcoreguidelines-pro-type-union-access <cppcoreguidelines-pro-type-union-access.html>`_,
    `cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_,
    `cppcoreguidelines-slicing <cppcoreguidelines-slicing.html>`_,
    `cppcoreguidelines-special-member-functions <cppcoreguidelines-special-member-functions.html>`_,
    `darwin-avoid-spinlock <darwin-avoid-spinlock.html>`_,
-   `darwin-dispatch-once-nonstatic <darwin-dispatch-once-nonstatic.html>`_, "Yes"
+   `darwin-dispatch-once-nonstatic <darwin-dispatch-once-nonstatic.html>`_,
    `fuchsia-default-arguments-calls <fuchsia-default-arguments-calls.html>`_,
-   `fuchsia-default-arguments-declarations <fuchsia-default-arguments-declarations.html>`_, "Yes"
+   `fuchsia-default-arguments-declarations <fuchsia-default-arguments-declarations.html>`_,
    `fuchsia-multiple-inheritance <fuchsia-multiple-inheritance.html>`_,
    `fuchsia-overloaded-operator <fuchsia-overloaded-operator.html>`_,
    `fuchsia-statically-constructed-objects <fuchsia-statically-constructed-objects.html>`_,
@@ -168,7 +169,7 @@
    `google-build-namespaces <google-build-namespaces.html>`_,
    `google-build-using-namespace <google-build-using-namespace.html>`_,
    `google-default-arguments <google-default-arguments.html>`_,
-   `google-explicit-constructor <google-explicit-constructor.html>`_, "Yes"
+   `google-explicit-constructor <google-explicit-constructor.html>`_,
    `google-global-names-in-headers <google-global-names-in-headers.html>`_,
    `google-objc-avoid-nsobject-new <google-objc-avoid-nsobject-new.html>`_,
    `google-objc-avoid-throwing-exception <google-objc-avoid-throwing-exception.html>`_,
@@ -180,7 +181,7 @@
    `google-runtime-int <google-runtime-int.html>`_,
    `google-runtime-operator <google-runtime-operator.html>`_,
    `google-runtime-references <google-runtime-references.html>`_,
-   `google-upgrade-googletest-case <google-upgrade-googletest-case.html>`_, "Yes"
+   `google-upgrade-googletest-case <google-upgrade-googletest-case.html>`_,
    `hicpp-avoid-goto <hicpp-avoid-goto.html>`_,
    `hicpp-exception-baseclass <hicpp-exception-baseclass.html>`_,
    `hicpp-multiway-paths-covered <hicpp-multiway-paths-covered.html>`_,
@@ -188,122 +189,122 @@
    `hicpp-signed-bitwise <hicpp-signed-bitwise.html>`_,
    `linuxkernel-must-use-errs <linuxkernel-must-use-errs.html>`_,
    `llvm-header-guard <llvm-header-guard.html>`_,
-   `llvm-include-order <llvm-include-order.html>`_, "Yes"
+   `llvm-include-order <llvm-include-order.html>`_,
    `llvm-namespace-comment <llvm-namespace-comment.html>`_,
-   `llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm-prefer-isa-or-dyn-cast-in-conditionals.html>`_, "Yes"
-   `llvm-prefer-register-over-unsigned <llvm-prefer-register-over-unsigned.html>`_, "Yes"
-   `llvm-twine-local <llvm-twine-local.html>`_, "Yes"
+   `llvm-prefer-isa-or-dyn-cast-in-conditionals <llvm-prefer-isa-or-dyn-cast-in-conditionals.html>`_,
+   `llvm-prefer-register-over-unsigned <llvm-prefer-register-over-unsigned.html>`_,
+   `llvm-twine-local <llvm-twine-local.html>`_,
    `llvmlibc-callee-namespace <llvmlibc-callee-namespace.html>`_,
    `llvmlibc-implementation-in-namespace <llvmlibc-implementation-in-namespace.html>`_,
-   `llvmlibc-restrict-system-libc-headers <llvmlibc-restrict-system-libc-headers.html>`_, "Yes"
-   `misc-definitions-in-headers <misc-definitions-in-headers.html>`_, "Yes"
+   `llvmlibc-restrict-system-libc-headers <llvmlibc-restrict-system-libc-headers.html>`_,
+   `misc-definitions-in-headers <misc-definitions-in-headers.html>`_,
    `misc-misplaced-const <misc-misplaced-const.html>`_,
    `misc-new-delete-overloads <misc-new-delete-overloads.html>`_,
    `misc-no-recursion <misc-no-recursion.html>`_,
    `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-static-assert <misc-static-assert.html>`_, "Yes"
+   `misc-redundant-expression <misc-redundant-expression.html>`_,
+   `misc-static-assert <misc-static-assert.html>`_,
    `misc-throw-by-value-catch-by-reference <misc-throw-by-value-catch-by-reference.html>`_,
    `misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_,
-   `misc-uniqueptr-reset-release <misc-uniqueptr-reset-release.html>`_, "Yes"
-   `misc-unused-alias-decls <misc-unused-alias-decls.html>`_, "Yes"
-   `misc-unused-parameters <misc-unused-parameters.html>`_, "Yes"
-   `misc-unused-using-decls <misc-unused-using-decls.html>`_, "Yes"
-   `modernize-avoid-bind <modernize-avoid-bind.html>`_, "Yes"
+   `misc-uniqueptr-reset-release <misc-uniqueptr-reset-release.html>`_,
+   `misc-unused-alias-decls <misc-unused-alias-decls.html>`_,
+   `misc-unused-parameters <misc-unused-parameters.html>`_,
+   `misc-unused-using-decls <misc-unused-using-decls.html>`_,
+   `modernize-avoid-bind <modernize-avoid-bind.html>`_,
    `modernize-avoid-c-arrays <modernize-avoid-c-arrays.html>`_,
-   `modernize-concat-nested-namespaces <modernize-concat-nested-namespaces.html>`_, "Yes"
-   `modernize-deprecated-headers <modernize-deprecated-headers.html>`_, "Yes"
-   `modernize-deprecated-ios-base-aliases <modernize-deprecated-ios-base-aliases.html>`_, "Yes"
-   `modernize-loop-convert <modernize-loop-convert.html>`_, "Yes"
-   `modernize-make-shared <modernize-make-shared.html>`_, "Yes"
-   `modernize-make-unique <modernize-make-unique.html>`_, "Yes"
-   `modernize-pass-by-value <modernize-pass-by-value.html>`_, "Yes"
-   `modernize-raw-string-literal <modernize-raw-string-literal.html>`_, "Yes"
-   `modernize-redundant-void-arg <modernize-redundant-void-arg.html>`_, "Yes"
-   `modernize-replace-auto-ptr <modernize-replace-auto-ptr.html>`_, "Yes"
-   `modernize-replace-disallow-copy-and-assign-macro <modernize-replace-disallow-copy-and-assign-macro.html>`_, "Yes"
-   `modernize-replace-random-shuffle <modernize-replace-random-shuffle.html>`_, "Yes"
-   `modernize-return-braced-init-list <modernize-return-braced-init-list.html>`_, "Yes"
-   `modernize-shrink-to-fit <modernize-shrink-to-fit.html>`_, "Yes"
-   `modernize-unary-static-assert <modernize-unary-static-assert.html>`_, "Yes"
-   `modernize-use-auto <modernize-use-auto.html>`_, "Yes"
-   `modernize-use-bool-literals <modernize-use-bool-literals.html>`_, "Yes"
-   `modernize-use-default-member-init <modernize-use-default-member-init.html>`_, "Yes"
-   `modernize-use-emplace <modernize-use-emplace.html>`_, "Yes"
-   `modernize-use-equals-default <modernize-use-equals-default.html>`_, "Yes"
-   `modernize-use-equals-delete <modernize-use-equals-delete.html>`_, "Yes"
-   `modernize-use-nodiscard <modernize-use-nodiscard.html>`_, "Yes"
-   `modernize-use-noexcept <modernize-use-noexcept.html>`_, "Yes"
-   `modernize-use-nullptr <modernize-use-nullptr.html>`_, "Yes"
-   `modernize-use-override <modernize-use-override.html>`_, "Yes"
-   `modernize-use-trailing-return-type <modernize-use-trailing-return-type.html>`_, "Yes"
-   `modernize-use-transparent-functors <modernize-use-transparent-functors.html>`_, "Yes"
-   `modernize-use-uncaught-exceptions <modernize-use-uncaught-exceptions.html>`_, "Yes"
-   `modernize-use-using <modernize-use-using.html>`_, "Yes"
-   `mpi-buffer-deref <mpi-buffer-deref.html>`_, "Yes"
-   `mpi-type-mismatch <mpi-type-mismatch.html>`_, "Yes"
+   `modernize-concat-nested-namespaces <modernize-concat-nested-namespaces.html>`_,
+   `modernize-deprecated-headers <modernize-deprecated-headers.html>`_,
+   `modernize-deprecated-ios-base-aliases <modernize-deprecated-ios-base-aliases.html>`_,
+   `modernize-loop-convert <modernize-loop-convert.html>`_,
+   `modernize-make-shared <modernize-make-shared.html>`_,
+   `modernize-make-unique <modernize-make-unique.html>`_,
+   `modernize-pass-by-value <modernize-pass-by-value.html>`_,
+   `modernize-raw-string-literal <modernize-raw-string-literal.html>`_,
+   `modernize-redundant-void-arg <modernize-redundant-void-arg.html>`_,
+   `modernize-replace-auto-ptr <modernize-replace-auto-ptr.html>`_,
+   `modernize-replace-disallow-copy-and-assign-macro <modernize-replace-disallow-copy-and-assign-macro.html>`_,
+   `modernize-replace-random-shuffle <modernize-replace-random-shuffle.html>`_,
+   `modernize-return-braced-init-list <modernize-return-braced-init-list.html>`_,
+   `modernize-shrink-to-fit <modernize-shrink-to-fit.html>`_,
+   `modernize-unary-static-assert <modernize-unary-static-assert.html>`_,
+   `modernize-use-auto <modernize-use-auto.html>`_,
+   `modernize-use-bool-literals <modernize-use-bool-literals.html>`_,
+   `modernize-use-default-member-init <modernize-use-default-member-init.html>`_,
+   `modernize-use-emplace <modernize-use-emplace.html>`_,
+   `modernize-use-equals-default <modernize-use-equals-default.html>`_,
+   `modernize-use-equals-delete <modernize-use-equals-delete.html>`_,
+   `modernize-use-nodiscard <modernize-use-nodiscard.html>`_,
+   `modernize-use-noexcept <modernize-use-noexcept.html>`_,
+   `modernize-use-nullptr <modernize-use-nullptr.html>`_,
+   `modernize-use-override <modernize-use-override.html>`_,
+   `modernize-use-trailing-return-type <modernize-use-trailing-return-type.html>`_,
+   `modernize-use-transparent-functors <modernize-use-transparent-functors.html>`_,
+   `modernize-use-uncaught-exceptions <modernize-use-uncaught-exceptions.html>`_,
+   `modernize-use-using <modernize-use-using.html>`_,
+   `mpi-buffer-deref <mpi-buffer-deref.html>`_,
+   `mpi-type-mismatch <mpi-type-mismatch.html>`_,
    `objc-avoid-nserror-init <objc-avoid-nserror-init.html>`_,
    `objc-dealloc-in-category <objc-dealloc-in-category.html>`_,
    `objc-forbidden-subclassing <objc-forbidden-subclassing.html>`_,
    `objc-missing-hash <objc-missing-hash.html>`_,
-   `objc-nsinvocation-argument-lifetime <objc-nsinvocation-argument-lifetime.html>`_, "Yes"
-   `objc-property-declaration <objc-property-declaration.html>`_, "Yes"
-   `objc-super-self <objc-super-self.html>`_, "Yes"
+   `objc-nsinvocation-argument-lifetime <objc-nsinvocation-argument-lifetime.html>`_,
+   `objc-property-declaration <objc-property-declaration.html>`_,
+   `objc-super-self <objc-super-self.html>`_,
    `openmp-exception-escape <openmp-exception-escape.html>`_,
    `openmp-use-default-none <openmp-use-default-none.html>`_,
-   `performance-faster-string-find <performance-faster-string-find.html>`_, "Yes"
-   `performance-for-range-copy <performance-for-range-copy.html>`_, "Yes"
+   `performance-faster-string-find <performance-faster-string-find.html>`_,
+   `performance-for-range-copy <performance-for-range-copy.html>`_,
    `performance-implicit-conversion-in-loop <performance-implicit-conversion-in-loop.html>`_,
-   `performance-inefficient-algorithm <performance-inefficient-algorithm.html>`_, "Yes"
+   `performance-inefficient-algorithm <performance-inefficient-algorithm.html>`_,
    `performance-inefficient-string-concatenation <performance-inefficient-string-concatenation.html>`_,
-   `performance-inefficient-vector-operation <performance-inefficient-vector-operation.html>`_, "Yes"
-   `performance-move-const-arg <performance-move-const-arg.html>`_, "Yes"
-   `performance-move-constructor-init <performance-move-constructor-init.html>`_, "Yes"
+   `performance-inefficient-vector-operation <performance-inefficient-vector-operation.html>`_,
+   `performance-move-const-arg <performance-move-const-arg.html>`_,
+   `performance-move-constructor-init <performance-move-constructor-init.html>`_,
    `performance-no-automatic-move <performance-no-automatic-move.html>`_,
-   `performance-noexcept-move-constructor <performance-noexcept-move-constructor.html>`_, "Yes"
-   `performance-trivially-destructible <performance-trivially-destructible.html>`_, "Yes"
-   `performance-type-promotion-in-math-fn <performance-type-promotion-in-math-fn.html>`_, "Yes"
+   `performance-noexcept-move-constructor <performance-noexcept-move-constructor.html>`_,
+   `performance-trivially-destructible <performance-trivially-destructible.html>`_,
+   `performance-type-promotion-in-math-fn <performance-type-promotion-in-math-fn.html>`_,
    `performance-unnecessary-copy-initialization <performance-unnecessary-copy-initialization.html>`_,
-   `performance-unnecessary-value-param <performance-unnecessary-value-param.html>`_, "Yes"
-   `portability-restrict-system-includes <portability-restrict-system-includes.html>`_, "Yes"
+   `performance-unnecessary-value-param <performance-unnecessary-value-param.html>`_,
+   `portability-restrict-system-includes <portability-restrict-system-includes.html>`_,
    `portability-simd-intrinsics <portability-simd-intrinsics.html>`_,
    `readability-avoid-const-params-in-decls <readability-avoid-const-params-in-decls.html>`_,
-   `readability-braces-around-statements <readability-braces-around-statements.html>`_, "Yes"
-   `readability-const-return-type <readability-const-return-type.html>`_, "Yes"
-   `readability-container-size-empty <readability-container-size-empty.html>`_, "Yes"
+   `readability-braces-around-statements <readability-braces-around-statements.html>`_,
+   `readability-const-return-type <readability-const-return-type.html>`_,
+   `readability-container-size-empty <readability-container-size-empty.html>`_,
    `readability-convert-member-functions-to-static <readability-convert-member-functions-to-static.html>`_,
-   `readability-delete-null-pointer <readability-delete-null-pointer.html>`_, "Yes"
+   `readability-delete-null-pointer <readability-delete-null-pointer.html>`_,
    `readability-deleted-default <readability-deleted-default.html>`_,
-   `readability-else-after-return <readability-else-after-return.html>`_, "Yes"
+   `readability-else-after-return <readability-else-after-return.html>`_,
    `readability-function-size <readability-function-size.html>`_,
-   `readability-identifier-naming <readability-identifier-naming.html>`_, "Yes"
-   `readability-implicit-bool-conversion <readability-implicit-bool-conversion.html>`_, "Yes"
-   `readability-inconsistent-declaration-parameter-name <readability-inconsistent-declaration-parameter-name.html>`_, "Yes"
-   `readability-isolate-declaration <readability-isolate-declaration.html>`_, "Yes"
+   `readability-identifier-naming <readability-identifier-naming.html>`_,
+   `readability-implicit-bool-conversion <readability-implicit-bool-conversion.html>`_,
+   `readability-inconsistent-declaration-parameter-name <readability-inconsistent-declaration-parameter-name.html>`_,
+   `readability-isolate-declaration <readability-isolate-declaration.html>`_,
    `readability-magic-numbers <readability-magic-numbers.html>`_,
-   `readability-make-member-function-const <readability-make-member-function-const.html>`_, "Yes"
+   `readability-make-member-function-const <readability-make-member-function-const.html>`_,
    `readability-misleading-indentation <readability-misleading-indentation.html>`_,
-   `readability-misplaced-array-index <readability-misplaced-array-index.html>`_, "Yes"
-   `readability-named-parameter <readability-named-parameter.html>`_, "Yes"
-   `readability-non-const-parameter <readability-non-const-parameter.html>`_, "Yes"
-   `readability-qualified-auto <readability-qualified-auto.html>`_, "Yes"
-   `readability-redundant-access-specifiers <readability-redundant-access-specifiers.html>`_, "Yes"
-   `readability-redundant-control-flow <readability-redundant-control-flow.html>`_, "Yes"
-   `readability-redundant-declaration <readability-redundant-declaration.html>`_, "Yes"
-   `readability-redundant-function-ptr-dereference <readability-redundant-function-ptr-dereference.html>`_, "Yes"
-   `readability-redundant-member-init <readability-redundant-member-init.html>`_, "Yes"
+   `readability-misplaced-array-index <readability-misplaced-array-index.html>`_,
+   `readability-named-parameter <readability-named-parameter.html>`_,
+   `readability-non-const-parameter <readability-non-const-parameter.html>`_,
+   `readability-qualified-auto <readability-qualified-auto.html>`_,
+   `readability-redundant-access-specifiers <readability-redundant-access-specifiers.html>`_,
+   `readability-redundant-control-flow <readability-redundant-control-flow.html>`_,
+   `readability-redundant-declaration <readability-redundant-declaration.html>`_,
+   `readability-redundant-function-ptr-dereference <readability-redundant-function-ptr-dereference.html>`_,
+   `readability-redundant-member-init <readability-redundant-member-init.html>`_,
    `readability-redundant-preprocessor <readability-redundant-preprocessor.html>`_,
-   `readability-redundant-smartptr-get <readability-redundant-smartptr-get.html>`_, "Yes"
-   `readability-redundant-string-cstr <readability-redundant-string-cstr.html>`_, "Yes"
-   `readability-redundant-string-init <readability-redundant-string-init.html>`_, "Yes"
-   `readability-simplify-boolean-expr <readability-simplify-boolean-expr.html>`_, "Yes"
-   `readability-simplify-subscript-expr <readability-simplify-subscript-expr.html>`_, "Yes"
-   `readability-static-accessed-through-instance <readability-static-accessed-through-instance.html>`_, "Yes"
-   `readability-static-definition-in-anonymous-namespace <readability-static-definition-in-anonymous-namespace.html>`_, "Yes"
-   `readability-string-compare <readability-string-compare.html>`_, "Yes"
-   `readability-uniqueptr-delete-release <readability-uniqueptr-delete-release.html>`_, "Yes"
-   `readability-uppercase-literal-suffix <readability-uppercase-literal-suffix.html>`_, "Yes"
+   `readability-redundant-smartptr-get <readability-redundant-smartptr-get.html>`_,
+   `readability-redundant-string-cstr <readability-redundant-string-cstr.html>`_,
+   `readability-redundant-string-init <readability-redundant-string-init.html>`_,
+   `readability-simplify-boolean-expr <readability-simplify-boolean-expr.html>`_,
+   `readability-simplify-subscript-expr <readability-simplify-subscript-expr.html>`_,
+   `readability-static-accessed-through-instance <readability-static-accessed-through-instance.html>`_,
+   `readability-static-definition-in-anonymous-namespace <readability-static-definition-in-anonymous-namespace.html>`_,
+   `readability-string-compare <readability-string-compare.html>`_,
+   `readability-uniqueptr-delete-release <readability-uniqueptr-delete-release.html>`_,
+   `readability-uppercase-literal-suffix <readability-uppercase-literal-suffix.html>`_,
    `readability-use-anyofallof <readability-use-anyofallof.html>`_,
    `zircon-temporary-objects <zircon-temporary-objects.html>`_,
 
@@ -313,10 +314,10 @@
 
    `cert-con36-c <cert-con36-c.html>`_, `bugprone-spuriously-wake-up-functions <bugprone-spuriously-wake-up-functions.html>`_,
    `cert-con54-cpp <cert-con54-cpp.html>`_, `bugprone-spuriously-wake-up-functions <bugprone-spuriously-wake-up-functions.html>`_,
-   `cert-dcl03-c <cert-dcl03-c.html>`_, `misc-static-assert <misc-static-assert.html>`_, "Yes"
-   `cert-dcl16-c <cert-dcl16-c.html>`_, `readability-uppercase-literal-suffix <readability-uppercase-literal-suffix.html>`_, "Yes"
-   `cert-dcl37-c <cert-dcl37-c.html>`_, `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_, "Yes"
-   `cert-dcl51-cpp <cert-dcl51-cpp.html>`_, `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_, "Yes"
+   `cert-dcl03-c <cert-dcl03-c.html>`_, `misc-static-assert <misc-static-assert.html>`_,
+   `cert-dcl16-c <cert-dcl16-c.html>`_, `readability-uppercase-literal-suffix <readability-uppercase-literal-suffix.html>`_,
+   `cert-dcl37-c <cert-dcl37-c.html>`_, `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_,
+   `cert-dcl51-cpp <cert-dcl51-cpp.html>`_, `bugprone-reserved-identifier <bugprone-reserved-identifier.html>`_,
    `cert-dcl54-cpp <cert-dcl54-cpp.html>`_, `misc-new-delete-overloads <misc-new-delete-overloads.html>`_,
    `cert-dcl59-cpp <cert-dcl59-cpp.html>`_, `google-build-namespaces <google-build-namespaces.html>`_,
    `cert-err09-cpp <cert-err09-cpp.html>`_, `misc-throw-by-value-catch-by-reference <misc-throw-by-value-catch-by-reference.html>`_,
@@ -324,7 +325,7 @@
    `cert-fio38-c <cert-fio38-c.html>`_, `misc-non-copyable-objects <misc-non-copyable-objects.html>`_,
    `cert-msc30-c <cert-msc30-c.html>`_, `cert-msc50-cpp <cert-msc50-cpp.html>`_,
    `cert-msc32-c <cert-msc32-c.html>`_, `cert-msc51-cpp <cert-msc51-cpp.html>`_,
-   `cert-oop11-cpp <cert-oop11-cpp.html>`_, `performance-move-constructor-init <performance-move-constructor-init.html>`_, "Yes"
+   `cert-oop11-cpp <cert-oop11-cpp.html>`_, `performance-move-constructor-init <performance-move-constructor-init.html>`_,
    `cert-oop54-cpp <cert-oop54-cpp.html>`_, `bugprone-unhandled-self-assignment <bugprone-unhandled-self-assignment.html>`_,
    `cert-pos44-c <cert-pos44-c.html>`_, `bugprone-bad-signal-to-kill-thread <bugprone-bad-signal-to-kill-thread.html>`_,
    `cert-str34-c <cert-str34-c.html>`_, `bugprone-signed-char-misuse <bugprone-signed-char-misuse.html>`_,
@@ -395,36 +396,36 @@
    `cppcoreguidelines-avoid-c-arrays <cppcoreguidelines-avoid-c-arrays.html>`_, `modernize-avoid-c-arrays <modernize-avoid-c-arrays.html>`_,
    `cppcoreguidelines-avoid-magic-numbers <cppcoreguidelines-avoid-magic-numbers.html>`_, `readability-magic-numbers <readability-magic-numbers.html>`_,
    `cppcoreguidelines-c-copy-assignment-signature <cppcoreguidelines-c-copy-assignment-signature.html>`_, `misc-unconventional-assign-operator <misc-unconventional-assign-operator.html>`_,
-   `cppcoreguidelines-explicit-virtual-functions <cppcoreguidelines-explicit-virtual-functions.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes"
+   `cppcoreguidelines-explicit-virtual-functions <cppcoreguidelines-explicit-virtual-functions.html>`_, `modernize-use-override <modernize-use-override.html>`_,
    `cppcoreguidelines-non-private-member-variables-in-classes <cppcoreguidelines-non-private-member-variables-in-classes.html>`_, `misc-non-private-member-variables-in-classes <misc-non-private-member-variables-in-classes.html>`_,
    `fuchsia-header-anon-namespaces <fuchsia-header-anon-namespaces.html>`_, `google-build-namespaces <google-build-namespaces.html>`_,
-   `google-readability-braces-around-statements <google-readability-braces-around-statements.html>`_, `readability-braces-around-statements <readability-braces-around-statements.html>`_, "Yes"
+   `google-readability-braces-around-statements <google-readability-braces-around-statements.html>`_, `readability-braces-around-statements <readability-braces-around-statements.html>`_,
    `google-readability-function-size <google-readability-function-size.html>`_, `readability-function-size <readability-function-size.html>`_,
    `google-readability-namespace-comments <google-readability-namespace-comments.html>`_, `llvm-namespace-comment <llvm-namespace-comment.html>`_,
    `hicpp-avoid-c-arrays <hicpp-avoid-c-arrays.html>`_, `modernize-avoid-c-arrays <modernize-avoid-c-arrays.html>`_,
-   `hicpp-braces-around-statements <hicpp-braces-around-statements.html>`_, `readability-braces-around-statements <readability-braces-around-statements.html>`_, "Yes"
-   `hicpp-deprecated-headers <hicpp-deprecated-headers.html>`_, `modernize-deprecated-headers <modernize-deprecated-headers.html>`_, "Yes"
-   `hicpp-explicit-conversions <hicpp-explicit-conversions.html>`_, `google-explicit-constructor <google-explicit-constructor.html>`_, "Yes"
+   `hicpp-braces-around-statements <hicpp-braces-around-statements.html>`_, `readability-braces-around-statements <readability-braces-around-statements.html>`_,
+   `hicpp-deprecated-headers <hicpp-deprecated-headers.html>`_, `modernize-deprecated-headers <modernize-deprecated-headers.html>`_,
+   `hicpp-explicit-conversions <hicpp-explicit-conversions.html>`_, `google-explicit-constructor <google-explicit-constructor.html>`_,
    `hicpp-function-size <hicpp-function-size.html>`_, `readability-function-size <readability-function-size.html>`_,
    `hicpp-invalid-access-moved <hicpp-invalid-access-moved.html>`_, `bugprone-use-after-move <bugprone-use-after-move.html>`_,
-   `hicpp-member-init <hicpp-member-init.html>`_, `cppcoreguidelines-pro-type-member-init <cppcoreguidelines-pro-type-member-init.html>`_, "Yes"
-   `hicpp-move-const-arg <hicpp-move-const-arg.html>`_, `performance-move-const-arg <performance-move-const-arg.html>`_, "Yes"
-   `hicpp-named-parameter <hicpp-named-parameter.html>`_, `readability-named-parameter <readability-named-parameter.html>`_, "Yes"
+   `hicpp-member-init <hicpp-member-init.html>`_, `cppcoreguidelines-pro-type-member-init <cppcoreguidelines-pro-type-member-init.html>`_,
+   `hicpp-move-const-arg <hicpp-move-const-arg.html>`_, `performance-move-const-arg <performance-move-const-arg.html>`_,
+   `hicpp-named-parameter <hicpp-named-parameter.html>`_, `readability-named-parameter <readability-named-parameter.html>`_,
    `hicpp-new-delete-operators <hicpp-new-delete-operators.html>`_, `misc-new-delete-overloads <misc-new-delete-overloads.html>`_,
    `hicpp-no-array-decay <hicpp-no-array-decay.html>`_, `cppcoreguidelines-pro-bounds-array-to-pointer-decay <cppcoreguidelines-pro-bounds-array-to-pointer-decay.html>`_,
    `hicpp-no-malloc <hicpp-no-malloc.html>`_, `cppcoreguidelines-no-malloc <cppcoreguidelines-no-malloc.html>`_,
-   `hicpp-noexcept-move <hicpp-noexcept-move.html>`_, `performance-noexcept-move-constructor <performance-noexcept-move-constructor.html>`_, "Yes"
+   `hicpp-noexcept-move <hicpp-noexcept-move.html>`_, `performance-noexcept-move-constructor <performance-noexcept-move-constructor.html>`_,
    `hicpp-special-member-functions <hicpp-special-member-functions.html>`_, `cppcoreguidelines-special-member-functions <cppcoreguidelines-special-member-functions.html>`_,
-   `hicpp-static-assert <hicpp-static-assert.html>`_, `misc-static-assert <misc-static-assert.html>`_, "Yes"
+   `hicpp-static-assert <hicpp-static-assert.html>`_, `misc-static-assert <misc-static-assert.html>`_,
    `hicpp-undelegated-constructor <hicpp-undelegated-constructor.html>`_, `bugprone-undelegated-constructor <bugprone-undelegated-constructor.html>`_,
-   `hicpp-uppercase-literal-suffix <hicpp-uppercase-literal-suffix.html>`_, `readability-uppercase-literal-suffix <readability-uppercase-literal-suffix.html>`_, "Yes"
-   `hicpp-use-auto <hicpp-use-auto.html>`_, `modernize-use-auto <modernize-use-auto.html>`_, "Yes"
-   `hicpp-use-emplace <hicpp-use-emplace.html>`_, `modernize-use-emplace <modernize-use-emplace.html>`_, "Yes"
-   `hicpp-use-equals-default <hicpp-use-equals-default.html>`_, `modernize-use-equals-default <modernize-use-equals-default.html>`_, "Yes"
-   `hicpp-use-equals-delete <hicpp-use-equals-delete.html>`_, `modernize-use-equals-delete <modernize-use-equals-delete.html>`_, "Yes"
-   `hicpp-use-noexcept <hicpp-use-noexcept.html>`_, `modernize-use-noexcept <modernize-use-noexcept.html>`_, "Yes"
-   `hicpp-use-nullptr <hicpp-use-nullptr.html>`_, `modernize-use-nullptr <modernize-use-nullptr.html>`_, "Yes"
-   `hicpp-use-override <hicpp-use-override.html>`_, `modernize-use-override <modernize-use-override.html>`_, "Yes"
+   `hicpp-uppercase-literal-suffix <hicpp-uppercase-literal-suffix.html>`_, `readability-uppercase-literal-suffix <readability-uppercase-literal-suffix.html>`_,
+   `hicpp-use-auto <hicpp-use-auto.html>`_, `modernize-use-auto <modernize-use-auto.html>`_,
+   `hicpp-use-emplace <hicpp-use-emplace.html>`_, `modernize-use-emplace <modernize-use-emplace.html>`_,
+   `hicpp-use-equals-default <hicpp-use-equals-default.html>`_, `modernize-use-equals-default <modernize-use-equals-default.html>`_,
+   `hicpp-use-equals-delete <hicpp-use-equals-delete.html>`_, `modernize-use-equals-delete <modernize-use-equals-delete.html>`_,
+   `hicpp-use-noexcept <hicpp-use-noexcept.html>`_, `modernize-use-noexcept <modernize-use-noexcept.html>`_,
+   `hicpp-use-nullptr <hicpp-use-nullptr.html>`_, `modernize-use-nullptr <modernize-use-nullptr.html>`_,
+   `hicpp-use-override <hicpp-use-override.html>`_, `modernize-use-override <modernize-use-override.html>`_,
    `hicpp-vararg <hicpp-vararg.html>`_, `cppcoreguidelines-pro-type-vararg <cppcoreguidelines-pro-type-vararg.html>`_,
-   `llvm-else-after-return <llvm-else-after-return.html>`_, `readability-else-after-return <readability-else-after-return.html>`_, "Yes"
-   `llvm-qualified-auto <llvm-qualified-auto.html>`_, `readability-qualified-auto <readability-qualified-auto.html>`_, "Yes"
+   `llvm-else-after-return <llvm-else-after-return.html>`_, `readability-else-after-return <readability-else-after-return.html>`_,
+   `llvm-qualified-auto <llvm-qualified-auto.html>`_, `readability-qualified-auto <readability-qualified-auto.html>`_,
Index: clang-tools-extra/docs/clang-tidy/checks/cert-sig30-c.rst
===================================================================
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/cert-sig30-c.rst
@@ -0,0 +1,14 @@
+.. title:: clang-tidy - cert-sig30-c
+
+cert-sig30-c
+============
+
+This check finds functions registered as signal handlers that call non asynchronous-safe functions.
+User functions called from the handlers are checked too, as far as possible.
+
+The minimal list of asynchronous-safe system functions is:
+``abort()``, ``_Exit()``, ``quick_exit()`` and ``signal()`` (for ``signal`` there are additional conditions that are not checked).
+
+This check corresponds to the CERT C Coding Standard rule
+`SIG30-C. Call only asynchronous-safe functions within signal handlers
+<https://www.securecoding.cert.org/confluence/display/c/SIG30-C.+Call+only+asynchronous-safe+functions+within+signal+handlers>`_.
Index: clang-tools-extra/clang-tidy/cert/SignalHandlerCheck.h
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cert/SignalHandlerCheck.h
@@ -0,0 +1,34 @@
+//===--- SignalHandlerCheck.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_CERT_SIGNALHANDLERCHECK_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_SIGNALHANDLERCHECK_H
+
+#include "../ClangTidyCheck.h"
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+/// Checker for SEI CERT rule SIG30-C
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cert-signal-handler-check.html
+class SignalHandlerCheck : public ClangTidyCheck {
+public:
+  SignalHandlerCheck(StringRef Name, ClangTidyContext *Context)
+      : ClangTidyCheck(Name, Context) {}
+  void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+  void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CERT_SIGNALHANDLERCHECK_H
\ No newline at end of file
Index: clang-tools-extra/clang-tidy/cert/SignalHandlerCheck.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/clang-tidy/cert/SignalHandlerCheck.cpp
@@ -0,0 +1,141 @@
+//===--- ExitHandlerCheck.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 "SignalHandlerCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include <deque>
+#include <iterator>
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+namespace cert {
+
+namespace {
+constexpr StringRef SignalFun = "signal";
+constexpr StringRef AbortFun = "abort";
+constexpr StringRef ExitFun = "_Exit";
+constexpr StringRef QuickExitFun = "quick_exit";
+
+bool isSystemCall(const FunctionDecl *FD) {
+  // This check does not work with function calls in std namespace.
+  if (!FD->isGlobal() || FD->isInStdNamespace())
+    return false;
+  return FD->getASTContext().getSourceManager().isInSystemHeader(
+      FD->getLocation());
+}
+
+bool isAllowedSystemCall(const FunctionDecl *FD) {
+  if (!FD->getIdentifier())
+    return true;
+  const StringRef N = FD->getName();
+  if (N == AbortFun || N == ExitFun || N == QuickExitFun || N == SignalFun)
+    return true;
+  return false;
+}
+
+class CalledFunctionsCollector
+    : public RecursiveASTVisitor<CalledFunctionsCollector> {
+  // The declarations and usages of encountered functions.
+  llvm::SmallVector<std::pair<const FunctionDecl *, const Expr *>, 32>
+      CalledFunctions;
+
+public:
+  bool VisitCallExpr(const CallExpr *CE) {
+    if (const auto *F = dyn_cast<FunctionDecl>(CE->getCalleeDecl()))
+      CalledFunctions.emplace_back(F, CE);
+    return true;
+  }
+
+  void clear() { CalledFunctions.clear(); }
+
+  /// Iteration over the collector is iteration over the found FunctionDecls.
+  /// In order to allow moving from the underlying container, non-const
+  /// interators are allowed.
+  auto begin() { return CalledFunctions.begin(); }
+  auto end() { return CalledFunctions.end(); }
+};
+} // namespace
+
+void SignalHandlerCheck::registerMatchers(MatchFinder *Finder) {
+  const auto HandlerProtoType = functionProtoType(parameterCountIs(1));
+  const auto IsSignalFunction =
+      callee(functionDecl(hasName(SignalFun), parameterCountIs(2)));
+  const auto HandlerAsSecondArg = hasArgument(
+      1, declRefExpr(hasDeclaration(functionDecl().bind("handler_decl")),
+                     unless(isExpandedFromMacro("SIG_IGN")),
+                     unless(isExpandedFromMacro("SIG_DFL")))
+             .bind("handler_expr"));
+  Finder->addMatcher(
+      callExpr(IsSignalFunction, HandlerAsSecondArg).bind("register_call"),
+      this);
+}
+
+void SignalHandlerCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *SignalCall = Result.Nodes.getNodeAs<CallExpr>("register_call");
+  const auto *HandlerDecl =
+      Result.Nodes.getNodeAs<FunctionDecl>("handler_decl");
+  const auto *HandlerExpr = Result.Nodes.getNodeAs<DeclRefExpr>("handler_expr");
+
+  // Visit each function encountered in the callgraph only once.
+  llvm::DenseSet<const FunctionDecl *> SeenFunctions;
+
+  // The worklist of the callgraph visitation algorithm.
+  std::deque<std::pair<const FunctionDecl *, const Expr *>> CalledFunctions{
+      {HandlerDecl, HandlerExpr}};
+
+  // Visit the definition of every function referenced by the handler function.
+  // Check for allowed function calls.
+  while (!CalledFunctions.empty()) {
+    // Use the canonical declaration.
+    const FunctionDecl *FunctionToCheck =
+        CalledFunctions.front().first->getCanonicalDecl();
+    const Expr *FunctionCall = CalledFunctions.front().second;
+    CalledFunctions.pop_front();
+
+    // Do not visit function if already encountered.
+    if (!SeenFunctions.insert(FunctionToCheck).second)
+      continue;
+
+    // Check if the call is allowed.
+    // Only system calls are to be checked.
+    if (isSystemCall(FunctionToCheck)) {
+      if (isAllowedSystemCall(FunctionToCheck))
+        continue;
+
+      diag(FunctionCall->getBeginLoc(),
+           "Signal handler potentially calls non asynchronous-safe function. "
+           "This may result in undefined behavior.");
+      diag(SignalCall->getSourceRange().getBegin(),
+           "Signal handler registered here.", DiagnosticIDs::Note);
+      diag(HandlerDecl->getBeginLoc(), "Handler function declared here.",
+           DiagnosticIDs::Note);
+      break;
+    }
+
+    // Get the body of the encountered non-system call function.
+    const FunctionDecl *FunctionBody;
+    if (!FunctionToCheck->hasBody(FunctionBody))
+      continue;
+
+    // Collect all called functions.
+    CalledFunctionsCollector Collector;
+    Collector.TraverseStmt(FunctionBody->getBody());
+    llvm::move(Collector, std::back_inserter(CalledFunctions));
+  }
+}
+
+} // namespace cert
+} // namespace tidy
+} // namespace clang
\ No newline at end of file
Index: clang-tools-extra/clang-tidy/cert/CMakeLists.txt
===================================================================
--- clang-tools-extra/clang-tidy/cert/CMakeLists.txt
+++ clang-tools-extra/clang-tidy/cert/CMakeLists.txt
@@ -15,6 +15,7 @@
   PostfixOperatorCheck.cpp
   ProperlySeededRandomGeneratorCheck.cpp
   SetLongJmpCheck.cpp
+  SignalHandlerCheck.cpp
   StaticObjectExceptionCheck.cpp
   StrToNumCheck.cpp
   ThrownExceptionTypeCheck.cpp
Index: clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
===================================================================
--- clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
+++ clang-tools-extra/clang-tidy/cert/CERTTidyModule.cpp
@@ -31,6 +31,7 @@
 #include "PostfixOperatorCheck.h"
 #include "ProperlySeededRandomGeneratorCheck.h"
 #include "SetLongJmpCheck.h"
+#include "SignalHandlerCheck.h"
 #include "StaticObjectExceptionCheck.h"
 #include "StrToNumCheck.h"
 #include "ThrownExceptionTypeCheck.h"
@@ -109,6 +110,8 @@
     // POS
     CheckFactories.registerCheck<bugprone::BadSignalToKillThreadCheck>(
         "cert-pos44-c");
+    // SIG
+    CheckFactories.registerCheck<SignalHandlerCheck>("cert-sig30-c");
     // STR
     CheckFactories.registerCheck<bugprone::SignedCharMisuseCheck>(
         "cert-str34-c");
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to