| // RUN: %clang_cc1 -fsyntax-only %s -verify |
| |
| [[noreturn]] extern void noret(); |
| [[noreturn]] extern void noret2(); |
| extern void ordinary(); |
| |
| typedef void (*func_type)(void); |
| |
| // Constant initialization. |
| |
| void (* const const_fptr)() = noret; |
| [[noreturn]] void test_global_const() { |
| const_fptr(); |
| } |
| |
| const func_type const_fptr_cast = (func_type)noret2; |
| [[noreturn]] void test_global_cast() { |
| const_fptr_cast(); |
| } |
| |
| void (* const const_fptr_list)() = {noret}; |
| [[noreturn]] void test_global_list() { |
| const_fptr_list(); |
| } |
| |
| const func_type const_fptr_fcast = func_type(noret2); |
| [[noreturn]] void test_global_fcast() { |
| const_fptr_fcast(); |
| } |
| |
| [[noreturn]] void test_local_const() { |
| void (* const fptr)() = noret; |
| fptr(); |
| } |
| |
| // Global variable assignment. |
| void (*global_fptr)() = noret; |
| |
| [[noreturn]] void test_global_noassign() { |
| global_fptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_global_assign() { |
| global_fptr = noret; |
| global_fptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| // Local variable assignment. |
| |
| [[noreturn]] void test_init() { |
| func_type func_ptr = noret; |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_assign() { |
| void (*func_ptr)(void); |
| func_ptr = noret; |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_override() { |
| func_type func_ptr; |
| func_ptr = ordinary; |
| func_ptr = noret; |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_if_all(int x) { |
| func_type func_ptr; |
| if (x > 0) |
| func_ptr = noret; |
| else |
| func_ptr = noret2; |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_if_mix(int x) { |
| func_type func_ptr; |
| if (x > 0) |
| func_ptr = noret; |
| else |
| func_ptr = ordinary; |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_if_opt(int x) { |
| func_type func_ptr = noret; |
| if (x > 0) |
| func_ptr = ordinary; |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_if_opt2(int x) { |
| func_type func_ptr = ordinary; |
| if (x > 0) |
| func_ptr = noret; |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_if_nest_all(int x, int y) { |
| func_type func_ptr; |
| if (x > 0) { |
| if (y > 0) |
| func_ptr = noret; |
| else |
| func_ptr = noret2; |
| } else { |
| if (y < 0) |
| func_ptr = noret2; |
| else |
| func_ptr = noret; |
| } |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_if_nest_mix(int x, int y) { |
| func_type func_ptr; |
| if (x > 0) { |
| if (y > 0) |
| func_ptr = noret; |
| else |
| func_ptr = noret2; |
| } else { |
| if (y < 0) |
| func_ptr = ordinary; |
| else |
| func_ptr = noret; |
| } |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_switch_all(int x) { |
| func_type func_ptr; |
| switch(x) { |
| case 1: |
| func_ptr = noret; |
| break; |
| default: |
| func_ptr = noret2; |
| break; |
| } |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_switch_mix(int x) { |
| func_type func_ptr; |
| switch(x) { |
| case 1: |
| func_ptr = ordinary; |
| break; |
| default: |
| func_ptr = noret; |
| break; |
| } |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_switch_fall(int x) { |
| func_type func_ptr; |
| switch(x) { |
| case 1: |
| func_ptr = ordinary; |
| default: |
| func_ptr = noret; |
| break; |
| } |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_switch_all_nest(int x, int y) { |
| func_type func_ptr; |
| switch(x) { |
| case 1: |
| func_ptr = noret; |
| break; |
| default: |
| if (y > 0) |
| func_ptr = noret2; |
| else |
| func_ptr = noret; |
| break; |
| } |
| func_ptr(); |
| } |
| |
| [[noreturn]] void test_switch_mix_nest(int x, int y) { |
| func_type func_ptr; |
| switch(x) { |
| case 1: |
| func_ptr = noret; |
| break; |
| default: |
| if (y > 0) |
| func_ptr = noret2; |
| else |
| func_ptr = ordinary; |
| break; |
| } |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| // Function parameters. |
| |
| [[noreturn]] void test_param(void (*func_ptr)() = noret) { |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_const_param(void (* const func_ptr)() = noret) { |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| // Escaped value. |
| |
| extern void abc_01(func_type &); |
| extern void abc_02(func_type *); |
| |
| [[noreturn]] void test_escape_ref() { |
| func_type func_ptr = noret; |
| abc_01(func_ptr); |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |
| |
| [[noreturn]] void test_escape_addr() { |
| func_type func_ptr = noret; |
| abc_02(&func_ptr); |
| func_ptr(); |
| } // expected-warning {{function declared 'noreturn' should not return}} |