reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
  194
  195
  196
  197
  198
  199
  200
  201
  202
  203
  204
  205
  206
  207
  208
  209
  210
  211
  212
  213
  214
  215
  216
  217
  218
  219
  220
  221
  222
  223
  224
  225
  226
  227
  228
  229
  230
  231
  232
  233
  234
  235
  236
  237
  238
  239
  240
  241
  242
  243
  244
  245
  246
  247
  248
  249
  250
  251
  252
  253
  254
  255
  256
  257
  258
  259
  260
  261
  262
  263
  264
// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default
// RUN: %clang_cc1 %s -fsyntax-only -fcxx-exceptions -std=c++11 -verify -Wreturn-type -Wmissing-noreturn -Wno-unreachable-code -Wno-covered-switch-default

// A destructor may be marked noreturn and should still influence the CFG.
void pr6884_abort() __attribute__((noreturn));

struct pr6884_abort_struct {
  pr6884_abort_struct() {}
  ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
};

struct other { ~other() {} };

// Ensure that destructors from objects are properly modeled in the CFG despite
// the presence of switches, case statements, labels, and blocks. These tests
// try to cover bugs reported in both PR6884 and PR10063.
namespace abort_struct_complex_cfgs {
  int basic(int x) {
    switch (x) { default: pr6884_abort(); }
  }
  int f1(int x) {
    switch (x) default: pr6884_abort_struct();
  }
  int f2(int x) {
    switch (x) { default: pr6884_abort_struct(); }
  }
  int f2_positive(int x) {
    switch (x) { default: ; }
  } // expected-warning {{control reaches end of non-void function}}
  int f3(int x) {
    switch (x) { default: { pr6884_abort_struct(); } }
  }
  int f4(int x) {
    switch (x) default: L1: L2: case 4: pr6884_abort_struct();
  }
  int f5(int x) {
    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
  }
  int f6(int x) {
    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
  }

  // FIXME: detect noreturn destructors triggered by calls to delete.
  int f7(int x) {
    switch (x) default: L1: L2: case 4: {
      pr6884_abort_struct *p = new pr6884_abort_struct();
      delete p;
    }
  } // expected-warning {{control reaches end of non-void function}}

  // Test that these constructs work even when extraneous blocks are created
  // before and after the switch due to implicit destructors.
  int g1(int x) {
    other o;
    switch (x) default: pr6884_abort_struct();
  }
  int g2(int x) {
    other o;
    switch (x) { default: pr6884_abort_struct(); }
  }
  int g2_positive(int x) {
    other o;
    switch (x) { default: ; }
  } // expected-warning {{control reaches end of non-void function}}
  int g3(int x) {
    other o;
    switch (x) { default: { pr6884_abort_struct(); } }
  }
  int g4(int x) {
    other o;
    switch (x) default: L1: L2: case 4: pr6884_abort_struct();
  }
  int g5(int x) {
    other o;
    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
  }
  int g6(int x) {
    other o;
    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
  }

  // Test that these constructs work even with variables carrying the no-return
  // destructor instead of temporaries.
  int h1(int x) {
    other o;
    switch (x) default: pr6884_abort_struct a;
  }
  int h2(int x) {
    other o;
    switch (x) { default: pr6884_abort_struct a; }
  }
  int h3(int x) {
    other o;
    switch (x) { default: { pr6884_abort_struct a; } }
  }
  int h4(int x) {
    other o;
    switch (x) default: L1: L2: case 4: pr6884_abort_struct a;
  }
  int h5(int x) {
    other o;
    switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; }
  }
  int h6(int x) {
    other o;
    switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; }
  }
}

// PR9380
struct PR9380 {
  ~PR9380();
};
struct PR9380_B : public PR9380 {
  PR9380_B( const PR9380& str );
};
void test_PR9380(const PR9380& aKey) {
  const PR9380& flatKey = PR9380_B(aKey);
}

// Array of objects with destructors.  This is purely a coverage test case.
void test_array() {
  PR9380 a[2];
}

// Test classes wrapped in typedefs.  This is purely a coverage test case
// for CFGImplictDtor::getDestructorDecl().
void test_typedefs() {
  typedef PR9380 PR9380_Ty;
  PR9380_Ty test;
  PR9380_Ty test2[20];
}

