From daa3b6bfa32e3be1c434b20ba91f6a519304c81c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sat, 5 Dec 2015 21:04:57 -0700 Subject: [PATCH] add unused label error --- README.md | 2 -- src/analyze.cpp | 18 ++++++++++++++++++ src/semantic_info.hpp | 1 + test/run_tests.cpp | 5 +++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4bb149bbc5..c63a8232a0 100644 --- a/README.md +++ b/README.md @@ -42,8 +42,6 @@ make ## Roadmap - * parseh: unreachable <--> noreturn attribute - * unused label error * loops * structs * tagged enums diff --git a/src/analyze.cpp b/src/analyze.cpp index 82d37de109..e53cda3b13 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -471,6 +471,7 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, assert(!node->codegen_node); node->codegen_node = allocate(1); node->codegen_node->data.label_entry = table_entry->value; + table_entry->value->used = true; } else { add_node_error(g, node, buf_sprintf("use of undeclared label '%s'", buf_ptr(&node->data.go_to.name))); @@ -758,6 +759,23 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, node->codegen_node = allocate(1); node->codegen_node->data.fn_def_node.implicit_return_type = block_return_type; node->codegen_node->data.fn_def_node.block_context = context; + + { + FnTableEntry *fn_table_entry = fn_proto_node->codegen_node->data.fn_proto_node.fn_table_entry; + auto it = fn_table_entry->label_table.entry_iterator(); + for (;;) { + auto *entry = it.next(); + if (!entry) + break; + + LabelTableEntry *label_entry = entry->value; + if (!label_entry->used) { + add_node_error(g, label_entry->label_node, + buf_sprintf("label '%s' defined but not used", + buf_ptr(&label_entry->label_node->data.label.name))); + } + } + } } break; diff --git a/src/semantic_info.hpp b/src/semantic_info.hpp index 6f4b7da8b3..3e3e87084a 100644 --- a/src/semantic_info.hpp +++ b/src/semantic_info.hpp @@ -41,6 +41,7 @@ struct ImportTableEntry { struct LabelTableEntry { AstNode *label_node; LLVMBasicBlockRef basic_block; + bool used; }; struct FnTableEntry { diff --git a/test/run_tests.cpp b/test/run_tests.cpp index b37a4d17f4..8c33cc1b8f 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -466,6 +466,11 @@ fn f(a : unreachable) {} export fn f(a : void) {} )SOURCE", 1, ".tmp_source.zig:2:17: error: parameter of type 'void' not allowed on exported functions"); + add_compile_fail_case("unused label", R"SOURCE( +export fn f() { +a_label: +} + )SOURCE", 1, ".tmp_source.zig:3:1: error: label 'a_label' defined but not used"); } static void print_compiler_invocation(TestCase *test_case, Buf *zig_stderr) {