]> git.xonotic.org Git - xonotic/gmqcc.git/blobdiff - parser.cpp
Add -Wunused-component like -Wunused-variable but warns about unused components of...
[xonotic/gmqcc.git] / parser.cpp
index df1715c53f2709371aeadb62af7810460b97f1d8..518a06da1919a22933031ef15f71652af95f118a 100644 (file)
@@ -2523,8 +2523,7 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou
             parseerror(parser, "expected for-loop condition");
             goto onerr;
         }
-    }
-    else if (!parser_next(parser)) {
+    } else if (!parser_next(parser)) {
         parseerror(parser, "expected for-loop condition");
         goto onerr;
     }
@@ -2535,7 +2534,6 @@ static bool parse_for_go(parser_t *parser, ast_block *block, ast_expression **ou
         if (!cond)
             goto onerr;
     }
-
     /* move on to incrementor */
     if (parser->tok != ';') {
         parseerror(parser, "expected semicolon after for-loop initializer");
@@ -3122,6 +3120,52 @@ static bool parse_switch_go(parser_t *parser, ast_block *block, ast_expression *
                 return false;
             }
             swcase.m_value = parse_expression_leave(parser, false, false, false);
+
+            if (!operand->compareType(*swcase.m_value)) {
+                char ty1[1024];
+                char ty2[1024];
+
+                ast_type_to_string(swcase.m_value, ty1, sizeof ty1);
+                ast_type_to_string(operand, ty2, sizeof ty2);
+
+                auto fnLiteral = [](ast_expression *expression) -> char* {
+                    if (!ast_istype(expression, ast_value))
+                        return nullptr;
+                    ast_value *value = (ast_value *)expression;
+                    if (!value->m_hasvalue)
+                        return nullptr;
+                    char *string = nullptr;
+                    basic_value_t *constval = &value->m_constval;
+                    switch (value->m_vtype)
+                    {
+                    case TYPE_FLOAT:
+                        util_asprintf(&string, "%.2f", constval->vfloat);
+                        return string;
+                    case TYPE_VECTOR:
+                        util_asprintf(&string, "'%.2f %.2f %.2f'",
+                            constval->vvec.x,
+                            constval->vvec.y,
+                            constval->vvec.z);
+                        return string;
+                    case TYPE_STRING:
+                        util_asprintf(&string, "\"%s\"", constval->vstring);
+                        return string;
+                    default:
+                        break;
+                    }
+                    return nullptr;
+                };
+
+                char *literal = fnLiteral(swcase.m_value);
+                if (literal)
+                    compile_error(parser_ctx(parser), "incompatible type `%s` for switch case `%s` expected `%s`", ty1, literal, ty2);
+                else
+                    compile_error(parser_ctx(parser), "incompatible type `%s` for switch case expected `%s`", ty1, ty2);
+                mem_d(literal);
+                delete switchnode;
+                return false;
+            }
+
             if (!swcase.m_value) {
                 delete switchnode;
                 parseerror(parser, "expected expression for case");
@@ -6228,7 +6272,7 @@ bool parser_finish(parser_t *parser, const char *output)
         if (!ast_istype(it, ast_value))
             continue;
         asvalue = (ast_value*)it;
-        if (!asvalue->m_uses && !asvalue->m_hasvalue && asvalue->m_vtype != TYPE_FUNCTION) {
+        if (!asvalue->m_uses && asvalue->m_cvq != CV_CONST && asvalue->m_vtype != TYPE_FUNCTION) {
             retval = retval && !compile_warning(asvalue->m_context, WARN_UNUSED_VARIABLE,
                                                 "unused global: `%s`", asvalue->m_name);
         }
@@ -6326,11 +6370,15 @@ bool parser_finish(parser_t *parser, const char *output)
     }
     parser_remove_ast(parser);
 
-    if (compile_Werrors) {
-        con_out("*** there were warnings treated as errors\n");
-        compile_show_werrors();
-        retval = false;
-    }
+    auto fnCheckWErrors = [&retval]() {
+        if (compile_Werrors) {
+            con_out("*** there were warnings treated as errors\n");
+            compile_show_werrors();
+            retval = false;
+        }
+    };
+
+    fnCheckWErrors();
 
     if (retval) {
         if (OPTS_OPTION_BOOL(OPTION_DUMPFIN))
@@ -6341,6 +6389,9 @@ bool parser_finish(parser_t *parser, const char *output)
             delete ir;
             return false;
         }
+
+        // ir->generate can generate compiler warnings
+        fnCheckWErrors();
     }
     delete ir;
     return retval;