]> git.tdb.fi Git - libs/gl.git/blobdiff - source/glsl/validate.cpp
Check that non-constant data is not accessed from constant expressions
[libs/gl.git] / source / glsl / validate.cpp
index 4a5ffe841801b064c04c7ea68d6d91eb53ea1c59..62f997bb5c29ad6d8a507620c3d78745118fc80f 100644 (file)
@@ -508,9 +508,22 @@ void ReferenceValidator::visit(FunctionDeclaration &func)
 
 
 ExpressionValidator::ExpressionValidator():
-       current_function(0)
+       current_function(0),
+       constant_expression(false)
 { }
 
+void ExpressionValidator::visit(VariableReference &var)
+{
+       if(var.declaration && constant_expression && !var.declaration->constant)
+               error(var, format("Reference to non-constant variable '%s' in a constant expression", var.name));
+}
+
+void ExpressionValidator::visit(InterfaceBlockReference &iface)
+{
+       if(constant_expression)
+               error(iface, format("Reference to interface block '%s' in a constant expression", iface.name));
+}
+
 void ExpressionValidator::visit(Swizzle &swizzle)
 {
        unsigned size = 0;
@@ -555,8 +568,13 @@ void ExpressionValidator::visit(UnaryExpression &unary)
        {
                if(!unary.type)
                        error(unary, format("No matching operator '%s' found for '%s'", unary.oper->token, unary.expression->type->name));
-               else if((unary.oper->token[1]=='+' || unary.oper->token[1]=='-') && !unary.expression->lvalue)
-                       error(unary, format("Operand of '%s' is not an lvalue", unary.oper->token));
+               else if(unary.oper->token[1]=='+' || unary.oper->token[1]=='-')
+               {
+                       if(constant_expression)
+                               error(unary, format("Use of '%s' in a constant expression", unary.oper->token));
+                       else if(!unary.expression->lvalue)
+                               error(unary, format("Operand of '%s' is not an lvalue", unary.oper->token));
+               }
        }
        TraversingVisitor::visit(unary);
 }
@@ -579,7 +597,9 @@ void ExpressionValidator::visit(Assignment &assign)
 {
        if(assign.left->type)
        {
-               if(!assign.left->lvalue)
+               if(constant_expression)
+                       error(assign, "Assignment in constant expression");
+               else if(!assign.left->lvalue)
                        error(assign, "Target of assignment is not an lvalue");
                if(assign.right->type)
                {
@@ -616,7 +636,19 @@ void ExpressionValidator::visit(VariableDeclaration &var)
        if(var.init_expression && var.init_expression->type && var.type_declaration && var.init_expression->type!=var.type_declaration)
                error(var, format("Initializing a variable of type '%s' with an expression of incompatible type '%s'",
                        var.type_declaration->name, var.init_expression->type->name));
-       TraversingVisitor::visit(var);
+
+       if(var.layout)
+               var.layout->visit(*this);
+       if(var.init_expression)
+       {
+               SetFlag set_const(constant_expression, var.constant);
+               TraversingVisitor::visit(var.init_expression);
+       }
+       if(var.array_size)
+       {
+               SetFlag set_const(constant_expression);
+               TraversingVisitor::visit(var.array_size);
+       }
 }
 
 void ExpressionValidator::visit(FunctionDeclaration &func)