X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2FREADME.Portability;h=4101a2f7b4240e998f83f5bd61583b6c92b33cac;hp=d6c8aecaa5df3255e0ac3a4c2f0fd890f225dc85;hb=7fd4009052d726cf42b4636e5b8cc33c236c9786;hpb=f2fbb03c56a8cca45e8be218f071db06591fa911 diff --git a/gcc/README.Portability b/gcc/README.Portability index d6c8aecaa5d..4101a2f7b42 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 @@ -10,54 +10,28 @@ This knowledge until know has been sparsely spread around, so I thought I'd collect it in one useful place. Please add and correct any problems as you come across them. -I'm going to start from a base of the ISO C89 standard, since that is +I'm going to start from a base of the ISO C90 standard, since that is 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. - - - 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); +For the complete coding style conventions used in GCC, please read +http://gcc.gnu.org/codingconventions.html String literals --------------- -K+R C did not allow concatenation of string literals like +Irix6 "cc -n32" and OSF4 "cc" have problems with constant string +initializers with parens around it, e.g. - "This is a " "single string literal". +const char string[] = ("A string"); -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. +This is unfortunate since this is what the GNU gettext macro N_ +produces. You need to find a different way to code it. + +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 @@ -77,178 +51,42 @@ foo (bar, ) needs to be coded in some other way. -signed keyword --------------- - -The signed keyword did not exist in K+R comilers, 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; -{ - ... -} - -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, ...)) -{ -#ifndef ANSI_PROTOTYPES - cpp_reader *pfile; - const char *msgid; -#endif - va_list ap; - - VA_START (ap, msgid); - -#ifndef ANSI_PROTOTYPES - pfile = va_arg (ap, cpp_reader *); - msgid = va_arg (ap, const char *); -#endif - - ... - va_end (ap); -} - -For the curious, here are the definitions of the above macros. See -ansidecl.h for the definitions of the above macros and more. - -#define PARAMS(paramlist) paramlist /* ISO C. */ -#define VPARAMS(args) args +Avoid unnecessary test before free +---------------------------------- -#define PARAMS(paramlist) () /* K+R C. */ -#define VPARAMS(args) (va_alist) va_dcl +Since SunOS 4 stopped being a reasonable portability target, +(which happened around 2007) there has been no need to guard +against "free (NULL)". Thus, any guard like the following +constitutes a redundant test: -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. + if (P) + free (P); -Calling functions through pointers to functions ------------------------------------------------ +It is better to avoid the test.[*] +Instead, simply free P, regardless of whether it is NULL. -K+R C compilers require brackets around the dereferenced pointer -variable. For example +[*] However, if your profiling exposes a test like this in a +performance-critical loop, say where P is nearly always NULL, and +the cost of calling free on a NULL pointer would be prohibitively +high, consider using __builtin_expect, e.g., like this: -typedef void (* cl_directive_handler) PARAMS ((cpp_reader *, const char *)); - p->handler (pfile, p->arg); + if (__builtin_expect (ptr != NULL, 0)) + free (ptr); -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. - - -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 ----------------- - -Some implementations crash upon attempts to free or realloc the null -pointer. Thus if mem might be null, you need to write - - if (mem) - 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'. +You should never use a 'l' suffix on integer constants ('L' is fine), +since it can easily be confused with the number '1'. Common Coding Pitfalls @@ -284,22 +122,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 @@ -352,7 +187,7 @@ WITH UMLAUT. Other common pitfalls --------------------- -o Expecting 'plain' char to be either sign or unsigned extending +o Expecting 'plain' char to be either sign or unsigned extending. o Shifting an item by a negative amount or by greater than or equal to the number of bits in a type (expecting shifts by 32 to be sensible