Subject: bin/2708: enhancement: Warn for invalid declarations of main.
To: None <gnats-bugs@NetBSD.ORG>
From: Peter Seebach <seebs@taniemarie.solon.com>
List: netbsd-bugs
Date: 08/20/1996 18:46:01
>Number: 2708
>Category: bin
>Synopsis: gcc is not aggressive enough.
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: bin-bug-people (Utility Bug People)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Tue Aug 20 19:50:01 1996
>Last-Modified:
>Originator: Peter Seebach
>Organization:
Peter Seebach - seebs@solon.com - Copyright 1996 Peter Seebach.
C/Unix wizard -- C/Unix questions? Send mail for help. No, really!
Unsolicited email is not welcome, and will be billed for at consulting rates.
The *other* C FAQ - http://www.solon.com/~seebs/c/c-iaq.html
>Release: 1.2_BETA
>Environment:
System: NetBSD taniemarie 1.2_BETA NetBSD 1.2_BETA (SEEBS) #0: Fri Aug 16 17:16:09 CDT 1996 seebs@taniemarie:/usr/src/sys/arch/amiga/compile/SEEBS amiga
>Description:
gcc does not detect or warn for any of the following:
void main(void); /* forbidden */
static int main; /* legal, but stupid */
double main(short); /* forbidden *and* stupid */
>How-To-Repeat:
Make an ass of yourself, and watch the compiler not notice
>Fix:
The following patch seems to help. I submitted it to the gcc
people, and will submit it here also. It detects, and warns for,
* static objects named main.
* non-function globals named main.
* functions named main with unusual behavior.
It allows the deprecated "char **envp" third argument, but warns
for it in -pedantic mode.
This will break the kernel; to fix, add
-Wno-main
when compiling modules expected to contain a main that should not
be warned for.
This patch is relative to /usr/src/gnu/usr.bin/gcc/
*** cc/gcc.1.orig Mon Dec 11 14:14:38 1995
--- cc/gcc.1 Tue Aug 20 18:38:26 1996
***************
*** 187,192 ****
--- 187,193 ----
.RI \-Wid\-clash\- len
\-Wimplicit
\-Winline
+ \-Wmain
\-Wmissing\-prototypes
\-Wmissing\-declarations
\-Wnested\-externs
***************
*** 1700,1705 ****
--- 1701,1714 ----
.TP
.B \-Wimplicit
Warn whenever a function or parameter is implicitly declared.
+ .TP
+ .B \-Wmain
+ Warn if
+ .B main\c
+ has an unusual type, or is not declared as a globally visible function. It
+ is normal for
+ .B main\c
+ to return an integer value, and have either no arguments, or two.
.TP
.B \-Wreturn\-type
Warn whenever a function is defined with a return-type that defaults
*** common/c-decl.c.orig Mon Dec 11 14:15:48 1995
--- common/c-decl.c Tue Aug 20 18:36:41 1996
***************
*** 541,546 ****
--- 541,550 ----
int warn_missing_braces;
+ /* Warn for any suspicious declaration of main. */
+
+ int warn_main;
+
/* Nonzero means `$' can be in an identifier.
See cccp.c for reasons why this breaks some obscure ANSI C programs. */
***************
*** 643,648 ****
--- 647,656 ----
warn_bad_function_cast = 1;
else if (!strcmp (p, "-Wno-bad-function-cast"))
warn_bad_function_cast = 0;
+ else if (!strcmp (p, "-Wmain"))
+ warn_main = 1;
+ else if (!strcmp (p, "-Wno-main"))
+ warn_main = 0;
else if (!strcmp (p, "-Wpointer-arith"))
warn_pointer_arith = 1;
else if (!strcmp (p, "-Wno-pointer-arith"))
***************
*** 723,728 ****
--- 731,737 ----
warn_unused = 1;
warn_switch = 1;
warn_format = 1;
+ warn_main = 1;
warn_char_subscripts = 1;
warn_parentheses = 1;
warn_missing_braces = 1;
***************
*** 3467,3472 ****
--- 3476,3486 ----
/* The corresponding pop_obstacks is in finish_decl. */
push_obstacks_nochange ();
+ if (warn_main
+ && !strcmp (IDENTIFIER_POINTER (declarator), "main"))
+ {
+ warning_with_decl (decl, "`%s' is usually a function");
+ }
if (initialized)
/* Is it valid for this decl to have an initializer at all?
If not, set INITIALIZED to zero, which will indirectly
***************
*** 6115,6120 ****
--- 6129,6198 ----
/* A nested function is not global. */
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
+
+ /* warn for unlikely, improbable, or stupid declarations of `main'. */
+ if (warn_main && strcmp ("main", IDENTIFIER_POINTER (DECL_NAME (decl1))) == 0)
+ {
+ if (TREE_PUBLIC (decl1))
+ {
+ tree args;
+ int argct = 0;
+
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
+ != integer_type_node)
+ warning_with_decl (decl1, "return type of `%s' is not `int'");
+
+ for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
+ args = TREE_CHAIN (args))
+ {
+ tree type = args ? TREE_VALUE (args) : 0;
+ if (type == void_type_node)
+ break;
+ ++argct;
+ switch (argct) {
+ case 1:
+ if (TYPE_MAIN_VARIANT (type) != integer_type_node)
+ warning_with_decl (decl1,
+ "first argument of `%s' should be `int'");
+ 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)
+ {
+ warning_with_decl (decl1,
+ "second argument of `%s' should be `char **'");
+ }
+ 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)
+ {
+ warning_with_decl (decl1,
+ "third argument of `%s' should probably be `char **'");
+ }
+ break;
+ }
+ }
+
+ /* it is intentional that this message does not mention the third
+ * argument, which is warned for only pedantically, because it's
+ * blessed by mention in an appendix of the standard. */
+ if (argct > 0 && (argct < 2 || argct > 3))
+ warning_with_decl (decl1, "`%s' takes only zero or two arguments");
+
+ /* see? I told you we'd get around to warning for it... */
+ if (argct == 3 && pedantic)
+ pedwarn_with_decl (decl1, "third argument of `%s' is deprecated");
+ }
+ else /* `main' isn't TREE_PUBLIC? */
+ {
+ warning_with_decl (decl1, "`%s' is normally a non-static function");
+ }
+ }
/* Record the decl so that the function name is defined.
If we already have a decl for this name, and it is a FUNCTION_DECL,
*** common/c-tree.h.orig Mon Dec 11 14:15:51 1995
--- common/c-tree.h Tue Aug 20 18:36:41 1996
***************
*** 474,479 ****
--- 474,483 ----
extern int warn_missing_braces;
+ /* Warn for any suspicious declaration of main. */
+
+ extern int warn_main;
+
/* Nonzero means this is a function to call to perform comptypes
on two record types. */
*** common/toplev.c.orig Mon Dec 11 14:19:05 1995
--- common/toplev.c Tue Aug 20 18:37:04 1996
***************
*** 609,614 ****
--- 609,616 ----
"-Wall",
"-Wbad-function-cast",
"-Wno-bad-function-cast",
+ "-Wmain",
+ "-Wno-main",
"-Wcast-qual",
"-Wno-cast-qual",
"-Wchar-subscripts",
>Audit-Trail:
>Unformatted: