User’s Guide
to
GNU C++
Michael D. Tiemann
last updated 1 March 1990
for version 1.37.1
Copyright 1988 Free Software Foundation, Inc.
The _U_s_e_r’_s _G_u_i_d_e _t_o _G_N_U _C++ is a derivative work of authorship based on the _U_s_i_n_g _a_n_d _P_o_r_t_i_n_g _G_N_U _C_C by Richard Stallman, and documentary comments in the source code of Doug Lea’s library functions. Both of these documents are copyright The Free Software Foundation.
The code described in this document represents a derivative work of authorship of the GNU CC compiler. The earlier GNU CC compiler was written by Richard Stallman. All copyright conditions applying to GNU CC also apply to GNU C++.
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the section entitled “GNU CC General Public License” is included exactly as in the ori- ginal, and provided that the entire resulting derived work is distributed under the terms of a permission notice ident- ical to this one.
Permission is granted to copy and distribute transla- tions of this manual into another language, under the above conditions for modified versions, except that the section entitled “GNU CC General Public License” may be included in a translation approved by the author instead of in the original English.
NNoottee:: GGNNUU CC++++ iiss ssttiillll iinn tteesstt rreelleeaassee.. KKnnoowwnn bbuuggss aarree ddooccuummeenntteedd iinn tthhee ‘“‘BBuuggLLiisstt’”’ sseeccttiioonn.. TThhee ‘“‘PPrroojjeeccttss’”’ sseeccttiioonn lliissttss tthhiinnggss tthhaatt ccoouulldd ssttiillll bbee ddoonnee..
GGNNUU CCCC GGEENNEERRAALL PPUUBBLLIICC LLIICCEENNSSEE (Clarified 11 Feb 1988)
The license agreements of most software companies keep you at the mercy of those companies. By contrast, our general public license is intended to give everyone the right to share GNU CC. To make sure that you get the rights we want you to have, we need to make restrictions that for- bid anyone to deny you these rights or to ask you to surrender the rights. Hence this license agreement.
Specifically, we want to make sure that you have the right to give away copies of GNU CC, that you receive source code or else can get it if you want it, that you can change GNU CC or use pieces of it in new free programs, and that
22 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
you know you can do these things.
To make sure that everyone has such rights, we have to forbid you to deprive anyone else of these rights. For example, if you distribute copies of GNU CC, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must tell them their rights.
Also, for our own protection, we must make certain that everyone finds out that there is no warranty for GNU CC. If GNU CC is modified by someone else and passed on, we want its recipients to know that what they have is not what we distributed, so that any problems introduced by others will not reflect on our reputation.
Therefore we (Richard Stallman and the Free Software Foundation, Inc.) make the following terms which say what you must do to be allowed to distribute or change GNU CC.
CCOOPPYYIINNGG PPOOLLIICCIIEESS
1. You may copy and distribute verbatim copies of GNU CC source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy a valid copyright notice “Copyright 1988 Free Software Foundation, Inc.” (or with whatever year is appropriate); keep in- tact the notices on all files that refer to this License Agreement and to the absence of any war- ranty; and give any other recipients of the GNU CC program a copy of this License Agreement along with the program. You may charge a distribution fee for the physical act of transferring a copy.
2. You may modify your copy or copies of GNU CC or any portion of it, and copy and distribute such modifications under the terms of Paragraph 1 above, provided that you also do the following:
cause the modified files to carry prominent notices stating that you changed the files and the date of any change; and
cause the whole of any work that you distri- bute or publish, that in whole or in part contains or is a derivative of GNU CC or any part thereof, to be licensed at no charge to all third parties on terms identical to those contained in this License Agreement (except that you may choose to grant more extensive warranty protection to some or all third par- ties, at your option).
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 33
You may charge a distribution fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.
Mere aggregation of another unrelated program with this program (or its derivative) on a volume of a storage or distribution medium does not bring the other program under the scope of these terms.
3. You may copy and distribute GNU CC (or any portion of it in under Paragraph 2) in object code or exe- cutable form under the terms of Paragraphs 1 and 2 above provided that you also do one of the follow- ing:
accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Paragraphs 1 and 2 above; or,
accompany it with a written offer, valid for at least three years, to give any third party free (except for a nominal shipping charge) a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Paragraphs 1 and 2 above; or,
accompany it with the information you re- ceived as to where the corresponding source code may be obtained. (This alternative is allowed only for noncommercial distribution and only if you received the program in ob- ject code or executable form alone.)
For an executable file, complete source code means all the source code for all modules it contains; but, as a special exception, it need not include source code for modules which are standard li- braries that accompany the operating system on which the executable file runs.
4. You may not copy, sublicense, distribute or transfer GNU CC except as expressly provided under this License Agreement. Any attempt otherwise to copy, sublicense, distribute or transfer GNU CC is void and your rights to use the program under this License agreement shall be automatically terminat- ed. However, parties who have received computer software programs from you with this License Agreement will not have their licenses terminated
44 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
so long as such parties remain in full compliance.
5. If you wish to incorporate parts of GNU CC into other free programs whose distribution conditions are different, write to the Free Software Founda- tion at 675 Mass Ave, Cambridge, MA 02139. We have not yet worked out a simple rule that can be stated here, but we will often permit this. We will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software.
Your comments and suggestions about our licensing poli- cies and our software are welcome! Please contact the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, or call (617) 876-3296.
NNOO WWAARRRRAANNTTYY
BECAUSE GNU CC IS LICENSED FREE OF CHARGE, WE PROVIDE ABSOLUTELY NO WARRANTY, TO THE EXTENT PERMITTED BY APPLICA- BLE STATE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING, FREE SOFTWARE FOUNDATION, INC, RICHARD M. STALLMAN AND/OR OTHER PARTIES PROVIDE GNU CC "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIM- ITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- NESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF GNU CC IS WITH YOU. SHOULD GNU CC PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW WILL RICHARD M. STALLMAN, THE FREE SOFTWARE FOUNDATION, INC., AND/OR ANY OTHER PARTY WHO MAY MODIFY AND REDISTRIBUTE GNU CC AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUD- ING ANY LOST PROFITS, LOST MONIES, OR OTHER SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS) GNU CC, EVEN IF YOU HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY.
CCoonnttrriibbuuttoorrss ttoo GGNNUU CC++++
Before GNU C++ was even conceived, Richard Stallman had begun his work on GNU CC, a program which would finally bring state-of-the-art compiler technology to the general public under his Free Software philosophy. GNU C++ serves to provide the same high-quality compiler technology with a front end to support the growing user base of object
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 55
oriented programmers, especially those who are currently using C++.
Aside from Michael Tiemann, who worked out the front end for GNU C++, and Richard Stallman, who worked out the back end, the following people (not including those who have made their contributions to GNU CC) should not go unmen- tioned.
Doug Lea contributed the GNU C++ library. This includes support for streams, obstacks, structured files, and other public service objects.
Doug Schmidt has spent countless hours pursuing bugs in this compiler for sport. He also wrote a perfect hash function generator in GNU C++ which was used to generate a replacement for the keyword recognizer in the lexical analyzer for both GNU CC and GNU C++.
Marc Shapiro and Phillipe Gautron helped me imple- ment features needed for the SOR distributed ob- ject management environment.
Dirk Grunwald made the collect program usable under COFF.
Angel Li adapted GNU C++ to VMS.
Ron Cole provided additional help getting GNU C++ working on COFF-based systems.
James Clark wrote a name demangler for the GNU C++ naming scheme, and integrated it with the linker.
Michael Powell and Jim Mitchell helped design the GNU C++ exception handling mechanism.
And of course, GNU C++ owes a great debt of success to Bjarne Stroustrup, who not only designed the C++ programming language, but also helped get it into the hands of so many thousands of people. Without having designed C++ to be implementable as such an efficient object-oriented language, GNU C++ would not be enjoying the popularity it is today.
11.. GGNNUU CC++++ CCoommmmaanndd OOppttiioonnss
The GNU C++ compiler uses a command syntax much like the AT&T C++ compiler. The g++ program accepts options and file names as operands. Multiple single-letter options may _n_o_t be grouped: ‘-dr’ is very different from ‘-d -r’.
66 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
When you invoke GNU C++, it normally does preprocess- ing, compilation, assembly and linking. File names which end in ‘.c’, ‘.cc’, or ‘.C’ are taken as GNU C++ source to be preprocessed and compiled; compiler output files plus any input files with names ending in ‘.s’ are assembled; then the resulting object files, plus any other input files, are linked together to produce an executable. Note that start- ing with GNU C++ version 1.36 you must explicitly add ‘- lg++’ to your compilation line in order to link in the GNU C++ library, libg++, with your object code (previous releases linked libg++ automatically).
Unlike C++, there is no ‘-F’ option. This is because GNU C++ is a native-code C++ compiler, not a front-end pre- processor. The advantages of this organization are faster compilation speed, better error-reporting capabilities, better opportunity for compiler optimization, and true source-level debuggability with the GDB debugger (version 3.4 or higher).
Command options allow you to stop this process at an intermediate stage. For example, the ‘-c’ option says not to run the linker. Then the output consists of object files output by the assembler.
Other command options are passed on to one stage. Some options control the preprocessor and others the compiler itself. Yet other options control the assembler and linker; these are not documented here because the GNU assembler and linker are not yet released.
Here are the options to control the overall compilation process, including those that say whether to link, whether to assemble, and so on.
‘-o _f_i_l_e’ Place output in file _f_i_l_e. This applies regard- less to whatever sort of output is being produced, whether it be an executable file, an object file, an assembler file or preprocessed C code.
If ‘-o’ is not specified, the default is to put an executable file in ‘a.out’, the object file ‘_s_o_u_r_c_e.cc’ in ‘_s_o_u_r_c_e.o’, an assembler file in ‘_s_o_u_r_c_e.s’, and preprocessed C on standard output.
‘-c’ Compile or assemble the source files, but do not link. Produce object files with names made by re- placing ‘.cc’ or ‘.s’ with ‘.o’ at the end of the input file names. Do nothing at all for object files specified as input.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 77
It is intended that the compiler driver of GNU C++ will invoke the appropriate translator (or series of translators) for a given source file. Current- ly, the translators are selected on the basis of their file extension. So that one driver can be used for many different translators, it is impor- tant that these extensions be distinct. It is strongly suggested that users become accustomed to using a ‘.cc’ file extension for GNU C++ code, to distinguish it from the ‘.c’ file extension al- ready used for GNU CC code.
‘-S’ Compile into assembler code but do not assemble. The assembler output file name is made by replac- ing ‘.cc’ with ‘.s’ at the end of the input file name. Do nothing at all for assembler source files or object files specified as input.
‘-E’ Run only the GNU C preprocessor. Preprocess all the GNU C++ source files specified and output the results to standard output. C++-style comments are handled correctly.
‘-v’ Compiler driver program prints the commands it ex- ecutes as it runs the preprocessor, compiler prop- er, assembler and linker. Some of these are directed to print their own version numbers.
‘-pipe’ Use pipes rather than temporary files for communi- cation between the various stages of compilation. This fails to work on some systems where the as- sembler is unable to read from a pipe; but the GNU assembler has no trouble.
‘-B_p_r_e_f_i_x’ Compiler driver program tries _p_r_e_f_i_x as a prefix for each program it tries to run. These programs are ‘cpp’, ‘cc1plus’, ‘as’ and ‘ld++’.
For each subprogram to be run, the compiler driver first tries the ‘-B’ prefix, if any. If that name is not found, or if ‘-B’ was not specified, the driver tries two standard prefixes, which are ‘/usr/lib/gcc-’ and ‘/usr/local/lib/gcc-’. If neither of those results in a file name that is found, the unmodified program name is searched for using the directories specified in your ‘PATH’ en- vironment variable.
88 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
The run-time support file ‘gnulib’ is also searched for using the ‘-B’ prefix, if needed. If it is not found there, the two standard prefixes above are tried, and that is all. The file is left out of the link if it is not found by those means. This library is necessary if any of the modules linked call constructors.
You can get a similar result from the environment variable; GCC_EXEC_PREFIX if it is defined, its value is used as a prefix in the same way. If both the ‘-B’ option and the GCC_EXEC_PREFIX vari- able are present, the ‘-B’ option is used first and the environment variable value second.
These options control the details of GNU C++ compila- tion itself.
‘-ansi’ Support all ANSI standard C programs, as best we can.
This turns off certain features of GNU C++ that are incompatible with ANSI C, such as the asm and typeof keywords, and predefined macros such as unix and vax to identify the type of system you are using. It also enables the undesirable and rarely used ANSI trigraph feature.
The ‘-ansi’ option does not cause non-ANSI pro- grams to be rejected gratuitously. For that, ‘- pedantic’ is required in addition to ‘-ansi’.
The macro __STRICT_ANSI__ is predefined when the ‘-ansi’ option is used. Some header files may no- tice this macro and refrain from declaring certain functions or defining certain macros that the ANSI standard doesn’t call for; this is to avoid in- terfering with any programs that might use these names for other things.
With this option enabled, differences between GNU C++ and AT&T C++ are also flagged. Because the C++ language definition and the ANSI draft differ on the interpretation of syntactically identical constructs, it is unlikely that this flag could possibly be of any real use. (For this reason, this flag is currently not fully implemented).
‘-traditional’ Attempt to support some aspects of traditional C compilers. Specifically:
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 99
All extern declarations take effect globally even if they are written inside of a function definition. This includes implicit declara- tions of functions.
The keywords typeof, inline, signed, const and volatile are not recognized.
Comparisons between pointers and integers are always allowed.
Integer types unsigned short and unsigned char promote to unsigned int.
Out-of-range floating point literals are not an error.
All automatic variables not declared register are preserved by longjmp. Ordinarily, GNU C follows ANSI C: automatic variables not de- clared volatile may be clobbered.
In the preprocessor, comments convert to nothing at all, rather than to a space. This allows traditional token concatenation.
In the preprocessor, macro arguments are recognized within string constants in a macro definition (and their values are stringified, though without additional quote marks, when they appear in such a context). The prepro- cessor always considers a string constant to end at a newline.
The predefined macro __STDC__ is not defined when you use ‘-traditional’, but __GNUC__ is (since the GNU extensions which __GNUC__ in- dicates are not affected by ‘-traditional’). If you need to write header files that work differently depending on whether ‘- traditional’ is in use, by testing both of these predefined macros you can distinguish four situations: GNU C, traditional GNU C, other ANSI C compilers, and other old C com- pilers.
The predefined macro __cplusplus is defined to identify compilation for C++ 2.0. C++ version 1.2 uses c_plusplus as its identify- ing macro. Since GNU C++ implements version 2.0 semantics, the former is defined, while the latter is not. The macro __GNUG__ is also defined, so that features specific to GNU C++ can be used conditionally.
1100 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
‘-O’ Optimize. Optimizing compilation takes somewhat more time, and a lot more memory for a large func- tion.
Without ‘-O’, the compiler’s goal is to reduce the cost of compilation and to make debugging produce the expected results. Statements are independent: if you stop the program with a breakpoint between statements, you can then assign a new value to any variable or change the program counter to any oth- er statement in the function and get exactly the results you would expect from the source code.
Without ‘-O’, only variables declared register are allocated in registers. The resulting compiled code is a little worse than produced by C++/PCC without ‘-O’.
With ‘-O’, the compiler tries to reduce code size and execution time.
Some of the ‘-f’ options described below turn specific kinds of optimization on or off.
‘-g’ Produce debugging information in DBX+ format. Programs compiled with this option can be debugged with GDB _a_t _t_h_e _C++ _s_o_u_r_c_e _l_a_n_g_u_a_g_e _l_e_v_e_l. Scope resolution, member functions, virtual functions, static class members, inline functions, pointers to members, etc., can be, for the first time, manipulated in as natural a fashion C debuggers handle C code. See the GDB documentation for more information about using this unique facility.
Some work has been done for people who have been forced to work under SystemV. Because this re- quires much change to GNU CC source code (which GNU C++ would ordinarily borrow), there is no sup- port in this release for those changes.
More bad news:
In this release of the compiler, many new features have been added, including multiple inheritance, static member functions, and optionally the au- tomatic overloading of all functions declared with C++ linkage. The debugger does not really know how to search for members in a multiple inheri- tance lattice, it does not understand static member functions, and overloaded global functions are very hard to implement due to an oversight in the a.out symbol table format. If you use these
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 1111
new features, beware that you may write code which the debugger will not treat properly.
On the positive side, GNU C++ retains this win:
Unlike most other C++ compiler systems, GNU C++ allows you to use ‘-g’ with ‘-O’. The shortcuts taken by optimized code may occasionally produce surprising results: some variables you declared may not exist at all; flow of control may briefly move where you did not expect it; some statements may not be executed because they compute constant results or their values were already at hand; some statements may execute in different places because they were moved out of loops. Nevertheless it proves possible to debug optimized output. This makes it reasonable to use the optimizer for pro- grams that might have bugs.
‘-g0’ Produce debugging information in DBX format. This format is fully compatible with vanilla DBX. How- ever, the extensions to the C language which are the essence of C++ will be inaccessible.
If you are running on a COFF system, you will be forced to use this flag until somebody makes ‘-g’ work with COFF, and gets those changes merged into the GNU CC compiler.
‘-gg’ Produce debugging information in GDB’s own format. This requires the GNU assembler and linker in ord- er to work.
This feature will probably be eliminated. It was intended to enable GDB to read the symbol table faster, but it doesn’t result in enough of a speedup to be worth the larger object files and executables. We are working on other ways of mak- ing GDB start even faster, which work with DBX format debugging information and could be made to work with SDB format.
‘-w’ Inhibit all warning messages.
‘-W’ Print extra warning messages for these events:
An automatic variable is used without first being initialized.
1122 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
These warnings are possible only in optimiz- ing compilation, because they require data flow information that is computed only when optimizing. If you don’t specify ‘-O’, you simply won’t get these warnings.
These warnings occur only for variables that are candidates for register allocation. Therefore, they do not occur for a variable that is declared volatile, or whose address is taken, or whose size is other than 1, 2, 4 or 8 bytes. Also, they do not occur for structures, unions or arrays, even when they are in registers.
Note that there may be no warning about a variable that is used only to compute a value that itself is never used, because such com- putations may be deleted by the flow analysis pass before the warnings are printed.
These warnings are made optional because GNU C++ is not smart enough to see all the rea- sons why the code might be correct despite appearing to have an error. Here is one ex- ample of how this can happen:
{ int x; switch (y) { case 1: x = 1; break; case 2: x = 4; break; case 3: x = 5; break; foo (x);
If the value of y is always 1, 2 or 3, then x is always initialized, but GNU C++ doesn’t know this. Here is another common case:
{ int save_y; if (change_y) save_y = y, y = new_y; ... if (change_y) y = save_y;
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 1133
This has no bug because save_y is used only if it is set.
Some spurious warnings can be avoided if you declare as volatile all the functions you use that never return. See section Function Attributes.
A nonvolatile automatic variable might be changed by a call to longjmp. These warnings as well are possible only in op- timizing compilation.
The compiler sees only the calls to setjmp. It cannot know where longjmp will be called; in fact, a signal handler could call it at any point in the code. As a result, you may get a warning even when there is in fact no problem because longjmp cannot in fact be called at the place which would cause a problem.
A function can return either with or without a value. (Falling off the end of the function body is considered returning without a value.) For example, this function would evoke such a warning:
foo (a) { if (a > 0) return a;
Spurious warnings can occur because GNU CC (and hence GNU C++) does not realize that certain functions (including abort and longjmp) will never return.
An expression-statement contains no side effects.
In the future, other useful warnings may also be enabled by this option.
1144 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
‘-Wimplicit’ Warn whenever a function is implicitly de- clared. It can be turned off with the option -fno-warn-implicit.
‘-Wreturn-type’ Warn whenever a function is defined with a return-type that defaults to int. Also warn about any return statement with no return- value in a function whose return-type is not void. The option -Wno-return-type will dis- able it.
‘-Wunused’ Warn whenever a local variable is unused aside from its declaration, and whenever a function is declared static but never defined.
‘-Wswitch’ Warn whenever a switch statement has an index of enumeral type and lacks a case for one or more of the named codes of that enumeration. (The presence of a default label prevents this warning.) case labels outside the enumeration range also provoke warnings when this option is used.
‘-Wcomment’ Warn whenever a comment-start sequence ‘/*’ appears in a comment.
‘-Wtrigraphs’ Warn if any trigraphs are encountered (assum- ing they are enabled).
‘-Wall’ All of the above ‘-W’ options combined. These are all the options which pertain to usage that we recommend avoiding and that we believe is easy to avoid, even in conjunction with macros.
The other ‘-W...’ options below are not im- plied by ‘-Wall’ because certain kinds of use- ful macros are almost impossible to write without causing those warnings.
‘-Wshadow’ Warn whenever a local variable shadows another local variable.
‘-Wid-clash-_l_e_n’ Warn whenever two distinct identifiers match
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 1155
in the first _l_e_n characters. This may help you prepare a program that will compile with certain obsolete, brain-damaged compilers.
‘-Wpointer-arith’ Warn about anything that depends on the “size of” a function type or of void. GNU C as- signs these types a size of 1, for convenience in calculations with void * pointers and pointers to functions.
‘-Wcast-qual’ Warn whenever a pointer is cast so as to re- move a type qualifier from the target type. For example, warn if a const char * is cast to an ordinary char *.
‘-Wwrite-strings’ Give string constants the type const char[_l_e_n_g_t_h] so that copying the address of one into a non-const char * pointer will get a warning. These warnings will help you find at compile time code that can try to write into a string constant, but only if you have been very careful about using const in declarations and prototypes. Otherwise, it will just be a nuisance; this is why we did not make ‘-Wall’ request these warnings.
‘-p’ TThhiiss ooppttiioonn iiss nnoott ssuuppppoorrtteedd,, yyeett. Generate extra code to write profile information suit- able for the analysis program prof.
‘-pg’ TThhiiss ooppttiioonn iiss nnoott ssuuppppoorrtteedd,, yyeett. Generate extra code to write profile information suit- able for the analysis program gprof.
‘-a’ TThhiiss ooppttiioonn iiss nnoott ssuuppppoorrtteedd,, yyeett. Generate extra code to write profile information for basic blocks, suitable for the analysis pro- gram tcov. Eventually GNU gprof should be ex- tended to process this data.
‘-l_l_i_b_r_a_r_y’ Search a standard list of directories for a library named _l_i_b_r_a_r_y, which is actually a file named ‘lib_l_i_b_r_a_r_y.a’. The linker uses this file as if it had been specified precise- ly by name.
1166 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
The directories searched include several stan- dard system directories plus any that you specify with ‘-L’.
Normally the files found this way are library files—archive files whose members are object files. The linker handles an archive file by scanning through it for members which define symbols that have so far been referenced but not defined. But if the file that is found is an ordinary object file, it is linked in the usual fashion. The only difference between using an ‘-l’ option and specifying a file name is that ‘-l’ searches several direc- tories.
‘-L_d_i_r’ Add directory _d_i_r to the list of directories to be searched for ‘-l’.
‘-nostdlib’ Don’t use the standard system libraries and startup files when linking. Only the files you specify (plus ‘gnulib’) will be passed to the linker.
‘-m_m_a_c_h_i_n_e_s_p_e_c’ Machine-dependent option specifying something about the type of target machine. These op- tions are defined by the macro TARGET_SWITCHES in the machine description. The default for the options is also defined by that macro, which enables you to change the defaults.
These are the ‘-m’ options defined in the 68000 machine description:
‘-m68020’
‘-mc68020’ Generate output for a 68020 (rather than a 68000). This is the default if you use the unmodified sources.
‘-m68000’
‘-mc68000’ Generate output for a 68000 (rather than a 68020).
‘-m68881’ Generate output containing 68881 instructions for floating point. This is the default if you use the unmodified sources.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 1177
‘-mfpa’ Generate output containing Sun FPA instruc- tions for floating point.
‘-msoft-float’ Generate output containing library calls for floating point.
‘-mshort’ Consider type int to be 16 bits wide, like short int.
‘-mnobitfield’ Do not use the bit-field instructions. ‘- m68000’ implies ‘-mnobitfield’.
‘-mbitfield’ Do use the bit-field instructions. ‘-m68020’ implies ‘-mbitfield’. This is the default if you use the unmodified sources.
‘-mrtd’ Use a different function-calling convention, in which functions that take a fixed number of arguments return with the rtd instruction, which pops their arguments while returning. This saves one instruction in the caller since there is no need to pop the arguments there.
This calling convention is incompatible with the one normally used on Unix, so you cannot use it if you need to call libraries compiled with the Unix compiler.
Also, you must provide function prototypes for all functions that take variable numbers of arguments (including printf); otherwise incorrect code will be generated for calls to those functions.
In addition, seriously incorrect code will result if you call a function with too many arguments. (Normally, extra arguments are harmlessly ignored.)
The rtd instruction is supported by the 68010 and 68020 processors, but not by the 68000.
These ‘-m’ options are defined in the Vax machine description:
1188 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
‘-munix’ Do not output certain jump instructions (aob- leq and so on) that the Unix assembler for the Vax cannot handle across long ranges.
‘-mgnu’ Do output those jump instructions, on the as- sumption that you will assemble with the GNU assembler.
‘-mg’ Output code for g-format floating point numbers instead of d-format.
These ‘-m’ switches are supported on the Sparc:
‘-mfpu’ Generate output containing floating point in- structions. This is the default if you use the unmodified sources.
‘-msoft-float’ Generate output containing library calls for floating point.
‘-mno-epilogue’ Generate separate return instructions for re- turn statements. This has both advantages and disadvantages; I don’t recall what they are.
‘-meager’ Do eager conditional branch scheduling to fill no-op slots. This optimization is new, so we suspect it has bugs; some day it will be done by default, but it is optional now so you can test it when you are ready.
_T_e_s_t _i_t _n_o_w, and report the bugs; otherwise we won’t find them, and this option may be- come the default with bugs still in it!
These ‘-m’ options are defined in the Convex machine description:
‘-mc1’ Generate output for a C1. This is the de- fault when the compiler is configured for a C1.
‘-mc2’ Generate output for a C2. This is the de-
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 1199
fault when the compiler is configured for a C2.
‘-margcount’ Generate code which puts an argument count in the word preceding each argument list. Some nonportable Convex and Vax programs need this word. (Debuggers don’t; this info is in the symbol table.)
‘-mnoargcount’ Omit the argument count word. This is the default if you use the unmodified sources.
‘-f_f_l_a_g’ Specify machine-independent flags. Most flags have both positive and negative forms; the nega- tive form of ‘-ffoo’ would be ‘-fno-foo’. In the table below, only one of the forms is listed—the one which is not the default. You can figure out the other form by either removing ‘no-’ or adding it.
‘-fpcc-struct-return’ Use the same convention for returning struct and union values that is used by the usual C compiler on your system. This convention is less efficient for small structures, and on many machines it fails to be reentrant; but it has the advantage of allowing intercalla- bility between GCC-compiled code and PCC- compiled code. YYoouu ddoonn’’tt wwaanntt ttoo uussee tthhiiss ffllaagg wwiitthh GGNNUU CC++++.
‘-ffloat-store’ Do not store floating-point variables in re- gisters. This prevents undesirable excess precision on machines such as the 68000 where the floating registers (of the 68881) keep more precision than a double is supposed to have.
For most programs, the excess precision does only good, but a few programs rely on the precise definition of IEEE floating point. Use ‘-ffloat-store’ for such programs.
‘-fno-asm’ Do not recognize asm or typeof as a keyword. These words may then be used as identifiers.
‘-fno-defer-pop’ Always pop the arguments to each function
2200 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
call as soon as that function returns. Nor- mally the compiler (when optimizing) lets ar- guments accumulate on the stack for several function calls and pops them all at once.
‘-fstrength-reduce’ Perform the optimizations of loop strength reduction and elimination of iteration vari- ables.
‘-fcombine-regs’ Allow the combine pass to combine an instruc- tion that copies one register into another. This might or might not produce better code when used in addition to ‘-O’. I am in- terested in hearing about the difference this makes.
‘-fforce-mem’ Force memory operands to be copied into re- gisters before doing arithmetic on them. This may produce better code by making all memory references potential common subexpres- sions. When they are not common subexpres- sions, instruction combination should elim- inate the separate register-load. I am in- terested in hearing about the difference this makes.
‘-fforce-addr’ Force memory address constants to be copied into registers before doing arithmetic on them. This may produce better code just as ‘-fforce-mem’ may. I am interested in hear- ing about the difference this makes.
‘-fomit-frame-pointer’ Don’t keep the frame pointer in a register for functions that don’t need one. This avoids the instructions to save, set up and restore frame pointers; it also makes an ex- tra register available in many functions. IItt aallssoo mmaakkeess ddeebbuuggggiinngg iimmppoossssiibbllee..
On some machines, such as the Vax, this flag has no effect, because the standard calling sequence automatically handles the frame pointer and nothing is saved by pretending it doesn’t exist. The machine-description macro FRAME_POINTER_REQUIRED controls whether a target machine supports this flag. See sec- tion Registers.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 2211
‘-finline-functions’ Integrate all simple functions into their callers. The compiler heuristically decides which functions are simple enough to be worth integrating in this way. -fno-inline suppresses all inlining of functions, even those that are declared inline.
If all calls to a given function are in- tegrated, then the function is normally not output as assembler code in its own right. Note that in C++, declaring a function to be inline implicitly declares it to be static as well.
‘-fdefault-inline’ If this option is enabled then member func- tions defined inside class scope are compiled inline by default, _i._e., you don’t need to add _i_n_l_i_n_e in front of the member function name. By popular demand, this option is now the default. To keep GNU C++ from inlining these member functions, specify -fno- default-inline.
‘-fcaller-saves’ Enable values to be allocated in registers that will be clobbered by function calls, by emitting extra instructions to save and re- store the registers around such calls. Such allocation is done only when it seems to result in better code than would otherwise be produced.
This option is enabled by default on certain machines, usually those which have no call- preserved registers to use instead.
‘-fkeep-inline-functions’ Even if all calls to a given function are in- tegrated, nevertheless output a separate run-time callable version of the function.
‘-fwritable-strings’ Store string constants in the writable data segment and don’t uniquize them. This is for compatibility with old programs which assume they can write into string constants. Writ- ing into string constants is a very bad idea; “constants” should be constant.
‘-fcond-mismatch’ Allow conditional expressions with mismatched types in the second and third arguments. The
2222 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
value of such an expression is void.
‘-fno-function-cse’ Do not put function addresses in registers; make each instruction that calls a constant function contain the function’s address ex- plicitly.
This option results in less efficient code, but some strange hacks that alter the assem- bler output may be confused by the optimiza- tions performed when this option is not used.
‘-fvolatile’ Consider all memory references through pointers to be volatile.
‘-fshared-data’ Requests that the data and non-const vari- ables of this compilation be shared data rather than private data. The distinction makes sense only on certain operating sys- tems, where shared data is shared between processes running the same program, while private data exists in one copy per process.
‘-funsigned-char’ Let the type char be the unsigned, like un- signed char.
Each kind of machine has a default for what char should be. It is either like unsigned char by default or like signed char by de- fault. (Actually, at present, the default is always signed.)
The type char is always a distinct type from either signed char or unsigned char, even though its behavior is always just like one of those two.
Note that this is equivalent to ‘-fno- signed-char’, which is the negative form of ‘-fsigned-char’.
‘-fsigned-char’ Let the type char be signed, like signed char.
Note that this is equivalent to ‘-fno- unsigned-char’, which is the negative form of ‘-funsigned-char’.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 2233
‘-ffixed-_r_e_g’ Treat the register named _r_e_g as a fixed re- gister; generated code should never refer to it (except perhaps as a stack pointer, frame pointer or in some other fixed role).
_r_e_g must be the name of a register. The re- gister names accepted are machine-specific and are defined in the REGISTER_NAMES macro in the machine description macro file.
This flag does not have a negative form, be- cause it specifies a three-way choice.
‘-fcall-used-_r_e_g’ Treat the register named _r_e_g as an allocat- able register that is clobbered by function calls. It may be allocated for temporaries or variables that do not live across a call. Functions compiled this way will not save and restore the register _r_e_g.
Use of this flag for a register that has a fixed pervasive role in the machine’s execu- tion model, such as the stack pointer or frame pointer, will produce disastrous results.
This flag does not have a negative form, be- cause it specifies a three-way choice.
‘-fcall-saved-_r_e_g’ Treat the register named _r_e_g as an allocat- able register saved by functions. It may be allocated even for temporaries or variables that live across a call. Functions compiled this way will save and restore the register _r_e_g if they use it.
Use of this flag for a register that has a fixed pervasive role in the machine’s execu- tion model, such as the stack pointer or frame pointer, will produce disastrous results.
A different sort of disaster will result from the use of this flag for a register in which function values may be returned.
This flag does not have a negative form, be- cause it specifies a three-way choice.
2244 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
‘-fstrict-prototype’ Consider the declaration int foo ();. In C++, this means that the function foo takes no argu- ments. In ANSI C, this is declared int foo(void);. With the flag ‘-fno-strict- prototype’, declaring functions with no arguments is equivalent to declaring its argument list to be untyped, i.e., int foo (); is equivalent to saying int foo (...);.
‘-felide-constructors’ Using this option instructs the compiler to be smarter about when it can elide constructors. With out this flag, GNU C++ and cfront both gen- erate effectively the same code for:
A foo (); A x (foo ()); // x is initialized by ‘foo ()’, no ctor called here A y = foo (); // call to ‘foo ()’ heads to temporary, // y is initialized from the temporary.
Note the difference! With this flag, GNU C++ ini- tializes ‘y’ directly from the call to ‘foo ()’ without going through a temporary.
‘-fall-virtual’ When the ‘-fall-virtual’ option is used, all member functions (except for constructor functions and new/delete member operators) declared in the same class with a “method-call” operator method have entries made for them in the vtable for the given class. In effect, all of these methods be- come “implicitly virtual.”
This does _n_o_t mean that all calls to these methods will be made through the vtable. There are some circumstances under which it is obvious that a call to a given virtual function can be made directly, and in these cases the calls still go direct.
The effect of making all methods of a class with a declared ‘operator->()()’ implicitly virtual using ‘-fall-virtual’ extends also to all non- constructor methods of any class derived from such a class.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 2255
‘-fthis-is-variable’ The incorporation of user-defined free store management into C++ has made assignment to _t_h_i_s an anachronism. Therefore, by default GNU C++ treats the type of _t_h_i_s in a member function of _c_l_a_s_s _X to be _X *_c_o_n_s_t. In other words, it is illegal to assign to _t_h_i_s within a class member function. However, for backwards compatibility, you can in- voke the old behavior by using ‘-fthis-is- variable’.
‘-fsave-memoized’
‘-fmemoize-lookups’ These flags are of use to get the compiler to com- pile programs faster using heuristics. They are not on by default since they only do so about half the time. They other half of the time programs compile more slowly (and take more memory).
The first time the compiler must build a call to a member function (or reference to a data member), it must (1) determine whether the class implements member functions of that name (2) resolve which member function to call (which involves figuring out what sorts of type conversions need to be made), and (3) check the visibility of the member function to the caller. All of this adds up to slower compilation. Normally, the second time a call is made to that member function (or reference to that data member), it must go through the same lengthy process again. This means that code like this
cout << "This " << p << " has " << n << " legs.\n";
makes six passes through all three steps. By using a software cache, a “hit” significantly reduces this cost. Unfortunately, using the cache intro- duces another layer of mechanisms which must be im- plemented, and so incurrs its own overhead. The ‘-fmemoize-lookups’ enables the software cache.
Because access privileges (visibility) to members and member functions may differ from one function context to the next, may need to be flushed. With the ‘-fmemoize-lookups’ flag, the cache is flushed after every func- tion that is compiled. With the ‘-fsave- memoized’ flag, when the compiler determines that the context of the last function compiled
2266 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
would yield the same access privileges of the next function to compile, it preserves the cache. This really helps when defining many member functions for the same class: with the exception of member functions which are friends of other classes, each member function has exactly the same access privileges as every other, and the cache need not be flushed.
‘-fSOS’ TBA
‘-d_l_e_t_t_e_r_s’ Says to make debugging dumps at times speci- fied by _l_e_t_t_e_r_s. Here are the possible letters:
‘r’ Dump after RTL generation.
‘j’ Dump after first jump optimization.
‘J’ Dump after last jump optimization.
‘s’ Dump after CSE (including the jump optimiza- tion that sometimes follows CSE).
‘L’ Dump after loop optimization.
‘f’ Dump after flow analysis.
‘c’ Dump after instruction combination.
‘l’ Dump after local register allocation.
‘g’ Dump after global register allocation.
‘d’ Dump after delayed branch scheduling.
‘m’ Print statistics on memory usage, at the end of the run.
‘-pedantic’ Attempt to support strict ANSI standard C. Since C++ invalidates a number of ANSI constructions, this switch is of dubious value. Some attempt has been made to warn about non-standard C++ features, however, even this is of uncertain value, as there are two C++ standards currently in existence: the standard as documented by AT&T, and the standard as implemented by the AT&T C++ compiler. Valid C++ programs should compile properly with or without this switch. However, without this
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 2277
switch, certain useful or traditional constructs banned by the standard are supported. With this switch, they are rejected. There is no reason to use this switch; it exists only to satisfy curious pedants.
‘-static’ On Suns running version 4, this prevents linking with the shared libraries. (‘-g’ has the same ef- fect.)
These options control the C preprocessor, which is run on each C source file before actual compilation. If you use the ‘-E’ option, nothing is done except C preprocessing. Some of these options make sense only together with ‘-E’ because they request preprocessor output that is not suit- able for actual compilation.
‘-C’ Tell the preprocessor not to discard comments. Used with the ‘-E’ option.
‘-I_d_i_r’ Search directory _d_i_r for include files.
‘-I-’ Any directories specified with ‘-I’ options before the ‘-I-’ option are searched only for the case of ‘#include "_f_i_l_e"’; they are not searched for ‘#include <_f_i_l_e>’.
If additional directories are specified with ‘-I’ options after the ‘-I-’, these directories are searched for all ‘#include’ directives. (Ordi- narily _a_l_l ‘-I’ directories are used this way.)
In addition, the ‘-I-’ option inhibits the use of the current directory as the first search directo- ry for ‘#include "_f_i_l_e"’. Therefore, the current directory is searched only if it is requested ex- plicitly with ‘-I.’. Specifying both ‘-I-’ and ‘-I.’ allows you to control precisely which direc- tories are searched before the current one and which are searched after.
‘-nostdinc’ Do not search the standard system directories for header files. Only the directories you have specified with ‘-I’ options (and the current directory, if appropriate) are searched.
Between ‘-nostdinc’ and ‘-I-’, you can eliminate all directories from the search path except those
2288 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
you specify.
‘-M’ Tell the preprocessor to output a rule suitable for make describing the dependencies of each source file. For each source file, the preproces- sor outputs one make-rule whose target is the ob- ject file name for that source file and whose dependencies are all the files ‘#include’d in it. This rule may be a single line or may be continued with ‘\’-newline if it is long.
‘-M’ implies ‘-E’.
‘-MM’ Like ‘-M’ but the output mentions only the user- header files included with ‘#include "_f_i_l_e"’. System header files included with ‘#include <_f_i_l_e>’ are omitted.
‘-MM’ implies ‘-E’.
‘-D_m_a_c_r_o’ Define macro _m_a_c_r_o with the empty string as its definition.
‘-D_m_a_c_r_o=_d_e_f_n’ Define macro _m_a_c_r_o as _d_e_f_n.
‘-U_m_a_c_r_o’ Undefine macro _m_a_c_r_o.
‘-T’ Support ANSI C trigraphs. You don’t want to know about this brain-damage. The ‘-ansi’ option also has this effect.
22.. IInnssttaalllliinngg GGNNUU CC++++
Here is the procedure for installing GNU CC on a Unix system.
1. GNU C++ borrows a considerable amount of code from GNU CC. Therefore, you should be familiar (at least a little bit) with the installation pro- cedure of GNU CC. In particular, it is possible to share some object files between the GNU CC and GNU C++. By running “make maketest” and setting the Makefile parameters DIR and TDIR to point to GNU CC source and GNU CC test directories, such sharing will be performed.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 2299
2. Edit ‘Makefile’. If you are using HPUX, or any form of system V, you must make a few changes described in comments at the beginning of the file. Genix requires changes also.
3. On a Sequent system, go to the Berkeley universe.
4. Choose configuration files. The easy way to do this is to run the command file ‘config.g++’ with a single argument, which is the name of the machine (and operating system, in some cases).
Here is a list of the possible arguments:
‘vax’ Vaxes running BSD.
‘vms’ Vaxes running VMS.
‘vax-sysv’ Vaxes running system V.
‘i386-sysv’ Intel 386 PCs running system V.
‘i386-sysv-gas’ Intel 386 PCs running system V, using the GNU assembler and GNU linker.
‘sequent-i386’ Sequent with Intel 386 processors.
‘sun2’ Sun 2 running system version 2 or 3.
‘sun3’ Sun 3 running system version 2 or 3, with 68881.
‘sun3-nfp’ Sun 3 running system version 2 or 3, without 68881.
‘sun3-fpa’ Sun 3 running system version 2 or 3, with 68881 and fpa.
‘sun4’ Sun 4 running system version 2 or 3.
‘sun2-os4’ Sun 2 running system version 4.
3300 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
‘sun3-os4’ Sun 3 running system version 4, with 68881.
‘sun3-nfp-os4’ Sun 3 running system version 4, without 68881.
‘sun3-fpa-os4’ Sun 3 running system version 4, with 68881 and fpa.
‘sun4-os4’ Sun 4 running system version 4.
‘sun386’ Sun 386 (“roadrunner”).
‘alliant’ Alliant FX/8 computer. Currently, there are bugs in the support for floating point. Also note that Alliant’s version of dbx does not manage to work with the output from GNU CC.
‘convex-c1’ Convex C1 computer.
‘convex-c2’ Convex C2 computer.
‘hp9k320’ HP 9000 series 300 using HPUX assembler.
‘hp9k320g’ HP 9000 series 300 using GNU assembler, link- er and debugger. This requires the HP-adapt package which is or will soon be available along with the linker.
‘isi68’ ISI 68000 or 68020 system.
‘news800’ Sony NEWS 68020 system.
‘next’ NeXT system.
‘3b1’ AT&T 3b1, a.k.a. 7300 PC.
‘sequent-ns32k’ Sequent containing ns32000 processors.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 3311
‘encore’ Encore ns32000 system.
‘genix’ National Semiconductor ns32000 system.
‘88000’ Motorola 88000 processor. This port is not finished.
Here we spell out what files need to be set up:
Make a symbolic link named ‘config.h’ to the top-level config file for the machine you are using (see section Config). This file is responsible for defining information about the host machine. It includes ‘tm.h’.
The file’s name should be ‘xm-_m_a_c_h_i_n_e.h’, with these exceptions:
‘xm-vms.h’ for vaxen running VMS.
‘xm-vaxv.h’ for vaxen running system V.
‘xm-i386v.h’ for Intel 80386’s running system V.
‘xm-sunos4.h’ for Suns (model 2, 3 or 4) running _o_p_e_r_a_t_i_n_g _s_y_s_t_e_m version 4. (Use ‘xm- m68k.h’ or ‘xm-sparc.h’ for version 3.)
‘xm-sun386i.h’ for Sun roadrunner running any version of the operating system.
‘xm-hp9k320.h’ for the HP 9000 series 300.
‘xm-genix.h’ for the ns32000 running Genix
If your system does not support symbolic links, you might want to set up ‘config.h’ to contain a ‘#include’ command which refers to the appropriate file.
Make a symbolic link named ‘tm.h’ to the machine-description macro file for your
3322 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
machine (its name should be ‘tm-_m_a_c_h_i_n_e.h’).
TThhiiss ppaarrtt ooff tthhee iinnssttaallllaattiioonn pprroocceedduurree iiss ddiiffffeerreenntt tthheenn ffoorr GGNNUU CCCC
GNU C++ may need to perform special initiali- zation before ‘main’ is logically called. It may also need to perform special cleanups after ‘exit’ is logically called. There are many ways this can be accomplished, and be- cause not all GNU tools have been ported to all platforms, there is not a uniform way of doing this.
The simplest (and best) way to accomplish these special tasks is to use GNU C++ in con- cert with the GNU assembler and the GNU link- er. If these programs have been ported to your machine, use them. GAS version 1.34 or later is sufficient, and the GNU linker dis- tributed with GNU C++ is also guaranteed to be current enough to work. Make sure that these programs are installed where GNU C++ will find them (i.e., logically adjacent to ‘cc1plus’). If these programs have not been ported to your machine, you have to worry about the rest of this section, which is very complicated.
The GNU C++ compiler, without the help of GAS and GLD, must use its own ‘crt0.c’, which, for purposes of disambiguation, will be re- ferred to as ‘crt0+.o’. To use the ‘crt0+.o’, it may be necessary to modify the file ‘tm.h’ to link with ‘crt0+.o’ rather than ‘crt0.o’. If the file ‘tm.h’ for your machine does not define a STARTFILE_SPEC then you must make this modification in the file ‘gcc.c’, which is used to make the compiler driver ‘g++’.
If your system is a Sun3 or Sun4, you should not be reading this. If your system is a Sun386i, you will notice that ‘tm-sun386i.h’ defines a STARTFILE_SPEC. Therefore, you should copy ‘tm-sun386i.h’ to ‘tm- sun386i+.h’, and then edit ‘tm-sun386i+.h’ to link in ‘crt0+.o’ instead of ‘crt0.o’.
The shell script ‘config.g++’ tries to per- form this editing for you. However, it is not very smart, and loses if one ‘tm’ file includes another, and does not specify a STARTFILE_SPEC when the included one does.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 3333
In this case, you should copy the link spec from the included file to the ‘tm’ file you are interested in, taking care to put ‘#undef STARTFILE_SPEC’ before you ‘#define STARTFILE_SPEC’ if you want to avoid warnings from the preprocessor.
{end of differences
If your system is a 68000, don’t use the file ‘tm-m68k.h’ directly. Instead, use one of these files as a starting point:
‘tm-sun3.h’ for Sun 3 machines with 68881.
‘tm-sun3-fpa.h’ for Sun 3 machines with floating point accelerator.
‘tm-sun3-nfp.h’ for Sun 3 machines with no hardware floating point.
‘tm-sun2.h’ for Sun 2 machines.
‘tm-3b1.h’ for AT&T 3b1 (aka 7300 Unix PC).
‘tm-isi68.h’ for Integrated Solutions systems. This file assumes you use the GNU assembler.
‘tm-news800.h’ for SONY News systems.
‘tm-hp9k320.h’ for HPUX systems, if you are using GNU CC with the system’s assembler and link- er.
‘tm-hp9k320g.h’ for HPUX systems, if you are using the GNU assembler, linker and other utili- ties. Not all of the pieces of GNU software needed for this mode of opera- tion are as yet in distribution; full instructions will appear here in the fu- ture.
For the vax, use ‘tm-vax.h’ on BSD Unix, ‘tm-vaxv.h’ on system V, or ‘tm-vms.h’ on
3344 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
VMS.
For the Motorola 88000, use ‘tm-m88k.h’. The support for the 88000 has a few unfinished spots because there was no way to run the output. Bugs are suspected in handling of branch-tables and in the function prologue and epilogue.
For the 80386, don’t use ‘tm-i386.h’ direct- ly. Use ‘tm-i386v.h’ if the target machine is running system V, ‘tm-i386gas.h’ if it is running system V but you are using the GNU assembler and linker, ‘tm-seq386.h’ for a Sequent 386 system, or ‘tm-compaq.h’ for a Compaq, or ‘tm-sun386i.h’ for a Sun 386 sys- tem.
For the 32000, use ‘tm-sequent.h’ if you are using a Sequent machine, or ‘tm-encore.h’ for an Encore machine, or ‘tm-genix.h’ if you are using Genix version 3; otherwise, perhaps ‘tm-ns32k.h’ will work for you.
Note that Genix has bugs in alloca and mal- loc; you must get the compiled versions of these from GNU Emacs and edit GNU CC’s ‘Makefile’ to use them.
Note that Encore systems are supported only under BSD.
For Sparc (Sun 4) machines, use ‘tm-sparc.h’ with operating system version 4, and ‘tm- sun4os3.h’ with system version 3.
Make a symbolic link named ‘md’ to the machine description pattern file. Its name should be ‘_m_a_c_h_i_n_e.md’, but _m_a_c_h_i_n_e is often not the same as the name used in the ‘tm.h’ file because the ‘md’ files are more general.
Make a symbolic link named ‘aux-output.c’ to the output subroutine file for your machine (its name should be ‘output-_m_a_c_h_i_n_e.c’).
5. Make sure the Bison parser generator is installed. (This is unnecessary if the Bison output files ‘c-parse.tab.c’ and ‘cexp.c’ are more recent than ‘c-parse.y’ and ‘cexp.y’ and you do not plan to change the ‘.y’ files.)
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 3355
Bison versions older that May 8, 1989 (version 1.01) will produce incorrect output for ‘c- parse.tab.c’. If your bison does not understand the ‘-version’ flag, it is too old.
6. If you are using a Sun, make sure the environment variable FLOAT_OPTION is not set. If this option were set to f68881 when ‘gnulib’ is compiled, the resulting code would demand to be linked with a special startup file and will not link properly without special pains.
7. Build the compiler. Just type ‘make’ in the com- piler directory.
Ignore any warnings you may see about “statement not reached” in the ‘insn-emit.c’; they are nor- mal. Any other compilation errors may represent bugs in the port to your machine or operating sys- tem, and should be investigated and reported (see section Bugs).
8. If you are using COFF-encapsulation, you must con- vert ‘gnulib’ to a GNU-format library at this point. See the file ‘README-ENCAP’ in the direc- tory containing the GNU binary file utilities, for directions.
9. Move the first-stage object files and executables into a subdirectory with this command:
make stage1
The files are moved into a subdirectory named ‘stage1’. Once installation is complete, you may wish to delete these files with rm -r stage1.
10. Recompile the compiler with itself, with this command:
make CC=stage1/gcc CFLAGS="-g -O -Bstage1/"
On a 68000 or 68020 system lacking floating point hardware, unless you have selected a ‘tm.h’ file that expects by default that there is no such hardware, do this instead:
3366 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
make CC=stage1/gcc CFLAGS="-g -O -Bstage1/ -msoft-float"
11. If you wish to test the compiler by compiling it with itself one more time, do this:
make stage2 make CC=stage2/gcc CFLAGS="-g -O -Bstage2/" foreach file (*.o) cmp $file stage2/$file end
This will notify you if any of these stage 3 object files differs from those of stage 2. Any difference, no matter how innocuous, indi- cates that the stage 2 compiler has compiled GNU CC incorrectly, and is therefore a poten- tially serious bug which you should investi- gate and report (see section Bugs).
Aside from the ‘-B’ option, the options should be the same as when you made stage 2.
12. Install the compiler driver, the compiler’s passes and run-time support. You can use the following command:
make install
This copies the files ‘cc1’, ‘cpp’ and ‘gnulib’ to files ‘gcc-cc1’, ‘gcc-cpp’ and ‘gcc-gnulib’ in directory ‘/usr/local/lib’, which is where the com- piler driver program looks for them. It also copies the driver program ‘gcc’ into the directory ‘/usr/local/bin’, so that it appears in typical ex- ecution search paths.
WWaarrnniinngg:: tthheerree iiss aa bbuugg iinn alloca iinn tthhee SSuunn lliibbrraarryy.. TToo aavvooiidd tthhiiss bbuugg,, iinnssttaallll tthhee bbiinnaarriieess ooff GGNNUU CCCC tthhaatt wweerree ccoommppiilleedd bbyy GGNNUU CCCC.. TThheeyy uussee alloca aass aa bbuuiilltt--iinn ffuunnccttiioonn aanndd nneevveerr tthhee oonnee iinn tthhee lliibbrraarryy..
WWaarrnniinngg:: tthhee GGNNUU CCPPPP mmaayy nnoott wwoorrkk ffoorr ‘ioctl.h’,, ‘ttychars.h’ aanndd ootthheerr ssyysstteemm hheeaaddeerr ffiilleess uunnlleessss tthhee ‘-traditional’ ooppttiioonn
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 3377
iiss uusseedd.. The bug is in the header files: at least on some machines, they rely on behavior that is incompatible with ANSI C. This behavior consists of substituting for macro argument names when they appear inside of character constants. The ‘-traditional’ op- tion tells GNU CC to behave the way these headers expect.
Because of this problem, you might prefer to configure GNU CC to use the system’s own C preprocessor. To do so, make the file ‘/usr/local/lib/gcc-cpp’ a link to ‘/lib/cpp’.
Alternatively, on Sun systems and 4.3BSD at least, you can correct the include files by running the shell script ‘fixincludes’. This installs modified, corrected copies of the files ‘ioctl.h’, ‘ttychars.h’ and many others, in a special directory where only GNU CC will normally look for them. This script will work on various systems because it chooses the files by searching all the system headers for the problem cases that we know about.
If you cannot install the compiler’s passes and run-time support in ‘/usr/local/lib’, you can alternatively use the ‘-B’ option to specify a prefix by which they may be found. The compiler concatenates the prefix with the names ‘cpp’, ‘cc1’ and ‘gnulib’. Thus, you can put the files in a directory ‘/usr/foo/gcc’ and specify ‘-B/usr/foo/gcc/’ when you run GNU CC.
Also, you can specify an alternative default directory for these files by setting the Make variable libdir when you make GNU CC.
Note: the modified GNU linker which is distri- buted with GNU C++ does not yet work on the Sequent. This is because it uses non-standard ‘a.out.h’ format (in order to handle shared vs. private text and data). When building the compiler driver ‘g++’, be sure to define NO_GNU_LD.
For the vax, use ‘tm-vax.h’ on BSD Unix. VMS is not yet supported.
13. Make sure the Bison parser generator is in- stalled. (This is unnecessary if the Bison output file ‘parse.tab.c’ is more recent than ‘parse.y’ and you do not plan to change
3388 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
‘parse.y’.)
Note that if you have an old version of Bison you may get an error from the line with the ‘%expect’ directive. If so, simply remove that line from ‘parse.y’ and proceed.
The C++ grammar is inherently ambiguous. Given enough left and right context, a recursive-descent parser will often be able to guess the user’s intentions when analyzing a piece of code. GNU C++ is implemented using a simple LALR parser which does not have backup and restart capabilities. As a result, it cannot handle some of the harder cases of C++ syntax. Fortunately, the real problems only occur when trying to maintain backwards compa- tibility. When making the GNU C++ parser you will notice a message from BISON (or YACC) that the grammar contains reduce/reduce con- flicts. For now, that is the way it is. For more details, see the Projects (See section Projects) section.
The compiler you have just built is now ready to run. This compiler does not bootstrap it- self. It is written in C, which is not compa- tible with its implementation of C++. There- fore, there is no need to try to bootstrap it. The main incompatibility is that C-style func- tion definitions, such as int f (a, b) int a, b; are beyond the grasp of GNU C++. Currently, functions mmuusstt be declared, e.g., int f (int a, int b). Otherwise, the com- piler may abort.
14. Install the compiler’s passes and run-time support.
Copy or link the file ‘cc1plus’ made by the compiler to the name ‘/usr/local/lib/gcc- cc1plus’.
Copy or link the file ‘gnulib’ made by the original compilation of GNU GCC to the name ‘/usr/local/lib/gcc-gnulib’. This file is in- cluded automatically when GNU C++ runs the linker.
Make the file ‘/usr/local/lib/gcc-cpp’ either a link to ‘/lib/cpp’ or a link to or copy of the file ‘cpp’ generated by ‘make’.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 3399
WWaarrnniinngg:: tthhee GGNNUU CCPPPP mmaayy nnoott wwoorrkk ffoorr ‘ioctl.h’,, ‘ttychars.h’ aanndd ootthheerr ffiilleess.. This cannot be fixed in the GNU CPP because the bug is in the include files: at least on some machines, they rely on behavior that is incom- patible with ANSI C. This behavior consists of substituting for macro argument names when they appear inside of character constants.
Because of this problem, you might prefer to configure GNU CC to use the system’s own C preprocessor. To do so, make the file ‘/usr/local/lib/gcc-cpp’ a link to ‘/lib/cpp’. This will leave C++-style comments (which be- gin with //) in the output, but the compiler will scan past them.
Alternatively, on Sun systems and 4.3BSD at least, you can correct the include files by running the shell script ‘fixincludes’. This installs modified, corrected copies of the files ‘ioctl.h’ and ‘ttychars.h’ in a special directory where only GNU C++ will normally look for them.
The file ‘/usr/include/vaxuba/qvioctl.h’ used in the X window system needs a similar correc- tion.
15. Install the compiler driver. This is the file ‘g++’ generated by ‘make’.
If you cannot install the compiler’s passes and run- time support in ‘/usr/local/lib’, you can alternatively use the ‘-B’ option to specify a prefix by which they may be found. The compiler concatenates the prefix with the names ‘cpp’, ‘cc1plus’ and ‘gnulib’. Thus, you can put the files in a directory ‘/usr/foo/g++’ and specify ‘-B/usr/foo/g++/’ when you run GNU C++.
If you wish to make use of the GNU C++ libraries, install the header files found in the directory ‘dist- libg++-1.36.2/g++-include’ in a directory which cpp knows to search. By default, this is the directory ‘/usr/local/lib/g++-include’. Once these header files are installed, go to the directory ‘dist-libg++/src’ and just type "make". This will make the library ‘libg++.a’ which can then be copied to the directory /usr/lib. After copying the library, remember to run ranlib on ‘libg++.a’ to avoid getting a “library contents out of date” warning from the linker.
4400 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
33.. TTrroouubbllee iinn IInnssttaallllaattiioonn
Here are some of the things that have caused trouble for people installing or using GNU C++.
Using header files straight from ‘/usr/include’ with GNU C++ will cause problems unless those header files contain fully-prototyped function de- clarations. A set of common header files are dis- tributed with the GNU C++ library. These should be installed in a directory which the GNU C++ preprocessor can find them (such as ‘/usr/local/lib/g++-include’).
Using AT&T 1.2 header files (from ‘/usr/include/CC’ with GNU C++ may cause more trouble than they are worth. They assume that external linkage is performed in an obsolete way (first function definition gets C linkage, subse- quent ones get mangled). GNU C++ now implements 2.0 “name mangling” semantics, which means that all functions defined in C++ scope are overloaded, and no functions defined in C scope are overload- ed. If you get system functions as being unde- fined, and you used the AT&T 1.2 header files, you should remove the AT&T header files from your search path.
On certain systems, defining certain environment variables such as ‘CC’ can interfere with the functioning of make.
Cross compilation can run into trouble for certain machines because some target machines’ assemblers require floating point numbers to be written as _i_n_t_e_g_e_r constants in certain contexts.
The compiler writes these integer constants by ex- amining the floating point value as an integer and printing that integer, because this is simple to write and independent of the details of the float- ing point representation. But this does not work if the compiler is running on a different machine with an incompatible floating point format, or even a different byte-ordering.
In addition, correct constant folding of floating point values requires representing them in the target machine’s format. (The C standard does not quite require this, but in practice it is the only way to win.)
It is now possible to overcome these problems by defining macros such as REAL_VALUE_TYPE. But do-
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 4411
ing so is a substantial amount of work for each target machine. See section Cross-compilation.
DBX rejects some files produced by GNU CC, though it accepts similar constructs in output from PCC. Until someone can supply a coherent description of what is valid DBX input and what is not, there is nothing I can do about these problems. You are on your own.
44.. GGNNUU CC++++ HHeeaaddeerr FFiilleess aanndd LLiibbrraarriieess
The GNU C++ compiler is a program which translates C++ code into the assembly language of a given machine. As such, it may be said that GNU C++ iimmpplleemmeennttss the C++ pro- gramming language for that machine. However, most users are accustomed to a certain amount of support beyond the bare language itself. A set of header files are provided which simplify interfacing GNU C++ code with C and UNIX routines. These header files are needed to solve the following two problems.
First, while it is optional in C to declare a function like ‘printf’ before using it, in GNU C++, failure to do so results in a warning, whether or not the ‘-Wall’ option is envoked. Second, in C the declaration int atoi() declares that ‘atoi’ is a function returning an int, while in GNU C++ that declaration would mean that function ‘atoi’ _t_a_k_e_s _n_o _a_r_g_u_m_e_n_t_s and returns an int. Consequently, the following call
int i = atoi ("20");
would be tagged as an error in GNU C++ (unless the user specified the flag ‘-fno-strict-prototype’ See section Options). The header files provided in the GNU C++ distri- bution provide appropriate declarations for many of the most frequently used functions. In the cases where a GNU C++ header file has the same name as a standard C header file (such as ‘stdio.h’), that header file should take precedence over the C version. This can be ensured by placing the GNU C++ header files in a directory which is always searched _b_e_f_o_r_e the standard directories, such as ‘/usr/include’.
As of release 1.35.0, the extern "C" and extern "C++" constructs are supported. This means that if you want to include a C header file, and you want it to Do The Right Thing, all you have to do is this:
4422 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
extern "C" { #include <dusty.h>
However, life is not always so simple. For example, the file ‘dusty.h’ may include ‘shiny.h’, which has been recently polished, and rewritten in C++. In this case, unless ‘shiny.h’ is wrapped with extern "C++", then all its scoping rules will be wrong: structure tags won’t automati- cally go into the identifier name space, functions are not overloadable, let alone automatically overloadable, and the compiler will gripe at constructs unique to C++.
Descriptions of the libg++ classes support files are provided in a separate document which comes with the GNU C++ library.
55.. IInnccoommppaattiibbiilliittiieess ooff GGNNUU CC++++
There are several noteworthy incompatibilities between GNU C++ and most versions of C++ and/or C.
Ultimately our intention is that the ‘-traditional’ option will eliminate all the incompatibilities that can be eliminated by telling GNU C++ to behave like the other C++/C compiler combinations.
GNU C++ normally makes string constants read-only. If several identical-looking string constants are used, GNU C++ stores only one copy of the string.
One consequence is that you cannot call mktemp with a string constant argument. The function mktemp always alters the string its argument points to.
Another consequence is that sscanf does not work on some systems when passed a string constant as its format control string. This is because sscanf incorrectly tries to write into the string con- stant.
The best solution to these problems is to change the program to use char-array variables with ini- tialization strings for these purposes instead of string constants. But if this is not possible, you can use the ‘-fwritable-strings’ flag, which directs GNU CC to handle string constants the same way most C compilers do.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 4433
GNU C++ does not substitute macro arguments when they appear inside of string constants. For exam- ple, the following macro in GNU C++
#define foo(a) "a"
will produce output ‘"a"’ regardless of what the argument _a is.
The ‘-traditional’ option directs GNU C++ to handle such cases (among others) in the old- fashioned (non-ANSI) fashion.
When you use setjmp and longjmp, the only au- tomatic variables guaranteed to remain valid are those declared volatile. This is a conse- quence of automatic register allocation. Con- sider this function:
jmp_buf j;
foo () { int a, b;
a = fun1 (); if (setjmp (j)) return a;
a = fun2 (); /* longjmp (j) may be occur in fun3. */ return a + fun3 ();
Here a may or may not be restored to its first value when the longjmp occurs. If a is allo- cated in a register, then its first value is restored; otherwise, it keeps the last value stored in it.
If you use the ‘-W’ option with the ‘-O’ op- tion, you will get a warning when GNU C++ thinks such a problem might be possible.
The ‘-traditional’ option directs GNU C++ to put variables in the stack by default, rather than in registers, in functions that call setjmp. This results in the behavior found in
4444 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
traditional C compilers.
Declarations of external variables and func- tions within a block apply only to the block containing the declaration. In other words, they have the same scope as any other declara- tion in the same place.
In some other C++/C compiler systems, a extern declaration affects all the rest of the file even if it happens within a block.
The ‘-traditional’ option directs GNU C++ to treat all extern declarations as global, like traditional compilers.
In traditional C, you can combine long, etc., with a typedef name, as shown here:
typedef int foo; typedef long foo bar;
In ANSI C, this is not allowed: long and other type modifiers require an explicit int. Be- cause this criterion is expressed by Bison grammar rules rather than C code, the ‘- traditional’ flag cannot alter it.
PCC allows typedef names to be used as func- tion parameters. The difficulty described im- mediately above applies here too.
PCC allows whitespace in the middle of com- pound assignment operators such as ‘+=’. GNU C++, following the ANSI standard, does not al- low this. The difficulty described immediate- ly above applies here too.
GNU C++ will flag unterminated character con- stants inside of preprocessor conditionals that fail. Some programs have English com- ments enclosed in conditionals that are guaranteed to fail; if these comments contain apostrophes, GNU C++ will probably report an error. For example, this code would produce an error:
#if 0 You can’t expect this to work. #endif
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 4455
The best solution to such a problem is to put the text into an actual C comment delimited by ‘/*...*/’. However, ‘-traditional’ suppresses these error messages.
When compiling functions that return float, PCC converts it to a double. GNU CC actually returns a float. If you are concerned with PCC compatibility, you should declare your functions to return double; you might as well say what you mean.
When compiling functions that return struc- tures or unions, GNU C++ output code uses a method different from that used on most ver- sions of Unix. As a result, code compiled with GNU C++ cannot call a structure-returning function compiled with PCC, and vice versa.
The method used by GNU C++ is as follows: a structure or union which is 1, 2, 4 or 8 bytes long is returned like a scalar. A structure or union with any other size is stored into an address supplied by the caller in a special, fixed register. (Structures which have con- structors are passed by value via the special register, regardless of their size.)
PCC usually handles all sizes of structures and unions by returning the address of a block of static storage containing the value. This method is not used in GNU C++ because it is slower and nonreentrant.
On systems where PCC works this way, you may be able to make GNU C++-compiled code call such functions that were compiled with PCC by declaring them to return a pointer to the structure or union instead of the structure or union itself. For example, instead of this:
struct foo nextfoo ();
write this:
struct foo *nextfoo (); #define nextfoo *nextfoo
4466 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
(Note that this assumes you are using the GNU preprocessor, so that the ANSI antirecursion rules for macro expansions are effective.)
Member functions which are declared in the scope of a class declaration are implicitly declared inline in C++. In GNU C++, the in- line declaration must be explicitly specified in order to take effect. This makes it possi- ble to keep functions from being integrated without changing a great deal of code (there is no noinline specifier). If you want func- tions to be inlined as much as possible, use the -finline-functions flag.
I am considering reversing the polarity of this option, and providing a -fno-default- inline-functions flag. I am interested in hearing what people think about this.
The naming convention of GNU C++ and AT&T C++ for overloaded functions (and member func- tions) are incompatible. You cannot use AT&T C++ libraries with GNU C++. Even if the same naming convention were used, you still would not want to use libraries compiled by the AT&T compiler. Because the AT&T compiler is con- strained to generate C code, there are some things it cannot implement, such as the way GNU C++ passes objects constructed on the stack. GNU C++ can also make most virtual function calls take one or two memory refer- ences, while the AT&T compiler must make 5 or 6 memory references to do the same thing. This efficiency has its cost: if you want to link with AT&T code, compile it with GNU C++.
For those of you without access to AT&T’s li- brary source code, you may not miss it at all. The GNU C++ library is bigger and better than ever. It implements all the standard classes (such as istream and ostream), and a multitude of other ones: many more than is available from the AT&T library. See the documentation in the libg++ distribution for details.
The ANSI draft stipulates an interpretation for items declared const which is incompatible with C++. GNU C++ makes an attempt to support both interpretations, using a flag to select between them. Currently, GNU C++ does not fully support the C++ interpretation of const.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 4477
To have the effect of declaring a variable value constant, you must specify static for that variable. Otherwise, it is unclear whether storage should be reserved for that variable, as well as how that variable should be initialized. It is hoped that these issues will be resolved in a satisfactory way in the future.
The syntactic form xyzzy lose(frob); where xyzzy is an aggregate type and frob is an object of that type, is a declaration of a new aggregate object lose. Under AT&T C++, this interpretation could lead to the calling of a constructor if one exists for that argu- ment list, or it could have the equivalent meaning of the form xyzzy lose = frob discouraged.
The dual of this case is even more bizarre: the syntactic form xyzzy lose = frob; is a declaration, and hence lose receives the value of frob via initialization semantics. If there is no constructor defined for xyzzy, then initialization semantics and assignment semantics are equivalent. But, if there is a constructor for xyzzy, but one which does not take something of lose’s type, then cfront 1.2 initializes with assignment semantics. GNU C++ emits an error message in this case.
The design of the C++ programming language did not take into account the usefulness of being able to specify that language using an LALR(1) grammar. As a result, in order to correctly parse C++, one needs a look-ahead lexical analyzer (with infinite lookahead), and a re- cursive descent parser, guided by some good heuristics. This approach was not taken in GNU C++, because it is considered archaic, no- toriously difficult to extend syntactically, and generally offensive. GNU C++ uses an LALR(1) grammar so that users can easily understand, and readily modify the compiler to suit their needs. Free software is useless if it becomes captive to an inaccessible or un- desirable technology.
Some syntactic forms were lost by utilizing an LALR(1) grammar, however. Most notably old- style C function declarations and function parameters and local variables that are de- clared longhand to be pointers to functions are not recognized properly (note that GNU C++
4488 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
_c_a_n grok pointer-to-function casts, for exam- ple, (void (*)())0 is parsed correctly). The first problem is solved by converting old- style C code to the ANSI-standard function prototype form. The second problem can always be solved by using a typedef for the pointer to function, and working from there. Another hack which can be used, if the parameter can legitimately be declared with a storage class (such as ‘register’, or ‘auto’) is to make that storage class explicit: int f (register int (*pf)(int,int)) {...
In addition to the syntactic problems mentioned above, the C++ language suffers from another deficiency due to its layering on top of C. When a function is declared over- loaded, some or all variants of that function must be renamed in order that they not conflict. The way that the AT&T C++ compiler accomplishes this is by not renaming the first function, but overloading all subsequent functions. As a result, when the first function declared in one compi- lation module is not the first such one declared in all other compilation modules, the AT&T C++ compiler may gen- erate incorrect calls, or function definitions may conflict at link time. The GNU C++ compiler avoids this problem by renaming all overloaded functions. This happens to be the way that cfront 2.0 will handle things.
As distributed, functions are now by default automati- cally overloaded, in conformance with the C++ 2.0 language specification. The main reason you might {\em not want this behavior is debugging: GDB does not yet understand overloaded functions. We are working on this deficiency.
In the case where functions are not automatically over- loaded (e.g., a compiler compiled with -DNO_AUTO_OVERLOAD), note that declaring a function as friend has the hidden feature of declaring the function overloaded as well. How- ever, this has the negative feature that when a function is declared, and then subsequently declared as a ‘friend’ (or is otherwise overloaded), the function will end up being inconsistently declared. There is really no way around this problem except to be very careful when using overloaded functions. In GNU C++, all functions which are intended to be friend functions should be declared overloaded before they are declared friends. Or bite the bullet, fix GDB, and overload everything by default.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 4499
66.. GGNNUU EExxtteennssiioonnss ttoo tthhee CC++++ LLaanngguuaaggee
GNU C++ provides several language features not found in either ANSI standard C or in AT&T’s C++. Many of these features are also available with the GNU C compiler. (The ‘-pedantic’ switch directs GNU C++ to print a warning mes- sage if any of these features is used.) To check for the availability of these features, check for predefined macros __GNUC__ or __GNUG__, which is always defined under GNU C++.
66..11.. SSttaatteemmeennttss aanndd DDeeccllaarraattiioonnss iinnssiiddee ooff EExxpprreessssiioonnss
A compound statement in parentheses may appear inside an expression in GNU C++. This allows you to declare vari- ables within an expression. For example:
({ int y = foo (); int z; if (y > 0) z = y; else z = - y; z; )
is a valid (though slightly more complex than necessary) expression for the absolute value of foo ().
This feature is especially useful in making macro definitions “safe” (so that they evaluate each operand exactly once). For example, the “maximum” function is commonly defined as a macro in standard C as follows:
#define max(a,b) ((a) > (b) ? (a) : (b))
But this definition computes either _a or _b twice, with bad results if the operand has side effects. In GNU C++, if you know the type of the operands (here let’s assume int), you can define the macro safely as follows:
#define maxint(a,b) \ ({int _a = (a), _b = (b); _a > _b ? _a : _b; )
Embedded statements are not allowed in constant expres- sions, such as the value of an enumeration constant, the width of a bit field, or the initial value of a static vari- able.
5500 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
If you don’t know the type of the operand, you can still do this, but you must use typeof (see section Typeof) or type naming (see section Naming Types).
66..22.. NNaammiinngg aann EExxpprreessssiioonn’’ss TTyyppee
You can give a name to the type of an expression using a typedef declaration with an initializer. Here is how to define _n_a_m_e as a type name for the type of _e_x_p:
typedef _n_a_m_e = _e_x_p;
This is useful in conjunction with the statements- within-expressions feature. Here is how the two together can be used to define a safe “maximum” macro that operates on any arithmetic type:
#define max(a,b) \ ({typedef _ta = (a), _tb = (b); \ _ta _a = (a); _tb _b = (b); \ _a > _b ? _a : _b; )
The reason for using names that start with underscores for the local variables is to avoid conflicts with variable names that occur within the expressions that are substituted for a and b. Eventually we hope to design a new form of declaration syntax that allows you to declare variables whose scopes start only after their initializers; this will be a more reliable way to prevent such conflicts.
66..33.. RReeffeerrrriinngg ttoo aa TTyyppee wwiitthh typeof
Another way to refer to the type of an expression is with typeof. The syntax of using of this keyword looks like sizeof, but the construct acts semantically like a type name defined with typedef.
There are two ways of writing the argument to typeof: with an expression or with a type. Here is an example with an expression:
typeof (x[0](1))
This assumes that x is an array of functions; the type described is that of the values of the functions.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 5511
Here is an example with a typename as the argument:
typeof (int *)
Here the type described is that of pointers to int.
A typeof-construct can be used anywhere a typedef name could be used. For example, you can use it in a declara- tion, in a cast, or inside of sizeof or typeof.
This declares y with the type of what x points to.
typeof (*x) y;
This declares y as an array of such values.
typeof (*x) y[4];
This declares y as an array of pointers to characters:
typeof (typeof (char *)[4]) y;
It is equivalent to the following traditional C de- claration:
char *y[4];
To see the meaning of the declaration using typeof, and why it might be a useful way to write, let’s rewrite it with these macros:
#define pointer(T) typeof(T *) #define array(T, N) typeof(T [N])
5522 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
Now the declaration can be rewritten this way:
array (pointer (char), 4) y;
Thus, ‘array (pointer (char), 4)’ is the type of arrays of 4 pointers to char.
66..44.. GGeenneerraalliizzeedd LLvvaalluueess
Compound expressions, conditional expressions and casts are allowed as lvalues provided their operands are lvalues. This means that you can take their addresses or store values into them.
For example, a compound expression can be assigned, provided the last expression in the sequence is an lvalue. These two expressions are equivalent:
(a, b) += 5 a, (b += 5)
Similarly, the address of the compound expression can be taken. These two expressions are equivalent:
&(a, b) a, &b
A conditional expression is a valid lvalue if its type is not void and the true and false branches are both valid lvalues. For example, these two expressions are equivalent:
(a ? b : c) = 5 (a ? b = 5 : (c = 5))
A cast is a valid lvalue if its operand is valid. Tak- ing the address of the cast is the same as taking the address without a cast, except for the type of the result. For example, these two expressions are equivalent (but the second may be valid when the type of ‘a’ does not permit a cast to ‘int *’).
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 5533
&(int *)a (int **)&a
A simple assignment whose left-hand side is a cast works by converting the right-hand side first to the speci- fied type, then to the type of the inner left-hand side expression. After this is stored, the value is converter back to the specified type to become the value of the assignment. Thus, if ‘a’ has type ‘char *’, the following two expressions are equivalent:
(int)a = 5 (int)(a = (char *)5)
An assignment-with-arithmetic operation such as ‘+=’ applied to a cast performs the arithmetic using the type resulting from the cast, and then continues as in the previ- ous case. Therefore, these two expressions are equivalent:
(int)a += 5 (int)(a = (char *) ((int)a + 5))
66..55.. CCoonnddiittiioonnaall EExxpprreessssiioonnss wwiitthh OOmmiitttteedd MMiiddddllee--OOppeerraannddss
The middle operand in a conditional expression may be omitted. Then if the first operand is nonzero, its value is the value of the conditional expression.
Therefore, the expression
x ? : y
has the value of x if that is nonzero; otherwise, the value of y.
This example is perfectly equivalent to
x ? x : y
5544 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
In this simple case, the ability to omit the middle operand is not especially useful. When it becomes useful is when the first operand does, or may (if it is a macro argument), contain a side effect. Then repeating the operand in the middle would perform the side effect twice. Omitting the middle operand uses the value already computed without the undesirable effects of recomputing it.
66..66.. AArrrraayyss ooff LLeennggtthh ZZeerroo
Zero-length arrays are allowed in GNU C++. They are very useful as the last element of a structure which is really a header for a variable-length object:
struct line { int length; char contents[0]; ;
{ struct line *thisline = (struct line *) malloc (sizeof (struct line) + this_length); thisline->length = this_length;
In standard C, you would have to give contents a length of 1, which means either you waste space or complicate the argument to malloc.
66..77.. AArrrraayyss ooff VVaarriiaabbllee LLeennggtthh
Variable-length automatic arrays are allowed in GNU C++. These arrays are declared like any other automatic arrays, but with a length that is not a constant expression. The storage is allocated at that time and deallocated when the brace-level is exited. For example:
FILE *concat_fopen (char *s1, char *s2, char *mode) { char str[strlen (s1) + strlen (s2) + 1]; strcpy (str, s1); strcat (str, s2); return fopen (str, mode);
Currently, you cannot use variable-length arrays as arguments to functions, due to the implementation of the parser.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 5555
The length of an array is computed on entry to the brace-level where the array is declared and is remembered for the scope of the array in case you access it with sizeof.
Jumping or breaking out of the scope of the array name will also deallocate the storage. Jumping into the scope is not allowed; you will get an error message for it.
You can use the function alloca to get an effect much like variable-length arrays. The function alloca is avail- able in many other C implementations (but not in all). On the other hand, variable-length arrays are more elegant.
There are other differences between these two methods. Space allocated with alloca exists until the containing _f_u_n_c_t_i_o_n returns. The space for a variable-length array is deallocated as soon as the array name’s scope ends. (If you use both variable-length arrays and alloca in the same func- tion, deallocation of a variable-length array will also deallocate anything more recently allocated with alloca.)
GNU C++ does not currently support variable length arrays which are class members, in the case where the length of the array is a member of the class. Thus, the following is not yet implemented:
class foo { static const int i = 10; int array[i]; ;
It is not implemented because the member variable _i is not in scope to be used for the declaration of _a_r_r_a_y.
66..88.. NNoonn--LLvvaalluuee AArrrraayyss MMaayy HHaavvee SSuubbssccrriippttss
Subscripting is allowed on arrays that are not lvalues, even though the unary ‘&’ operator is not. For example, this is valid in GNU C++ though not valid in other C and C++ dialects:
struct foo {int a[4];;
struct foo f();
bar (int index) { return f().a[index];
5566 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
66..99.. AArriitthhmmeettiicc oonn void--PPooiinntteerrss aanndd FFuunnccttiioonn PPooiinntteerrss
In GNU C++, addition and subtraction operations are supported on pointers to void and on pointers to functions. This is done by treating the size of a void or of a function as 1.
A consequence of this is that sizeof is also allowed on void and on function types, and returns 1.
66..1100.. NNoonn--CCoonnssttaanntt IInniittiiaalliizzeerrss
The elements of an aggregate initializer are not required to be constant expressions in GNU C++. Here is an example of an initializer with run-time varying elements:
foo (float f, float g) { float beat_freqs[2] = { f-g, f+g ; ...
66..1111.. CCoonnssttrruuccttoorr EExxpprreessssiioonnss
GNU C++ supports constructor expressions. Note that a constructor expression is _n_o_t the same as a constructor for a C++ struct or class. A constructor looks like a cast con- taining an initializer. Its value is an object of the type specified in the cast, containing the elements specified in the initializer. The type must be a structure, union or array type.
Assume that struct foo and structure are declared as shown:
struct foo {int a; char b[2]; structure;
Here is an example of constructing a ‘struct foo’ with a constructor:
structure = ((struct foo) {x + y, ’a’, 0);
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 5577
This is equivalent to writing the following:
{ struct foo temp = {x + y, ’a’, 0; structure = temp;
You can also construct an array. If all the elements of the constructor are (made up of) simple constant expres- sions, suitable for use in initializers, then the construc- tor is an lvalue and can be coerced to a pointer to its first element, as shown here:
char **foo = (char *[]) { "x", "y", "z" ;
Array constructors whose elements are not simple con- stants are not very useful, because the constructor is not an lvalue. There are only two valid ways to use it: to sub- script it, or initialize an array variable with it. The former is probably slower than a switch statement, while the latter does the same thing an ordinary C initializer would do.
output = ((int[]) { 2, x, 28 ) [input];
66..1122.. DDeeccllaarriinngg AAttttrriibbuutteess ooff FFuunnccttiioonnss
In GNU C++, you declare certain things about functions called in your program which help the compiler optimize function calls.
A few functions, such as abort and exit, cannot return. These functions should be declared volatile. For example,
extern volatile void abort ();
tells the compiler that it can assume that abort will not return. This makes slightly better code, but more impor- tantly it helps avoid spurious warnings of uninitialized variables.
5588 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
Many functions do not examine any values except their arguments, and have no effects except the return value. Such a function can be subject to common subexpression elim- ination and loop optimization just as an arithmetic operator would be. These functions should be declared const. For example,
extern const void square ();
says that the hypothetical function square is safe to call fewer times than the program says.
Note that a function that has pointer arguments and examines the data pointed to must _n_o_t be declared const. Likewise, a function that calls a non-const function must not be const.
Some people object to this feature, claiming that ANSI C’s #pragma should be used instead. There are two reasons I did not do this.
1. It is impossible to generate #pragma commands from a macro.
2. The #pragma command is just as likely as these keywords to mean something else in another com- piler.
These two reasons apply to _a_n_y application whatever: as far as I can see, #pragma is never useful.
66..1133.. DDoollllaarr SSiiggnnss iinn IIddeennttiiffiieerr NNaammeess
In GNU C++, you may use dollar signs in identifier names. This is because many traditional C implementations allow such identifiers.
66..1144.. IInnqquuiirriinngg aabboouutt tthhee AAlliiggnnmmeenntt ooff aa TTyyppee oorr VVaarriiaabbllee
The keyword __alignof allows you to inquire about how an object is aligned, or the minimum alignment usually required by a type. Its syntax is just like sizeof.
For example, if the target machine requires a double value to be aligned on an 8-byte boundary, then __alignof (double) is 8. This is true on many RISC machines. On more traditional machine designs, __alignof (double) is 4 or even 2.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 5599
Some machines never actually require alignment; they allow reference to any data type even at an odd addresses. For these machines, __alignof reports the _r_e_c_o_m_m_e_n_d_e_d align- ment of a type.
When the operand of __alignof is an lvalue rather than a type, the value is the largest alignment that the lvalue is known to have. It may have this alignment as a result of its data type, or because it is part of a structure and inherits alignment from that structure. For example, after this declaration:
struct foo { int x; char y; foo1;
the value of __alignof (foo1.y) is probably 2 or 4, the same as __alignof (int), even though the data type of foo1.y does not itself demand any alignment.
66..1155.. AAsssseemmbblleerr IInnssttrruuccttiioonnss wwiitthh CC EExxpprreessssiioonn OOppeerraannddss
In an assembler instruction using asm, you can now specify the operands of the instruction using C expressions. This means no more guessing which registers or memory loca- tions will contain the data you want to use.
You must specify an assembler instruction template much like what appears in a machine description, plus an operand constraint string for each operand.
For example, here is how to use the 68881’s fsinx instruction:
asm ("fsinx %1,%0" : "=f" (result) : "f" (angle));
Here angle is the C expression for the input operand while result is that of the output operand. Each has ‘"f"’ as its operand constraint, saying that a floating-point register is required. The constraints use the same language used in the machine description (See the Constraints section in the “Using and Porting GNU CC” document).
Each operand is described by an operand-constraint string followed by the C++ expression in parentheses. A colon separates the assembler template from the first output operand, and another separates the last output operand from the first input, if any. Commas separate output operands and separate inputs. The total number of operands is lim- ited to the maximum number of operands in any instruction
6600 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
pattern in the machine description.
If there are no output operands, and there are input operands, then there must be two consecutive colons sur- rounding the place where the output operands would go.
Output operand expressions must be lvalues; the com- piler can check this. The input operands need not be lvalues. The compiler cannot check whether the operands have data types that are reasonable for the instruction being executed. It does not parse the assembler instruction template and does not know what it means, or whether it is valid assembler input. The extended asm feature is most often used for machine instructions that the compiler itself does not know exist.
The output operands must be write-only; GNU C++ will assume that the values in these operands before the instruc- tion are dead and need not be generated. For an operand that is read-write, or in which not all bits are written and the other bits contain useful information, you must logi- cally split its function into two separate operands, one input operand and one write-only output operand. The con- nection between them is expressed by constraints which say they need to be in the same location when the instruction executes. You can use the same C++ expression for both operands, or different expressions. For example, here we write the (fictitious) ‘combine’ instruction with bar as its read-only source operand and foo as its read-write destina- tion:
asm ("combine %2,%0" : "=r" (foo) : "0" (foo), "g" (bar));
The constraint ‘"0"’ for operand 1 says that it must occupy the same location as operand 0. A digit in constraint is allowed only in an input operand, and it must refer to an output operand.
Only a digit in the constraint can guarantee that one operand will be in the same place as another. The mere fact that foo is the value of both operands is not enough to guarantee that they will be in the same place in the gen- erated assembler code. The following would not work:
asm ("combine %2,%0" : "=r" (foo) : "r" (foo), "g" (bar));
Various optimizations or reloading could cause operands 0 and 1 to be in different registers; GNU C++ knows no
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 6611
reason not to do so. For example, the compiler might find a copy of the value of foo in one register and use it for operand 1, but generate the output operand 0 in a different register (copying it afterward to foo’s own address). Of course, since the register for operand 1 is not even men- tioned in the assembler code, the result will not work, but GNU C++ can’t tell that.
Unless an output operand has the ‘&’ constraint modif- ier, GNU C++ may allocate it in the same register as an unrelated input operand, on the assumption that the inputs are consumed before the outputs are produced. This assump- tion may be false if the assembler code actually consists of more than one instruction. In such a case, use ‘&’ for each output operand that may not overlap an input. See section Modifiers.
Some instructions clobber specific hard registers. To describe this, write a third colon after the input operands, followed by the names of the clobbered hard registers (given as strings). Here is a realistic example for the vax:
asm volatile ("movc3 %0,%1,%2" : /* no outputs */ : "g" (from), "g" (to), "g" (count) : "r0", "r1", "r2", "r3", "r4", "r5");
You can put multiple assembler instructions together in a single asm template, separated with semicolons. The input operands are guaranteed not to use any of the clobbered registers, and neither will the output operands’ addresses, so you can read and write the clobbered registers as many times as you like. Here is an example of multiple instruc- tions in a template; it assumes that the subroutine _foo accepts arguments in registers 9 and 10:
asm ("movl %0,r9;movl %1,r10;call _foo" : /* no outputs */ : "g" (from), "g" (to) : "r9", "r10");
Usually the most convenient way to use these asm instructions is to encapsulate them in macros that look like functions. For example,
#define sin(x) \ ({ double __value, __arg = (x); \
6622 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
asm ("fsinx %1,%0": "=f" (__value): "f" (__arg)); \ __value; )
Here the variable __arg is used to make sure that the instruction operates on a proper double value, and to accept only those arguments x which can convert automatically to a double.
Another way to make sure the instruction operates on the correct data type is to use a cast in the asm. This is different from using a variable __arg in that it converts more different types. For example, if the desired type were int, casting the argument to int would accept a pointer with no complaint, while assigning the argument to an int vari- able named __arg would warn about using a pointer unless the caller explicitly casts it.
GNU C++ assumes for optimization purposes that these instructions have no side effects except to change the out- put operands. This does not mean that instructions with a side effect cannot be used, but you must be careful, because the compiler may eliminate them if the output operands aren’t used, or move them out of loops, or replace two with one if they constitute a common subexpression. Also, if your instruction does have a side effect on a variable that otherwise appears not to change, the old value of the vari- able may be reused later if it happens to be found in a register.
You can prevent an asm instruction from being deleted, moved or combined by writing the keyword volatile after the asm. For example:
#define set_priority(x) \ asm volatile ("set_priority %0": /* no outputs */ : "g" (x))
If there are no output operands, the instruction will not be deleted or moved.
It is a natural idea to look for a way to give access to the condition code left by the assembler instruction. However, when we attempted to implement this, we found no way to make it work reliably. The problem is that output operands might need reloading, which would result in addi- tional following “store” instructions. On most machines, these instructions would alter the condition code before there was time to test it. This problem doesn’t arise for ordinary “test” and “compare” instructions because they don’t have any output operands.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 6633
66..1166.. CCoonnttrroolllliinngg NNaammeess UUsseedd iinn AAsssseemmbblleerr CCooddee
You can specify the name to be used in the assembler code for a C++ function or variable (including static class variables and global anonymous union members) by writing the asm keyword after the declarator as follows:
int foo asm ("myfoo") = 2;
This specifies that the name to be used for the variable foo in the assembler code should be ‘myfoo’ rather than the usual ‘_foo’.
On systems where an underscore is normally prepended to the name of a C++ function or variable, this feature allows you to define names for the linker that do not start with an underscore.
You cannot use asm in this way in a function _d_e_f_i_n_i_- _t_i_o_n; but you can get the same effect by writing a declara- tion for the function before its definition and putting asm there, like this:
extern func () asm ("FUNC");
func (int x, int y) ...
It is up to you to make sure that the assembler names you choose do not conflict with any other assembler symbols. Also, you must not use a register name; that would produce completely invalid assembler code. GNU C++ does not as yet have the ability to store static variables in registers. Perhaps that will be added.
66..1177.. GGlloobbaall VVaarriiaabblleess iinn RReeggiisstteerrss
A few programs, such as programming language inter- preters, may have a couple of global variables that are accessed so often that it is worth while to reserve regis- ters throughout the program just for them.
You can define a global register variable in GNU C++ like this:
register int *foo asm ("a5");
6644 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
Here a5 is the name of the register which should be used. Choose a register which is normally saved and restored by function calls on your machine, so that library routines will not clobber it.
Naturally the register name is cpu-dependent, so you would need to conditionalize your program according to cpu type. The register a5 would be a good choice on a 68000 for a variable of pointer type. On machines with register win- dows, be sure to choose a “global” register that is not affected by the function call mechanism.
In addition, operating systems on one type of cpu may differ in how they name the registers; then you would need additional conditionals. For example, some 68000 operating systems call this register %a5.
Eventually there may be a way of asking the compiler to choose a register automatically, but first we need to figure out how it should choose and how to enable you to guide the choice. No solution is evident.
Defining a global register variable in a certain regis- ter reserves that register entirely for this use, at least within the current compilation. The register will not be allocated for any other purpose in the functions in the current compilation. The register will not be saved and restored by these functions. Stores into this register are never deleted even if they would appear to be dead, but references may be deleted or moved or simplified.
It is not safe to access the global register variables from signal handlers, or from more than one thread of con- trol, because the system library routines may temporarily use the register for other things (unless you recompile them specially for the task at hand).
It is not safe for one function that uses a global register variable to call another such function foo by way of a third function lose that was compiled without knowledge of this variable (i.e. in a different source file in which the variable wasn’t declared). This is because lose might save the register and put some other value there. For exam- ple, you can’t expect a global register variable to be available in the comparison-function that you pass to qsort, since qsort might have put something else in that register. (If you are prepared to recompile qsort with the same global register variable, you can solve this problem.)
If you want to recompile qsort or other source files which do not actually use your global register variable, so that they will not use that register for any other purpose,
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 6655
then it suffices to specify the compiler option ‘-ffixed- _r_e_g’. You need not actually add a global register declara- tion to their source code.
A function which can alter the value of a global regis- ter variable cannot safely be called from a function com- piled without this variable, because it could clobber the value the caller expects to find there on return. There- fore, the function which is the entry point into the part of the program that uses the global register variable must explicitly save and restore the value which belongs to its caller.
On most machines, longjmp will restore to each global register variable the value it had at the time of the setjmp. On some machines, however, longjmp will not change the value of global register variables. To be portable, the function that called setjmp should make other arrangements to save the values of the global register variables, and to restore them if a longjmp. This way, the the same thing will happen regardless of what longjmp does.
All global register variable declarations must precede all function definitions. If such a declaration could appear after function definitions, the declaration would be too late to prevent the register from being used for other purposes in the preceding functions.
Global register variables may not have initial values, because an executable file has no means to supply initial contents for a register.
The GNU C++ language makes some extensions to the C++ new operator, and adds a few non-C operators as well.
66..1188.. NNoonn--CC ooppeerraattoorrss:: operator <? aanndd operator >?
It is very convenient to have operators which return the "minimum" or the "maximum" of two arguments. It is pos- sible to specify a macro to return the minimum of two things in C++, as the following example shows.
#define MIN(X,Y) ((X) < (Y) ? : (X) : (Y))
You might then use this as follows:
int min = MIN (i, j);
6666 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
to set _m_i_n to the minimum value of variables _i and _j.
However, this is not clean, because side-effects in X or Y may cause unintended behavior (_e._g., MIN (i++, j++) will fail. It also requires that users employ a functional notation for a fundamental operation. Using GNU C++ exten- sions this example could be rewritten as:
int min = i <? j;
Since <? and >? are built-in the compiler they properly handle expressions with side-effects, so that:
int min = i++ <? j++;
works correctly.
66..1199.. CCoonnttrroolllliinngg operator new..
The user now has much more control over the operator new. Normally, operator new calls the function __builtin_new with a size argument, and __builtin_new returns a pointer to a block of storage at least size bytes long. It is now possible to pass arguments to operator new, which will pass those arguments, along with a size parame- ter, to a function called __user_new, which can return any- thing the users wants it to. It is the user’s responsibil- ity to define __user_new. The function __user_new may be declared overloaded, just like any other function. It is not implicitly overloaded. The following is an example of its use:
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 6677
// Create a C++ equivalent of “realloc”. inline void *__user_new (int new_size, void *old_ptr) { return (void *) realloc (old_ptr, new_size);
char *manipulate_string (char *string) { int len = strlen (string) + 1; char *s = strcpy (new char [len], string); // ... char *t = new {s char [len * 2];
return strcat (t, string);
In this example, __user_new is defined to provide realloc-style behavior for the built-in operator new. All other semantics of ‘new’ are preserved: initializations are performed in exactly the same manner. One must be careful when using such a function, however: it is up to the con- structors to know what actions to take if the memory returned from __user_new is not in their address space.
66..2200.. FFuunnccttiioonn ccaallllss aass ffiirrsstt--ccllaassss oobbjjeeccttss
In some cases it is desirable not to execute a function call immediately, but to perform some actions before the function is to be called, call the function, or otherwise obtain a value as a function of the called function’s code and its arguments, perform some more actions afterwards, and return a result. An example of such a use would be the exe- cution of remote procedure calls on a distributed system. One may get a request on one node to apply a function to some arguments, but that function may actually be on another node (as might some of the arguments). A “wrapper” allows a function call to be turned into an argument list which includes as arguments an encoding of the function being “wrapped” and its arguments. From this, it is possible, for example, to send a message to the node where the func- tion actually lives, along with an encoding of the arguments as a list, have that function execute, return its result via another message, and ultimately return a result to the caller. A “wrapper” allows the user great flexibility in the implementation of such behaviors, flexibility which allows one to specify many different ways of implementing the semantics of a function call, without requiring that the actual code for the function being wrapped be modified in any way.
6688 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
An example will demonstrate one use of wrappers. This is a highly experimental feature, and one which should be expected to evolve suddenly. Users are therefore encouraged to participate in this evolutionary process.
// Memoizing example. Normal C++ code.
class NumTheory { // Use a hash table for memoizing HashTable h;
int lookup (int (NumTheory::*)(int), int); int install (int (NumTheory::*)(int), int, int);
public: // Some functions to memoize int fib (int); // Fibonacci numbers int prime (int); // Prime Numbers
int NumTheory::fib (int n) { if (n == 0) return 0; if (n == 1) return 1; return fib (n - 1) + fib (n - 2);
main (int, char *[]) { NumTheory n;
// find the 100th prime. int p100 = n.prime (100); // find the 101st prime–might be fast, since we know the 100th int p101 = n.prime (101);
// find the 10th Fibonacci number int f10 = n.fib (10); // find the 11th Fibonacci number–might also be fast int f11 = n.fib (11);
printf ("The 100th prime number is %d\n", p100); printf ("The 101st prime number is %d\n", p101); // etc ...
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 6699
A “wrapper” can be added to the class declaration of ‘NumTheory’ with the following declaration:
()NumTheory (int (NumTheory::*)(int), int);
A wrapper declaration is syntactically valid anywhere a member function declaration is. By adding this declaration, the compiler catches out calls to member functions of the class ‘NumTheory’ and replaces them with calls to the wrapper. A wrapper may therefore be used to implement memoizing as follows:
// This wrapper uses previously computed results, if available. // Newly generated results are entered into the hash table. int NumTheory::()NumTheory (int (NumTheory::*pf)(int), int arg) { // try to use a previously computed value. int val = hash (pf, arg); if (val < 0) { // Must compute value. val = (this->*pf)(arg); // Save it into hash table. install (pf, arg, val); // else, we can use previously computed value. return val;
A paper explaining the possible uses and implementa- tions of wrappers is available from the proceedings from the 1988 USENIX workshop on C++, held in Denver, Colorado.
66..2211.. SSwwiittcchh RRaannggeess
A GNU C++ extension to the switch statement permits range specification for case values. For example, below is a concise way to print out a function parameter’s “charac- ter class:”
7700 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
print_char_class (char c) { switch (c) { case ’a’..’z’: printf ("lower case\n"); break; case ’A’..’Z’: printf ("upper case\n"); break; case ’0’..’9’: printf ("digit\n"); break; default: printf ("other\n");
Duplicate, overlapping case values and empty ranges are detected and rejected by the compiler.
66..2222.. SSttaattiicc MMeemmbbeerr FFuunnccttiioonnss
Programmers familiar with Ada packages, Pascal units, or Modula-2 modules recognize the benefits of hiding func- tions within an encapsulation unit. GNU G++ further aug- ments C++’s data abstraction capability with _s_t_a_t_i_c _m_e_m_b_e_r _f_u_n_c_t_i_o_n_s. Static member functions are subject to the same inlining and visibility features available with regular member functions. The major differences between static and non-static member functions are that:
It is possible to call any visible static class member function regardless of whether a class in- stance exists.
Static member functions may only access global variables and static class data elements.
Static member functions may not be declared virtu- al.
Since static member functions exist independently of any class instances they lack an implicit ‘this’ pointer. Therefore, they have no access to any _n_o_n-static class member functions or data.
Here’s an familiar Abstract Data Type application demonstrating static member functions:
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 7711
#include <stream.h>
static const int MAX_STACK = 100;
class Stack { private: static int stack[MAX_STACK]; static int top;
public: static void push (int item) { stack[top++] = item; static int pop () { return stack[–top]; static int is_empty () { return top == 0; static int is_full () { return top >= MAX_STACK; ;
main () { for (srandom (time (0L)); !Stack::is_full (); Stack::push (random ())) ;
while (!Stack::is_empty ()) cout << Stack::pop () << "\n";
This example is similar in spirit to how an Ada or Modula-2 programmer might design a bounded-stack abstrac- tion. Note how there is only oonnee _s_t_a_c_k array for all instances of class Stack. Naturally, in this particular case it isn’t very useful to declare multiple instances of class Stack, since the data would be shared between all class instances.
Several benefits accrue from the use of static member functions:
Static member functions have no access to the class instance pointer ‘this’. Thus, there is no need to pass an extra hidden parameter for each static member function call, thereby decreasing parameter passing overhead.
Static member functions provide an encapsulation mechanism for manipulating static data objects.
Another important use of static member functions is writing type-safe handler routines. Doug Lea can explain how this works with the Fix{xx classes in libg++.
7722 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
Note that it is possible to mix static and non-static member functions in the same class.
66..2233.. EExxcceeppttiioonn HHaannddiinngg
The GNU C++ compiler implements a simple form of excep- tion handling. This extension is subject to change, but is presented here because so many people have asked about it.
Exceptions are declared as follows:
class String { ... ; // some random class
exception { EX; // an exception that is just a name exception { int i; // an integer value contained in this exception String s; // a String object contained in this exception EY;
With these declarations, EX and EY name exception types. Variables of exception type cannot be declared, but from a conceptual point of view, objects whose types mirror the exception declarations can be created.
Exceptions are raised and handled as shown in the fol- lowing example:
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 7733
int f () { int i = foo ();
try { int j = bar (); i += j; int k = bazzle (); if (i < k) return 7; i *= k; except ex { EX { // if the EX exception was raised... if (i < 0) // raise ‘EY’ exception raise EY (i, "foo"); return 4; EY { // if the EY exception was raised... // use the exception’s parameters printString (ex.s); return ex.i; default { // handle other exceptions
Functions which propagate exceptions (either by passing them through, or by raising them) can be declared to do so as follows:
int f () raises EY;
A shorthand notation exists for reraising exceptions:
7744 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
try { bar (); // may raise an exception... reraise EX, EY; // reraise only EX and EY
When there is a notion of unhandled exceptions, for example a reraise which does not list the exception type being handled, a call is made to __unhandled_exception with arguments of source filename and line number where exception was not handled.
For those interested in reading more about this exten- sion, a paper explaining the exception handling design is available in the proceedings from the 1990 USENIX workshop on C++, held in San Francisco, California.
77.. FFeeaattuurreess ooff GGNNUU CC++++
Because the GNU C++ compiler is a native code compiler, there are opportunities for optimization which do not exist for C++ to C translators. Additional features which have been ignored by other systems, but implemented by the GNU C++ system, are also listed here.
77..11.. SSttrruuccttuurreess aass AArrgguummeennttss The GNU C++ compiler can pass structures as arguments to functions. This can be dif- ficult in C++, since the structure may take a constructor (the constructor of the form X(X&) in particular), in which case the structure passed must be initialized by that con- structor as it lies on the stack. The GNU C++ compiler takes care of initializing the stack space before the func- tion is called. If a destructor for the structure is defined, then GNU C++ also takes care of protecting that space until it is in fact destroyed.
When it comes to code generation, the advantage of this feature is that all structure parameters can be accessed via the same register: the frame pointer (or the stack pointer if the frame pointer can be eliminated). Other strategies which require passing pointers to structures either must use multiple indirections to access elements of the structures, or they must use extra registers to point to the structures.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 7755
77..22.. TThhee ggoottoo ssttaatteemmeenntt iinn GGNNUU CC++++
The goto statement can be used to exit blocks which contain aggregates requiring destructors. The destructors are called, and then the goto is performed.
77..33.. TTyyppee iinnssttaannttiiaattiioonn iinn GGNNUU CC++++
Overloaded operators and user-defined type conversions provide the user with the freedom to implement abstract data types, often with very a natural syntax. This freedom places a certain burden on the compiler, however. Whenever an object which is of some user-defined type appears in a context where a built-in type must appear, the compiler must make the proper choices in translating the code from its C++ representation to something which executes in a predictable way. For example, in the following code:
struct A { A (); int operator+ (A&); operator int (); ;
struct B { B (); operator int (); ;
main () { A a; B b;
int i = a + b; // some more stuff...
the compiler may try to overload operator+, but when that fails, it must be prepared to convert vaiables a and b to integer type, and perform normal addition. Sometimes it is not possible to determine, strictly from a bottom-up translation, what conversions should take place. Sometimes a technique known as type instantiation can help. Here is an example:
struct A {
7766 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
A (); A& operator *(); // The indirection operator A& operator *(A&); // The multiply operator ;
main () { A a; A& (*pf)(A*, A&);
pf = a.operator*; // Which operator??
Type instantiation allows the compiler to choose from among many candidates, the most appropriate one given con- textual information such as type. If an ambiguity still remains, then a warning or an error message is given.
This facility has been extended for releases 1.35.0 and later. Consider the following code:
struct X { double d; int i; int *mf1 (); int X::* mf2 (); int mf3 (); ;
int * X::mf1 () { return &X::i; // return pointer to this->X::i
int X::* X::mf2 () { return &X::i; // return pointer to member X::i
int X::mf3 () { return X::i; // return this->X::i
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 7777
77..44.. IInnccrreemmeennttaall LLiinnkkiinngg aanndd GGNNUU CC++++
Incremental linking adds a new dimension to programming with GNU C++. Standard C++ requires that constructors and destructors be called on all objects which declare them, including global data. For example, when using the ‘stream’ library facilities, the global variables cin, cout, and cerr are global variables which are initialized before control ever reaches main. GNU C++ extends this model to incor- porate code which is linked with a program at run-time. Code which illustrates this behavior is distributed in the GNU C++ library, libg++, in the files ‘test.hello.cc’, ‘test.bye’, and others which comprise ‘test0’, one of the tests in the ‘Makefile’ in the GNU C++ library tests direc- tory.
Care should be taken when writing code which uses incremental linking. Because GNU C++ can put more than just program code in text space (read-only variables and charac- ter strings typically into text space as well), the starting address of text space may not always be the first function defined. It is therefore suggested that users include the file ‘Incremental.h’ as the _f_i_r_s_t file included in any pro- gram which will be linked incrementally, and immediately use the macro DECLARE_INIT_FUNCTION to tell GNU C++ what func- tion should be called to initialize the module.
77..55.. AAvvooiidd eexxttrraa ccoonnssttrruuccttoorr ccaallll wwhheenn rreettuurrnniinngg ccllaasssseess ffrroomm ffuunnccttiioonnss..
Consider a function m () with a return value of class X.
X m () { X b; b.a = 23; return b;
and the declaration
X v = m ();
What happens here is that m () secretly has an argu- ment, the address of the return value. At invocation, the address of enough space to hold v is sent in as the hidden argument. Then b is constructed and its b field is set to the value 23. Then an X(X&) constructor is applied to b, with the hidden return value location as the target, so that v is now bound to the return value.
7788 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
But this is pretty wasteful. The local b is declared just to hold something that will be copied right out. While a compiler that combined an “elision” algorithm with interprocedural data flow analysis could conceivably elim- inate all of this, it seems much more practical to allow programmers to assist the compiler in generating efficient code by somehow manipulating the return value explicitly, thus avoiding the local variable and X(X&) constructor all together.
A simple-looking and appealing solution to this is to allow programmers to name, and thus explicitly manipulate the return value. The new syntax (optionally, of course) enables a programmer to declare the return value in almost just the way you declare a local, but as part of the declaration header instead of the code part. For example,
X m () return r; { r.a = 23;
says that m returns an X, that we are calling r. The declaration of r is a standard proper declaration, whose effects are executed bbeeffoorree any of the { ... part of m.
Executing return statements or falling-off-the-edge of the function are legal ways to return out of a function declared in this fashion. Thus, things like
X m () return r(23); { return;
or even
X m () return r(23); {
are perfectly legal, since the return value r has been initialized in either case. The following code presents a problem:
X m () return r; { X b; return b;
The return value slot denoted by r has already been initialized, but the statement return b; passes its value through r via initialization semantics. There are two pos- sible approaches the compiler could take to deal with this:
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 7799
1. It could disallow it.
2. It could destroy r (calling the destructor if there is one, or doing nothing if there is not), and then it could reinitialize r with b.
I will give users a chance to provide feedback before settling on one or the other. This extension was provided primarily to help people who were using overloaded opera- tors, where there is a great need to control not just the arguments, but the return values of functions. For classes in which the X(X&) constructor incurs a heavy copying penalty, (and especially in the usual case where there is a quick “X()” constructor), this is a major savings: at least one X(X&) constructor is avoided. The only disadvan- tage of this extension is that programmers do not have any control over when the constructor for the return value is called: it must be at the beginning.
88.. RReeppoorrttiinngg BBuuggss
Your bug reports play an essential role in making GNU C++ reliable.
Reporting a bug may help you by bringing a solution to your problem, or it may not. But in any case the important function of a bug report is to help the entire community by making the next version of GNU C++ work better. Bug reports are your contribution to the maintenance of GNU C++.
In order for a bug report to serve its purpose, you must include the information that makes for fixing the bug.
88..11.. HHaavvee YYoouu FFoouunndd aa BBuugg??
If you are not sure whether you have found a bug, here are some guidelines:
If the compiler gets a fatal signal, for any input whatever, that is a compiler bug. Reliable com- pilers never crash.
If the compiler produces invalid assembly code, for any input whatever (except an asm statement), that is a compiler bug, unless the compiler re- ports errors (not just warnings) which would ordi- narily prevent the assembler from being run.
If the compiler produces valid assembly code that does not correctly execute the input source code, that is a compiler bug.
8800 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
However, you must double-check to make sure, be- cause you may have run into an incompatibility between GNU C++ and traditional C++/PCC (see sec- tion Incompatibilities). These incompatibilities might be considered bugs, but they are inescapable consequences of adding valuable features.
Or you may have a program whose behavior is unde- fined, which happened by chance to give the desired results with another C++ compiler, or C++ front-end/C compiler combination.
For example, in many nonoptimizing compilers, you can write ‘x;’ at the end of a function instead of ‘return x;’, with the same results. But the value of the function is undefined if ‘return’ is omit- ted; it is not a bug when GNU C++ produces dif- ferent results.
Problems often result from expressions with two increment operators, as in ‘f (*p++, *p++)’. Your previous compiler might have interpreted that ex- pression the way you intended; GNU C++ might in- terpret it another way; neither compiler is wrong.
After you have localized the error to a single source line, it should be easy to check for these things. If your program is correct and well de- fined, you have found a compiler bug.
If the compiler produces an error message for valid input, that is a compiler bug.
If the compiler does not produce an error message for invalid input, that is a compiler bug. Howev- er, you should note that your idea of “invalid input” might be my idea of “an extension” or “support for traditional practice”.
If you are an experienced user of C++ compilers, your suggestions for improvement of GNU C++ are welcome in any case.
88..22.. HHooww ttoo RReeppoorrtt BBuuggss
Send bug reports for GNU C++ to one of these addresses:
bug-g++@prep.ai.mit.edu {ucbvax|mit-eddie|uunet!prep.ai.mit.edu!bug-g++
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 8811
As a last resort, snail them to:
GNU C++ Compiler Bugs Box #629 Crothers Memorial Hall ATTN: Michael Tiemann Stanford, CA 94305
The fundamental principle of reporting bugs usefully is this: rreeppoorrtt aallll tthhee ffaaccttss. If you are not sure whether to mention a fact or leave it out, mention it!
Often people omit facts because they think they know what causes the problem and they conclude that some details don’t matter. Thus, you might assume that the name of the variable you use in an example does not matter. Well, prob- ably it doesn’t, but one cannot be sure. Perhaps the bug is a stray memory reference which happens to fetch from the location where that name is stored in memory; perhaps, if the name were different, the contents of that location would fool the compiler into doing the right thing despite the bug. Play it safe and give an exact example.
If you want to enable me to fix the bug, you should include all these things:
The version of GNU C++. You can get this by run- ning it with the ‘-v’ option.
Without this, I won’t know whether there is any point in looking for the bug in the current ver- sion of GNU C++.
A complete input file that will reproduce the bug. If the bug is in the C preprocessor, send me a source file and any header files that it requires. If the bug is in the compiler proper (‘cc1plus’), run your source file through the C preprocessor by doing ‘g++ -E _s_o_u_r_c_e_f_i_l_e > _o_u_t_f_i_l_e’, then include the contents of _o_u_t_f_i_l_e in the bug report. (Any ‘-I’, ‘-D’ or ‘-U’ options that you used in actual compilation should also be used when doing this.)
A single statement is not enough of an example. In order to compile it, it must be embedded in a function definition; and the bug might depend on the details of how this is done.
Without a real example I can compile, all I can do about your bug report is wish you luck. It would be futile to try to guess how to provoke the bug. For example, bugs in register allocation and re-
8822 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
loading frequently depend on every little detail of the function in which they happen.
The command arguments you gave GNU C++ to compile that example and observe the bug. For example, did you use ‘-O’? To guarantee you won’t omit something important, list them all.
If I were to try to guess the arguments, I would probably guess wrong and then I would not en- counter the bug.
The names of the files that you used for ‘tm.h’ and ‘md’ when you installed the compiler.
The type of machine you are using, and the operat- ing system name and version number.
A description of what behavior you observe that you believe is incorrect. For example, “It gets a fatal signal,” or, “There is an incorrect as- sembler instruction in the output.”
Of course, if the bug is that the compiler gets a fatal signal, then I will certainly notice it. But if the bug is incorrect output, I might not notice unless it is glaringly wrong. I won’t study all the assembler code from a 50-line C pro- gram just on the off chance that it might be wrong.
Even if the problem you experience is a fatal sig- nal, you should still say so explicitly. Suppose something strange is going on, such as, your copy of the compiler is out of synch, or you have en- countered a bug in the C library on your system. (This has happened!) Your copy might crash and mine would not. If you _t_o_l_d me to expect a crash, then when mine fails to crash, I would know that the bug was not happening for me. If you had not told me to expect a crash, then I would not be able to draw any conclusion from my observations.
In cases where GNU C++ generates incorrect code, if you send me a small complete sample program I will find the error myself by running the program under a debugger. If you send me a large example or a part of a larger program, I cannot do this; you must debug the compiled program and narrow the problem down to one source line. Tell me which source line it is, and what you believe is in- correct about the code generated for that line.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 8833
If you send me examples of output from GNU C++, please use ‘-g’ when you make them. The debugging information includes source line numbers which are essential for correlating the output with the in- put.
Here are some things that are not necessary:
A description of the envelope of the bug.
Often people who encounter a bug spend a lot of time investigating which changes to the input file will make the bug go away and which changes will not affect it.
This is often time consuming and not very useful, because the way I will find the bug is by running a single example under the debugger with break- points, not by pure deduction from a series of ex- amples.
Of course, it can’t hurt if you can find a simpler example that triggers the same bug. Errors in the output will be easier to spot, running under the debugger will take less time, etc. An easy way to simplify an example is to delete all the function definitions except the one where the bug occurs. Those earlier in the file may be replaced by external declarations.
However, simplification is not necessary; if you don’t want to do this, report the bug anyway.
A patch for the bug.
A patch for the bug does help me if it is a good one. But don’t omit the necessary information, such as the test case, because I might see prob- lems with your patch and decide to fix the problem another way.
Sometimes with a program as complicated as GNU C++ it is very hard to construct an example that will make the program go through a certain point in the code. If you don’t send me the example, I won’t be able to verify that the bug is fixed.
A guess about what the bug is or what it depends on.
Such guesses are usually wrong. Even I can’t guess right about such things without using the debugger to find the facts. They also don’t serve
8844 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
a useful purpose.
99.. GGNNUU CC++++ aanndd PPoorrttaabbiilliittyy
The main goal of GNU C++ was to make a good, fast com- piler for machines in the class that the GNU system aims to run on: 32-bit machines that address 8-bit bytes and have several general registers. Elegance, theoretical power and simplicity are only secondary.
GNU C++ gets most of the information about the target machine from a machine description which gives an algebraic formula for each of the machine’s instructions. This is a very clean way to describe the target. But when the com- piler needs information that is difficult to express in this fashion, I have not hesitated to define an ad-hoc parameter to the machine description. The purpose of portability is to reduce the total work needed on the compiler; it was not of interest for its own sake.
GNU C++ does not contain machine dependent code, but it does contain code that depends on machine parameters such as endianness (whether the most significant byte has the highest or lowest address of the bytes in a word) and the availability of auto-increment addressing. In the RTL- generation pass, it is often necessary to have multiple strategies for generating code for a particular kind of syn- tax tree, strategies that are usable for different combina- tions of parameters. Often I have not tried to address all possible cases, but only the common ones or only the ones that I have encountered. As a result, a new target may require additional strategies. You will know if this hap- pens because the compiler will call abort. Fortunately, the new strategies can be added in a machine-independent fashion, and will affect only the target machines that need them.
The implementation of pointers to virtual member func- tions is not entirely portable. This is because to be truly portable, these pointers would have to be twice the size of normal pointers. The assumption that is made is that offsets into a virtual function table can be distinguished from addresses of functions. In GNU C++, there are two ways of doing this: if the assumption is made that the largest offset into a virtual function table will always be smaller than the first text address available to the user, then define the symbol VTABLE_USES_MASK, and set VINDEX_MAX to the largest power of two less than or equal to that size. When GNU C++ programs are linked with the GNU linker and crt0+.o, the GNU C++ startup code, a check is performed that virtual tables did not exceed this size when the program is run.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 8855
If VTABLE_USES_MASK is not defined, then the compiler assumes that pointers with their high bit set are offsets into the virtual function table, otherwise they are pointers to addresses in text space. Neither one of these strategies is particularly attractive for machines with segmented architectures with small segments, but then again, for these machines, nothing is.
Pointers to static class members are not implemented. It was felt that use of this feature would be extremely rare, and the run-time overhead associated with the imple- mentation of this feature would, in general, not be worth it.
1100.. IInntteerrffaacciinngg ttoo GGNNUU CC++++ OOuuttppuutt
GNU C++ is normally configured to use the same function calling convention normally in use on the target system. This is done with the machine-description macros described (See the Machine Macros section of the “Using and Porting GNU CC” document).
However, returning of structure and union values is done differently on some target machines. As a result, functions compiled with PCC returning such types cannot be called from code compiled with GNU C++, and vice versa. This does not cause trouble often because few Unix library routines return structures or unions.
GNU C++ code returns structures and unions that are 1, 2, 4 or 8 bytes long in the same registers used for int or double return values. (GNU C++ typically allocates vari- ables of such types in registers also.) Structures and unions of other sizes are returned by storing them into an address passed by the caller (usually in a register). The machine-description macros STRUCT_VALUE and STRUCT_INCOMING_VALUE tell GNU C++ where to pass this address.
By contrast, PCC on most target machines returns struc- tures and unions of any size by copying the data into an area of static storage, and then returning the address of that storage as if it were a pointer value. The caller must copy the data from that memory area to the place where the value is wanted. This is slower than the method used by GNU C++, and fails to be reentrant.
On some target machines, such as RISC machines and the 80386, the standard system convention is to pass to the sub- routine the address of where to return the value. On these machines, GNU C++ has been configured to be compatible with the standard compiler, when this method is used. It may not be compatible for structures of 1, 2, 4 or 8 bytes.
8866 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
GNU C++ uses the system’s standard convention for pass- ing arguments. On some machines, the first few arguments are passed in registers; in others, all are passed on the stack. It would be possible to use registers for argument passing on any machine, and this would probably result in a significant speedup. But the result would be complete incompatibility with code that follows the standard conven- tion. So this change is practical only if you are switching to GNU C++ and use GNU CC as the sole C compiler for the system. We may implement register argument passing on cer- tain machines once we have a complete GNU system so that we can compile the libraries with GNU C++.
If you use longjmp, beware of automatic variables. ANSI C says that automatic variables that are not declared volatile have undefined values after a longjmp. And this is all GNU C++ promises to do, because it is very difficult to restore register variables correctly, and one of GNU C++’s features is that it can put variables in registers without your asking it to.
If you want a variable to be unaltered by longjmp, and you don’t want to write volatile because old C compilers don’t accept it, just take the address of the variable. If a variable’s address is ever taken, even if just to compute it and ignore it, then the variable cannot go in a register:
{ int careful; &careful; ...
Code compiled with GNU C++ may call certain library routines. The routines needed on the Vax and 68000 are in the file ‘gnulib.c’. You must compile this file with the standard C compiler, not with GNU C++, and then link it with each program you compile with GNU C++. The usual function call interface is used for calling the library routines. Some standard parts of the C library, such as bcopy, are also called automatically.
The file ‘gnulib.c’ also provides the implementation for the functions __builtin_new and __builtin_delete, the functions responsible for actually allocating and deallocat- ing storage for GNU C++ programs.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 8877
1111.. PPaasssseess aanndd FFiilleess ooff tthhee CCoommppiilleerr
The overall control structure of the compiler is in ‘toplev.c’. This file is responsible for initialization, decoding arguments, opening and closing files, and sequenc- ing the passes. For information about the internals of the GNU C++ compiler, at this level and below it is functionally identical to the GNU CC compiler. Please consult that docu- ment for further details.
The parsing pass is invoked only once, to parse the entire input. The RTL intermediate code for a function is generated as the function is parsed, a statement at a time. Each statement is read in as a syntax tree and then con- verted to RTL; then the storage for the tree for the state- ment is reclaimed. Storage for types (and the expressions for their sizes), declarations, and a representation of the binding contours and how they nest, remains until the func- tion is finished being compiled; these are all needed to output the debugging information.
Each time the parsing pass reads a complete function definition or top-level declaration, it calls the function rest_of_compilation or rest_of_decl_compilation in ‘toplev.c’, which are responsible for all further processing necessary, ending with output of the assembler language. All other compiler passes run, in sequence, within rest_of_compilation. When that function returns from com- piling a function definition, the storage used for that function definition’s compilation is entirely freed, unless it is an inline function.
Here is a list of all the passes of the compiler and their source files. Also included is a description of where debugging dumps can be requested with ‘-d’ options.
Parsing. This pass reads the entire text of a function definition, constructing partial syntax trees. This and RTL generation are no longer tru- ly separate passes (formerly they were), but it is easier to think of them as separate.
The tree representation does not entirely follow C++ syntax, because it is intended to support oth- er languages as well.
C++ data type analysis is also done in this pass, and every tree node that represents an expression has a data type attached. Variables are represented as declaration nodes.
Constant folding and associative-law simplifica- tions are also done during this pass.
8888 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
The source files for parsing are ‘cplus-parse.y’, ‘cplus-decl.c’, ‘cplus-typeck.c’, ‘stor-layout.c’, ‘fold-const.c’, and ‘tree.c’. The last three are intended to be language-independent. There are also header files ‘cplus-parse.h’, ‘cplus-tree.h’, ‘c-tree.h’, ‘tree.h’ and ‘tree.def’. The last two define the format of the tree representation.
RTL generation. This is the conversion of syntax tree into RTL code. It is actually done statement-by-statement during parsing, but for most purposes it can be thought of as a separate pass. Constructors and destructors are processed specially by finish_function.
This is where the bulk of target-parameter- dependent code is found, since often it is neces- sary for strategies to apply only when certain standard kinds of instructions are available. The purpose of named instruction patterns is to pro- vide this information to the RTL generation pass.
Optimization is done in this pass for if- conditions that are comparisons, boolean opera- tions or conditional expressions. Tail recursion is detected at this time also. Decisions are made about how best to arrange loops and how to output switch statements.
The source files for RTL generation are ‘stmt.c’, ‘expr.c’, ‘explow.c’, ‘expmed.c’, ‘optabs.c’ and ‘emit-rtl.c’. Also, the file ‘insn-emit.c’, gen- erated from the machine description by the program genemit, is used in this pass. The header files ‘expr.h’ is used for communication within this pass.
The header files ‘insn-flags.h’ and ‘insn- codes.h’, generated from the machine description by the programs genflags and gencodes, tell this pass which standard names are available for use and which patterns correspond to them.
Aside from debugging information output, none of the following passes refers to the tree structure representation of the function (only part of which is saved).
The decision of whether the function can and should be expanded inline in its subsequent call- ers is made at the end of rtl generation. The function must meet certain criteria, currently re- lated to the size of the function and the types and number of parameters it has. Note that this
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 8899
function may contain loops, recursive calls to it- self (tail-recursive functions can be inlined!), gotos, in short, all constructs supported by GNU CC.
The option ‘-dr’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.rtl’ to the input file name.
Jump optimization. This pass simplifies jumps to the following instruction, jumps across jumps, and jumps to jumps. It deletes unreferenced labels and unreachable code, except that unreachable code that contains a loop is not recognized as unreach- able in this pass. (Such loops are deleted later in the basic block analysis.)
Jump optimization is performed two or three times. The first time is immediately following RTL gen- eration. The second time is after CSE, but only if CSE says repeated jump optimization is needed. The last time is right before the final pass. That time, cross-jumping and deletion of no-op move instructions are done together with the op- timizations described above.
The source file of this pass is ‘jump.c’.
The option ‘-dj’ causes a debugging dump of the RTL code after this pass is run for the first time. This dump file’s name is made by appending ‘.jump’ to the input file name.
Register scan. This pass finds the first and last use of each register, as a guide for common subex- pression elimination. Its source is in ‘regclass.c’.
Common subexpression elimination. This pass also does constant propagation. Its source file is ‘cse.c’. If constant propagation causes condi- tional jumps to become unconditional or to become no-ops, jump optimization is run again when CSE is finished.
The option ‘-ds’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.cse’ to the input file name.
Loop optimization. This pass moves constant ex- pressions out of loops. Its source file is ‘loop.c’.
9900 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
The option ‘-dL’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.loop’ to the input file name.
Stupid register allocation is performed at this point in a nonoptimizing compilation. It does a little data flow analysis as well. When stupid register allocation is in use, the next pass exe- cuted is the reloading pass; the others in between are skipped. The source file is ‘stupid.c’.
Data flow analysis (‘flow.c’). This pass divides the program into basic blocks (and in the process deletes unreachable loops); then it computes which pseudo-registers are live at each point in the program, and makes the first instruction that uses a value point at the instruction that computed the value.
This pass also deletes computations whose results are never used, and combines memory references with add or subtract instructions to make autoin- crement or autodecrement addressing.
The option ‘-df’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.flow’ to the input file name. If stupid register allocation is in use, this dump file reflects the full results of such allocation.
Instruction combination (‘combine.c’). This pass attempts to combine groups of two or three in- structions that are related by data flow into sin- gle instructions. It combines the RTL expressions for the instructions by substitution, simplifies the result using algebra, and then attempts to match the result against the machine description.
The option ‘-dc’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.combine’ to the input file name.
Register class preferencing. The RTL code is scanned to find out which register class is best for each pseudo register. The source file is ‘regclass.c’.
Local register allocation (‘local-alloc.c’). This pass allocates hard registers to pseudo registers that are used only within one basic block. Be- cause the basic block is linear, it can use fast
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 9911
and powerful techniques to do a very good job.
The option ‘-dl’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.lreg’ to the input file name.
Global register allocation (‘global-alloc.c’). This pass allocates hard registers for the remain- ing pseudo registers (those whose life spans are not contained in one basic block).
Reloading. This pass renumbers pseudo registers with the hardware registers numbers they were al- located. Pseudo registers that did not get hard registers are replaced with stack slots. Then it finds instructions that are invalid because a value has failed to end up in a register, or has ended up in a register of the wrong kind. It fixes up these instructions by reloading the prob- lematical values temporarily into registers. Ad- ditional instructions are generated to do the copying.
Source files are ‘reload.c’ and ‘reload1.c’, plus the header ‘reload.h’ used for communication between them.
The option ‘-dg’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.greg’ to the input file name.
Jump optimization is repeated, this time including cross-jumping and deletion of no-op move instruc- tions.
The option ‘-dJ’ causes a debugging dump of the RTL code after this pass. This dump file’s name is made by appending ‘.jump2’ to the input file name.
Final. This pass outputs the assembler code for the function. It is also responsible for identi- fying spurious test and compare instructions. Machine-specific peephole optimizations are per- formed at the same time. The function entry and exit sequences are generated directly as assembler code in this pass; they never exist as RTL.
The source files are ‘final.c’ plus ‘insn- output.c’; the latter is generated automatically from the machine description by the tool ‘genout- put’. The header file ‘conditions.h’ is used for
9922 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
communication between these files.
Debugging information output. This is run after final because it must output the stack slot offsets for pseudo registers that did not get hard registers. Source files are ‘dbxout.c’ for DBX symbol table format and ‘symout.c’ for GDB’s own symbol table format.
Some additional files are used by all or many passes:
Every pass uses ‘machmode.def’, which defines the machine modes.
All the passes that work with RTL use the header files ‘rtl.h’ and ‘rtl.def’, and subroutines in file ‘rtl.c’. The tools gen* also use these files to read and work with the machine description RTL.
Several passes refer to the header file ‘insn- config.h’ which contains a few parameters (C macro definitions) generated automatically from the machine description RTL by the tool genconfig.
Several passes use the instruction recognizer, which consists of ‘recog.c’ and ‘recog.h’, plus the files ‘insn-recog.c’ and ‘insn-extract.c’ that are generated automatically from the machine description by the tools ‘genrecog’ and ‘genex- tract’.
Several passes use the header files ‘regs.h’ which defines the information recorded about pseudo re- gister usage, and ‘basic-block.h’ which defines the information recorded about basic blocks.
‘hard-reg-set.h’ defines the type HARD_REG_SET, a bit-vector with a bit for each hard register, and some macros to manipulate it. This type is just int if the machine has few enough hard registers; otherwise it is an array of int and some of the macros expand into loops.
1122.. TThhee CCoonnffiigguurraattiioonn FFiillee
The configuration file ‘xm-_m_a_c_h_i_n_e.h’ contains macro definitions that describe the machine and system on which the compiler is running. Most of the values in it are actu- ally the same on all machines that GNU C++ runs on, so large parts of all configuration files are identical. But there are some macros that vary:
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 9933
FAILURE_EXIT_CODE A C expression for the status code to be returned when the compiler exits after serious errors.
SORRY_EXIT_CODE A C expression for the status code to be returned when the compiler exits after compiling a file which used a feature not yet implemented.
SUCCESS_EXIT_CODE A C expression for the status code to be returned when the compiler exits without serious errors.
In addition, configuration files for system V define bcopy, bzero and bcmp as aliases. Some files define alloca as a macro when compiled with GNU CC, in order to take advantage of the benefit of GNU CC’s built-in alloca.
1133.. TThhiinnggss ssttiillll lleefftt ttoo ddoo ffoorr GGNNUU CC++++
The GNU C++ grammar is an LALR grammar in Bison format. It currently uses the simple LALR parser driver (bison.simple). It would be hard, but not impossible, to adapt GNU C++ to take full advantage of the Bison parsing machinery (bison.hairy), so that syntactic ambiguities which led to semantic errors could be unparsed, and reparsed with different syn-tactics. This would give the GNU C++ parser the same heuristic power as a recursive descent parser, while maintaining an LALR grammar basis.
Applications which make heavy use of virtual functions can pay a high price for function call overhead to its vir- tual functions. Small virtual functions are particularly troublesome because call overhead is high, and they cannot usually be inlined to take care of that. A more efficient calling sequence, which preserves both the class variable (this) and its virtual function table pointer, could elim- inate memory traffic in many cases for these two often used parameters.
1144.. LLiisstt ooff ccuurrrreennttllyy kknnoowwnn bbuuggss iinn GGNNUU CC++++
The single greatest mis-feature of GNU C++ is that it cannot handle C-style function definitions. It also does not handle pointer to function declarations or casts grace- fully in a number of contexts, especially in parameter declarations.
GNU C++ does not yet handle local class declarations. A local class declaration permanently shadows a previous declaration. GNU C++ does however support local enum declarations. Access to class-level enum values are checked the same way that access is checked for class members and
9944 UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
member functions, so it is possible to have private and pro- tected enum values.
The ‘-p’ and ‘-pg’ options are not yet supported. The reason for this is that to work with these options, a spe- cial crt0.o file must be used. Such files have not yet been modified to work with GNU C++.
GNU C++ does not currently implement the arcane C trick that permits the commutativity of arrays and integer indexes. For example, the legal C fragment:
int i = 10; int a[20];
i[a] = 100;
does not compile with GNU C++. Do not expect this “feature” to work until a compelling argument for its inclusion is presented.
GNU C++ does not yet detect and warn about all possible misuses of goto statements that incorrectly jump into and out of nested blocks containing class objects with construc- tors and destructors.
Work on supporting multiple inheritance is underway, and appears almost fully operational in the current imple- mentation. Your help with testing and debugging multiple inheritance in GNU C++ is very useful.
1155.. RReellaatteedd ddooccuummeennttaattiioonn aanndd bbiibblliiooggrraapphhyy
[1] Stroustrup, Bjarne: _T_h_e _C++ _P_r_o_g_r_a_m_m_i_n_g _L_a_n_g_u_a_g_e. Addison-Wesley, 1986.
[2] Stroustrup, Bjarne: _T_h_e _E_v_o_l_u_t_i_o_n _o_f _C++: _1_9_8_5 _t_o _1_9_8_7 First USENIX C++ Workshop Proceedings, Santa Fe NM, 1987.
[3] Stallman, Richard: _U_s_i_n_g _a_n_d _P_o_r_t_i_n_g _G_N_U _C_C Free Software Foundation, 1988.
[4] Stallman, Richard: _G_D_B, _T_h_e _G_N_U _D_e_b_u_g_g_e_r Free Software Foundation, 1988.
[5] Stallman, Richard: _G_N_U _E_m_a_c_s _M_a_n_u_a_l Fifth Edition, Emacs Version 18 for Unix Users, Free Software Foundation, October 1986.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ 9955
[6] Tiemann, Michael: _W_r_a_p_p_e_r_s: _S_o_l_v_i_n_g _t_h_e _R_P_C _P_r_o_b_l_e_m _i_n _G_N_U _C++ First USENIX Technical Conference, Denver CO, 1988.
[7] Tiemann, Michael: _A_n _E_x_c_e_p_t_i_o_n _H_a_n_d_l_i_n_g _I_m_p_l_e_m_e_n_t_a_- _t_i_o_n _f_o_r _C++ (to appear) USENIX Technical Conference, San Francisco CA, 1990.
[8] Stroustrup, Bjarne: _T_h_e _E_v_o_l_u_t_i_o_n _o_f _C++: _1_9_8_5 _t_o _1_9_8_9 AT&T Bell Labs Tech Report.
UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++ ii
TTaabbllee ooff CCoonntteennttss
GNU CC GENERAL PUBLIC LICENSE ......................... 1 COPYING POLICIES ...................................... 2 NO WARRANTY ........................................... 4 Contributors to GNU C++ ............................... 4 1 GNU C++ Command Options ....................... 5 2 Installing GNU C++ ............................ 28 3 Trouble in Installation ....................... 40 4 GNU C++ Header Files and Libraries ............ 41 5 Incompatibilities of GNU C++ .................. 42 6 GNU Extensions to the C++ Language ............ 49 6.1 Statements and Declarations inside of Expressions .................................................. 49 6.2 Naming an Expression’s Type .................. 50 6.3 Referring to a Type with typeof .............. 5500 66..44 GGeenneerraalliizzeedd LLvvaalluueess .......................... 5522 66..55 CCoonnddiittiioonnaall EExxpprreessssiioonnss wwiitthh OOmmiitttteedd MMiiddddllee-- OOppeerraannddss ......................................... 5533 66..66 AArrrraayyss ooff LLeennggtthh ZZeerroo ........................ 5544 66..77 AArrrraayyss ooff VVaarriiaabbllee LLeennggtthh .................... 5544 66..88 NNoonn--LLvvaalluuee AArrrraayyss MMaayy HHaavvee SSuubbssccrriippttss ........ 5555 66..99 AArriitthhmmeettiicc oonn void-- PPooiinntteerrss aanndd FFuunnccttiioonn PPooiinntteerrss ................... 5566 66..1100 NNoonn--CCoonnssttaanntt IInniittiiaalliizzeerrss ................... 5566 66..1111 CCoonnssttrruuccttoorr EExxpprreessssiioonnss ..................... 5566 66..1122 DDeeccllaarriinngg AAttttrriibbuutteess ooff FFuunnccttiioonnss ........... 5577 66..1133 DDoollllaarr SSiiggnnss iinn IIddeennttiiffiieerr NNaammeess ............ 5588 66..1144 IInnqquuiirriinngg aabboouutt tthhee AAlliiggnnmmeenntt ooff aa TTyyppee oorr VVaarriiaabbllee .................................................. 5588 66..1155 AAsssseemmbblleerr IInnssttrruuccttiioonnss wwiitthh CC EExxpprreessssiioonn OOppeerraannddss .................................................. 5599 66..1166 CCoonnttrroolllliinngg NNaammeess UUsseedd iinn AAsssseemmbblleerr CCooddee .................................................. 6633 66..1177 GGlloobbaall VVaarriiaabblleess iinn RReeggiisstteerrss ............... 6633 66..1188 NNoonn-- CC ooppeerraattoorrss:: operator <? aanndd operator >? ......... 6655 66..1199 CCoonnttrroolllliinngg operator new.. ................... 6666 66..2200 FFuunnccttiioonn ccaallllss aass ffiirrsstt--ccllaassss oobbjjeeccttss ....... 6677 66..2211 SSwwiittcchh RRaannggeess ............................... 6699 66..2222 SSttaattiicc MMeemmbbeerr FFuunnccttiioonnss ..................... 7700 66..2233 EExxcceeppttiioonn HHaannddiinngg ........................... 7722 77 FFeeaattuurreess ooff GGNNUU CC++++ ........................... 7744 77..11 SSttrruuccttuurreess aass AArrgguummeennttss ...................... 7744 77..22 TThhee ggoottoo ssttaatteemmeenntt iinn GGNNUU CC++++ ................ 7755 77..33 TTyyppee iinnssttaannttiiaattiioonn iinn GGNNUU CC++++ ................ 7755 77..44 IInnccrreemmeennttaall LLiinnkkiinngg aanndd GGNNUU CC++++ .............. 7777 77..55 AAvvooiidd eexxttrraa ccoonnssttrruuccttoorr ccaallll wwhheenn rreettuurrnniinngg ccllaasssseess ffrroomm ffuunnccttiioonnss..
iiii UUsseerr’’ss GGuuiiddee ttoo GGNNUU CC++++
.................................................. 7777 88 RReeppoorrttiinngg BBuuggss ................................ 7799 88..11 HHaavvee YYoouu FFoouunndd aa BBuugg?? ........................ 7799 88..22 HHooww ttoo RReeppoorrtt BBuuggss ........................... 8800 99 GGNNUU CC++++ aanndd PPoorrttaabbiilliittyy ....................... 8844 1100 IInntteerrffaacciinngg ttoo GGNNUU CC++++ OOuuttppuutt ................. 8855 1111 PPaasssseess aanndd FFiilleess ooff tthhee CCoommppiilleerr .............. 8877 1122 TThhee CCoonnffiigguurraattiioonn FFiillee ........................ 9922 1133 TThhiinnggss ssttiillll lleefftt ttoo ddoo ffoorr GGNNUU CC++++ ........... 9933 1144 LLiisstt ooff ccuurrrreennttllyy kknnoowwnn bbuuggss iinn GGNNUU CC++++ ....... 9933 1155 RReellaatteedd ddooccuummeennttaattiioonn aanndd bbiibblliiooggrraapphhyy ........ 9944
This document was generated on April 2, 2025 using texi2html 5.0.