brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.7 KiB · 873e4c7 Raw
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