--- htdocs/gcc-14/porting_to.html | 465 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 465 insertions(+)
diff --git a/htdocs/gcc-14/porting_to.html b/htdocs/gcc-14/porting_to.html index 3e4cedc3..4c8f9c8f 100644 --- a/htdocs/gcc-14/porting_to.html +++ b/htdocs/gcc-14/porting_to.html @@ -24,6 +24,471 @@ porting to GCC 14. This document is an effort to identify common issues and provide solutions. Let us know if you have suggestions for improvements! </p> +<h2 id="c">C language issues</h2> + +<h3 id="warnings-as-errors">Certain warnings are now errors</h3> + +<blockquote cite="https://archive.org/details/PC-Mag-1988-09-13/page/n115/mode/2up"> + Function prototyping was added, first to help enforce type checking + on both the types of the arguments passed to the function, and also + to check the assignment compatibility of the function return type. + <footer> + <cite>Standard C: The ANSI Draft Grows Up. + PC Magazine, September 13, 1988, page 117.</cite> + </footer> +</blockquote> + +The initial ISO C standard and its 1999 revision removed support for +many C language features that were widely known as sources of +application bugs due to accidental misuse. For backwards +compatibility, GCC 13 and earlier compiler versions diagnosed use of +these features as warnings only. Although these warnings have been +enabled by default for many releases, experience shows that these +warnings are easily ignored, resulting in difficult-to-diagnose bugs. +In GCC 14, these issues are now reported as errors, and no output file +is created, providing clearer feedback to programmers that something +is wrong. + +<p> +Most components of the GNU project have already been fixed for +compatibility, but not all of them have had releases since fixes were +applied. Programs that bundle parts +of <a href="https://www.gnu.org/software/gnulib/">gnulib</a> or +<a href="https://www.gnu.org/software/autoconf-archive/">autoconf-archive</a> +may need to update these sources files from their upstream versions. + +<p> +Several GNU/Linux distributions have shared patches from their porting +efforts on relevant upstream mailing lists and bug trackers, but of +course there is a strong overlap between programs that have these +historic C compatibility issues and are dormant today. + +<h4 id="implicit-int">Implicit <code>int</code> types (<code>-Werror=implicit-int</code>)</h4> + +In most cases, simply adding the missing <code>int</code> keyword +addresses the error. For example, a flag like + +<pre> + static initialized; +</pre> + +might turn into: + +<pre> + static <ins>int</ins> initialized; +</pre> + +<p>If the return type of a function is omitted, the correct type to +add could be <code>int</code> or <code>void</code>, depending on +whether the function returns a value or not. + +<p>In some cases, the previously implied <code>int</code> type +was not correct. This mostly happens in function definitions +that are not prototypes, when argument types are not +declared outside the parameter list. Using the correct +type maybe required to avoid int-conversion errors (see below). +In the example below, the type of <code>s</code> should be +<code>const char *</code>, not <code>int</code>: + +<pre> + write_string (fd, s) + { + write (1, s, strlen (s)); + } +</pre> + +The corrected standard C source code might look like this (still +disregarding error handling and short writes): + +<pre> + <ins>void</ins> + write_string (<ins>int</ins> fd, const char *s) + { + write (1, s, strlen (s)); + } +</pre> + +<h4 id="implicit-function-declaration">Implicit function declarations (<code>-Werror=implicit-function-declaration</code>)</h4> + +It is no longer possible to call a function that has not been +declared. In general, the solution is to include a header file with +an appropriate function prototype. Note that GCC will perform further +type checks based on the function prototype, which can reveal further +type errors that require additional changes. + +<p> +For well-known functions declared in standard headers, GCC provides +fix-it hints with the appropriate <code>#include</code> directives: + +<pre> +error: implicit declaration of function ‘strlen’ [-Wimplicit-function-declaration] + 5 | return strlen (s); + | ^~~~~~ +note: include ‘<string.h>’ or provide a declaration of ‘strlen’ + +++ |+#include <string.h> + 1 | +</pre> + +<p> +On GNU systems, headers described in standards (such as the C +standard, or POSIX) may require the definition of certain +macros at the start of the compilation before all required +function declarations are made available. +See <a href="https://sourceware.org/glibc/manual/html_node/Feature-Test-Macros.html">Feature Test Macros</a> +in the GNU C Library manual for details. + +<p> +Some programs are built with <code>-std=c11</code> or +similar <code>-std</code> options that do not contain the +string <code>gnu</code>, but these programs still use POSIX or other +extensions in standard C headers such as <code><stdio.h></code>. +The GNU C library automatically suppresses these extensions in +standard C mode, which can result in implicit function declarations. +To address this, the <code>-std=c11</code> option can be +dropped, <code>-std=gnu11</code> can be used instead, +or <code>-std=c11 -D_DEFAULT_SOURCE</code> can be used re-enable +common extensions. + +<p> +If undeclared functions from the same project are called and there is +yet no suitable shared header file, you should add a declaration to a +header file that is included by both the callers and the source file +containing the function definition. This ensures that GCC checks that +the prototype matches the function definition. GCC can perform type +checks across translation units when building with options such as +<code>-flto -Werror=lto-type-mismatch</code>, which can help with +adding appropriate prototypes. + +<p> +In some rare cases, adding a prototype may change ABI in inappropriate +ways. In these situations, it is necessary to declaration a function +without prototype: + +<pre> + void no_prototype (); +</pre> + +However, this is an obsolete C feature that will change meaning in C23 +(declaration a function with a prototype and accepting no arguments, +similar to C++). Usually, a prototype with the default argument +promotions applied can be used instead. + +<p> +When building library code on GNU systems, it was possible to call +undefined (not just undeclared) functions and still run other code in +the library, particularly if ELF lazy binding was used. Only +executing the undefined function call would result in a lazy binding +error and program crash. + +<h4 id="missing-parameter-types">Typos in function prototypes (<code>-Werror=declaration-missing-parameter-type</code>)</h4> + +Incorrectly spelled type names in function declarations are treated as +errors in more cases, under a +new <code>-Wdeclaration-missing-parameter-type</code> warning. The +second line in the following example is now treated as an error +(previously this resulted in an unnamed warning): + +<pre> + typedef int *int_array; + int first_element (intarray); +</pre> + +The fix is to correct the spelling mistake: + +<pre> + typedef int *int_array; + int first_element (<ins>int_array</ins>); +</pre> + +GCC will type-check function arguments after that, potentially +requiring further changes. (Previously, the function declaration was +treated as not having no prototype.) + +<h4 id="return-mismatch">Incorrect uses of the <code>return</code> statement (<code>-Werror=return-mismatch</code>)</h4> + +GCC no longer accepts <code>return</code> statements with expressions +in functions which are declared to return <code>void</code>, or +<code>return</code> statements without expressions for functions +returning a non<code>void</code> type. + +<p> +To address this, remove the incorrect expression (or turn it into a +statement expression immediately prior to the <code>return</code> +statements if the expression has side effects), or add a dummy return +value, as appropriate. If there is no suitable dummy return value, +further changes may be needed to implement appropriate error handling. + +<p> +Previously, these mismatches were diagnosed as +a <code>-Wreturn-type</code> warning. This warning still exists, and +is not treated as an error by default. It now covers remaining +potential correctness issues, such as reaching the closing +brace <code>}</code> of function that does not +return <code>void</code>. + +<p> +By default, GCC still accepts returning an expression of +type <code>void</code> from within a function that itself +returns <code>void</code>, as a GNU extension that matches C++ rules +in this area. + +<h4 id="int-conversion">Using pointers as integers and vice versa (<code>-Werror=int-conversion</code>)</h4> + +GCC no longer treats integer types and pointer types as equivalent in +assignments (including implied assignments of function arguments and +return values), and instead fails the compilation with a type error. + +<p> +It makes sense to address missing <code>int</code> type, implicit +function declarations, and incorrect <code>return</code> statement +usage prior to tackling these <code>int</code>-conversion issues. +Some of them will be caused by missing types resulting +in <code>int</code>, and the default <code>int</code> return type of +implicitly declared functions. + +<p>To fix the remaining <code>int</code>-conversions issues, add casts +to an appropriate pointer or integer type. On GNU systems, the +standard (but generally optional) types +<code>intptr_t</code> and <code>uintptr_t</code> (defined +in <code><stdint.h></code>) are always large enough to store all +pointer values. If you need a generic pointer type, consider +using <code>void *</code>. + +<p> Note that in some cases, it may be more appropriate to pass the +address of an integer variable instead of a cast of the variable's +value. + +<h4 id="incompatible-pointer-types">Type checking on pointer types (<code>-Werror=incompatible-pointer-types</code>)</h4> + +GCC no longer casts all pointer types to all other pointer types. +This behavior is now restricted to the <code>void *</code> type and +its qualified variations. + +<p> +To fix the compilation errors resulting from that, you can add the +appropriate casts, and maybe consider using code <code>void *</code> +in more places (particularly for old programs that predate the +introduction of <code>void</code> into the C language). + +<p> +Programs that do not carefully track pointer types are likely to +contain aliasing violations, so consider building +with <code>-fno-strict-aliasing</code> as well. (Whether the casts +are written manually or performed by GCC automatically does not make a +difference in terms of strict aliasing violations.) + +<p> +A frequent source of incompatible function pointer types involves +callback functions that have more specific argument types (or less +specific return types) than the function pointer they are assigned to. +For example, old code which attempts to sort an array of strings might +look like this: + +<pre> +#include <stddef.h> +#include <stdlib.h> +#include <string.h> + +int +compare (char **a, char **b) +{ + return strcmp (*a, *b); +} + +void +sort (char **array, size_t length) +{ + qsort (array, length, sizeof (*array), compare); +} +</pre> + +To correct this, the callback function should be defined with the +correct type, and the arguments should be cast as appropriate before +they are used (as calling a function through a function pointer of an +incorrect type is undefined): + +<pre> +int +compare (<ins>const void *a1</ins>, <ins>const void *b1</ins>) +{ + <ins>char *const *a = a1;</ins> + <ins>char *const *b = b1;</ins> + return strcmp (*a, *b); +} +</pre> + +<p> +A similar issue can arise with object pointer types. Consider a +function that is declared with an argument of type +<code>void **</code>, and you want to pass the address of a variable +of type <code>int *</code>: + +<pre> +extern int *pointer; +extern void operate (int command, void **); + +operate (0, &pointer); +</pre> + +In these cases, it may be appropriate to make a copy of the pointer +with the correct <code>void *</code> type: + +<pre> +extern int *pointer; +extern void operate (int command, void **); + +<ins>void *pointer1 = pointer;</ins> +operate (0, &pointer<ins>1</ins>); +<ins>pointer = pointer1;</ins> +</pre> + +As mentioned initially, adding the cast here would not eliminate any +strict aliasing violation in the implementation of +the <code>operate</code> function. Of course in general, introducing +such additional copies may alter program behavior. + +<p> +Some programming styles rely on implicit casts between related object +pointer types to implement C++-style <code>struct</code> inheritance. +It may be possible to avoid writing manual casts with +the <code>-fplan9-extensions</code> options and unnamed +initial <code>struct</code> fields for the base type in +derived <code>struct</code>s. + +<p> +Some programs use a concrete function pointer type such as +<code>void (*) (void)</code> as a generic function pointer type +(similar to <code>void *</code> for object pointer types), and rely on +implicit casts to and from this type. The reason for that is that C +does not offer a generic function pointer type, and standard C +disallows casts between function pointer types and object pointer +types. On most targets, GCC supports implicit conversion +between <code>void *</code> and function pointer types. However, for +a portable solution, the concrete function pointer type needs to be +used, together with explicit casts. + +<h4 id="autoconf">Impact on Autoconf and build environment probing in general</h4> + +Most <a href="https://www.gnu.org/software/autoconf/">Autoconf</a> +probes that check for build system features are written in such a way +that they trigger a compiler error if a feature is missing. The new +errors may cause GCC to fail compiling a probe when it worked before, +unrelated to the actual objective of the probe. These failed probes +tend to consistently disable program features and their tests, which +means that an unexpected probe failure may result in silently dropping +features. + +<p> +In cases where this is a concern, generated <code>config.log</code>, +<code>config.h</code> and other source code files can be compared +using <a href="https://www.gnu.org/software/diffutils/">diff</a>, +to ensure there are no unexpected differences. + +<p> +This phenomenon also impacts similar procedures part of CMake, Meson, +and various build tools for C extension modules of scripting +languages. + +<p> +Autoconf has supported C99 compilers since at least version 2.69 in +its generic, core probes. (Specific functionality probes may have +issues addressed in more recent versions.) Versions before 2.69 may +have generic probes (for example for standard C support) that rely on +C features that were removed in 1999 and thus fail with GCC 14. + +<h4 id="errors-as-warnings">Turning errors back into warnings</h4> + +<p> +Sources that cannot be ported to standard C can be compiled +with <code>-fpermissive</code>, <code>-std=gnu89</code>, +or <code>-std=c89</code>. Despite their names, the latter two options +turn on support for pre-standard C constructs, too. With the +<code>-fpermissive</code> options, programs can use C99 inlining +semantics and features that were removed from C99. Alternatively, +individual warnings can be downgraded to warnings using +the <code>-Wno-error=…</code> option, or disabled complete +with <code>-Wno-…</code>. For example, +<code>-Wno-error=incompatible-pointer-types</code> turns off most type +checking for pointer assignments. + +<p> +Some build systems do not pass the <code>CFLAGS</code> environment +or <code>make</code> variable to all parts of the builds, and may +require setting <code>CC</code> to something like <code>gcc +-fpermissive</code> instead. If the build system does not support +whitespace in the <code>CC</code> variable, a wrapper script like this +may be required: + +<pre> +#!/bin/sh +exec /usr/bin/gcc -fpermissive "$@" +</pre> + +<h4 id="c-code-generators">Accommodating C code generators</h4> + +C code generators that cannot be updated to generate valid standard C +can emit <code>#pragma GCC diagnostic warning</code> directives to +turn these errors back into warnings: + +<pre> +#if defined __GNUC__ && __GNUC__ >= 14 +#pragma GCC diagnostic warning "-Wimplicit-function-declaration" +#pragma GCC diagnostic warning "-Wincompatible-pointer-types" +#pragma GCC diagnostic warning "-Wint-conversion" +#pragma GCC diagnostic warning "-Wreturn-mismatch" +#endif +</pre> + +Not listed here are <code>-Wimplicit-int</code> +and <code>-Wdeclaration-missing-parameter-type</code> because they +should be straightforward to address in a code generator. + +<h4 id="warnings-as-errors-future-directions">Future directions</h4> + +This section concerns potential future changes related to language +features from the C standard and other backwards compatibility +hazards. These plans may change and are mentioned here only to give +guidance which source-level changes to prioritize for future compiler +compatibility. + +<p> +It is unclear at which point GCC can enable the C23 <code>bool</code> +keyword by default (making the <code>bool</code> type available +without including <code>#include <stdbool.h></code> explicitly). +Many programs define their own <code>bool</code> types, sometimes with +a different size of the already-available <code>_Bool</code> type. A +further complication is that even if the sizes are the same, a custom +<code>bool</code> typically does not have trap representations, +while <code>_Bool</code> and the new <code>bool</code> type do. This +means that there can be subtle compatibility issues, particularly when +processing untrusted, not necessarily well-formed input data. + +<p> +GCC is unlikely to warn about function declarations that are not +prototypes by default. This means that there is no stringent reason +to turn + +<pre> +void do_something (); +</pre> + +into + +<pre> +void do_something (void); +</pre> + +except for diagnosing extraneous ignored arguments as errors. A +future version of GCC will likely warn about calls to functions +without a prototype which specify such extraneous arguments +(<code>do_something (1)</code>, for example). Eventually, GCC will +diagnose such calls as errors because they are constraint violations +in C23. + +<p> +GCC will probably continue to support old-style function definitions +even once C23 is used as the default language dialect. + <h2 id="cxx">C++ language issues</h2> <h3 id="header-dep-changes">Header dependency changes</h3> base-commit: 15056edbb60e24a6410d9b75f7386de28ea60bc1
