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;
{
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);
}
{
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)
{
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)