and case statements. Use this to make the logic in the CFG builder more
robust at finding the actual statements within a compound statement,
even when there are many layers of labels obscuring it.
Also extend the test cases for a large chunk of PR10063. Still more work
to do here though.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@139437
91177308-0d34-0410-b5e6-
96231b3b80d8
/// statement, such as ExprWithCleanups or ImplicitCastExpr nodes.
Stmt *IgnoreImplicit();
+ const Stmt *stripLabelLikeStatements() const;
+ Stmt *stripLabelLikeStatements() {
+ return const_cast<Stmt*>(
+ const_cast<const Stmt*>(this)->stripLabelLikeStatements());
+ }
+
// Implement isa<T> support.
static bool classof(const Stmt *) { return true; }
return s;
}
+/// \brief Strip off all label-like statements.
+///
+/// This will strip off label statements, case statements, and default
+/// statements recursively.
+const Stmt *Stmt::stripLabelLikeStatements() const {
+ const Stmt *S = this;
+ while (true) {
+ if (const LabelStmt *LS = dyn_cast<LabelStmt>(S))
+ S = LS->getSubStmt();
+ else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S))
+ S = SC->getSubStmt();
+ else
+ return S;
+ }
+}
+
namespace {
struct good {};
struct bad {};
if (CompoundStmt *CS = dyn_cast<CompoundStmt>(S)) {
for (CompoundStmt::body_iterator BI = CS->body_begin(), BE = CS->body_end()
; BI != BE; ++BI) {
- Stmt *SI = *BI;
- if (LabelStmt *LS = dyn_cast<LabelStmt>(SI))
- SI = LS->getSubStmt();
+ Stmt *SI = (*BI)->stripLabelLikeStatements();
if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
Scope = addLocalScopeForDeclStmt(DS, Scope);
}
// For any other statement scope will be implicit and as such will be
// interesting only for DeclStmt.
- if (LabelStmt *LS = dyn_cast<LabelStmt>(S))
- S = LS->getSubStmt();
- if (DeclStmt *DS = dyn_cast<DeclStmt>(S))
+ if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
addLocalScopeForDeclStmt(DS);
}
~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
};
-int pr6884_f(int x) {
- switch (x) { default: pr6884_abort(); }
-}
-
-int pr6884_g(int x) {
- switch (x) { default: pr6884_abort_struct(); }
-}
-
-int pr6884_g_positive(int x) {
- switch (x) { default: ; }
-} // expected-warning {{control reaches end of non-void function}}
+// 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(); }
+ }
-int pr6884_h(int x) {
- switch (x) {
- default: {
- pr6884_abort_struct a;
- }
+ int h(int x) {
+ switch (x) { default: { pr6884_abort_struct a; } }
}
}