From: Eric Anholt Date: Mon, 30 Jan 2012 16:50:14 +0000 (-0800) Subject: glsl: Throw an error when faced with a duplicated switch() case label. X-Git-Tag: android-x86-4.4-r1~7165 X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=140632190cf41e6a035ca199b181091d4ed46986;p=android-x86%2Fexternal-mesa.git glsl: Throw an error when faced with a duplicated switch() case label. The error message I chose matches gcc's error. Fixes piglit switch-case-duplicated.vert. NOTE: This is a candidate for the 8.0 branch. Reviewed-by: Ian Romanick --- diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 28aff397757..4f328ad8f46 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -54,6 +54,7 @@ #include "glsl_parser_extras.h" #include "ast.h" #include "glsl_types.h" +#include "program/hash_table.h" #include "ir.h" void @@ -3534,6 +3535,8 @@ ast_switch_statement::hir(exec_list *instructions, state->switch_state.is_switch_innermost = true; state->switch_state.switch_nesting_ast = this; + state->switch_state.labels_ht = hash_table_ctor(0, hash_table_pointer_hash, + hash_table_pointer_compare); /* Initalize is_fallthru state to false. */ @@ -3572,6 +3575,8 @@ ast_switch_statement::hir(exec_list *instructions, */ body->hir(instructions, state); + hash_table_dtor(state->switch_state.labels_ht); + state->switch_state = saved; /* Switch statements do not have r-values. @@ -3709,6 +3714,24 @@ ast_switch_statement::hir(exec_list *instructions, /* Stuff a dummy value in to allow processing to continue. */ label_const = new(ctx) ir_constant(0); + } else { + ast_expression *previous_label = (ast_expression *) + hash_table_find(state->switch_state.labels_ht, + (void *)(uintptr_t)label_const->value.u[0]); + + if (previous_label) { + YYLTYPE loc = this->test_value->get_location(); + _mesa_glsl_error(& loc, state, + "duplicate case value"); + + loc = previous_label->get_location(); + _mesa_glsl_error(& loc, state, + "this is the previous case label"); + } else { + hash_table_insert(state->switch_state.labels_ht, + this->test_value, + (void *)(uintptr_t)label_const->value.u[0]); + } } ir_dereference_variable *deref_test_var = diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 35d1e3aee26..d5d5101a820 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -48,6 +48,10 @@ struct glsl_switch_state { ir_variable *is_fallthru_var; ir_variable *is_break_var; class ast_switch_statement *switch_nesting_ast; + + /** Table of constant values already used in case labels */ + struct hash_table *labels_ht; + bool is_switch_innermost; // if switch stmt is closest to break, ... };