Implement -Wmain.
authorChristoph Mallon <christoph.mallon@gmx.de>
Fri, 14 Dec 2007 19:21:54 +0000 (19:21 +0000)
committerChristoph Mallon <christoph.mallon@gmx.de>
Fri, 14 Dec 2007 19:21:54 +0000 (19:21 +0000)
[r18756]

parser.c
types.c
types.h
warning.c
warning.h

index 845f491..d1182b1 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -2249,6 +2249,33 @@ static declaration_t *append_declaration(declaration_t* const declaration)
        return declaration;
 }
 
+static void check_type_of_main(const declaration_t *const decl, const function_type_t *const func_type)
+{
+       if (skip_typeref(func_type->return_type) != type_int) {
+               warningf(decl->source_position, "return type of 'main' should be 'int', but is '%T'", func_type->return_type);
+       }
+       const function_parameter_t *parm = func_type->parameters;
+       if (parm != NULL) {
+               type_t *const first_type = parm->type;
+               if (!types_compatible(skip_typeref(first_type), type_int)) {
+                       warningf(decl->source_position, "first argument of 'main' should be 'int', but is '%T'", first_type);
+               }
+               parm = parm->next;
+               if (parm != NULL) {
+                       type_t *const second_type = parm->type;
+                       if (!types_compatible(skip_typeref(second_type), type_char_ptr_ptr)) {
+                               warningf(decl->source_position, "second argument of 'main' should be 'char**', but is '%T'", second_type);
+                       }
+                       parm = parm->next;
+                       if (parm != NULL) {
+                               warningf(decl->source_position, "'main' takes only zero or two arguments");
+                       }
+               } else {
+                       warningf(decl->source_position, "'main' takes only zero or two arguments");
+               }
+       }
+}
+
 static bool is_sym_main(const symbol_t *const sym)
 {
        return strcmp(sym->string, "main") == 0;
@@ -2271,6 +2298,10 @@ static declaration_t *internal_record_declaration(
                         orig_type, declaration->symbol);
        }
 
+       if (is_function_definition && warning.main && is_sym_main(symbol)) {
+               check_type_of_main(declaration, &type->function);
+       }
+
        declaration_t *const previous_declaration = get_declaration(symbol, namespc);
        assert(declaration != previous_declaration);
        if (previous_declaration != NULL) {
diff --git a/types.c b/types.c
index 7aed56e..ad35a19 100644 (file)
--- a/types.c
+++ b/types.c
@@ -26,6 +26,8 @@ type_t *type_short_ptr;
 type_t *type_signed_char_ptr;
 type_t *type_void_ptr;
 
+type_t *type_char_ptr_ptr;
+
 type_t *type_intmax_t;
 type_t *type_ptrdiff_t;
 type_t *type_size_t;
@@ -67,4 +69,6 @@ void init_basic_types(void)
        type_int_ptr            = make_pointer_type(type_int,               TYPE_QUALIFIER_NONE);
        type_long_ptr           = make_pointer_type(type_long,              TYPE_QUALIFIER_NONE);
        type_long_long_ptr      = make_pointer_type(type_long_long,         TYPE_QUALIFIER_NONE);
+
+       type_char_ptr_ptr       = make_pointer_type(type_string,            TYPE_QUALIFIER_NONE);
 }
diff --git a/types.h b/types.h
index 690e683..32fc5bc 100644 (file)
--- a/types.h
+++ b/types.h
@@ -27,6 +27,8 @@ extern type_t *type_short_ptr;
 extern type_t *type_signed_char_ptr;
 extern type_t *type_void_ptr;
 
+extern type_t *type_char_ptr_ptr;
+
 extern type_t *type_intmax_t;
 extern type_t *type_ptrdiff_t;
 extern type_t *type_size_t;
index f2429d6..ba1a021 100644 (file)
--- a/warning.c
+++ b/warning.c
@@ -28,6 +28,7 @@ void set_warning_opt(const char *const opt)
        }
        OPT("implicit-function-declaration", implicit_function_declaration)
        OPT("implicit-int",                  implicit_int)
+       OPT("main",                          main)
        OPT("missing-declarations",          missing_declarations)
        OPT("missing-prototypes",            missing_prototypes)
        OPT("redundant-decls",               redundant_decls)
@@ -59,6 +60,7 @@ warning_t warning = {
        .fatal_errors                  = false,
        .implicit_function_declaration = true,
        .implicit_int                  = true,
+       .main                          = true,
        .missing_declarations          = true,
        .missing_prototypes            = true,
        .redundant_decls               = true,
index f1eafb7..4bacbb5 100644 (file)
--- a/warning.h
+++ b/warning.h
@@ -33,7 +33,9 @@ typedef struct warning_t {
 #if 0 // TODO
        bool inline:1;                        /* Warn if a function can not be inlined and it was declared as inline */
        bool long_long:1;                     /* Warn if 'long long' type is used */
+#endif
        bool main:1;                          /* Warn if the type of 'main' is suspicious */
+#if 0 // TODO
        bool missing_braces:1;                /* Warn if an aggregate or union initializer is not fully bracketed */
 #endif
        bool missing_declarations:1;          /* Warn if a global function is defined without a previous declaration */