From e5855df9ffd46bebc1be2e5f974dd4f822ac1ee3 Mon Sep 17 00:00:00 2001 From: danielsan901998 Date: Thu, 8 Feb 2024 19:23:09 +0100 Subject: [PATCH] Parser: improve handling in nodeIsNoreturn to avoid false positives --- src/aro/Parser.zig | 21 ++++++++++++------- test/cases/return.c | 1 - test/cases/unreachable code.c | 38 +++++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+), 8 deletions(-) create mode 100644 test/cases/unreachable code.c 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]"