]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.cpp
fix bug 197, 198, and 199 properly
[xonotic/gmqcc.git] / parser.cpp
index cc2b3589b4ab85b9ec1c08c59655947e43e8773b..57fc7e2257e99921d60196d140be0ce659ab66d1 100644 (file)
@@ -18,7 +18,6 @@ static void parser_addglobal(parser_t *parser, const char *name, ast_expression
 static void parser_addglobal(parser_t *parser, const std::string &name, ast_expression *e);
 static bool parse_typedef(parser_t *parser);
 static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofields, int qualifier, ast_value *cached_typedef, bool noref, bool is_static, uint32_t qflags, char *vstring);
-static ast_block* parse_block(parser_t *parser);
 static bool parse_block_into(parser_t *parser, ast_block *block);
 static bool parse_statement_or_block(parser_t *parser, ast_expression **out);
 static bool parse_statement(parser_t *parser, ast_block *block, ast_expression **out, bool allow_cases);
@@ -2763,6 +2762,7 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *
         { "noreturn",   AST_FLAG_NORETURN   },
         { "inline",     AST_FLAG_INLINE     },
         { "eraseable",  AST_FLAG_ERASEABLE  },
+        { "noerase",    AST_FLAG_NOERASE    },
         { "accumulate", AST_FLAG_ACCUMULATE },
         { "last",       AST_FLAG_FINAL_DECL }
     };
@@ -2796,7 +2796,6 @@ static bool parse_qualifiers(parser_t *parser, bool with_local, int *cvq, bool *
             if (i != GMQCC_ARRAY_COUNT(attributes))
                 goto leave;
 
-
             if (!strcmp(parser_tokval(parser), "noref")) {
                 had_noref = true;
                 if (!parser_next(parser) || parser->tok != TOKEN_ATTRIBUTE_CLOSE) {
@@ -3550,12 +3549,7 @@ static bool parse_statement(parser_t *parser, ast_block *block, ast_expression *
     }
     else if (parser->tok == '{')
     {
-        ast_block *inner;
-        inner = parse_block(parser);
-        if (!inner)
-            return false;
-        *out = inner;
-        return true;
+        return parse_statement_or_block(parser, out);
     }
     else if (parser->tok == ':')
     {
@@ -3792,26 +3786,37 @@ cleanup:
     return retval && !!block;
 }
 
-static ast_block* parse_block(parser_t *parser)
-{
-    ast_block *block;
-    block = new ast_block(parser_ctx(parser));
-    if (!block)
-        return nullptr;
-    if (!parse_block_into(parser, block)) {
-        delete block;
-        return nullptr;
-    }
-    return block;
-}
-
 static bool parse_statement_or_block(parser_t *parser, ast_expression **out)
 {
+    bool result = true;
+    std::unique_ptr<ast_block> block(new ast_block(parser_ctx(parser)));
     if (parser->tok == '{') {
-        *out = parse_block(parser);
-        return !!*out;
+        if (!parse_block_into(parser, block.get())) {
+            return false;
+        }
+    } else {
+        parser_enterblock(parser);
+
+        ast_expression* expression = nullptr;
+        if (!parse_statement(parser, block.get(), &expression, false)) {
+            result = false;
+        }
+
+        if (expression && !block->addExpr(expression)) {
+            result = false;
+        }
+
+        if (!parser_leaveblock(parser)) {
+            return false;
+        }
+    }
+
+    if (result) {
+        *out = block.release();
+        return true;
     }
-    return parse_statement(parser, nullptr, out, false);
+
+    return false;
 }
 
 static bool create_vector_members(ast_value *var, ast_member **me)
@@ -4178,8 +4183,18 @@ static bool parse_function_body(parser_t *parser, ast_value *var)
 
 enderrfn:
     (void)!parser_leaveblock(parser);
-    parser->functions.pop_back();
+
     delete func;
+
+    // Remove |func| from |parser->functions|. It may not actually be at the
+    // back of the vector for accumulated functions.
+    for (auto it = parser->functions.begin(); it != parser->functions.end(); it++) {
+        if (*it == func) {
+            parser->functions.erase(it, it + 1);
+            break;
+        }
+    }
+
     var->m_constval.vfunc = nullptr;
 
 enderr:
@@ -4977,7 +4992,7 @@ static bool parse_typedef(parser_t *parser)
     }
 
     if ( (old = parser_find_var(parser, typevar->m_name)) ) {
-        parseerror(parser, "cannot define a type with the same name as a variable: %s\n"
+        parseerror(parser, "cannot define a type with the same name as a variable:\n"
                    " -> `%s` has been declared here: %s:%i",
                    typevar->m_name, old->m_context.file, old->m_context.line);
         delete typevar;
@@ -5197,8 +5212,7 @@ static bool parse_variable(parser_t *parser, ast_block *localblock, bool nofield
          * store the vstring back to var for alias and
          * deprecation messages.
          */
-        if (var->m_flags & AST_FLAG_DEPRECATED ||
-            var->m_flags & AST_FLAG_ALIAS)
+        if (var->m_flags & AST_FLAG_DEPRECATED || var->m_flags & AST_FLAG_ALIAS)
             var->m_desc = vstring;
 
         if (parser_find_global(parser, var->m_name) && var->m_flags & AST_FLAG_ALIAS) {