229 lines · cpp
1// RUN: %check_clang_tidy -std=c++14 %s bugprone-signal-handler %t -- -- -isystem %clang_tidy_headers -isystem %S/Inputs/signal-handler -target x86_64-unknown-unknown2// FIXME: Fix the checker to work in C++17 or later mode.3#include "stdcpp.h"4#include "stdio.h"5 6// Functions called "signal" that are different from the system version.7typedef void (*callback_t)(int);8void signal(int, callback_t, int);9namespace ns {10void signal(int, callback_t);11}12 13extern "C" void handler_unsafe(int) {14 printf("xxx");15}16 17extern "C" void handler_unsafe_1(int) {18 printf("xxx");19}20 21namespace test_invalid_handler {22 23void handler_non_extern_c(int) {24 printf("xxx");25}26 27struct A {28 static void handler_member(int) {29 printf("xxx");30 }31};32 33void test() {34 std::signal(SIGINT, handler_unsafe_1);35 // CHECK-MESSAGES: :[[@LINE-17]]:3: warning: standard function 'printf' may not be asynchronous-safe; calling it from a signal handler may be dangerous [bugprone-signal-handler]36 // CHECK-MESSAGES: :[[@LINE-2]]:23: note: function 'handler_unsafe_1' registered here as signal handler37 38 std::signal(SIGINT, handler_non_extern_c);39 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: functions without C linkage are not allowed as signal handler (until C++17) [bugprone-signal-handler]40 std::signal(SIGINT, A::handler_member);41 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: functions without C linkage are not allowed as signal handler (until C++17) [bugprone-signal-handler]42 std::signal(SIGINT, [](int) { printf("xxx"); });43 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: lambda function is not allowed as signal handler (until C++17) [bugprone-signal-handler]44 45 // This case is (deliberately) not found by the checker.46 std::signal(SIGINT, [](int) -> callback_t { return &handler_unsafe; }(1));47}48 49} // namespace test_invalid_handler50 51namespace test_non_standard_signal_call {52 53struct Signal {54 static void signal(int, callback_t);55};56 57void test() {58 // No diagnostics here. All these signal calls differ from the standard system one.59 signal(SIGINT, handler_unsafe, 1);60 ns::signal(SIGINT, handler_unsafe);61 Signal::signal(SIGINT, handler_unsafe);62 system_other::signal(SIGINT, handler_unsafe);63}64 65} // namespace test_non_standard_signal_call66 67namespace test_cpp_construct_in_handler {68 69struct Struct {70 virtual ~Struct() {}71 void f1();72 int *begin();73 int *end();74 static void f2();75};76struct Derived : public Struct {77};78 79struct X {80 X(int, float);81};82 83Struct *S_Global;84const Struct *S_GlobalConst;85 86void f_non_extern_c() {87}88 89void f_default_arg(int P1 = 0) {90}91 92extern "C" void handler_cpp(int) {93 using namespace ::test_cpp_construct_in_handler;94 95 // These calls are not found as problems.96 // (Called functions are not analyzed if the current function has already97 // other problems.)98 f_non_extern_c();99 Struct::f2();100 // 'auto' is not disallowed101 auto Auto = 28u;102 103 Struct S;104 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]105 // CHECK-MESSAGES: :[[@LINE-2]]:10: remark: internally, the statement is parsed as a 'CXXConstructExpr'106 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler107 S_Global->f1();108 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]109 // CHECK-MESSAGES: :[[@LINE-2]]:3: remark: internally, the statement is parsed as a 'CXXMemberCallExpr'110 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler111 const Struct &SRef = Struct();112 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]113 // CHECK-MESSAGES: :[[@LINE-2]]:24: remark: internally, the statement is parsed as a 'CXXBindTemporaryExpr'114 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler115 X(3, 4.4);116 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]117 // CHECK-MESSAGES: :[[@LINE-2]]:3: remark: internally, the statement is parsed as a 'CXXTemporaryObjectExpr'118 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler119 120 auto L = [](int i) { printf("%d", i); };121 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]122 // CHECK-MESSAGES: :[[@LINE-2]]:12: remark: internally, the statement is parsed as a 'CXXConstructExpr'123 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler124 L(2);125 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]126 // CHECK-MESSAGES: :[[@LINE-2]]:3: remark: internally, the statement is parsed as a 'CXXOperatorCallExpr'127 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler128 129 try {130 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]131 // CHECK-MESSAGES: :[[@LINE-2]]:3: remark: internally, the statement is parsed as a 'CXXTryStmt'132 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler133 int A;134 } catch (int) {135 };136 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]137 // CHECK-MESSAGES: :[[@LINE-3]]:5: remark: internally, the statement is parsed as a 'CXXCatchStmt'138 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler139 140 throw(12);141 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]142 // CHECK-MESSAGES: :[[@LINE-2]]:3: remark: internally, the statement is parsed as a 'CXXThrowExpr'143 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler144 145 for (int I : S) {146 }147 // CHECK-MESSAGES: :[[@LINE-2]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]148 // CHECK-MESSAGES: :[[@LINE-3]]:3: remark: internally, the statement is parsed as a 'CXXForRangeStmt'149 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler150 // CHECK-MESSAGES: :[[@LINE-5]]:14: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]151 // CHECK-MESSAGES: :[[@LINE-6]]:14: remark: internally, the statement is parsed as a 'CXXMemberCallExpr'152 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler153 154 int Int = *(reinterpret_cast<int *>(&S));155 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]156 // CHECK-MESSAGES: :[[@LINE-2]]:15: remark: internally, the statement is parsed as a 'CXXReinterpretCastExpr'157 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler158 Int = static_cast<int>(12.34);159 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]160 // CHECK-MESSAGES: :[[@LINE-2]]:9: remark: internally, the statement is parsed as a 'CXXStaticCastExpr'161 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler162 Derived *Der = dynamic_cast<Derived *>(S_Global);163 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]164 // CHECK-MESSAGES: :[[@LINE-2]]:18: remark: internally, the statement is parsed as a 'CXXDynamicCastExpr'165 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler166 Struct *SPtr = const_cast<Struct *>(S_GlobalConst);167 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]168 // CHECK-MESSAGES: :[[@LINE-2]]:18: remark: internally, the statement is parsed as a 'CXXConstCastExpr'169 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler170 Int = int(12.34);171 // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]172 // CHECK-MESSAGES: :[[@LINE-2]]:9: remark: internally, the statement is parsed as a 'CXXFunctionalCastExpr'173 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler174 175 int *IPtr = new int[10];176 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]177 // CHECK-MESSAGES: :[[@LINE-2]]:15: remark: internally, the statement is parsed as a 'CXXNewExpr'178 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler179 delete[] IPtr;180 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]181 // CHECK-MESSAGES: :[[@LINE-2]]:3: remark: internally, the statement is parsed as a 'CXXDeleteExpr'182 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler183 IPtr = nullptr;184 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]185 // CHECK-MESSAGES: :[[@LINE-2]]:10: remark: internally, the statement is parsed as a 'CXXNullPtrLiteralExpr'186 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler187 bool Bool = true;188 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]189 // CHECK-MESSAGES: :[[@LINE-2]]:15: remark: internally, the statement is parsed as a 'CXXBoolLiteralExpr'190 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler191 f_default_arg();192 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]193 // CHECK-MESSAGES: :[[@LINE-2]]:3: remark: internally, the statement is parsed as a 'CXXDefaultArgExpr'194 // CHECK-MESSAGES: :198:23: note: function 'handler_cpp' registered here as signal handler195}196 197void test() {198 std::signal(SIGINT, handler_cpp);199}200 201} // namespace test_cpp_construct_in_handler202 203namespace test_cpp_indirect {204 205void non_extern_c() {206 int *P = nullptr;207}208 209extern "C" void call_cpp_indirect() {210 int *P = nullptr;211 // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: C++-only construct is not allowed in signal handler (until C++17) [bugprone-signal-handler]212 // CHECK-MESSAGES: :[[@LINE-2]]:12: remark: internally, the statement is parsed as a 'CXXNullPtrLiteralExpr'213 // CHECK-MESSAGES: :[[@LINE+8]]:3: note: function 'call_cpp_indirect' called here from 'handler_cpp_indirect'214 // CHECK-MESSAGES: :[[@LINE+11]]:23: note: function 'handler_cpp_indirect' registered here as signal handler215}216 217extern "C" void handler_cpp_indirect(int) {218 non_extern_c();219 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: functions without C linkage are not allowed as signal handler (until C++17) [bugprone-signal-handler]220 // CHECK-MESSAGES: :[[@LINE+5]]:23: note: function 'handler_cpp_indirect' registered here as signal handler221 call_cpp_indirect();222}223 224void test() {225 std::signal(SIGINT, handler_cpp_indirect);226}227 228} // namespace test_cpp_indirect229