// PR9412 - Handle CFG traversal with null successors.
enum PR9412_MatchType { PR9412_Exact };

template <PR9412_MatchType type> int PR9412_t() {
  switch (type) {
    case PR9412_Exact:
    default:
        break;
  }
} // expected-warning {{control reaches end of non-void function}}

void PR9412_f() {
    PR9412_t<PR9412_Exact>(); // expected-note {{in instantiation of function template specialization 'PR9412_t<PR9412_Exact>' requested here}}
}

struct NoReturn {
  ~NoReturn() __attribute__((noreturn));
  operator bool() const;
};
struct Return {
  ~Return();
  operator bool() const;
};

int testTernaryUnconditionalNoreturn() {
  true ? NoReturn() : NoReturn();
}

int testTernaryStaticallyConditionalNoretrunOnTrue() {
  true ? NoReturn() : Return();
}

int testTernaryStaticallyConditionalRetrunOnTrue() {
  true ? Return() : NoReturn();
} // expected-warning {{control reaches end of non-void function}}

int testTernaryStaticallyConditionalNoretrunOnFalse() {
  false ? Return() : NoReturn();
}

int testTernaryStaticallyConditionalRetrunOnFalse() {
  false ? NoReturn() : Return();
} // expected-warning {{control reaches end of non-void function}}

int testTernaryConditionalNoreturnTrueBranch(bool value) {
  value ? (NoReturn() || NoReturn()) : Return();
} // expected-warning {{control may reach end of non-void function}}

int testTernaryConditionalNoreturnFalseBranch(bool value) {
  value ? Return() : (NoReturn() || NoReturn());
} // expected-warning {{control may reach end of non-void function}}

int testConditionallyExecutedComplexTernaryTrueBranch(bool value) {
  value || (true ? NoReturn() : true);
} // expected-warning {{control may reach end of non-void function}}

int testConditionallyExecutedComplexTernaryFalseBranch(bool value) {
  value || (false ? true : NoReturn());
} // expected-warning {{control may reach end of non-void function}}

int testStaticallyExecutedLogicalOrBranch() {
  false || NoReturn();
}

int testStaticallyExecutedLogicalAndBranch() {
  true && NoReturn();
}

int testStaticallySkippedLogicalOrBranch() {
  true || NoReturn();
} // expected-warning {{control reaches end of non-void function}}

int testStaticallySkppedLogicalAndBranch() {
  false && NoReturn();
} // expected-warning {{control reaches end of non-void function}}

int testConditionallyExecutedComplexLogicalBranch(bool value) {
  value || (true && NoReturn());
} // expected-warning {{control may reach end of non-void function}}

int testConditionallyExecutedComplexLogicalBranch2(bool value) {
  (true && value) || (true && NoReturn());
} // expected-warning {{control may reach end of non-void function}}

int testConditionallyExecutedComplexLogicalBranch3(bool value) {
  (false && (Return() || true)) || (true && NoReturn());
}

int testConditionallyExecutedComplexLogicalBranch4(bool value) {
  false || ((Return() || true) && (true && NoReturn()));
}

#if __cplusplus >= 201103L
namespace LambdaVsTemporaryDtor {
  struct Y { ~Y(); };
  struct X { template<typename T> X(T, Y = Y()) {} };

  struct Fatal { ~Fatal() __attribute__((noreturn)); };
  struct FatalCopy { FatalCopy(); FatalCopy(const FatalCopy&, Fatal F = Fatal()); };

  void foo();

  int bar() {
    X work([](){ Fatal(); });
    foo();
  } // expected-warning {{control reaches end of non-void function}}

  int baz() {
    FatalCopy fc;
    X work([fc](){});
    foo();
  } // ok, initialization of lambda does not return
}
#endif

// Ensure that function-try-blocks also check for return values properly.
int functionTryBlock1(int s) try {
  return 0;
} catch (...) {
} // expected-warning {{control may reach end of non-void function}}

int functionTryBlock2(int s) try {
} catch (...) {
  return 0;
} // expected-warning {{control may reach end of non-void function}}

int functionTryBlock3(int s) try {
  return 0;
} catch (...) {
  return 0;
} // ok, both paths return.