From: Nikolay Sivov nsivov@codeweavers.com
Signed-off-by: Nikolay Sivov nsivov@codeweavers.com --- libs/vkd3d-shader/hlsl.y | 36 ++++++++++++++++++++++++ libs/vkd3d-shader/vkd3d_shader_private.h | 1 + 2 files changed, 37 insertions(+)
diff --git a/libs/vkd3d-shader/hlsl.y b/libs/vkd3d-shader/hlsl.y index 3d194a0c..5530f848 100644 --- a/libs/vkd3d-shader/hlsl.y +++ b/libs/vkd3d-shader/hlsl.y @@ -4648,6 +4648,26 @@ static struct hlsl_scope *get_loop_scope(struct hlsl_scope *scope) return scope->upper ? get_loop_scope(scope->upper) : NULL; }
+static void check_duplicated_switch_cases(struct hlsl_ctx *ctx, const struct hlsl_ir_switch_case *check, struct list *cases) +{ + const struct list *next = &check->entry; + struct hlsl_ir_switch_case *c; + + if (check->is_default) + return; + + while ((next = list_next(cases, next))) + { + c = LIST_ENTRY(next, struct hlsl_ir_switch_case, entry); + if (c->is_default) continue; + if (c->value == check->value) + { + hlsl_error(ctx, &c->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE, "Found duplicate 'case' statement."); + hlsl_note(ctx, &check->loc, VKD3D_SHADER_LOG_ERROR, "The same 'case' statement was previously found here."); + } + } +} + }
%locations @@ -6357,6 +6377,7 @@ switch_statement: attribute_list_optional switch_scope_start KW_SWITCH '(' expr ')' '{' switch_cases '}' { struct hlsl_ir_node *selector = node_from_block($5); + struct hlsl_ir_switch_case *c, *def = NULL; struct hlsl_ir_node *s;
if (!(selector = add_implicit_conversion(ctx, $5, selector, hlsl_get_scalar_type(ctx, HLSL_TYPE_UINT), &@5))) @@ -6366,6 +6387,21 @@ switch_statement: YYABORT; }
+ /* Check for duplicated cases and multiple default statements. */ + LIST_FOR_EACH_ENTRY(c, $8, struct hlsl_ir_switch_case, entry) + { + if (def && c->is_default) + { + hlsl_error(ctx, &c->loc, VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE, "Found multiple 'default' statements."); + hlsl_note(ctx, &def->loc, VKD3D_SHADER_LOG_ERROR, "The 'default' statement was previously found here."); + } + + if (!def && c->is_default) + def = c; + + check_duplicated_switch_cases(ctx, c, $8); + } + s = hlsl_new_switch(ctx, selector, $8, &@3);
destroy_switch_cases($8); diff --git a/libs/vkd3d-shader/vkd3d_shader_private.h b/libs/vkd3d-shader/vkd3d_shader_private.h index c9d2dec8..93154c0f 100644 --- a/libs/vkd3d-shader/vkd3d_shader_private.h +++ b/libs/vkd3d-shader/vkd3d_shader_private.h @@ -142,6 +142,7 @@ enum vkd3d_shader_error VKD3D_SHADER_ERROR_HLSL_RECURSIVE_CALL = 5025, VKD3D_SHADER_ERROR_HLSL_INCONSISTENT_SAMPLER = 5026, VKD3D_SHADER_ERROR_HLSL_NON_FINITE_RESULT = 5027, + VKD3D_SHADER_ERROR_HLSL_DUPLICATE_SWITCH_CASE = 5028,
VKD3D_SHADER_WARNING_HLSL_IMPLICIT_TRUNCATION = 5300, VKD3D_SHADER_WARNING_HLSL_DIVISION_BY_ZERO = 5301,