glsl: add support for `precise` in type_qualifier
[mesa.git] / src / glsl / ast_to_hir.cpp
index 7516c33e1dfd70867f799d3ba04081dbb3355a97..0b28b4814c42a7ac73f9f7cb3af918e13edbc6d4 100644 (file)
@@ -799,11 +799,10 @@ do_assignment(exec_list *instructions, struct _mesa_glsl_parse_state *state,
                           "assignment to %s",
                           non_lvalue_description);
          error_emitted = true;
-      } else if (lhs->variable_referenced() != NULL
-                 && lhs->variable_referenced()->data.read_only) {
+      } else if (lhs_var != NULL && lhs_var->data.read_only) {
          _mesa_glsl_error(&lhs_loc, state,
                           "assignment to read-only variable '%s'",
-                          lhs->variable_referenced()->name);
+                          lhs_var->name);
          error_emitted = true;
       } else if (lhs->type->is_array() &&
                  !state->check_version(120, 300, &lhs_loc,
@@ -2394,6 +2393,17 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
       }
    }
 
+   if (qual->flags.q.precise) {
+      if (var->data.used) {
+         _mesa_glsl_error(loc, state,
+                          "variable `%s' may not be redeclared "
+                          "`precise' after being used",
+                          var->name);
+      } else {
+         var->data.precise = 1;
+      }
+   }
+
    if (qual->flags.q.constant || qual->flags.q.attribute
        || qual->flags.q.uniform
        || (qual->flags.q.varying && (state->stage == MESA_SHADER_FRAGMENT)))
@@ -3079,7 +3089,7 @@ validate_identifier(const char *identifier, YYLTYPE loc,
     *   OpenGL, and may not be declared in a shader as either a
     *   variable or a function."
     */
-   if (strncmp(identifier, "gl_", 3) == 0) {
+   if (is_gl_identifier(identifier)) {
       _mesa_glsl_error(&loc, state,
                        "identifier `%s' uses reserved `gl_' prefix",
                        identifier);
@@ -3166,6 +3176,7 @@ ast_declarator_list::hir(exec_list *instructions,
 
    assert(this->type != NULL);
    assert(!this->invariant);
+   assert(!this->precise);
 
    /* The type specifier may contain a structure definition.  Process that
     * before any of the variable declarations.
@@ -3652,11 +3663,15 @@ ast_declarator_list::hir(exec_list *instructions,
        * instruction stream.
        */
       exec_list initializer_instructions;
+
+      /* Examine var name here since var may get deleted in the next call */
+      bool var_is_gl_id = is_gl_identifier(var->name);
+
       ir_variable *earlier =
          get_variable_being_redeclared(var, decl->get_location(), state,
                                        false /* allow_all_redeclarations */);
       if (earlier != NULL) {
-         if (strncmp(var->name, "gl_", 3) == 0 &&
+         if (var_is_gl_id &&
              earlier->data.how_declared == ir_var_declared_in_block) {
             _mesa_glsl_error(&loc, state,
                              "`%s' has already been redeclared using "
@@ -5400,7 +5415,7 @@ ast_interface_block::hir(exec_list *instructions,
             ir_variable *earlier =
                get_variable_being_redeclared(var, loc, state,
                                              true /* allow_all_redeclarations */);
-            if (strncmp(var->name, "gl_", 3) != 0 || earlier == NULL) {
+            if (!is_gl_identifier(var->name) || earlier == NULL) {
                _mesa_glsl_error(&loc, state,
                                 "redeclaration of gl_PerVertex can only "
                                 "include built-in variables");
@@ -5635,7 +5650,7 @@ detect_conflicting_assignments(struct _mesa_glsl_parse_state *state,
          gl_FragColor_assigned = true;
       else if (strcmp(var->name, "gl_FragData") == 0)
          gl_FragData_assigned = true;
-      else if (strncmp(var->name, "gl_", 3) != 0) {
+      else if (!is_gl_identifier(var->name)) {
          if (state->stage == MESA_SHADER_FRAGMENT &&
              var->data.mode == ir_var_shader_out) {
             user_defined_fs_output_assigned = true;