From 9d5d648529676b3d0f51d635109d5fcf6c7bf719 Mon Sep 17 00:00:00 2001 From: Christoph Mallon Date: Fri, 14 Dec 2007 19:21:54 +0000 Subject: [PATCH] Implement -Wmain. [r18756] --- parser.c | 31 +++++++++++++++++++++++++++++++ types.c | 4 ++++ types.h | 2 ++ warning.c | 2 ++ warning.h | 2 ++ 5 files changed, 41 insertions(+) diff --git a/parser.c b/parser.c index 845f491..d1182b1 100644 --- 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 --- 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 --- 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; diff --git a/warning.c b/warning.c index f2429d6..ba1a021 100644 --- 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, diff --git a/warning.h b/warning.h index f1eafb7..4bacbb5 100644 --- 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 */ -- 2.20.1