Explorar o código

Fix unreachable code detection in match statements

Shiqing %!s(int64=6) %!d(string=hai) anos
pai
achega
206d515783
Modificáronse 1 ficheiros con 19 adicións e 2 borrados
  1. 19 2
      modules/gdscript/gdscript_parser.cpp

+ 19 - 2
modules/gdscript/gdscript_parser.cpp

@@ -2211,6 +2211,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
 
 	p_block->has_return = true;
 
+	bool catch_all_appeared = false;
+
 	while (true) {
 
 		while (tokenizer->get_token() == GDScriptTokenizer::TK_NEWLINE && _parse_newline())
@@ -2221,7 +2223,7 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
 			return;
 
 		if (indent_level > tab_level.back()->get()) {
-			return; // go back a level
+			break; // go back a level
 		}
 
 		if (pending_newline != -1) {
@@ -2236,12 +2238,20 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
 
 		branch->patterns.push_back(_parse_pattern(p_static));
 		if (!branch->patterns[0]) {
-			return;
+			break;
 		}
 
 		bool has_binding = branch->patterns[0]->pt_type == PatternNode::PT_BIND;
 		bool catch_all = has_binding || branch->patterns[0]->pt_type == PatternNode::PT_WILDCARD;
 
+#ifdef DEBUG_ENABLED
+		// Branches after a wildcard or binding are unreachable
+		if (catch_all_appeared && !current_function->has_unreachable_code) {
+			_add_warning(GDScriptWarning::UNREACHABLE_CODE, -1, current_function->name.operator String());
+			current_function->has_unreachable_code = true;
+		}
+#endif
+
 		while (tokenizer->get_token() == GDScriptTokenizer::TK_COMMA) {
 			tokenizer->advance();
 			branch->patterns.push_back(_parse_pattern(p_static));
@@ -2259,6 +2269,8 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
 			catch_all = catch_all || pt == PatternNode::PT_WILDCARD;
 		}
 
+		catch_all_appeared = catch_all_appeared || catch_all;
+
 		if (!_enter_indent_block()) {
 			_set_error("Expected block in pattern branch");
 			return;
@@ -2274,6 +2286,11 @@ void GDScriptParser::_parse_pattern_block(BlockNode *p_block, Vector<PatternBran
 
 		p_branches.push_back(branch);
 	}
+
+	// Even if all branches return, there is possibility of default fallthrough
+	if (!catch_all_appeared) {
+		p_block->has_return = false;
+	}
 }
 
 void GDScriptParser::_generate_pattern(PatternNode *p_pattern, Node *p_node_to_match, Node *&p_resulting_node, Map<StringName, Node *> &p_bindings) {