[Mesa-dev] [PATCH 5/6] glsl: Throw an error when faced with a duplicated switch() case label.

Eric Anholt eric at anholt.net
Mon Jan 30 09:58:06 PST 2012


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.
---
 src/glsl/ast_to_hir.cpp       |   23 +++++++++++++++++++++++
 src/glsl/glsl_parser_extras.h |    4 ++++
 2 files changed, 27 insertions(+), 0 deletions(-)

diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
index 28aff39..4f328ad 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 35d1e3a..d5d5101 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, ...
 };
 
-- 
1.7.7.3



More information about the mesa-dev mailing list