PATCH for crash on redefinition of main

Mark Mitchell mmitchell@usa.net
Tue May 19 21:49:00 GMT 1998


Jason --
  
  Here's a patch to avoid crashing on two definitions of main in the
same translation unit.  OK?

-- 
Mark Mitchell <mmitchell@usa.net>
http://home.earthlink.net/~mbmitchell
Consulting Services Available

Tue May 19 15:59:02 1998  Mark Mitchell  <mmitchell@usa.net>

	* cp-tree.h (MAIN_NAME_P): New macro.
	(DECL_MAIN_P): Likwise.
	* decl.c (pushdecl): Avoid crashing on redefinitions of `main'.
	(grokfndecl): Use the new macros.
	(grokdeclarator): Likewise.
	(start_function): Likewise.
	(store_parm_decls): Likewise.
	(finsh_function): Likewise.
	* friend.c (do_friend): Likewise.
	* typeck.c (build_function_call_real): Likewise.
	(build_unary_op): Likewise.

Index: cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.69
diff -c -p -r1.69 cp-tree.h
*** cp-tree.h	1998/05/19 14:51:34	1.69
--- cp-tree.h	1998/05/19 22:38:19
*************** extern int current_function_parms_stored
*** 1918,1923 ****
--- 1921,1941 ----
  #define ANON_PARMNAME_P(ID_NODE) (IDENTIFIER_POINTER (ID_NODE)[0] == '_' \
  				  && IDENTIFIER_POINTER (ID_NODE)[1] <= '9')
  #endif /* !defined(NO_DOLLAR_IN_LABEL) || !defined(NO_DOT_IN_LABEL) */
+ 
+ /* Returns non-zero iff ID_NODE is an IDENTIFIER_NODE whose name is
+    `main'.  */
+ #define MAIN_NAME_P(ID_NODE) \
+    (strcmp (IDENTIFIER_POINTER (ID_NODE), "main") == 0)
+ 
+ /* Returns non-zero iff NODE is a declaration for the global function
+    `main'.  */
+ #define DECL_MAIN_P(NODE)				\
+    (TREE_CODE (NODE) == FUNCTION_DECL			\
+     && (DECL_CONTEXT (NODE) == global_namespace 	\
+ 	|| DECL_CONTEXT (NODE) == NULL_TREE)		\
+     && DECL_NAME (NODE) != NULL_TREE			\
+     && MAIN_NAME_P (DECL_NAME (NODE)))
+ 
  
  /* Define the sets of attributes that member functions and baseclasses
     can have.  These are sensible combinations of {public,private,protected}
Index: decl.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl.c,v
retrieving revision 1.112
diff -c -p -r1.112 decl.c
*** decl.c	1998/05/19 15:15:20	1.112
--- decl.c	1998/05/19 22:39:00
*************** pushdecl (x)
*** 3345,3350 ****
--- 3345,3364 ----
  
  	      return t;
  	    }
+ 	  else if (DECL_MAIN_P (x))
+ 	    {
+ 	      /* A redeclaration of main, but not a duplicate of the
+ 		 previous one. 
+ 
+ 		 [basic.start.main]
+ 
+ 	         This function shall not be overloaded.  */
+ 	      cp_error_at ("invalid redeclaration of `%D'", t);
+ 	      cp_error ("as `%D'", x);
+ 	      /* We don't try to push this declaration since that
+ 		 causes a crash.  */
+ 	      return x;
+ 	    }
  	}
  
        if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
