Skip to content

Commit

Permalink
Parser: improve return detection for switch statments
Browse files Browse the repository at this point in the history
  • Loading branch information
danielsan901998 committed Feb 1, 2024
1 parent 557fcc0 commit 7d79206
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 9 deletions.
29 changes: 20 additions & 9 deletions src/aro/Parser.zig
Original file line number Diff line number Diff line change
Expand Up @@ -4588,38 +4588,49 @@ fn compoundStmt(p: *Parser, is_fn_body: bool, stmt_expr_state: ?*StmtExprState)
return try p.addNode(node);
}

const NoreturnKind = enum { no, yes, complex };
const NoreturnKind = enum { no, yes };

fn nodeIsNoreturn(p: *Parser, node: NodeIndex) NoreturnKind {
switch (p.nodes.items(.tag)[@intFromEnum(node)]) {
.break_stmt, .continue_stmt, .return_stmt => return .yes,
.break_stmt,
.continue_stmt,
=> return .no,
.return_stmt => return .yes,
.if_then_else_stmt => {
const data = p.data.items[p.nodes.items(.data)[@intFromEnum(node)].if3.body..];
const then_type = p.nodeIsNoreturn(data[0]);
const else_type = p.nodeIsNoreturn(data[1]);
if (then_type == .complex or else_type == .complex) return .complex;
if (then_type == .yes and else_type == .yes) return .yes;
return .no;
},
.compound_stmt_two => {
const data = p.nodes.items(.data)[@intFromEnum(node)];
if (data.bin.rhs != .none) return p.nodeIsNoreturn(data.bin.rhs);
if (data.bin.lhs != .none) return p.nodeIsNoreturn(data.bin.lhs);
const lhs_type = if (data.bin.lhs != .none) p.nodeIsNoreturn(data.bin.lhs) else .no;
const rhs_type = if (data.bin.rhs != .none) p.nodeIsNoreturn(data.bin.rhs) else .no;
if (lhs_type == .yes or rhs_type == .yes) return .yes;
return .no;
},
.compound_stmt => {
const data = p.nodes.items(.data)[@intFromEnum(node)];
return p.nodeIsNoreturn(p.data.items[data.range.end - 1]);
var it = data.range.start;
while (it != data.range.end) : (it += 1) {
if (p.nodeIsNoreturn(p.data.items[it]) == .yes) return .yes;
}
return .no;
},
.labeled_stmt => {
const data = p.nodes.items(.data)[@intFromEnum(node)];
return p.nodeIsNoreturn(data.decl.node);
},
.default_stmt => {
const data = p.nodes.items(.data)[@intFromEnum(node)];
if (data.un == .none) return .no;
return p.nodeIsNoreturn(data.un);
},
.switch_stmt => {
const data = p.nodes.items(.data)[@intFromEnum(node)];
if (data.bin.rhs == .none) return .complex;
if (p.nodeIsNoreturn(data.bin.rhs) == .yes) return .yes;
return .complex;
if (data.bin.rhs == .none) return .no;
return p.nodeIsNoreturn(data.bin.rhs);
},
else => return .no,
}
Expand Down
71 changes: 71 additions & 0 deletions test/cases/unreachable code.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
int test1(int a){
switch(a){
return 1;
};
return 1;
}
int test2(int a){
switch(a){
return 1;
a=1;
a=1;
};
return 1;
}
int test3(int a){
switch(a){
default:
return 1;
};
return 1;
}
int test4(int a){
switch(a) {
case 1: a=1; break;
}
return 1;
}
int test5(int a){
switch(a) {
default: return 1; break;
}
return 1;
}
int test6(int a){
switch(a) {
default: a=1; break;
}
if (a) return 0;
return 1;
}
int test7(int a){
{
return 0;
}
}
int test8(int a){
{
return 0;
a=1;
}
}
int test9(int a){
{
return 0;
a=1;
a=1;
a=1;
}
}
int test10(int a){
switch (a)case a: return 1;
return 1;
}
#define EXPECTED_ERRORS "unreachable code.c:4:3: warning: unreachable code [-Wunreachable-code]" \
"unreachable code.c:10:3: warning: unreachable code [-Wunreachable-code]" \
"unreachable code.c:12:3: warning: unreachable code [-Wunreachable-code]" \
"unreachable code.c:19:3: warning: unreachable code [-Wunreachable-code]" \
"unreachable code.c:32:2: warning: unreachable code [-Wunreachable-code]" \
"unreachable code.c:49:3: warning: unreachable code [-Wunreachable-code]" \
"unreachable code.c:55:3: warning: unreachable code [-Wunreachable-code]" \
"unreachable code.c:61:16: error: case value must be an integer constant expression"

0 comments on commit 7d79206

Please sign in to comment.