This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] PR6321
- From: Dirk Mueller <dmuell at gmx dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 29 Oct 2006 01:53:30 +0200
- Subject: [PATCH] PR6321
Hi,
this patch implements checking for incorrect parameters to "main" in the C++
frontend. It already error'ed upon a wrong return type, now it will also
error out if the types of the parameters don't match (the app would most
likely crash then upon use anyway).
The C frontend already had pedwarns implemented for this, so it was easy to
reuse them. Patch bootstrapped, regtested on i686-suse-linux.
This patch unfortunately needs approval (I think) of a C frontend maintainer,
a C++ frontend maintainer and a testsuite maintainer.
Ok for mainline?
2006-10-29 Dirk Mueller <dmueller@suse.de>
PR c++/6321
* c-decl (start_function): Move code for main decl warning ..
* c-common.c (main_args_warning): .. here.
* c-common.h (main_args_warning): Declare.
* decl.c(grokfndecl): Use main_args_warning.
* g++.old-deja/g++.pt/eichin01a.C (main): Fix prototype.
* g++.old-deja/g++.pt/eichin01b.C (main): Same.
* g++.old-deja/g++.pt/eichin01.C (main): Same.
* g++.old-deja/g++.mike/net25.C (main): Same.
* g++.dg/lookup/exception1.C (main): Same.
* g++.dg/parse/parens2.C (main): Same.
--- cp/decl.c
+++ cp/decl.c
@@ -6026,6 +6026,7 @@ grokfndecl (tree ctype,
oldtypeargs);
TREE_TYPE (decl) = newtype;
}
+ main_args_warning (decl);
inlinep = 0;
publicp = 1;
}
--- c-decl.c
+++ c-decl.c
@@ -6133,54 +6133,7 @@ start_function (struct c_declspecs *decl
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1)))
{
- tree args;
- int argct = 0;
-
- if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
- != integer_type_node)
- pedwarn ("return type of %q+D is not %<int%>", decl1);
-
- 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)
- pedwarn ("first argument of %q+D should be %<int%>", decl1);
- 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 ("second argument of %q+D should be %<char **%>",
- decl1);
- 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 ("third argument of %q+D should probably be "
- "%<char **%>", decl1);
- 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 ("%q+D takes only zero or two arguments", decl1);
+ main_args_warning (decl1);
if (!TREE_PUBLIC (decl1))
pedwarn ("%q+D is normally a non-static function", decl1);
--- c-common.c
+++ c-common.c
@@ -1010,7 +1010,6 @@ strict_aliasing_warning (tree otype, tre
}
}
-
/* Print a warning about if (); or if () .. else; constructs
via the special empty statement node that we create. INNER_THEN
and INNER_ELSE are the statement lists of the if and the else
@@ -1039,7 +1038,63 @@ empty_body_warning (tree inner_then, tre
}
}
-
+/* Warn for unlikely, improbable, or stupid DECL declarations
+ of `main'. */
+
+void
+main_args_warning (tree decl)
+{
+ tree args;
+ int argct = 0;
+
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl)))
+ != integer_type_node)
+ pedwarn ("return type of %q+D is not %<int%>", decl);
+
+ for (args = TYPE_ARG_TYPES (TREE_TYPE (decl)); 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)
+ pedwarn ("first argument of %q+D should be %<int%>", 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 ("second argument of %q+D should be %<char **%>",
+ 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 ("third argument of %q+D should probably be "
+ "%<char **%>", 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 ("%q+D takes only zero or two arguments", decl);
+}
+
+
/* Nonzero if constant C has a value that is permissible
for type TYPE (an INTEGER_TYPE). */
--- c-common.h
+++ c-common.h
@@ -658,6 +658,7 @@ extern void strict_aliasing_warning(tree
extern void empty_body_warning (tree, tree);
extern tree convert_and_check (tree, tree);
extern void overflow_warning (tree);
+extern void main_args_warning (tree decl);
extern bool c_determine_visibility (tree);
extern bool same_scalar_type_ignoring_signedness (tree, tree);
--- g++.old-deja/g++.pt/eichin01a.C
+++ g++.old-deja/g++.pt/eichin01a.C
@@ -14,7 +14,7 @@
TC<long> xjj(1,2);
-int main(int,char*) {
+int main(int,char**) {
TC<float> xff(9.9,3.14);
xjj.sz(123);
xff.sz(2.71828);
--- g++.old-deja/g++.pt/eichin01b.C
+++ g++.old-deja/g++.pt/eichin01b.C
@@ -14,7 +14,7 @@
TC<long> xjj(1,2);
-int main(int,char*) {
+int main(int,char**) {
TC<float> xff(9.9,3.14);
xjj.sz(123);
xff.sz(2.71828);
--- g++.old-deja/g++.pt/eichin01.C
+++ g++.old-deja/g++.pt/eichin01.C
@@ -20,7 +20,7 @@
TC<long> xjj(1,2);
-int main(int,char*) {
+int main(int,char**) {
TC<float> xff(9.9,3.14);
xjj.sz(123);
xff.sz(2.71828);
--- g++.old-deja/g++.mike/net25.C
+++ g++.old-deja/g++.mike/net25.C
@@ -10,7 +10,7 @@
void (*foo)();
-int main(int a)
+int main(int a, char** /*argv*/)
{
foo = a ? shake_zero : shake_one;
return 0;
--- g++.dg/lookup/exception1.C
+++ g++.dg/lookup/exception1.C
@@ -28,6 +28,6 @@
{
}
-int main(int argc, char* argv) {
+int main(int argc, char* argv[]) {
ns::Test test;
}
--- g++.dg/parse/parens2.C
+++ g++.dg/parse/parens2.C
@@ -1,6 +1,6 @@
/* PR c++/8842. */
/* { dg-do compile } */
-int main( int argc, char* argv )
+int main( int argc, char* argv[] )
{
int i = 5;
// This always worked: