group valid "Valid scoping and name redeclaration cases"

    case local_variable_hides_global_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int a = -1;

            void main()
            {
                ${SETUP}
                int a = in0;

                out0 = a;
                ${OUTPUT}
            }
        ""
    end

    case block_variable_hides_local_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}
            void main()
            {
                ${SETUP}
                int a = in0;
                {
                    int a = -1;
                }
                out0 = a;
                ${OUTPUT}
            }
        ""
    end

    case block_variable_hides_global_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int a = -1;

            void main()
            {
                ${SETUP}
                {
                    int a = in0;

                    out0 = a;
                }
                ${OUTPUT}
            }
        ""
    end

    case for_init_statement_variable_hides_local_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}
            void main()
            {
                ${SETUP}
                int a = in0;
                for (int a = 0; a < 10; a++)
                {
                }
                out0 = a;
                ${OUTPUT}
            }
        ""
    end

    case while_condition_variable_hides_local_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}
            void main()
            {
                ${SETUP}
                int a = in0;
                int i = 0;
                while (bool a = (i < 1))
                {
                    i++;
                }
                out0 = a;
                ${OUTPUT}
            }
        ""
    end

    case for_init_statement_variable_hides_global_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int a = 5;

            void main()
            {
                ${SETUP}
                for (int a = 0; a < 10; a++)
                {
                }
                out0 = in0 + a - 5;
                ${OUTPUT}
            }
        ""
    end

    case while_condition_variable_hides_global_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int a = 5;

            void main()
            {
                ${SETUP}
                int i = 0;
                while (bool a = (i < 1))
                {
                    i++;
                }
                out0 = in0 + a - 5;
                ${OUTPUT}
            }
        ""
    end

    case variable_in_if_hides_global_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int a = 1;

            void main()
            {
                ${SETUP}
                if (true)
                    int a = 42;
                out0 = a*in0;
                ${OUTPUT}
            }
        ""
    end

    case variable_from_outer_scope_visible_in_initializer
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}
            void main()
            {
                ${SETUP}
                int a = in0;
                {
                    int a = a+5, b = a-5;
                    out0 = b;
                    a = 42;
                }
                out0 = out0 + a - in0;
                ${OUTPUT}
            }
        ""
    end

    case local_int_variable_hides_struct_type
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            struct S { int val; };

            void main()
            {
                ${SETUP}
                int S = S(in0).val;
                out0 = S;
                ${OUTPUT}
            }
        ""
    end

    case local_struct_variable_hides_struct_type
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            struct S { int val; };

            void main()
            {
                ${SETUP}
                S S = S(in0);
                out0 = S.val;
                ${OUTPUT}
            }
        ""
    end

    case local_variable_hides_function
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int foo (int x) { return x; }

            void main()
            {
                ${SETUP}
                int foo = in0;
                out0 = foo;
                ${OUTPUT}
            }
        ""
    end

    case function_parameter_hides_global_variable
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int a = -1;

            int func (int a) { return a; }

            void main()
            {
                ${SETUP}
                out0 = func(in0);
                ${OUTPUT}
            }
        ""
    end

    case function_parameter_hides_struct_type
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            struct S { int x; };

            int func (int S) { return S; }

            void main()
            {
                ${SETUP}
                out0 = func(in0);
                ${OUTPUT}
            }
        ""
    end

    case function_parameter_hides_function
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int func (int func) { return func; }

            void main()
            {
                ${SETUP}
                out0 = func(in0);
                ${OUTPUT}
            }
        ""
    end

    case local_variable_in_inner_scope_hides_function_parameter
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}
            int func (int inp, int x) { { int x = 5; return inp + x - 5; } }

            void main()
            {
                ${SETUP}
                out0 = func(in0, 42);
                ${OUTPUT}
            }
        ""
    end

    case redeclare_function
        version 300 es
        values
        {
            input int in0 = [ 1 | 2 | 3 ];
            output int out0 = [ 1 | 2 | 3 ];
        }

        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int func (int x);
            int func (int);
            int func (int inp) { return inp; }

            void main()
            {
                ${SETUP}
                out0 = func(in0);
                ${OUTPUT}
            }
        ""
    end

end

