Index: gcc/doc/invoke.texi =================================================================== --- gcc/doc/invoke.texi (revision 138311) +++ gcc/doc/invoke.texi (working copy) @@ -2940,14 +2940,15 @@ even without this option. This warning is also enabled by @option{-Wextra}. @item -Wmain @opindex Wmain @opindex Wno-main -Warn if the type of @samp{main} is suspicious. @samp{main} should be a -function with external linkage, returning int, taking either zero -arguments, two, or three arguments of appropriate types. -This warning is enabled by @option{-Wall}. +Warn if the type of @samp{main} is suspicious. @samp{main} should be +a function with external linkage, returning int, taking either zero +arguments, two, or three arguments of appropriate types. This warning +is enabled by default in C++ and is enabled by either @option{-Wall} +or @option{-pedantic}. @item -Wmissing-braces @opindex Wmissing-braces @opindex Wno-missing-braces Warn if an aggregate or union initializer is not fully bracketed. In Index: gcc/testsuite/gcc.dg/pr30551-2.c =================================================================== --- gcc/testsuite/gcc.dg/pr30551-2.c (revision 0) +++ gcc/testsuite/gcc.dg/pr30551-2.c (revision 0) @@ -0,0 +1,8 @@ +/* PR 30551 -Wmain is not enabled by default. */ +/* { dg-do compile } */ +/* { dg-options "" } */ + +void main(char a) {} /* { dg-bogus "first argument of .main. should be .int." } */ +/* { dg-bogus ".main. takes only zero or two arguments" "" { target *-*-* } 5 } */ +/* { dg-bogus "return type of .main. is not .int." "" { target *-*-* } 5 } */ + Index: gcc/testsuite/gcc.dg/pr30551-4.c =================================================================== --- gcc/testsuite/gcc.dg/pr30551-4.c (revision 0) +++ gcc/testsuite/gcc.dg/pr30551-4.c (revision 0) @@ -0,0 +1,8 @@ +/* PR 30551 -Wmain is enabled by -pedantic-errors and can be disabled. */ +/* { dg-do compile } */ +/* { dg-options "-pedantic-errors -Wno-main" } */ + +void main(char a) {} /* { dg-bogus "first argument of .main. should be .int." } */ +/* { dg-bogus ".main. takes only zero or two arguments" "" { target *-*-* } 5 } */ +/* { dg-bogus "return type of .main. is not .int." "" { target *-*-* } 5 } */ + Index: gcc/testsuite/gcc.dg/pr30551-6.c =================================================================== --- gcc/testsuite/gcc.dg/pr30551-6.c (revision 0) +++ gcc/testsuite/gcc.dg/pr30551-6.c (revision 0) @@ -0,0 +1,7 @@ +/* PR 30551 -Wmain is enabled by -pedantic. */ +/* { dg-do compile } */ +/* { dg-options "-pedantic" } */ + +void main(char a) {} /* { dg-warning "first argument of .main. should be .int." } */ +/* { dg-warning ".main. takes only zero or two arguments" "" { target *-*-* } 5 } */ +/* { dg-warning "return type of .main. is not .int." "" { target *-*-* } 5 } */ Index: gcc/testsuite/gcc.dg/tree-ssa/reassoc-3.c =================================================================== --- gcc/testsuite/gcc.dg/tree-ssa/reassoc-3.c (revision 138311) +++ gcc/testsuite/gcc.dg/tree-ssa/reassoc-3.c (working copy) @@ -1,5 +1,6 @@ +/* { dg-options "" } */ int main(int a, int b, int c, int d) { int e = (a & ~b) & (~c & d); int f = (~c & a) & (b & ~d); return (e & f); Index: gcc/testsuite/gcc.dg/pr30551-3.c =================================================================== --- gcc/testsuite/gcc.dg/pr30551-3.c (revision 0) +++ gcc/testsuite/gcc.dg/pr30551-3.c (revision 0) @@ -0,0 +1,7 @@ +/* PR 30551 -Wmain is enabled by -pedantic-errors. */ +/* { dg-do compile } */ +/* { dg-options "-pedantic-errors" } */ + +void main(char a) {} /* { dg-error "first argument of .main. should be .int." } */ +/* { dg-error ".main. takes only zero or two arguments" "" { target *-*-* } 5 } */ +/* { dg-error "return type of .main. is not .int." "" { target *-*-* } 5 } */ Index: gcc/testsuite/gcc.dg/pr30551-5.c =================================================================== --- gcc/testsuite/gcc.dg/pr30551-5.c (revision 0) +++ gcc/testsuite/gcc.dg/pr30551-5.c (revision 0) @@ -0,0 +1,7 @@ +/* PR 30551 -Wmain is enabled by -pedantic and can be disabled. */ +/* { dg-do compile } */ +/* { dg-options "-pedantic -Wno-main" } */ + +void main(char a) {} /* { dg-bogus "first argument of .main. should be .int." } */ +/* { dg-bogus ".main. takes only zero or two arguments" "" { target *-*-* } 5 } */ +/* { dg-bogus "return type of .main. is not .int." "" { target *-*-* } 5 } */ Index: gcc/testsuite/gcc.dg/pr30551.c =================================================================== --- gcc/testsuite/gcc.dg/pr30551.c (revision 0) +++ gcc/testsuite/gcc.dg/pr30551.c (revision 0) @@ -0,0 +1,7 @@ +/* PR 30551 -Wmain is enabled by -Wall. */ +/* { dg-do compile } */ +/* { dg-options "-Wall" } */ + +void main(char a) {} /* { dg-warning "first argument of .main. should be .int." } */ +/* { dg-warning ".main. takes only zero or two arguments" "" { target *-*-* } 5 } */ +/* { dg-warning "return type of .main. is not .int." "" { target *-*-* } 5 } */ Index: gcc/testsuite/g++.dg/warn/pr30551-2.C =================================================================== --- gcc/testsuite/g++.dg/warn/pr30551-2.C (revision 0) +++ gcc/testsuite/g++.dg/warn/pr30551-2.C (revision 0) @@ -0,0 +1,6 @@ +// PR 30551 -Wmain is enabled by -pedantic/-pedantic-errors. +// { dg-do compile } +// { dg-options "-pedantic-errors" } + +int main(char a) {} /* { dg-error "error: first argument of .*main.* should be .int." } */ +/* { dg-error "error: .*main.* takes only zero or two arguments" "" { target *-*-* } 5 } */ Index: gcc/testsuite/g++.dg/warn/pr30551.C =================================================================== --- gcc/testsuite/g++.dg/warn/pr30551.C (revision 0) +++ gcc/testsuite/g++.dg/warn/pr30551.C (revision 0) @@ -0,0 +1,6 @@ +// PR 30551 -Wmain is enabled by default. +// { dg-do compile } +// { dg-options "" } + +int main(char a) {} /* { dg-warning "warning: first argument of .*main.* should be .int." } */ +/* { dg-warning "warning: .*main.* takes only zero or two arguments" "" { target *-*-* } 5 } */ Index: gcc/cp/decl.c =================================================================== --- gcc/cp/decl.c (revision 138311) +++ gcc/cp/decl.c (working copy) @@ -6690,11 +6690,12 @@ grokfndecl (tree ctype, tree newtype; error ("%<::main%> must return %"); newtype = build_function_type (integer_type_node, oldtypeargs); TREE_TYPE (decl) = newtype; } - check_main_parameter_types (decl); + if (warn_main) + check_main_parameter_types (decl); } if (ctype != NULL_TREE && (! TYPE_FOR_JAVA (ctype) || check_java_method (decl)) && check) Index: gcc/c-decl.c =================================================================== --- gcc/c-decl.c (revision 138311) +++ gcc/c-decl.c (working copy) @@ -3153,12 +3153,11 @@ start_decl (struct c_declarator *declara NORMAL, initialized, NULL, &attributes, deprecated_state); if (!decl) return 0; - if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL - && MAIN_NAME_P (DECL_NAME (decl))) + if (TREE_CODE (decl) != FUNCTION_DECL && MAIN_NAME_P (DECL_NAME (decl))) warning (OPT_Wmain, "%q+D is usually a function", decl); if (initialized) /* Is it valid for this decl to have an initializer at all? If not, set INITIALIZED to zero, which will indirectly @@ -6205,17 +6204,17 @@ start_function (struct c_declspecs *decl /* If #pragma weak was used, mark the decl weak now. */ if (current_scope == file_scope) maybe_apply_pragma_weak (decl1); /* Warn for unlikely, improbable, or stupid declarations of `main'. */ - if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1))) + if (warn_main && MAIN_NAME_P (DECL_NAME (decl1))) { if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1))) != integer_type_node) pedwarn (OPT_Wmain, "return type of %q+D is not %", decl1); - check_main_parameter_types(decl1); + check_main_parameter_types (decl1); if (!TREE_PUBLIC (decl1)) pedwarn (OPT_Wmain, "%q+D is normally a non-static function", decl1); } @@ -6670,34 +6669,22 @@ finish_function (void) /* Must mark the RESULT_DECL as being in this function. */ if (DECL_RESULT (fndecl) && DECL_RESULT (fndecl) != error_mark_node) DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl; - if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted) - { - if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) - != integer_type_node) - { - /* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned. - If warn_main is -1 (-Wno-main) we don't want to be warned. */ - if (!warn_main) - pedwarn (0, "return type of %q+D is not %", fndecl); - } - else - { - if (flag_isoc99) - { - tree stmt = c_finish_return (integer_zero_node); - /* Hack. We don't want the middle-end to warn that this return - is unreachable, so we mark its location as special. Using - UNKNOWN_LOCATION has the problem that it gets clobbered in - annotate_one_with_locus. A cleaner solution might be to - ensure ! should_carry_locus_p (stmt), but that needs a flag. - */ - SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION); - } - } + if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted + && TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl))) + == integer_type_node && flag_isoc99) + { + tree stmt = c_finish_return (integer_zero_node); + /* Hack. We don't want the middle-end to warn that this return + is unreachable, so we mark its location as special. Using + UNKNOWN_LOCATION has the problem that it gets clobbered in + annotate_one_with_locus. A cleaner solution might be to + ensure ! should_carry_locus_p (stmt), but that needs a flag. + */ + SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION); } /* Tie off the statement tree for this function. */ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl)); Index: gcc/c.opt =================================================================== --- gcc/c.opt (revision 138311) +++ gcc/c.opt (working copy) @@ -279,11 +279,11 @@ Warn about PCH files that are found but Wlong-long C ObjC C++ ObjC++ Var(warn_long_long) Init(1) Warning Do not warn about using \"long long\" when -pedantic Wmain -C ObjC C++ ObjC++ Warning +C ObjC C++ ObjC++ Var(warn_main) Init(-1) Warning Warn about suspicious declarations of \"main\" Wmissing-braces C ObjC C++ ObjC++ Var(warn_missing_braces) Warning Warn about possibly missing braces around initializers Index: gcc/c-opts.c =================================================================== --- gcc/c-opts.c (revision 138311) +++ gcc/c-opts.c (working copy) @@ -402,13 +402,16 @@ c_common_handle_option (size_t scode, co warning about not using it without also specifying -O. */ if (warn_uninitialized != 1) warn_uninitialized = (value ? 2 : 0); if (!c_dialect_cxx ()) - /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding - can turn it off only if it's not explicit. */ - warn_main = value * 2; + { + /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding + can turn it off only if it's not explicit. */ + if (warn_main == -1) + warn_main = (value ? 2 : 0); + } else { /* C++-specific warnings. */ warn_sign_compare = value; warn_reorder = value; @@ -465,17 +468,10 @@ c_common_handle_option (size_t scode, co case OPT_Winvalid_pch: cpp_opts->warn_invalid_pch = value; break; - case OPT_Wmain: - if (value) - warn_main = 1; - else - warn_main = -1; - break; - case OPT_Wmissing_include_dirs: cpp_opts->warn_missing_include_dirs = value; break; case OPT_Wmultichar: @@ -613,13 +609,10 @@ c_common_handle_option (size_t scode, co value = !value; /* Fall through.... */ case OPT_fhosted: flag_hosted = value; flag_no_builtin = !value; - /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */ - if (!value && warn_main == 2) - warn_main = 0; break; case OPT_fshort_double: flag_short_double = value; break; @@ -905,10 +898,12 @@ c_common_handle_option (size_t scode, co cpp_opts->warn_endif_labels = 1; if (warn_pointer_sign == -1) warn_pointer_sign = 1; if (warn_overlength_strings == -1) warn_overlength_strings = 1; + if (warn_main == -1) + warn_main = 2; break; case OPT_print_objc_runtime_info: print_struct_values = 1; break; @@ -1069,10 +1064,19 @@ c_common_post_options (const char **pfil It is never enabled in C++, as the minimum limit is not normative in that standard. */ if (warn_overlength_strings == -1 || c_dialect_cxx ()) warn_overlength_strings = 0; + /* Wmain is enabled by default in C++ but not in C. */ + /* Wmain is disabled by default for -ffreestanding (!flag_hosted), + even if -Wall was given (warn_main will be 2 if set by -Wall, 1 + if set by -Wmain). */ + if (warn_main == -1) + warn_main = (c_dialect_cxx () && flag_hosted) ? 1 : 0; + else if (warn_main == 2) + warn_main = flag_hosted ? 1 : 0; + /* In C, -Wconversion enables -Wsign-conversion (unless disabled through -Wno-sign-conversion). While in C++, -Wsign-conversion needs to be requested explicitly. */ if (warn_sign_conversion == -1) warn_sign_conversion = (c_dialect_cxx ()) ? 0 : warn_conversion; Index: gcc/c-common.c =================================================================== --- gcc/c-common.c (revision 138311) +++ gcc/c-common.c (working copy) @@ -340,14 +340,10 @@ int flag_isoc99; /* Nonzero means that we have builtin functions, and main is an int. */ int flag_hosted = 1; -/* Warn if main is suspicious. */ - -int warn_main; - /* ObjC language option variables. */ /* Open and close the file for outputting class declarations, if @@ -1361,38 +1357,39 @@ check_main_parameter_types (tree decl) ++argct; switch (argct) { case 1: if (TYPE_MAIN_VARIANT (type) != integer_type_node) - pedwarn (0, "first argument of %q+D should be %", decl); + pedwarn (OPT_Wmain, "first argument of %q+D should be %", + decl); break; case 2: if (TREE_CODE (type) != POINTER_TYPE || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) != char_type_node)) - pedwarn (0, "second argument of %q+D should be %", - decl); + pedwarn (OPT_Wmain, "second argument of %q+D should be %", + decl); break; case 3: if (TREE_CODE (type) != POINTER_TYPE || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))) != char_type_node)) - pedwarn (0, "third argument of %q+D should probably be " - "%", decl); + pedwarn (OPT_Wmain, "third argument of %q+D should probably be " + "%", decl); break; } } /* It is intentional that this message does not mention the third argument because it's only mentioned in an appendix of the standard. */ if (argct > 0 && (argct < 2 || argct > 3)) - pedwarn (0, "%q+D takes only zero or two arguments", decl); + pedwarn (OPT_Wmain, "%q+D takes only zero or two arguments", decl); } /* True if pointers to distinct types T1 and T2 can be converted to each other without an explicit cast. Only returns true for opaque vector types. */ Index: gcc/c-common.h =================================================================== --- gcc/c-common.h (revision 138311) +++ gcc/c-common.h (working copy) @@ -496,15 +496,10 @@ extern int flag_isoc99; /* Nonzero means that we have builtin functions, and main is an int. */ extern int flag_hosted; -/* Warn if main is suspicious. */ - -extern int warn_main; - - /* ObjC language option variables. */ /* Open and close the file for outputting class declarations, if requested (ObjC). */