Additional error checking for 'return' statements.
authorBrian <brian@yutani.localnet.net>
Mon, 26 Mar 2007 21:46:35 +0000 (15:46 -0600)
committerBrian <brian@yutani.localnet.net>
Mon, 26 Mar 2007 21:46:35 +0000 (15:46 -0600)
src/mesa/shader/slang/slang_codegen.c
src/mesa/shader/slang/slang_emit.c
src/mesa/shader/slang/slang_typeinfo.h

index f9dae9f..9859628 100644 (file)
@@ -716,7 +716,7 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
    case SLANG_OPER_RETURN:
       /* do return replacement here too */
       assert(oper->num_children == 0 || oper->num_children == 1);
-      if (!_slang_is_noop(oper)) {
+      if (oper->num_children == 1 && !_slang_is_noop(&oper->children[0])) {
          /* replace:
           *   return expr;
           * with:
@@ -725,6 +725,14 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
           * then do substitutions on the assignment.
           */
          slang_operation *blockOper, *assignOper, *returnOper;
+
+         /* check if function actually has a return type */
+         assert(A->CurFunction);
+         if (A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
+            slang_info_log_error(A->log, "illegal return expression");
+            return;
+         }
+
          blockOper = slang_operation_new(1);
          blockOper->type = SLANG_OPER_BLOCK_NO_NEW_SCOPE;
          blockOper->num_children = 2;
@@ -755,6 +763,14 @@ slang_substitute(slang_assemble_ctx *A, slang_operation *oper,
          slang_operation_copy(oper, blockOper);
          slang_operation_destruct(blockOper);
       }
+      else {
+         /* check if return value was expected */
+         assert(A->CurFunction);
+         if (A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
+            slang_info_log_error(A->log, "return statement requires an expression");
+            return;
+         }
+      }
       break;
 
    case SLANG_OPER_ASSIGN:
@@ -806,6 +822,11 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
    slang_variable **substOld;
    slang_operation **substNew;
    GLuint substCount, numCopyIn, i;
+   slang_function *prevFunction;
+
+   /* save / push */
+   prevFunction = A->CurFunction;
+   A->CurFunction = fun;
 
    /*assert(oper->type == SLANG_OPER_CALL); (or (matrix) multiply, etc) */
    assert(fun->param_count == totalArgs);
@@ -1027,6 +1048,10 @@ slang_inline_function_call(slang_assemble_ctx * A, slang_function *fun,
          fun->parameters->num_variables, numArgs);
    slang_print_tree(top, 0);
 #endif
+
+   /* pop */
+   A->CurFunction = prevFunction;
+
    return top;
 }
 
@@ -1703,9 +1728,24 @@ _slang_gen_logical_or(slang_assemble_ctx *A, slang_operation *oper)
 static slang_ir_node *
 _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
 {
-   if (oper->num_children == 0 ||
-       (oper->num_children == 1 &&
-        oper->children[0].type == SLANG_OPER_VOID)) {
+   const GLboolean haveReturnValue
+      = (oper->num_children == 1 &&
+         oper->children[0].type != SLANG_OPER_VOID);
+
+   /* error checking */
+   assert(A->CurFunction);
+   if (haveReturnValue &&
+       A->CurFunction->header.type.specifier.type == SLANG_SPEC_VOID) {
+      slang_info_log_error(A->log, "illegal return expression");
+      return NULL;
+   }
+   else if (!haveReturnValue &&
+       A->CurFunction->header.type.specifier.type != SLANG_SPEC_VOID) {
+      slang_info_log_error(A->log, "return statement requires an expression");
+      return NULL;
+   }
+
+   if (!haveReturnValue) {
       /* Convert from:
        *   return;
        * To:
@@ -1718,7 +1758,6 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
       gotoOp.label = A->curFuncEndLabel;
       assert(gotoOp.label);
 
-      /* assemble the new code */
       n = _slang_gen_operation(A, &gotoOp);
       /* destroy temp code */
       slang_operation_destruct(&gotoOp);
@@ -1743,7 +1782,10 @@ _slang_gen_return(slang_assemble_ctx * A, slang_operation *oper)
       {
          slang_variable *v
             = _slang_locate_variable(oper->locals, a_retVal, GL_TRUE);
-         assert(v);
+         if (!v) {
+            /* trying to return a value in a void-valued function */
+            return NULL;
+         }
       }
 #endif
 
@@ -1843,6 +1885,9 @@ _slang_gen_declaration(slang_assemble_ctx *A, slang_operation *oper)
       _slang_simplify(v->initializer, &A->space, A->atoms); 
       rhs = _slang_gen_operation(A, v->initializer);
 #endif
+      if (!rhs)
+         return NULL;
+
       assert(rhs);
       init = new_node2(IR_MOVE, var, rhs);
       /*
@@ -2786,6 +2831,8 @@ _slang_codegen_function(slang_assemble_ctx * A, slang_function * fun)
    assert(A->program->Parameters );
    assert(A->program->Varying);
    assert(A->vartable);
+   A->CurLoop = NULL;
+   A->CurFunction = fun;
 
    /* fold constant expressions, etc. */
    _slang_simplify(fun->body, &A->space, A->atoms);
index 77470ac..6507cde 100644 (file)
@@ -793,11 +793,12 @@ emit_move(slang_emit_info *emitInfo, slang_ir_node *n)
    assert(n->Children[1]);
    inst = emit(emitInfo, n->Children[1]);
 
+   if (!n->Children[1]->Store) {
+      slang_info_log_error(emitInfo->log, "invalid assignment");
+      return NULL;
+   }
    assert(n->Children[1]->Store->Index >= 0);
 
-#if 0
-   assert(!n->Store);
-#endif
    n->Store = n->Children[0]->Store;
 
 #if PEEPHOLE_OPTIMIZATIONS
index be2e229..c815c99 100644 (file)
@@ -64,6 +64,7 @@ typedef struct slang_assemble_ctx_
    slang_info_log *log;
    struct slang_label_ *curFuncEndLabel;
    struct slang_ir_node_ *CurLoop;
+   struct slang_function_ *CurFunction;
 } slang_assemble_ctx;