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;
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) {
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;
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);
}
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;
}
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)
.fatal_errors = false,
.implicit_function_declaration = true,
.implicit_int = true,
+ .main = true,
.missing_declarations = true,
.missing_prototypes = true,
.redundant_decls = true,
#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 */