+/**
+ * Check if the declaration of main is suspicious. main should be a
+ * function with external linkage, returning int, taking either zero
+ * arguments, two, or three arguments of appropriate types, ie.
+ *
+ * int main([ int argc, char **argv [, char **env ] ]).
+ *
+ * @param decl the declaration to check
+ * @param type the function type of the declaration
+ */
+static void check_type_of_main(const declaration_t *const decl, const function_type_t *const func_type)
+{
+ if (decl->storage_class == STORAGE_CLASS_STATIC) {
+ warningf(decl->source_position, "'main' is normally a non-static function");
+ }
+ 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) {
+ type_t *const third_type = parm->type;
+ if (!types_compatible(skip_typeref(third_type), type_char_ptr_ptr)) {
+ warningf(decl->source_position, "third argument of 'main' should be 'char**', but is '%T'", third_type);
+ }
+ parm = parm->next;
+ if (parm != NULL) {
+ warningf(decl->source_position, "'main' takes only zero, two or three arguments");
+ }
+ }
+ } else {
+ warningf(decl->source_position, "'main' takes only zero, two or three arguments");
+ }
+ }
+}
+
+/**
+ * Check if a symbol is the equal to "main".
+ */
+static bool is_sym_main(const symbol_t *const sym)
+{
+ return strcmp(sym->string, "main") == 0;
+}
+