* Joseph Myers:

> On Wed, 10 May 2023, Eli Zaretskii via Gcc wrote:
>
>> That is not the case we are discussing, AFAIU.  Or at least no one has
>> yet explained why accepting those old K&R programs will adversely
>> affect the ability of GCC to compile C2x programs.
>
> At block scope,
>
>   auto x = 1.5;
>
> declares x to have type double in C2x (C++-style auto), but type int in 
> C89 (and is invalid for versions in between).  In this case, there is an 
> incompatible semantic change between implicit int and C++-style auto.  
> Giving an error before we make -std=gnu2x the default seems like a 
> particularly good idea, to further alert anyone who has been ignoring the 
> warnings about implicit int that semantics will change incompatibly.

Obviously makes sense to me.

> In cases where the standard requires a diagnostic, some are errors, some 
> are pedwarns-by-default or unconditional pedwarns, some are 
> pedwarns-if-pedantic - the choice depending on how suspicious the 
> construct in question is and whether it corresponds to a meaningful 
> extension (this is not making an automatic choice for every such situation 
> in the standard, it's a case-by-case judgement by maintainers).  By now, 
> the cases discussed in this thread are sufficiently suspicious - 
> sufficiently likely to result in unintended execution at runtime (not, of 
> course, reliably detected because programs with such dodgy code are very 
> unlikely to have thorough automated tests covering all their code) - that 
> is it in the interests of users for them to be errors by default (for C99 
> and later modes, in the cases that were valid in C89).

Just to recap, those are controlled by
-Wimplicit-function-declaration, -Wimplicit-int, -Wint-conversion, and
-Wincompatible-pointer-types, roughly in increasing order of
compatibility impact with old sources.

> It might also make sense to review other pedwarns-by-default and 
> unconditional pedwarns to consider if any of those should be errors by 
> default, though I suspect most of those are less significant.

I went through the pedwarn calls in the C front end.

First, these two appear to be genuine bugs:

  Incompatible pointer types in ?: not covered by -Wincompatible-pointer-types
  <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109826>

  Pointer/integer mismatch in ?: not covered by -Wint-conversion
  <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109827

Maybe the latter more so than the former.  These create pointer
values, so they seem problematic.

There are related coverage gaps for comparison operators for the more
specific -W… options:

  pedwarn (location, 0, "comparison of distinct pointer types lacks a cast");
  pedwarn (location, OPT_Wpedantic, 
           "ordered comparison of pointer with integer zero");
  pedwarn (location, 0, "comparison between pointer and integer");

These expressions do not create pointer values, so maybe they are less
likely to introduce bugs?  But they are type errors in standard C.
(Clang has separate warnings for those, -Wcompare-distinct-pointer-types.)


Moving on, this seems to be a good candidate for an error:

  pedwarn (input_location, 0, "parameter names (without types) in "
           "function declaration");

The reason is that

  void f (uint3_t);

is a function declaration without a prototype, which is very likely
not what is intended.  The error diagnostic could also provide a
spelling hint for the type.


We may not need to do anything for this one (except removing cascading
errors) because I think this is only reachable when an implicit int is
involved:

  pedwarn (here, 0, "data definition has no type or storage class");


(Slightly unrelated because it's a purely syntactic issue.  It's about
designated initaliziers of the form “{ a[0] 1 }”:

  pedwarn (c_parser_peek_token (parser)->location, OPT_Wpedantic,
           "obsolete use of designated initializer without %<=%>");

Unclear whether we still need to support that, but also harmless, I
guess.)


This one seems to be hack to support obsolete wait function usage.  We
probably don't need it any more because the union wait was removed
from glibc 2.24, and the function prototypes in glibc are now more
standard.  The union wait type was deprecated in the early 90s.

  /* Given  wait (union {union wait *u; int *i} *)
     and  wait (union wait *),
     prefer  union wait *  as type of parm.  */
   pedwarn (input_location, OPT_Wpedantic,
            "function types not truly compatible in ISO C")

And furher below in c-typeck.cc:

  /* Allow  wait (union {union wait *u; int *i} *)
     and  wait (union wait *)  to be compatible.  */

I think it should be safe to error for these by default.


I couldn't figure out what these warnings are about:

  pedwarn (input_location, OPT_Wpedantic,
           "function types not truly compatible in ISO C");
  pedwarn (location, OPT_Wpedantic, "types are not quite compatible");


This seems to be mainly for &*p if p is of type void *:

  warning_at (loc, 0, "dereferencing %<void *%> pointer");
  pedwarn (location, 0, "taking address of expression of type %<void%>");

Rather hideous, but maybe harmless in the grand scheme of things?


One rather large set of pedwarns concerns qualifier mismatches.  I
believe this is about technically undefined behavior, so maybe the
warning is not about things that are entirely harmless.  Implicitly
dropping const-ness from pointers could cause crashes at a later
stage, so more rigorous errors could point at the location of the
actual mistake.  On the other hand, C programs aiming for full
const-correctness are quite rare.  Adding all those casts for things
like

  volatile int x[4];
  memset (x, 0, sizeof (x));

would be quite cumbersome, too.  So I'm not sure what to do about
these.

Then there is -Wpointer-sign.  The Linux kernel really dislikes that
warning, so we would want a mechanism to control that separately.
Again not sure what to do about those.


This sone seems to be a good candidate for additional errors, though:

  warned_here = pedwarn
    (loc, warn_return_type >= 0 ? OPT_Wreturn_type : 0,
     "%<return%> with no value, in function returning non-void");

It's a clear type volation that can lead to obscure bugs.  Maybe the
converse as well.


In summary, all these seems to be good candidates for errors by default:

* int-conversion as errors (already raised separately
* -Wint-conversion for ?:
* parameter names in non-prototype function declarations
* the union wait function pointer compatibility kludge
* return-with-out-value for non-void functions
* -Wincomatible-pointer-types warning for ?: (but no error yet, see below)

This are more “maybe“:

* incompatible-pointer-types as errors (already raised separately)
* int-conversion and incompatible-pointer-types in comparisons
* return with value in a function returning void
* dereferencing void *
* taking the address of void
* "function types not truly compatible in ISO C"
  and "types are not quite compatible" (depending on what they actually mean)
* qualifier mismatches (may need separate opt-out)
* sign mismatches in pointers (definitely needs separate opt-out)

I can do experiments on the Fedora code base in the coming weeks for
at least a subset of those.  The second list likely has a few with
quite high cost for us.  I suspect even incompatible-pointer-types is
problematic in that regard.  The first list seems more manageable,
although int-conversion is also a fairly big work item (and I need to
find a way to cut down the number of false positives from the tester).

Reply via email to