diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 176f4b12ee10..4c22e8fcd67d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2003-04-19 Matt Kraai + + * README.Portability: Move to a new section and obsolete K+R + portability issues. + Sat Apr 19 14:56:17 CEST 2003 Jan Hubicka * rtlanal.c (subreg_offset_representable_p): Fix call of diff --git a/gcc/README.Portability b/gcc/README.Portability index 04638b2a00cd..d50947a43492 100644 --- a/gcc/README.Portability +++ b/gcc/README.Portability @@ -1,4 +1,4 @@ -Copyright (C) 2000 Free Software Foundation, Inc. +Copyright (C) 2000, 2003 Free Software Foundation, Inc. This file is intended to contain a few notes about writing C code within GCC so that it compiles without error on the full range of @@ -15,42 +15,13 @@ probably what most people code to naturally. Obviously using constructs introduced after that is not a good idea. The first section of this file deals strictly with portability issues, -the second with common coding pitfalls. +the second with common coding pitfalls, and the third with obsolete +K+R portability issues. Portability Issues ================== -Unary + -------- - -K+R C compilers and preprocessors have no notion of unary '+'. Thus -the following code snippet contains 2 portability problems. - -int x = +2; /* int x = 2; */ -#if +1 /* #if 1 */ -#endif - - -Pointers to void ----------------- - -K+R C compilers did not have a void pointer, and used char * as the -pointer to anything. The macro PTR is defined as either void * or -char * depending on whether you have a standards compliant compiler or -a K+R one. Thus - - free ((void *) h->value.expansion); - -should be written - - free ((PTR) h->value.expansion); - -Further, an initial investigation indicates that pointers to functions -returning void are okay. Thus the example given by "Calling functions -through pointers to functions" below appears not to cause a problem. - - String literals --------------- @@ -61,14 +32,9 @@ const char string[] = ("A string"); This is unfortunate since this is what the GNU gettext macro N_ produces. You need to find a different way to code it. -K+R C did not allow concatenation of string literals like - - "This is a " "single string literal". - -Moreover, some compilers like MSVC++ have fairly low limits on the -maximum length of a string literal; 509 is the lowest we've come -across. You may need to break up a long printf statement into many -smaller ones. +Some compilers like MSVC++ have fairly low limits on the maximum +length of a string literal; 509 is the lowest we've come across. You +may need to break up a long printf statement into many smaller ones. Empty macro arguments @@ -88,140 +54,6 @@ foo (bar, ) needs to be coded in some other way. -signed keyword --------------- - -The signed keyword did not exist in K+R compilers; it was introduced -in ISO C89, so you cannot use it. In both K+R and standard C, -unqualified char and bitfields may be signed or unsigned. There is no -way to portably declare signed chars or signed bitfields. - -All other arithmetic types are signed unless you use the 'unsigned' -qualifier. For instance, it is safe to write - - short paramc; - -instead of - - signed short paramc; - -If you have an algorithm that depends on signed char or signed -bitfields, you must find another way to write it before it can be -integrated into GCC. - - -Function prototypes -------------------- - -You need to provide a function prototype for every function before you -use it, and functions must be defined K+R style. The function -prototype should use the PARAMS macro, which takes a single argument. -Therefore the parameter list must be enclosed in parentheses. For -example, - -int myfunc PARAMS ((double, int *)); - -int -myfunc (var1, var2) - double var1; - int *var2; -{ - ... -} - -This implies that if the function takes no arguments, it should be -declared and defined as follows: - -int myfunc PARAMS ((void)); - -int -myfunc () -{ - ... -} - -You also need to use PARAMS when referring to function protypes in -other circumstances, for example see "Calling functions through -pointers to functions" below. - -Variable-argument functions are best described by example:- - -void cpp_ice PARAMS ((cpp_reader *, const char *msgid, ...)); - -void -cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...)) -{ - VA_OPEN (ap, msgid); - VA_FIXEDARG (ap, cpp_reader *, pfile); - VA_FIXEDARG (ap, const char *, msgid); - - ... - VA_CLOSE (ap); -} - -See ansidecl.h for the definitions of the above macros and more. - -One aspect of using K+R style function declarations, is you cannot -have arguments whose types are char, short, or float, since without -prototypes (ie, K+R rules), these types are promoted to int, int, and -double respectively. - -Calling functions through pointers to functions ------------------------------------------------ - -K+R C compilers require parentheses around the dereferenced function -pointer expression in the call, whereas ISO C relaxes the syntax. For -example - -typedef void (* cl_directive_handler) PARAMS ((cpp_reader *, const char *)); - *p->handler (pfile, p->arg); - -needs to become - - (*p->handler) (pfile, p->arg); - - -Macros ------- - -The rules under K+R C and ISO C for achieving stringification and -token pasting are quite different. Therefore some macros have been -defined which will get it right depending upon the compiler. - - CONCAT2(a,b) CONCAT3(a,b,c) and CONCAT4(a,b,c,d) - -will paste the tokens passed as arguments. You must not leave any -space around the commas. Also, - - STRINGX(x) - -will stringify an argument; to get the same result on K+R and ISO -compilers x should not have spaces around it. - - -Passing structures by value ---------------------------- - -Avoid passing structures by value, either to or from functions. It -seems some K+R compilers handle this differently or not at all. - - -Enums ------ - -In K+R C, you have to cast enum types to use them as integers, and -some compilers in particular give lots of warnings for using an enum -as an array index. - - -Bitfields ---------- - -See also "signed keyword" above. In K+R C only unsigned int bitfields -were defined (i.e. unsigned char, unsigned short, unsigned long. -Using plain int/short/long was not allowed). - - free and realloc ---------------- @@ -232,37 +64,16 @@ pointer. Thus if mem might be null, you need to write free (mem); -Reserved Keywords ------------------ - -K+R C has "entry" as a reserved keyword, so you should not use it for -your variable names. - - -Type promotions ---------------- - -K+R used unsigned-preserving rules for arithmetic expresssions, while -ISO uses value-preserving. This means an unsigned char compared to an -int is done as an unsigned comparison in K+R (since unsigned char -promotes to unsigned) while it is signed in ISO (since all of the -values in unsigned char fit in an int, it promotes to int). - Trigraphs --------- -You weren't going to use them anyway, but trigraphs were not defined -in K+R C, and some otherwise ISO C compliant compilers do not accept -them. +You weren't going to use them anyway, but some otherwise ISO C +compliant compilers do not accept trigraphs. Suffixes on Integer Constants ----------------------------- -K+R C did not accept a 'u' suffix on integer constants. If you want -to declare a constant to be be unsigned, you must use an explicit -cast. - You should never use a 'l' suffix on integer constants ('L' is fine), since it can easily be confused with the number '1'. @@ -300,22 +111,19 @@ long and int are not the same size. Second, if you write a function definition with no return type at all: - operate (a, b) - int a, b; + operate (int a, int b) { ... } that function is expected to return int, *not* void. GCC will warn -about this. K+R C has no problem with 'void' as a return type, so you -need not worry about that. +about this. Implicit function declarations always have return type int. So if you correct the above definition to void - operate (a, b) - int a, b; + operate (int a, int b) ... but operate() is called above its definition, you will get an error @@ -389,3 +197,205 @@ o Passing incorrect types to fprintf and friends. o Adding a function declaration for a module declared in another file to a .c file instead of to a .h file. + + + K+R Portability Issues + ====================== + +Unary + +------- + +K+R C compilers and preprocessors have no notion of unary '+'. Thus +the following code snippet contained 2 portability problems. + +int x = +2; /* int x = 2; */ +#if +1 /* #if 1 */ +#endif + + +Pointers to void +---------------- + +K+R C compilers did not have a void pointer, and used char * as the +pointer to anything. The macro PTR is defined as either void * or +char * depending on whether you have a standards compliant compiler or +a K+R one. Thus + + free ((void *) h->value.expansion); + +should have been written + + free ((PTR) h->value.expansion); + +Further, an initial investigation indicates that pointers to functions +returning void were okay. Thus the example given by "Calling +functions through pointers to functions" below appeared not to cause a +problem. + + +String literals +--------------- + +K+R C did not allow concatenation of string literals like + + "This is a " "single string literal". + + +signed keyword +-------------- + +The signed keyword did not exist in K+R compilers; it was introduced +in ISO C89, so you could not use it. In both K+R and standard C, +unqualified char and bitfields may be signed or unsigned. There is no +way to portably declare signed chars or signed bitfields. + +All other arithmetic types are signed unless you use the 'unsigned' +qualifier. For instance, it was safe to write + + short paramc; + +instead of + + signed short paramc; + +If you have an algorithm that depends on signed char or signed +bitfields, you had to find another way to write it before it could be +integrated into GCC. + + +Function prototypes +------------------- + +You need to provide a function prototype for every function before you +use it, and functions had to be defined K+R style. The function +prototype should have used the PARAMS macro, which takes a single +argument. Therefore the parameter list had to be enclosed in +parentheses. For example, + +int myfunc PARAMS ((double, int *)); + +int +myfunc (var1, var2) + double var1; + int *var2; +{ + ... +} + +This implies that if the function takes no arguments, it had to be +declared and defined as follows: + +int myfunc PARAMS ((void)); + +int +myfunc () +{ + ... +} + +You also had to use PARAMS when referring to function protypes in +other circumstances, for example see "Calling functions through +pointers to functions" below. + +Variable-argument functions are best described by example:- + +void cpp_ice PARAMS ((cpp_reader *, const char *msgid, ...)); + +void +cpp_ice VPARAMS ((cpp_reader *pfile, const char *msgid, ...)) +{ + VA_OPEN (ap, msgid); + VA_FIXEDARG (ap, cpp_reader *, pfile); + VA_FIXEDARG (ap, const char *, msgid); + + ... + VA_CLOSE (ap); +} + +See ansidecl.h for the definitions of the above macros and more. + +One aspect of using K+R style function declarations, is you could not +have arguments whose types are char, short, or float, since without +prototypes (ie, K+R rules), these types are promoted to int, int, and +double respectively. + +Calling functions through pointers to functions +----------------------------------------------- + +K+R C compilers require parentheses around the dereferenced function +pointer expression in the call, whereas ISO C relaxes the syntax. For +example + +typedef void (* cl_directive_handler) PARAMS ((cpp_reader *, const char *)); + *p->handler (pfile, p->arg); + +had to become + + (*p->handler) (pfile, p->arg); + + +Macros +------ + +The rules under K+R C and ISO C for achieving stringification and +token pasting are quite different. Therefore some macros have been +defined which will get it right depending upon the compiler. + + CONCAT2(a,b) CONCAT3(a,b,c) and CONCAT4(a,b,c,d) + +will paste the tokens passed as arguments. You must not leave any +space around the commas. Also, + + STRINGX(x) + +will stringify an argument; to get the same result on K+R and ISO +compilers x should not have spaces around it. + + +Passing structures by value +--------------------------- + +You had to avoid passing structures by value, either to or from +functions. It seems some K+R compilers handle this differently or not +at all. + + +Enums +----- + +In K+R C, you had to cast enum types to use them as integers, and some +compilers in particular give lots of warnings for using an enum as an +array index. + + +Bitfields +--------- + +See also "signed keyword" above. In K+R C only unsigned int bitfields +were defined (i.e. unsigned char, unsigned short, unsigned long. +Using plain int/short/long was not allowed). + + +Reserved Keywords +----------------- + +K+R C has "entry" as a reserved keyword, so you had to not use it for +your variable names. + + +Type promotions +--------------- + +K+R used unsigned-preserving rules for arithmetic expresssions, while +ISO uses value-preserving. This means an unsigned char compared to an +int is done as an unsigned comparison in K+R (since unsigned char +promotes to unsigned) while it is signed in ISO (since all of the +values in unsigned char fit in an int, it promotes to int). + + +Suffixes on Integer Constants +----------------------------- + +K+R C did not accept a 'u' suffix on integer constants. If you wanted +to declare a constant to be be unsigned, you had to use an explicit +cast.