warn-unreachable.cpp revision a9bb955b499c244d24d02311f0f9100ade506794
1// RUN: %clang_cc1 %s -fcxx-exceptions -fexceptions -fsyntax-only -verify -fblocks -Wunreachable-code -Wno-unused-value
2
3int &halt() __attribute__((noreturn));
4int &live();
5int dead();
6int liveti() throw(int);
7int (*livetip)() throw(int);
8
9int test1() {
10  try {
11    live();
12  } catch (int i) {
13    live();
14  }
15  return 1;
16}
17
18void test2() {
19  try {
20    live();
21  } catch (int i) {
22    live();
23  }
24  try {
25    liveti();
26  } catch (int i) {
27    live();
28  }
29  try {
30    livetip();
31  } catch (int i) {
32    live();
33  }
34  throw 1;
35  dead();       // expected-warning {{will never be executed}}
36}
37
38
39void test3() {
40  halt()
41    --;         // expected-warning {{will never be executed}}
42  // FIXME: The unreachable part is just the '?', but really all of this
43  // code is unreachable and shouldn't be separately reported.
44  halt()        // expected-warning {{will never be executed}}
45    ?
46    dead() : dead();
47  live(),
48    float
49      (halt()); // expected-warning {{will never be executed}}
50}
51
52void test4() {
53  struct S {
54    int mem;
55  } s;
56  S &foor();
57  halt(), foor()// expected-warning {{will never be executed}}
58    .mem;
59}
60
61void test5() {
62  struct S {
63    int mem;
64  } s;
65  S &foor() __attribute__((noreturn));
66  foor()
67    .mem;       // expected-warning {{will never be executed}}
68}
69
70void test6() {
71  struct S {
72    ~S() { }
73    S(int i) { }
74  };
75  live(),
76    S
77      (halt());  // expected-warning {{will never be executed}}
78}
79
80// Don't warn about unreachable code in template instantiations, as
81// they may only be unreachable in that specific instantiation.
82void isUnreachable();
83
84template <typename T> void test_unreachable_templates() {
85  T::foo();
86  isUnreachable();  // no-warning
87}
88
89struct TestUnreachableA {
90  static void foo() __attribute__((noreturn));
91};
92struct TestUnreachableB {
93  static void foo();
94};
95
96void test_unreachable_templates_harness() {
97  test_unreachable_templates<TestUnreachableA>();
98  test_unreachable_templates<TestUnreachableB>();
99}
100
101// Do warn about non-dependent unreachable code in templates
102// Warn even if the template is never instantiated
103
104template<typename T> void test_non_dependent_unreachable_templates() {
105  TestUnreachableA::foo();
106  isUnreachable(); // expected-warning {{will never be executed}}
107}
108
109// Warn only once even if the template is instantiated multiple times
110
111template<typename T> void test_non_dependent_unreachable_templates2() {
112  TestUnreachableA::foo();
113  isUnreachable(); // expected-warning {{will never be executed}}
114}
115
116template void test_non_dependent_unreachable_templates2<int>();
117template void test_non_dependent_unreachable_templates2<long>();
118
119// Do warn about explict template specializations, as they represent
120// actual concrete functions that somebody wrote.
121
122template <typename T> void funcToSpecialize() {}
123template <> void funcToSpecialize<int>() {
124  halt();
125  dead(); // expected-warning {{will never be executed}}
126}
127
128// Ensure we don't regress a fix involving undefined bases to template
129// destructors when computing the CFG for unreachable code analysis
130template<int> struct imp;
131template<int a>
132struct aligned_storage : imp<a> {
133 ~aligned_storage() { }
134};
135
136// is this valid?
137template<typename T>
138class outer {
139  class inner;
140  void func() {
141    inner t;
142  }
143};
144