group invalid "Invalid scoping behavior"

    case redeclare_global_variable
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            int a;
            float a;

            void main()
            {
                a = 1.0;
                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case redeclare_local_variable
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                int a;
                float a;
                a = 1.0;
                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case redeclare_for_init_statement_variable
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                for (int i = 0; i < 10; i++)
                {
                    int i = 11;
                }
                ${POSITION_FRAG_COLOR} = vec4(0.0);
            }
        ""
    end

    case redeclare_for_condition_variable
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                for (int i = 0; int a = (i < 10); i++)
                {
                    int a = 0;
                }
                ${POSITION_FRAG_COLOR} = vec4(0.0);
            }
        ""
    end

    case redeclare_for_init_statement_variable_in_for_condition
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                float a;
                for (int i = 0; int i = (i < 10); i++)
                {
                    a = sin(i);
                }
                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case redeclare_while_condition_variable
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                int a = 0;
                while (int i = (a < 5))
                {
                    int i = 11;
                    a += i;
                }
                ${POSITION_FRAG_COLOR} = vec4(0.0);
            }
        ""
    end

    case redefine_function
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            float func(float x);

            float func(float x) { return x + 1.0; }
            float func(float x) { return x + 2.0; }

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(func(1.0));
            }
        ""
    end

    case redeclare_builtin
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            float sin(float x);

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(sin(1.0));
            }
        ""
    end

    case redefine_builtin
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            float sin(float x) { return x + 1.0; }

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(sin(1.0));
            }
        ""
    end

    case conflict_function_struct
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void f(int x);
            struct f { int x; };

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(1);
            }
        ""
    end

    case conflict_function_variable
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void f(int x);
            float f;

            void main()
            {
                f = 1.0;
                ${POSITION_FRAG_COLOR} = vec4(f);
            }
        ""
    end

    case use_global_variable_before_declaration
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void func()
            {
                a = 2.0;
            }

            float a;

            void main()
            {
                func();
                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case use_local_variable_before_declaration
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                float a = 1.0;
                a = b;
                float b = 2.0;

                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case use_struct_type_before_declaration
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            float func (float x) { return S(x).val; }
            struct S { float val; };

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(func(1.0));
            }
        ""
    end

    case use_function_before_declaration
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            float func (float x) { return bar(x); }
            float bar (float x) { return x; }

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(func(1.0));
            }
        ""
    end

    case use_variable_from_block_in_outer_scope
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                {
                    float a = 1.0;
                }
                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case use_variable_from_if_in_outer_scope
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                if (true)
                    float a = 1.0;
                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case use_variable_from_else_in_outer_scope
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                if (false)
                    float a = 1.0;
                else
                    float b = 2.0;
                ${POSITION_FRAG_COLOR} = vec4(b);
            }
        ""
    end

    case use_variable_from_if_in_else
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                float a = 1.0;
                if (true)
                {
                    float b = 2.0;
                }
                else
                {
                    a = b;
                }
                ${POSITION_FRAG_COLOR} = vec4(a);
            }
        ""
    end

    case use_variable_from_for_init_statement_in_outer_scope
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                float x = 0.0;
                for (int i = 0; i < 10; i++)
                {
                    x += sin(i);
                }
                ${POSITION_FRAG_COLOR} = vec4(float(i));
            }
        ""
    end

    case use_variable_from_while_condition_in_outer_scope
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                int a = 1;
                while (bool b = (a == 1))
                {
                    a++;
                }
                ${POSITION_FRAG_COLOR} = vec4(float(b));
            }
        ""
    end

    case use_parameter_names_from_function_declaration
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            float func(float a, float b);

            float func(float x, float y) { return a+b; }

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(func(1.0, 2.0));
            }
        ""
    end

    case variable_not_visible_in_own_initializer
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}

            void main()
            {
                float x = x;
                ${POSITION_FRAG_COLOR} = vec4(x);
            }
        ""
    end

    case local_variable_hides_function_parameter
        version 300 es
        expect compile_fail
        both ""
            #version 300 es
            precision mediump float;
            ${DECLARATIONS}
            float func (float inp, float x) { int x = 5.0; return inp + x - 5.0; }

            void main()
            {
                ${POSITION_FRAG_COLOR} = vec4(func(1.0, 2.0));
            }
        ""
    end

end # invalid
