diff --git a/src/aro/Parser.zig b/src/aro/Parser.zig index 704c672d..31cfd64c 100644 --- a/src/aro/Parser.zig +++ b/src/aro/Parser.zig @@ -4603,24 +4603,31 @@ fn nodeIsNoreturn(p: *Parser, node: NodeIndex) NoreturnKind { }, .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 == .complex or rhs_type == .complex) return .complex; + 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) { + const kind = p.nodeIsNoreturn(p.data.items[it]); + if (kind != .no) return kind; + } + return .no; }, .labeled_stmt => { const data = p.nodes.items(.data)[@intFromEnum(node)]; return p.nodeIsNoreturn(data.decl.node); }, - .switch_stmt => { + .default_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.un == .none) return .no; + return p.nodeIsNoreturn(data.un); }, + .while_stmt, .do_while_stmt, .for_decl_stmt, .forever_stmt, .for_stmt, .switch_stmt => return .complex, else => return .no, } } diff --git a/test/cases/return.c b/test/cases/return.c index 14070c79..b5015dd2 100644 --- a/test/cases/return.c +++ b/test/cases/return.c @@ -120,7 +120,6 @@ void call_return_signed(void) { "return.c:32:5: error: non-void function 'bar' should return a value [-Wreturn-type]" \ "return.c:35:12: error: void function 'baz' should not return a value [-Wreturn-type]" \ "return.c:38:17: error: function cannot return a function" \ - "return.c:74:5: warning: unreachable code [-Wunreachable-code]" \ "return.c:96:12: error: returning 'double' from a function with incompatible result type 'void *'" \ "warning: returning 'unsigned int *' from a function with incompatible result type 'int *' converts between pointers to integer types with different sign [-Wpointer-sign]" \ diff --git a/test/cases/unreachable code.c b/test/cases/unreachable code.c new file mode 100644 index 00000000..3360ff1e --- /dev/null +++ b/test/cases/unreachable code.c @@ -0,0 +1,38 @@ +int test(int a){ + switch(a) { + default: break; + } + return 1; +} +int test1(int a){ + switch(a) { + break; + a=1; + } + return 1; +} +int test2(int a){ + switch(a) { + return 1; + a=1; + } + return 1; +} +int compound_stmt(int a){ + { + a=1; + return 1; + a=2; + } +} +int if_then_else(int a){ + if(a) + return 1; + else + return 2; + return 3; +} +#define EXPECTED_ERRORS "unreachable code.c:10:3: warning: unreachable code [-Wunreachable-code]" \ + "unreachable code.c:17:3: warning: unreachable code [-Wunreachable-code]" \ + "unreachable code.c:25:3: warning: unreachable code [-Wunreachable-code]" \ + "unreachable code.c:33:2: warning: unreachable code [-Wunreachable-code]"