*************** grokfndecl (ctype, type, declarator, ori
*** 7545,7551 ****
    if (ctype)
      DECL_CLASS_CONTEXT (decl) = ctype;
  
!   if (ctype == NULL_TREE && ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
      {
        if (inlinep)
  	error ("cannot declare `main' to be inline");
--- 7559,7565 ----
    if (ctype)
      DECL_CLASS_CONTEXT (decl) = ctype;
  
!   if (ctype == NULL_TREE && MAIN_NAME_P (declarator))
      {
        if (inlinep)
  	error ("cannot declare `main' to be inline");
*************** grokdeclarator (declarator, declspecs, d
*** 10077,10085 ****
  
  	    if (current_lang_name == lang_name_cplusplus
  		&& ! processing_template_decl
! 		&& ! (IDENTIFIER_LENGTH (original_name) == 4
! 		      && IDENTIFIER_POINTER (original_name)[0] == 'm'
! 		      && strcmp (IDENTIFIER_POINTER (original_name), "main") == 0)
  		&& ! (IDENTIFIER_LENGTH (original_name) > 10
  		      && IDENTIFIER_POINTER (original_name)[0] == '_'
  		      && IDENTIFIER_POINTER (original_name)[1] == '_'
--- 10091,10097 ----
  
  	    if (current_lang_name == lang_name_cplusplus
  		&& ! processing_template_decl
! 		&& ! MAIN_NAME_P (original_name)
  		&& ! (IDENTIFIER_LENGTH (original_name) > 10
  		      && IDENTIFIER_POINTER (original_name)[0] == '_'
  		      && IDENTIFIER_POINTER (original_name)[1] == '_'
*************** start_function (declspecs, declarator, a
*** 11724,11732 ****
  
        if (TREE_CODE (fntype) == METHOD_TYPE)
  	ctype = TYPE_METHOD_BASETYPE (fntype);
!       else if (IDENTIFIER_LENGTH (DECL_NAME (decl1)) == 4
! 	       && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (decl1)), "main")
! 	       && DECL_CONTEXT (decl1) == NULL_TREE)
  	{
  	  /* If this doesn't return integer_type, complain.  */
  	  if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
--- 11736,11742 ----
  
        if (TREE_CODE (fntype) == METHOD_TYPE)
  	ctype = TYPE_METHOD_BASETYPE (fntype);
!       else if (DECL_MAIN_P (decl1))
  	{
  	  /* If this doesn't return integer_type, complain.  */
  	  if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
*************** store_parm_decls ()
*** 12121,12130 ****
  
    /* If this function is `main', emit a call to `__main'
       to run global initializers, etc.  */
!   if (DECL_NAME (fndecl)
!       && IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
!       && strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main") == 0
!       && DECL_CONTEXT (fndecl) == global_namespace)
      {
        expand_main_function ();
      }
--- 12131,12138 ----
  
    /* If this function is `main', emit a call to `__main'
       to run global initializers, etc.  */
!   if (DECL_MAIN_P (fndecl))
!     expand_main_function ();
      {
        expand_main_function ();
      }
*************** finish_function (lineno, call_poplevel, 
*** 12576,12584 ****
  	  current_function_assigns_this = 0;
  	  current_function_just_assigned_this = 0;
  	}
!       else if (IDENTIFIER_LENGTH (DECL_NAME (fndecl)) == 4
! 	       && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (fndecl)), "main")
! 	       && DECL_CONTEXT (fndecl) == global_namespace)
  	{
  	  /* Make it so that `main' always returns 0 by default.  */
  #ifdef VMS
--- 12584,12590 ----
  	  current_function_assigns_this = 0;
  	  current_function_just_assigned_this = 0;
  	}
!       else if (DECL_MAIN_P (fndecl))
  	{
  	  /* Make it so that `main' always returns 0 by default.  */
  #ifdef VMS
Index: friend.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/friend.c,v
retrieving revision 1.15
diff -c -p -r1.15 friend.c
*** friend.c	1998/05/08 02:05:54	1.15
--- friend.c	1998/05/19 22:39:14
*************** do_friend (ctype, declarator, decl, parm
*** 364,372 ****
  	}
      }
    else if (TREE_CODE (decl) == FUNCTION_DECL
! 	   && ((IDENTIFIER_LENGTH (declarator) == 4
! 		&& IDENTIFIER_POINTER (declarator)[0] == 'm'
! 		&& ! strcmp (IDENTIFIER_POINTER (declarator), "main"))
  	       || (IDENTIFIER_LENGTH (declarator) > 10
  		   && IDENTIFIER_POINTER (declarator)[0] == '_'
  		   && IDENTIFIER_POINTER (declarator)[1] == '_'
--- 364,370 ----
  	}
      }
    else if (TREE_CODE (decl) == FUNCTION_DECL
! 	   && (MAIN_NAME_P (declarator)
  	       || (IDENTIFIER_LENGTH (declarator) > 10
  		   && IDENTIFIER_POINTER (declarator)[0] == '_'
  		   && IDENTIFIER_POINTER (declarator)[1] == '_'
Index: typeck.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/typeck.c,v
retrieving revision 1.70
diff -c -p -r1.70 typeck.c
*** typeck.c	1998/05/19 14:51:37	1.70
--- typeck.c	1998/05/19 22:40:18
*************** build_function_call_real (function, para
*** 2744,2757 ****
        fndecl = function;
  
        /* Convert anything with function type to a pointer-to-function.  */
!       if (pedantic
! 	  && name
! 	  && IDENTIFIER_LENGTH (name) == 4
! 	  && ! strcmp (IDENTIFIER_POINTER (name), "main")
! 	  && DECL_CONTEXT (function) == global_namespace)
! 	{
! 	  pedwarn ("ANSI C++ forbids calling `main' from within program");
! 	}
  
        /* Differs from default_conversion by not setting TREE_ADDRESSABLE
  	 (because calling an inline function does not mean the function
--- 2744,2751 ----
        fndecl = function;
  
        /* Convert anything with function type to a pointer-to-function.  */
!       if (pedantic && DECL_MAIN_P (function))
! 	pedwarn ("ANSI C++ forbids calling `main' from within program");
  
        /* Differs from default_conversion by not setting TREE_ADDRESSABLE
  	 (because calling an inline function does not mean the function
*************** build_unary_op (code, xarg, noconvert)
*** 4509,4521 ****
  	  TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
  	  return arg;
  	}
!       else if (pedantic
! 	       && TREE_CODE (arg) == FUNCTION_DECL
! 	       && DECL_NAME (arg)
! 	       && DECL_CONTEXT (arg) == global_namespace
! 	       && IDENTIFIER_LENGTH (DECL_NAME (arg)) == 4
! 	       && IDENTIFIER_POINTER (DECL_NAME (arg))[0] == 'm'
! 	       && ! strcmp (IDENTIFIER_POINTER (DECL_NAME (arg)), "main"))
  	/* ARM $3.4 */
  	pedwarn ("taking address of function `main'");
  
--- 4503,4509 ----
  	  TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
  	  return arg;
  	}
!       else if (pedantic && DECL_MAIN_P (arg))
  	/* ARM $3.4 */
  	pedwarn ("taking address of function `main'");
  
Index: ../testsuite/g++.old-deja/g++.other/main1.C
===================================================================
RCS file: main1.C
diff -N main1.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- main1.C	Tue May 19 15:40:38 1998
***************
*** 0 ****
--- 1,12 ----
+ // Build don't linK:
+ 
+ int main()
+ {
+   return 0;
+ }
+ 
+ 
+ int main(int, const char**)
+ {
+   return 0;
+ }



More information about the Gcc-bugs mailing list