From mboxrd@z Thu Jan 1 00:00:00 1970
Return-Path:
>+ 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. >+ >+>+ >+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. >+ >+
>+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 gnulib or >+autoconf-archive >+may need to update these sources files from their upstream versions. >+ >+
>+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. >+ >+
int
types (-Werror=implicit-int
)int
keyword
>+addresses the error. For example, a flag like
>+
>+>+ static initialized; >+>+ >+might turn into: >+ >+
>+ static int initialized; >+>+ >+
If the return type of a function is omitted, the correct type to
>+add could be int
or void
, depending on
>+whether the function returns a value or not.
>+
>+
In some cases, the previously implied int
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 s
should be
>+const char *
, not int
:
>+
>+
>+ write_string (fd, s) >+ { >+ write (1, s, strlen (s)); >+ } >+>+ >+The corrected standard C source code might look like this (still >+disregarding error handling and short writes): >+ >+
>+ void >+ write_string (int fd, const char *s) >+ { >+ write (1, s, strlen (s)); >+ } >+>+ >+
-Werror=implicit-function-declaration
)
>+For well-known functions declared in standard headers, GCC provides
>+fix-it hints with the appropriate #include
directives:
>+
>+
>+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 | >+>+ >+
>+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 Feature Test Macros >+in the GNU C Library manual for details. >+ >+
>+Some programs are built with -std=c11
or
>+similar -std
options that do not contain the
>+string gnu
, but these programs still use POSIX or other
>+extensions in standard C headers such as <stdio.h>
.
>+The GNU C library automatically suppresses these extensions in
>+standard C mode, which can result in implicit function declarations.
>+To address this, the -std=c11
option can be
>+dropped, -std=gnu11
can be used instead,
>+or -std=c11 -D_DEFAULT_SOURCE
can be used re-enable
>+common extensions.
>+
>+
>+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
>+-flto -Werror=lto-type-mismatch
, which can help with
>+adding appropriate prototypes.
>+
>+
>+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: >+ >+
>+ void no_prototype (); >+>+ >+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. >+ >+
>+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. >+ >+
-Werror=declaration-missing-parameter-type
)-Wdeclaration-missing-parameter-type
warning. The
>+second line in the following example is now treated as an error
>+(previously this resulted in an unnamed warning):
>+
>+>+ typedef int *int_array; >+ int first_element (intarray); >+>+ >+The fix is to correct the spelling mistake: >+ >+
>+ typedef int *int_array; >+ int first_element (int_array); >+>+ >+GCC will type-check function arguments after that, potentially >+requiring further changes. (Previously, the function declaration was >+treated as not having no prototype.) >+ >+
return
statement (-Werror=return-mismatch
)return
statements with expressions
>+in functions which are declared to return void
, or
>+return
statements without expressions for functions
>+returning a nonvoid
type.
>+
>+
>+To address this, remove the incorrect expression (or turn it into a
>+statement expression immediately prior to the return
>+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.
>+
>+
>+Previously, these mismatches were diagnosed as
>+a -Wreturn-type
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 }
of function that does not
>+return void
.
>+
>+
>+By default, GCC still accepts returning an expression of
>+type void
from within a function that itself
>+returns void
, as a GNU extension that matches C++ rules
>+in this area.
>+
>+
-Werror=int-conversion
)
>+It makes sense to address missing int
type, implicit
>+function declarations, and incorrect return
statement
>+usage prior to tackling these int
-conversion issues.
>+Some of them will be caused by missing types resulting
>+in int
, and the default int
return type of
>+implicitly declared functions.
>+
>+
To fix the remaining int
-conversions issues, add casts
>+to an appropriate pointer or integer type. On GNU systems, the
>+standard (but generally optional) types
>+intptr_t
and uintptr_t
(defined
>+in <stdint.h>
) are always large enough to store all
>+pointer values. If you need a generic pointer type, consider
>+using void *
.
>+
>+
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. >+ >+
-Werror=incompatible-pointer-types
)void *
type and
>+its qualified variations.
>+
>+
>+To fix the compilation errors resulting from that, you can add the
>+appropriate casts, and maybe consider using code void *
>+in more places (particularly for old programs that predate the
>+introduction of void
into the C language).
>+
>+
>+Programs that do not carefully track pointer types are likely to
>+contain aliasing violations, so consider building
>+with -fno-strict-aliasing
as well. (Whether the casts
>+are written manually or performed by GCC automatically does not make a
>+difference in terms of strict aliasing violations.)
>+
>+
>+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: >+ >+
>+#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); >+} >+>+ >+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): >+ >+
>+int >+compare (const void *a1, const void *b1) >+{ >+ char *const *a = a1; >+ char *const *b = b1; >+ return strcmp (*a, *b); >+} >+>+ >+
>+A similar issue can arise with object pointer types. Consider a
>+function that is declared with an argument of type
>+void **
, and you want to pass the address of a variable
>+of type int *
:
>+
>+
>+extern int *pointer; >+extern void operate (int command, void **); >+ >+operate (0, &pointer); >+>+ >+In these cases, it may be appropriate to make a copy of the pointer >+with the correct
void *
type:
>+
>+>+extern int *pointer; >+extern void operate (int command, void **); >+ >+void *pointer1 = pointer; >+operate (0, &pointer1); >+pointer = pointer1; >+>+ >+As mentioned initially, adding the cast here would not eliminate any >+strict aliasing violation in the implementation of >+the
operate
function. Of course in general, introducing
>+such additional copies may alter program behavior.
>+
>+
>+Some programming styles rely on implicit casts between related object
>+pointer types to implement C++-style struct
inheritance.
>+It may be possible to avoid writing manual casts with
>+the -fplan9-extensions
options and unnamed
>+initial struct
fields for the base type in
>+derived struct
s.
>+
>+
>+Some programs use a concrete function pointer type such as
>+void (*) (void)
as a generic function pointer type
>+(similar to void *
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 void *
and function pointer types. However, for
>+a portable solution, the concrete function pointer type needs to be
>+used, together with explicit casts.
>+
>+
>+In cases where this is a concern, generated config.log
,
>+config.h
and other source code files can be compared
>+using diff,
>+to ensure there are no unexpected differences.
>+
>+
>+This phenomenon also impacts similar procedures part of CMake, Meson, s/part of/that are part of/ ? >+and various build tools for C extension modules of scripting >+languages. >+ >+
>+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. >+ >+
>+Sources that cannot be ported to standard C can be compiled
>+with -fpermissive
, -std=gnu89
,
>+or -std=c89
. Despite their names, the latter two options
>+turn on support for pre-standard C constructs, too. With the
>+-fpermissive
options, programs can use C99 inlining
s/options/option/
>+semantics and features that were removed from C99. Alternatively,
>+individual warnings can be downgraded to warnings using
s/individual warnings/individual errors/ ?
>+the -Wno-error=…
option, or disabled complete
s/the/the relevant/ ?
>+with -Wno-…
. For example,
>+-Wno-error=incompatible-pointer-types
turns off most type
>+checking for pointer assignments.
>+
>+
>+Some build systems do not pass the CFLAGS
environment
>+or make
variable to all parts of the builds, and may
>+require setting CC
to something like gcc
>+-fpermissive
instead. If the build system does not support
>+whitespace in the CC
variable, a wrapper script like this
>+may be required:
>+
>+
>+#!/bin/sh >+exec /usr/bin/gcc -fpermissive "$@" >+>+ >+
#pragma GCC diagnostic warning
directives to
You could link this text to
https://gcc.gnu.org/onlinedocs/gcc/Diagnostic-Pragmas.html
>+turn these errors back into warnings:
>+
>+>+#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 >+>+ >+Not listed here are
-Wimplicit-int
>+and -Wdeclaration-missing-parameter-type
because they
>+should be straightforward to address in a code generator.
>+
>+
>+It is unclear at which point GCC can enable the C23 bool
>+keyword by default (making the bool
type available
>+without including #include <stdbool.h>
explicitly).
>+Many programs define their own bool
types, sometimes with
>+a different size of the already-available _Bool
type. A
>+further complication is that even if the sizes are the same, a custom
>+bool
typically does not have trap representations,
>+while _Bool
and the new bool
type do. This
>+means that there can be subtle compatibility issues, particularly when
>+processing untrusted, not necessarily well-formed input data.
>+
>+
>+GCC is unlikely to warn about function declarations that are not >+prototypes by default. This means that there is no stringent reason >+to turn >+ >+
>+void do_something (); >+>+ >+into >+ >+
>+void do_something (void); >+>+ >+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 >+(
do_something (1)
, for example). Eventually, GCC will
>+diagnose such calls as errors because they are constraint violations
>+in C23.
>+
>+>+GCC will probably continue to support old-style function definitions >+even once C23 is used as the default language dialect. >+ >