xref: /llvm-project/clang/test/Analysis/no-return.c (revision ec6da3fb9d8c7859da22d9eb7e814faf2e5a524a)
1*ec6da3fbSArseniy Zaostrovnykh // RUN: %clang_analyze_cc1 -analyzer-checker=core -verify %s
2*ec6da3fbSArseniy Zaostrovnykh 
3*ec6da3fbSArseniy Zaostrovnykh typedef void(fatal_fun)() __attribute__((__noreturn__));
4*ec6da3fbSArseniy Zaostrovnykh fatal_fun* fatal_fptr;
5*ec6da3fbSArseniy Zaostrovnykh void fatal_decl() __attribute__((__noreturn__));
6*ec6da3fbSArseniy Zaostrovnykh 
7*ec6da3fbSArseniy Zaostrovnykh int rng();
8*ec6da3fbSArseniy Zaostrovnykh 
9*ec6da3fbSArseniy Zaostrovnykh /// This code calls a [[noreturn]] function pointer, which used to be handled
10*ec6da3fbSArseniy Zaostrovnykh /// inconsistently between AST builder and CSA.
11*ec6da3fbSArseniy Zaostrovnykh /// In the result, CSA produces a path where this function returns non-0.
return_zero_or_abort_by_fnptr()12*ec6da3fbSArseniy Zaostrovnykh int return_zero_or_abort_by_fnptr() {
13*ec6da3fbSArseniy Zaostrovnykh   if (rng()) fatal_fptr();
14*ec6da3fbSArseniy Zaostrovnykh   return 0;
15*ec6da3fbSArseniy Zaostrovnykh }
16*ec6da3fbSArseniy Zaostrovnykh 
17*ec6da3fbSArseniy Zaostrovnykh /// This function calls a [[noreturn]] function.
18*ec6da3fbSArseniy Zaostrovnykh /// If it does return, it always returns 0.
return_zero_or_abort_by_direct_fun()19*ec6da3fbSArseniy Zaostrovnykh int return_zero_or_abort_by_direct_fun() {
20*ec6da3fbSArseniy Zaostrovnykh   if (rng()) fatal_decl();
21*ec6da3fbSArseniy Zaostrovnykh   return 0;
22*ec6da3fbSArseniy Zaostrovnykh }
23*ec6da3fbSArseniy Zaostrovnykh 
24*ec6da3fbSArseniy Zaostrovnykh /// Trigger a division by zero issue depending on the return value
25*ec6da3fbSArseniy Zaostrovnykh /// of the called functions.
caller()26*ec6da3fbSArseniy Zaostrovnykh int caller() {
27*ec6da3fbSArseniy Zaostrovnykh   int x = 0;
28*ec6da3fbSArseniy Zaostrovnykh   // The following if branches must never be taken.
29*ec6da3fbSArseniy Zaostrovnykh   if (return_zero_or_abort_by_fnptr())
30*ec6da3fbSArseniy Zaostrovnykh     return 1 / x; // no-warning: Dead code.
31*ec6da3fbSArseniy Zaostrovnykh   if (return_zero_or_abort_by_direct_fun())
32*ec6da3fbSArseniy Zaostrovnykh     return 1 / x; // no-warning: Dead code.
33*ec6da3fbSArseniy Zaostrovnykh 
34*ec6da3fbSArseniy Zaostrovnykh   // Make sure the warning is still reported when viable.
35*ec6da3fbSArseniy Zaostrovnykh   return 1 / x; // expected-warning {{Division by zero}}
36*ec6da3fbSArseniy Zaostrovnykh }
37