🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: gnu.gcc.help
Article #52667

Re: prototypes with short args generate fatal error

#52667
From: Paul Eggert
Date: Mon, 08 Jun 1992 21:15
206 lines
7875 bytes
aab@cichlid.com (Andy Burgess) writes:

>	int foo(short x);
>	int bar(short x);
>	int foo(short x) {} /* this works */
>	int bar(x) short x; {} /* this does not */

The C Standard requires a diagnostic for the fourth line,
so GCC is not in error here.
Look under ``promotion of formal parameters'' in the GCC manual.

However, it is an inconvenience for GCC to not allow it as an extension,
particularly since it is a common extension in other C compilers.
Here's a patch for GCC 2.1 to support this usage.
I submitted this patch to the GNU Project,
and I think something like it will appear in a future version of GCC.

Wed Mar 25 19:22:26 1992  Paul Eggert  (eggert@twinsun.com)

	* c-decl.c (store_parm_decls): Function prototypes now override
	old-style definitions if argument types disagree only because of
	promotions.
	* extend.texi, gcc.texi: Describe this extension to ANSI C.

===================================================================
RCS file: c-decl.c,v
retrieving revision 2.1
diff -u2 -r2.1 c-decl.c
--- c-decl.c	1992/03/23 02:07:53	2.1
+++ c-decl.c	1992/03/26 01:32:34
@@ -5290,26 +5290,30 @@
 	      /* Type for passing arg must be consistent
 		 with that declared for the arg.  */
-	      if (! comptypes (DECL_ARG_TYPE (parm), TREE_VALUE (type))
-		  /* If -traditional, allow `unsigned int' instead of `int'
-		     in the prototype.  */
-		  && (! (flag_traditional
-			 && DECL_ARG_TYPE (parm) == integer_type_node
-			 && TREE_VALUE (type) == unsigned_type_node)))
-		{
+	      if (! comptypes (DECL_ARG_TYPE (parm), TREE_VALUE (type)))
+		if (TREE_TYPE (parm) == TREE_VALUE (type))
+		  {
+		    /* Adjust argument to match prototype.  E.g. a previous
+		       `int foo(float);' prototype causes
+		       `int foo(x) float x; {...}' to be treated like
+		       `int foo(float x) {...}'.  This is particularly
+		       useful for argument types like uid_t.  */
+		    DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
+#ifdef PROMOTE_PROTOTYPES
+		    if (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
+			&& TYPE_PRECISION (TREE_TYPE (parm))
+			   < TYPE_PRECISION (integer_type_node))
+		      DECL_ARG_TYPE (parm) = integer_type_node;
+#endif
+		    if (pedantic)
+		      warning ("after promotion, argument `%s' doesn't match function prototype",
+			       IDENTIFIER_POINTER (DECL_NAME (parm)));
+		  }
+		/* If -traditional, allow `int' argument to match
+		   `unsigned' prototype.  */
+		else if (! (flag_traditional
+			    && TREE_TYPE (parm) == integer_type_node
+			    && TREE_VALUE (type) == unsigned_type_node))
 		  error ("argument `%s' doesn't match function prototype",
 			 IDENTIFIER_POINTER (DECL_NAME (parm)));
-		  if (DECL_ARG_TYPE (parm) == integer_type_node
-		      && TREE_VALUE (type) == TREE_TYPE (parm))
-		    {
-		      error ("a formal parameter type that promotes to `int'");
-		      error ("can match only `int' in the prototype");
-		    }
-		  if (DECL_ARG_TYPE (parm) == double_type_node
-		      && TREE_VALUE (type) == TREE_TYPE (parm))
-		    {
-		      error ("a formal parameter type that promotes to `double'");
-		      error ("can match only `double' in the prototype");
-		    }
-		}
 	    }
 	  TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
===================================================================
RCS file: extend.texi,v
retrieving revision 2.1
diff -u2 -r2.1 extend.texi
--- extend.texi	1992/02/27 12:45:33	2.1
+++ extend.texi	1992/03/26 01:47:40
@@ -37,4 +37,5 @@
 * Function Attributes:: Declaring that functions have no side effects,
                          or that they can never return.
+* Function Prototypes:: Prototype declarations and old-style definitions.
 * Dollar Signs::        Dollar sign is allowed in identifiers.
 * Character Escapes::   @samp{\e} stands for the character @key{ESC}.
