1 // RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default 2 // RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default 3 4 // A destructor may be marked noreturn and should still influence the CFG. 5 void pr6884_abort() __attribute__((noreturn)); 6 7 struct pr6884_abort_struct { pr6884_abort_structpr6884_abort_struct8 pr6884_abort_struct() {} ~pr6884_abort_structpr6884_abort_struct9 ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); } 10 }; 11 ~otherother12struct other { ~other() {} }; 13 14 // Ensure that destructors from objects are properly modeled in the CFG despite 15 // the presence of switches, case statements, labels, and blocks. These tests 16 // try to cover bugs reported in both PR6884 and PR10063. 17 namespace abort_struct_complex_cfgs { basic(int x)18 int basic(int x) { 19 switch (x) { default: pr6884_abort(); } 20 } f1(int x)21 int f1(int x) { 22 switch (x) default: pr6884_abort_struct(); 23 } f2(int x)24 int f2(int x) { 25 switch (x) { default: pr6884_abort_struct(); } 26 } f2_positive(int x)27 int f2_positive(int x) { 28 switch (x) { default: ; } 29 } // expected-warning {{control reaches end of non-void function}} f3(int x)30 int f3(int x) { 31 switch (x) { default: { pr6884_abort_struct(); } } 32 } f4(int x)33 int f4(int x) { 34 switch (x) default: L1: L2: case 4: pr6884_abort_struct(); 35 } f5(int x)36 int f5(int x) { 37 switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); } 38 } f6(int x)39 int f6(int x) { 40 switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); } 41 } 42 43 // FIXME: detect noreturn destructors triggered by calls to delete. f7(int x)44 int f7(int x) { 45 switch (x) default: L1: L2: case 4: { 46 pr6884_abort_struct *p = new pr6884_abort_struct(); 47 delete p; 48 } 49 } // expected-warning {{control reaches end of non-void function}} 50 51 // Test that these constructs work even when extraneous blocks are created 52 // before and after the switch due to implicit destructors. g1(int x)53 int g1(int x) { 54 other o; 55 switch (x) default: pr6884_abort_struct(); 56 } g2(int x)57 int g2(int x) { 58 other o; 59 switch (x) { default: pr6884_abort_struct(); } 60 } g2_positive(int x)61 int g2_positive(int x) { 62 other o; 63 switch (x) { default: ; } 64 } // expected-warning {{control reaches end of non-void function}} g3(int x)65 int g3(int x) { 66 other o; 67 switch (x) { default: { pr6884_abort_struct(); } } 68 } g4(int x)69 int g4(int x) { 70 other o; 71 switch (x) default: L1: L2: case 4: pr6884_abort_struct(); 72 } g5(int x)73 int g5(int x) { 74 other o; 75 switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); } 76 } g6(int x)77 int g6(int x) { 78 other o; 79 switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); } 80 } 81 82 // Test that these constructs work even with variables carrying the no-return 83 // destructor instead of temporaries. h1(int x)84 int h1(int x) { 85 other o; 86 switch (x) default: pr6884_abort_struct a; 87 } h2(int x)88 int h2(int x) { 89 other o; 90 switch (x) { default: pr6884_abort_struct a; } 91 } h3(int x)92 int h3(int x) { 93 other o; 94 switch (x) { default: { pr6884_abort_struct a; } } 95 } h4(int x)96 int h4(int x) { 97 other o; 98 switch (x) default: L1: L2: case 4: pr6884_abort_struct a; 99 } h5(int x)100 int h5(int x) { 101 other o; 102 switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; } 103 } h6(int x)104 int h6(int x) { 105 other o; 106 switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; } 107 } 108 } 109 110 // PR9380 111 struct PR9380 { 112 ~PR9380(); 113 }; 114 struct PR9380_B : public PR9380 { 115 PR9380_B( const PR9380& str ); 116 }; test_PR9380(const PR9380 & aKey)117void test_PR9380(const PR9380& aKey) { 118 const PR9380& flatKey = PR9380_B(aKey); 119 } 120 121 // Array of objects with destructors. This is purely a coverage test case. test_array()122void test_array() { 123 PR9380 a[2]; 124 } 125 126 // Test classes wrapped in typedefs. This is purely a coverage test case 127 // for CFGImplictDtor::getDestructorDecl(). test_typedefs()128void test_typedefs() { 129 typedef PR9380 PR9380_Ty; 130 PR9380_Ty test; 131 PR9380_Ty test2[20]; 132 } 133 134 // PR9412 - Handle CFG traversal with null successors. 135 enum PR9412_MatchType { PR9412_Exact }; 136 PR9412_t()137template <PR9412_MatchType type> int PR9412_t() { 138 switch (type) { 139 case PR9412_Exact: 140 default: 141 break; 142 } 143 } // expected-warning {{control reaches end of non-void function}} 144 PR9412_f()145void PR9412_f() { 146 PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_MatchType::PR9412_Exact>' requested here}} 147 } 148 149 struct NoReturn { 150 ~NoReturn() __attribute__((noreturn)); 151 operator bool() const; 152 }; 153 struct Return { 154 ~Return(); 155 operator bool() const; 156 }; 157 testTernaryUnconditionalNoreturn()158int testTernaryUnconditionalNoreturn() { 159 true ? NoReturn() : NoReturn(); 160 } 161 testTernaryStaticallyConditionalNoretrunOnTrue()162int testTernaryStaticallyConditionalNoretrunOnTrue() { 163 true ? NoReturn() : Return(); 164 } 165 testTernaryStaticallyConditionalRetrunOnTrue()166int testTernaryStaticallyConditionalRetrunOnTrue() { 167 true ? Return() : NoReturn(); 168 } // expected-warning {{control reaches end of non-void function}} 169 testTernaryStaticallyConditionalNoretrunOnFalse()170int testTernaryStaticallyConditionalNoretrunOnFalse() { 171 false ? Return() : NoReturn(); 172 } 173 testTernaryStaticallyConditionalRetrunOnFalse()174int testTernaryStaticallyConditionalRetrunOnFalse() { 175 false ? NoReturn() : Return(); 176 } // expected-warning {{control reaches end of non-void function}} 177 testTernaryConditionalNoreturnTrueBranch(bool value)178int testTernaryConditionalNoreturnTrueBranch(bool value) { 179 value ? (NoReturn() || NoReturn()) : Return(); 180 } // expected-warning {{control may reach end of non-void function}} 181 testTernaryConditionalNoreturnFalseBranch(bool value)182int testTernaryConditionalNoreturnFalseBranch(bool value) { 183 value ? Return() : (NoReturn() || NoReturn()); 184 } // expected-warning {{control may reach end of non-void function}} 185 testConditionallyExecutedComplexTernaryTrueBranch(bool value)186int testConditionallyExecutedComplexTernaryTrueBranch(bool value) { 187 value || (true ? NoReturn() : true); 188 } // expected-warning {{control may reach end of non-void function}} 189 testConditionallyExecutedComplexTernaryFalseBranch(bool value)190int testConditionallyExecutedComplexTernaryFalseBranch(bool value) { 191 value || (false ? true : NoReturn()); 192 } // expected-warning {{control may reach end of non-void function}} 193 testStaticallyExecutedLogicalOrBranch()194int testStaticallyExecutedLogicalOrBranch() { 195 false || NoReturn(); 196 } 197 testStaticallyExecutedLogicalAndBranch()198int testStaticallyExecutedLogicalAndBranch() { 199 true && NoReturn(); 200 } 201 testStaticallySkippedLogicalOrBranch()202int testStaticallySkippedLogicalOrBranch() { 203 true || NoReturn(); 204 } // expected-warning {{control reaches end of non-void function}} 205 testStaticallySkppedLogicalAndBranch()206int testStaticallySkppedLogicalAndBranch() { 207 false && NoReturn(); 208 } // expected-warning {{control reaches end of non-void function}} 209 testConditionallyExecutedComplexLogicalBranch(bool value)210int testConditionallyExecutedComplexLogicalBranch(bool value) { 211 value || (true && NoReturn()); 212 } // expected-warning {{control may reach end of non-void function}} 213 testConditionallyExecutedComplexLogicalBranch2(bool value)214int testConditionallyExecutedComplexLogicalBranch2(bool value) { 215 (true && value) || (true && NoReturn()); 216 } // expected-warning {{control may reach end of non-void function}} 217 testConditionallyExecutedComplexLogicalBranch3(bool value)218int testConditionallyExecutedComplexLogicalBranch3(bool value) { 219 (false && (Return() || true)) || (true && NoReturn()); 220 } 221 testConditionallyExecutedComplexLogicalBranch4(bool value)222int testConditionallyExecutedComplexLogicalBranch4(bool value) { 223 false || ((Return() || true) && (true && NoReturn())); 224 } 225 226 #if __cplusplus >= 201103L 227 namespace LambdaVsTemporaryDtor { 228 struct Y { ~Y(); }; XLambdaVsTemporaryDtor::X229 struct X { template<typename T> X(T, Y = Y()) {} }; 230 231 struct Fatal { ~Fatal() __attribute__((noreturn)); }; 232 struct FatalCopy { FatalCopy(); FatalCopy(const FatalCopy&, Fatal F = Fatal()); }; 233 234 void foo(); 235 bar()236 int bar() { 237 X work([](){ Fatal(); }); 238 foo(); 239 } // expected-warning {{control reaches end of non-void function}} 240 baz()241 int baz() { 242 FatalCopy fc; 243 X work([fc](){}); 244 foo(); 245 } // ok, initialization of lambda does not return 246 } 247 #endif 248 249 // Ensure that function-try-blocks also check for return values properly. functionTryBlock1(int s)250int functionTryBlock1(int s) try { 251 return 0; 252 } catch (...) { 253 } // expected-warning {{control may reach end of non-void function}} 254 functionTryBlock2(int s)255int functionTryBlock2(int s) try { 256 } catch (...) { 257 return 0; 258 } // expected-warning {{control may reach end of non-void function}} 259 functionTryBlock3(int s)260int functionTryBlock3(int s) try { 261 return 0; 262 } catch (...) { 263 return 0; 264 } // ok, both paths return. 265