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 Zaostrovnykhint 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 Zaostrovnykhint 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 Zaostrovnykhint 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