@@ -1073,4 +1074,57 @@
 for @code{#pragma}.  It is basically a mistake to use @code{#pragma} for
 @emph{anything}.
+
+@node Function Prototypes
+@section Function Prototype Declarations and Old-Style Function Definitions
+@cindex function prototype declarations
+@cindex old-style function definitions
+@cindex promotion of formal parameters
+
+GNU C extends ANSI C to allow a function prototype to override a later
+old-style non-prototype definition.  Consider the following example:
+
+@example
+/* Use prototypes unless the compiler is old-fashioned.  */
+#if __STDC__
+#  define P((x)) (x)
+#else
+#  define P((x)) ()
+#endif
+
+/* prototype function declaration */
+int isroot P((uid_t));
+
+/* old-style function definition */
+int isroot (x)
+     uid_t x;
+@{
+  return x == 0;
+@}
+@end example
+
+Suppose the type @code{uid_t} happens to be @code{short}.  ANSI C does
+not allow this example, because subword arguments in old-style
+non-prototype definitions are promoted.  Therefore in this example the
+function definition's argument is really an @code{int}, which does not
+match the prototype argument type of @code{short}.
+
+This restriction of ANSI C makes it hard to write code that is portable
+to traditional C compilers, because the programmer does not know
+whether the Posix @code{uid_t} type is @code{short}, @code{int}, or
+@code{long}.  Therefore, in cases like these GNU C allows a prototype
+to override a later old-style definition.  More precisely, in GNU C, a
+function prototype argument type overrides the argument type specified
+by a later old-style definition if the former type is the same as the
+latter type before promotion.  Thus in GNU C the above example is
+equivalent to the following:
+
+@example
+int isroot (uid_t);
+
+int isroot (uid_t x)
+@{
+  return x == 0;
+@}
+@end example
 
 @node Dollar Signs
===================================================================
RCS file: gcc.texi,v
retrieving revision 2.1
diff -u2 -r2.1 gcc.texi
--- gcc.texi	1992/03/22 21:19:05	2.1
+++ gcc.texi	1992/03/26 02:04:37
@@ -1813,26 +1813,4 @@
 @end ifclear
 
-@cindex promotion of formal parameters
-@item
-Users often think it is a bug when GNU CC reports an error for code
-like this:
-
-@example
-int foo (short);
-
-int foo (x)
-     short x;
-@{@dots{}@}
-@end example
-
-The error message is correct: this code really is erroneous, because the
-old-style non-prototype definition passes subword integers in their
-promoted types.  In other words, the argument is really an @code{int},
-not a @code{short}.  The correct prototype is this:
-
-@example
-int foo (int);
-@end example
-
 @cindex conflicting types
 @cindex scope of declaration
@@ -2390,21 +2368,4 @@
 If the compiler produces an error message for valid input, that is a
 compiler bug.
-
-Note that the following is not valid input, and the error message for
-it is not a bug:
-
-@example
-int foo (char);
-
-int
-foo (x)
-     char x;
-@{ @dots{} @}
-@end example
-
-@noindent
-The prototype says to pass a @code{char}, while the definition says to
-pass an @code{int} and treat the value as a @code{char}.  This is what
-the ANSI standard says, and it makes sense.
 
 @cindex invalid input
Technical Details
Message-ID: <bi'fG5w-@twinsun.com>
Path: arc1-ca.pugleaf.net!sparky!uunet!elroy.jpl.nasa.gov!ucla-cs!twinsun!eggert
References: <1992Jun8.174919.25532@cichlid.com>

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 11318c,b21c3ee4f807878a
X-Google-Attributes: gid11318c,public
X-Google-Thread: 1014db,b21c3ee4f807878a
X-Google-Attributes: gid1014db,public
X-Google-ArrivalTime: 1992-06-08 09:27:52 PST
Newsgroups: gnu.gcc.help,comp.lang.c
Path: arc1-ca.pugleaf.net!sparky!uunet!elroy.jpl.nasa.gov!ucla-cs!twinsun!eggert
From: eggert@twinsun.com (Paul Eggert)
Subject: Re: prototypes with short args generate fatal error
Message-ID: <bi'fG5w-@twinsun.com>
Sender: usenet@twinsun.com
Nntp-Posting-Host: farside
Organization: Twin Sun, Inc
References: <1992Jun8.174919.25532@cichlid.com>
Date: Mon, 8 Jun 1992 21:15:46 GMT
Lines: 207