From 7d792064820d932bf84121ace9010109181ec3b9 Mon Sep 17 00:00:00 2001 From: danielsan901998 Date: Thu, 1 Feb 2024 19:36:20 +0100 Subject: [PATCH] Parser: improve return detection for switch statments --- src/aro/Parser.zig | 29 +++++++++----- test/cases/unreachable code.c | 71 +++++++++++++++++++++++++++++++++++ 2 files changed, 91 insertions(+), 9 deletions(-) create mode 100644 test/cases/unreachable code.c diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 6e3b84df..0541801c 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -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, } diff --git a/test/cases/unreachable code.c b/test/cases/unreachable code.c new file mode 100644 index 00000000..f8eeeb50 --- /dev/null +++ b/test/cases/unreachable code.c @@ -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"