glsl: Process redeclarations before initializers
authorIan Romanick <ian.d.romanick@intel.com>
Sat, 5 Mar 2011 00:15:20 +0000 (16:15 -0800)
committerIan Romanick <ian.d.romanick@intel.com>
Sat, 5 Mar 2011 00:33:31 +0000 (16:33 -0800)
If an array redeclaration includes an initializer, the initializer
would previously be dropped on the floor.  Instead, directly apply the
initializer to the correct ir_variable instance and append the
generated instructions.

Fixes bugzilla #34374 and piglit tests glsl-{vs,fs}-array-redeclaration.

NOTE: This is a candidate for stable release branches.  0292ffb8 and
8e6cb9fe are also necessary.

src/glsl/ast_to_hir.cpp

index 0074ed2..651fae8 100644 (file)
@@ -2693,8 +2693,11 @@ ast_declarator_list::hir(exec_list *instructions,
        * instruction stream.
        */
       exec_list initializer_instructions;
+      ir_variable *earlier = get_variable_being_redeclared(var, decl, state);
+
       if (decl->initializer != NULL) {
-        result = process_initializer(var, decl, this->type,
+        result = process_initializer((earlier == NULL) ? var : earlier,
+                                     decl, this->type,
                                      &initializer_instructions, state);
       }
 
@@ -2710,52 +2713,50 @@ ast_declarator_list::hir(exec_list *instructions,
                          decl->identifier);
       }
 
-      ir_variable *earlier = get_variable_being_redeclared(var, decl, state);
-      if (earlier != NULL) {
-        continue;
-      }
-
-      /* By now, we know it's a new variable declaration (we didn't hit the
-       * above "continue").
-       *
-       * From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
-       *
-       *   "Identifiers starting with "gl_" are reserved for use by
-       *   OpenGL, and may not be declared in a shader as either a
-       *   variable or a function."
+      /* If the declaration is not a redeclaration, there are a few additional
+       * semantic checks that must be applied.  In addition, variable that was
+       * created for the declaration should be added to the IR stream.
        */
-      if (strncmp(decl->identifier, "gl_", 3) == 0)
-        _mesa_glsl_error(& loc, state,
-                         "identifier `%s' uses reserved `gl_' prefix",
-                         decl->identifier);
+      if (earlier == NULL) {
+        /* From page 15 (page 21 of the PDF) of the GLSL 1.10 spec,
+         *
+         *   "Identifiers starting with "gl_" are reserved for use by
+         *   OpenGL, and may not be declared in a shader as either a
+         *   variable or a function."
+         */
+        if (strncmp(decl->identifier, "gl_", 3) == 0)
+           _mesa_glsl_error(& loc, state,
+                            "identifier `%s' uses reserved `gl_' prefix",
+                            decl->identifier);
 
-      /* Add the variable to the symbol table.  Note that the initializer's
-       * IR was already processed earlier (though it hasn't been emitted yet),
-       * without the variable in scope.
-       *
-       * This differs from most C-like languages, but it follows the GLSL
-       * specification.  From page 28 (page 34 of the PDF) of the GLSL 1.50
-       * spec:
-       *
-       *     "Within a declaration, the scope of a name starts immediately
-       *     after the initializer if present or immediately after the name
-       *     being declared if not."
-       */
-      if (!state->symbols->add_variable(var)) {
-        YYLTYPE loc = this->get_location();
-        _mesa_glsl_error(&loc, state, "name `%s' already taken in the "
-                         "current scope", decl->identifier);
-        continue;
+        /* Add the variable to the symbol table.  Note that the initializer's
+         * IR was already processed earlier (though it hasn't been emitted
+         * yet), without the variable in scope.
+         *
+         * This differs from most C-like languages, but it follows the GLSL
+         * specification.  From page 28 (page 34 of the PDF) of the GLSL 1.50
+         * spec:
+         *
+         *     "Within a declaration, the scope of a name starts immediately
+         *     after the initializer if present or immediately after the name
+         *     being declared if not."
+         */
+        if (!state->symbols->add_variable(var)) {
+           YYLTYPE loc = this->get_location();
+           _mesa_glsl_error(&loc, state, "name `%s' already taken in the "
+                            "current scope", decl->identifier);
+           continue;
+        }
+
+        /* Push the variable declaration to the top.  It means that all the
+         * variable declarations will appear in a funny last-to-first order,
+         * but otherwise we run into trouble if a function is prototyped, a
+         * global var is decled, then the function is defined with usage of
+         * the global var.  See glslparsertest's CorrectModule.frag.
+         */
+        instructions->push_head(var);
       }
 
-      /* Push the variable declaration to the top.  It means that all
-       * the variable declarations will appear in a funny
-       * last-to-first order, but otherwise we run into trouble if a
-       * function is prototyped, a global var is decled, then the
-       * function is defined with usage of the global var.  See
-       * glslparsertest's CorrectModule.frag.
-       */
-      instructions->push_head(var);
       instructions->append_list(&initializer_instructions);
    }