265 lines · cpp
1// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -verify -Wreturn-type -Wno-error=return-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default2// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -std=c++11 -verify -Wreturn-type -Wno-error=return-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default3 4// A destructor may be marked noreturn and should still influence the CFG.5void pr6884_abort() __attribute__((noreturn));6 7struct pr6884_abort_struct {8 pr6884_abort_struct() {}9 ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }10};11 12struct other { ~other() {} };13 14// Ensure that destructors from objects are properly modeled in the CFG despite15// the presence of switches, case statements, labels, and blocks. These tests16// try to cover bugs reported in both PR6884 and PR10063.17namespace abort_struct_complex_cfgs {18 int basic(int x) {19 switch (x) { default: pr6884_abort(); }20 }21 int f1(int x) {22 switch (x) default: pr6884_abort_struct();23 }24 int f2(int x) {25 switch (x) { default: pr6884_abort_struct(); }26 }27 int f2_positive(int x) {28 switch (x) { default: ; }29 } // expected-warning {{non-void function does not return a value}}30 int f3(int x) {31 switch (x) { default: { pr6884_abort_struct(); } }32 }33 int f4(int x) {34 switch (x) default: L1: L2: case 4: pr6884_abort_struct();35 }36 int f5(int x) {37 switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }38 }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.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 {{non-void function does not return a value}}50 51 // Test that these constructs work even when extraneous blocks are created52 // before and after the switch due to implicit destructors.53 int g1(int x) {54 other o;55 switch (x) default: pr6884_abort_struct();56 }57 int g2(int x) {58 other o;59 switch (x) { default: pr6884_abort_struct(); }60 }61 int g2_positive(int x) {62 other o;63 switch (x) { default: ; }64 } // expected-warning {{non-void function does not return a value}}65 int g3(int x) {66 other o;67 switch (x) { default: { pr6884_abort_struct(); } }68 }69 int g4(int x) {70 other o;71 switch (x) default: L1: L2: case 4: pr6884_abort_struct();72 }73 int g5(int x) {74 other o;75 switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }76 }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-return83 // destructor instead of temporaries.84 int h1(int x) {85 other o;86 switch (x) default: pr6884_abort_struct a;87 }88 int h2(int x) {89 other o;90 switch (x) { default: pr6884_abort_struct a; }91 }92 int h3(int x) {93 other o;94 switch (x) { default: { pr6884_abort_struct a; } }95 }96 int h4(int x) {97 other o;98 switch (x) default: L1: L2: case 4: pr6884_abort_struct a;99 }100 int h5(int x) {101 other o;102 switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; }103 }104 int h6(int x) {105 other o;106 switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; }107 }108}109 110// PR9380111struct PR9380 {112 ~PR9380();113};114struct PR9380_B : public PR9380 {115 PR9380_B( const PR9380& str );116};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.122void test_array() {123 PR9380 a[2];124}125 126// Test classes wrapped in typedefs. This is purely a coverage test case127// for CFGImplictDtor::getDestructorDecl().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.135enum PR9412_MatchType { PR9412_Exact };136 137template <PR9412_MatchType type> int PR9412_t() {138 switch (type) {139 case PR9412_Exact:140 default:141 break;142 }143} // expected-warning {{non-void function does not return a value}}144 145void PR9412_f() {146 PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_Exact>' requested here}}147}148 149struct NoReturn {150 ~NoReturn() __attribute__((noreturn));151 operator bool() const;152};153struct Return {154 ~Return();155 operator bool() const;156};157 158int testTernaryUnconditionalNoreturn() {159 true ? NoReturn() : NoReturn();160}161 162int testTernaryStaticallyConditionalNoretrunOnTrue() {163 true ? NoReturn() : Return();164}165 166int testTernaryStaticallyConditionalRetrunOnTrue() {167 true ? Return() : NoReturn();168} // expected-warning {{non-void function does not return a value}}169 170int testTernaryStaticallyConditionalNoretrunOnFalse() {171 false ? Return() : NoReturn();172}173 174int testTernaryStaticallyConditionalRetrunOnFalse() {175 false ? NoReturn() : Return();176} // expected-warning {{non-void function does not return a value}}177 178int testTernaryConditionalNoreturnTrueBranch(bool value) {179 value ? (NoReturn() || NoReturn()) : Return();180} // expected-warning {{non-void function does not return a value in all control paths}}181 182int testTernaryConditionalNoreturnFalseBranch(bool value) {183 value ? Return() : (NoReturn() || NoReturn());184} // expected-warning {{non-void function does not return a value in all control paths}}185 186int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {187 value || (true ? NoReturn() : true);188} // expected-warning {{non-void function does not return a value in all control paths}}189 190int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {191 value || (false ? true : NoReturn());192} // expected-warning {{non-void function does not return a value in all control paths}}193 194int testStaticallyExecutedLogicalOrBranch() {195 false || NoReturn();196}197 198int testStaticallyExecutedLogicalAndBranch() {199 true && NoReturn();200}201 202int testStaticallySkippedLogicalOrBranch() {203 true || NoReturn();204} // expected-warning {{non-void function does not return a value}}205 206int testStaticallySkppedLogicalAndBranch() {207 false && NoReturn();208} // expected-warning {{non-void function does not return a value}}209 210int testConditionallyExecutedComplexLogicalBranch(bool value) {211 value || (true && NoReturn());212} // expected-warning {{non-void function does not return a value in all control paths}}213 214int testConditionallyExecutedComplexLogicalBranch2(bool value) {215 (true && value) || (true && NoReturn());216} // expected-warning {{non-void function does not return a value in all control paths}}217 218int testConditionallyExecutedComplexLogicalBranch3(bool value) {219 (false && (Return() || true)) || (true && NoReturn());220}221 222int testConditionallyExecutedComplexLogicalBranch4(bool value) {223 false || ((Return() || true) && (true && NoReturn()));224}225 226#if __cplusplus >= 201103L227namespace LambdaVsTemporaryDtor {228 struct Y { ~Y(); };229 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 236 int bar() {237 X work([](){ Fatal(); });238 foo();239 } // expected-warning {{non-void function does not return a value}}240 241 int baz() {242 FatalCopy fc;243 X work([fc](){});244 foo();245 } // ok, initialization of lambda does not return246}247#endif248 249// Ensure that function-try-blocks also check for return values properly.250int functionTryBlock1(int s) try {251 return 0;252} catch (...) {253} // expected-warning {{non-void function does not return a value in all control paths}}254 255int functionTryBlock2(int s) try {256} catch (...) {257 return 0;258} // expected-warning {{non-void function does not return a value in all control paths}}259 260int functionTryBlock3(int s) try {261 return 0;262} catch (...) {263 return 0;264} // ok, both paths return.265