]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.c
gcc lost it's magic analyzer and now complains about uninitialized stuff... <sadface>
[xonotic/gmqcc.git] / parser.c
index d86521230766627a9af734f485d6b7a9225218a5..96daaa4c08a09cdd083d2f9db99f8dbaea938291 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -415,6 +415,9 @@ static ast_value *parse_type(parser_t *parser, int basetype, bool *isfunc)
             goto on_error;
     }
 
+    if (params.p_count > 8)
+        parseerror(parser, "more than 8 parameters are currently not supported");
+
     var = ast_value_new(ctx, "<unnamed>", vtype);
     if (!var)
         goto on_error;
@@ -448,6 +451,7 @@ MEM_VEC_FUNCTIONS(shunt, sy_elem, ops)
 static sy_elem syexp(lex_ctx ctx, ast_expression *v) {
     sy_elem e;
     e.etype = 0;
+    e.off   = 0;
     e.out   = v;
     e.block = NULL;
     e.ctx   = ctx;
@@ -458,6 +462,7 @@ static sy_elem syexp(lex_ctx ctx, ast_expression *v) {
 static sy_elem syblock(lex_ctx ctx, ast_block *v) {
     sy_elem e;
     e.etype = 0;
+    e.off   = 0;
     e.out   = (ast_expression*)v;
     e.block = v;
     e.ctx   = ctx;
@@ -468,6 +473,7 @@ static sy_elem syblock(lex_ctx ctx, ast_block *v) {
 static sy_elem syop(lex_ctx ctx, const oper_info *op) {
     sy_elem e;
     e.etype = 1 + (op - operators);
+    e.off   = 0;
     e.out   = NULL;
     e.block = NULL;
     e.ctx   = ctx;
@@ -864,10 +870,50 @@ static bool parser_sy_pop(parser_t *parser, shunt *sy)
             break;
 
         case opid1('='):
-            if (ast_istype(exprs[0], ast_entfield))
+            if (ast_istype(exprs[0], ast_entfield)) {
+                ast_expression *field = ((ast_entfield*)exprs[0])->field;
                 assignop = type_storep_instr[exprs[0]->expression.vtype];
+                if (!ast_compare_type(field->expression.next, exprs[1])) {
+                    char ty1[1024];
+                    char ty2[1024];
+                    ast_type_to_string(field->expression.next, ty1, sizeof(ty1));
+                    ast_type_to_string(exprs[1], ty2, sizeof(ty2));
+                    if (opts_standard == COMPILER_QCC &&
+                        field->expression.next->expression.vtype == TYPE_FUNCTION &&
+                        exprs[1]->expression.vtype == TYPE_FUNCTION)
+                    {
+                        if (parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
+                                         "invalid types in assignment: cannot assign %s to %s", ty2, ty1))
+                        {
+                            parser->errors++;
+                        }
+                    }
+                    else
+                        parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
+                }
+            }
             else
+            {
                 assignop = type_store_instr[exprs[0]->expression.vtype];
+                if (!ast_compare_type(exprs[0], exprs[1])) {
+                    char ty1[1024];
+                    char ty2[1024];
+                    ast_type_to_string(exprs[0], ty1, sizeof(ty1));
+                    ast_type_to_string(exprs[1], ty2, sizeof(ty2));
+                    if (opts_standard == COMPILER_QCC &&
+                        exprs[0]->expression.vtype == TYPE_FUNCTION &&
+                        exprs[1]->expression.vtype == TYPE_FUNCTION)
+                    {
+                        if (parsewarning(parser, WARN_ASSIGN_FUNCTION_TYPES,
+                                         "invalid types in assignment: cannot assign %s to %s", ty2, ty1))
+                        {
+                            parser->errors++;
+                        }
+                    }
+                    else
+                        parseerror(parser, "invalid types in assignment: cannot assign %s to %s", ty2, ty1);
+                }
+            }
             out = (ast_expression*)ast_store_new(ctx, assignop, exprs[0], exprs[1]);
             break;
         case opid2('+','='):
@@ -967,6 +1013,8 @@ static bool parser_close_call(parser_t *parser, shunt *sy)
             MEM_VECTOR_MOVE(params, exprs, call, params);
             ast_delete(params);
         }
+        if (!ast_call_check_types(call))
+            parser->errors++;
     } else {
         parseerror(parser, "invalid function call");
         return false;
@@ -1815,7 +1863,7 @@ static bool parse_block_into(parser_t *parser, ast_block *block, bool warnreturn
             break;
 
         if (!parse_statement(parser, block, &expr)) {
-            parseerror(parser, "parse error");
+            /* parseerror(parser, "parse error"); */
             block = NULL;
             goto cleanup;
         }
@@ -1921,8 +1969,8 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
     ast_expression *framenum  = NULL;
     ast_expression *nextthink = NULL;
     /* None of the following have to be deleted */
-    ast_expression *fld_think, *fld_nextthink, *fld_frame;
-    ast_expression *gbl_time, *gbl_self;
+    ast_expression *fld_think = NULL, *fld_nextthink = NULL, *fld_frame = NULL;
+    ast_expression *gbl_time = NULL, *gbl_self = NULL;
     bool            has_frame_think;
 
     bool retval = true;
@@ -2197,12 +2245,12 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
     parser->function = func;
     if (!parse_block_into(parser, block, true)) {
         ast_block_delete(block);
-        goto enderrfn;
+        goto enderrfn2;
     }
 
     if (!ast_function_blocks_add(func, block)) {
         ast_block_delete(block);
-        goto enderrfn;
+        goto enderrfn2;
     }
 
     parser->function = old;
@@ -2215,6 +2263,8 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
         parseerror(parser, "missing semicolon after function body (mandatory with -std=qcc)");
     return retval;
 
+enderrfn2:
+    parser->functions_count--;
 enderrfn:
     ast_function_delete(func);
     var->constval.vfunc = NULL;
@@ -2846,7 +2896,7 @@ bool parser_compile(const char *filename)
                 if (parser->tok == TOKEN_EOF)
                     parseerror(parser, "unexpected eof");
                 else if (!parser->errors)
-                    parseerror(parser, "parse error");
+                    parseerror(parser, "there have been errors, bailing out");
                 lex_close(parser->lex);
                 parser->lex = NULL;
                 return false;