Unexpected warning in -std=gnu89 -pedantic mode.

Hello.

There seems to be a problem in the handling of diagnostic for GNU extensions: some warnings are produced even though the -std=gnu89 option is specified.

$ cat aaa.c
int foo() {
   return ({2+3;});
}

$ clang-cc -std=gnu89 -pedantic aaa.c
aaa.c:2:11: warning: use of GNU statement expression extension
   return ({2+3;});
           ^
1 diagnostic generated.
$

The same happens when using, e.g., __builtin_offsetof.

Cheers,
Enea Zaffanella.

There seems to be a problem in the handling of diagnostic for GNU
extensions: some warnings are produced even though the -std=gnu89 option
is specified.

We probably have quite a few of these problems, because many of these extension diagnostics were written before we distinguished between the different kinds of extensions (e.g., Microsoft vs. GNU), so they conflate "is an extension diagnostic" with "is a GNU extension.

$ cat aaa.c
int foo() {
  return ({2+3;});
}

$ clang-cc -std=gnu89 -pedantic aaa.c
aaa.c:2:11: warning: use of GNU statement expression extension
  return ({2+3;});
          ^
1 diagnostic generated.
$

The fix for this issue would be to change 1311 of ParseExpr.cpp from

     Diag(Tok, diag::ext_gnu_statement_expr);

to

   if (!getLang().GNUMode)
     Diag(Tok, diag::ext_gnu_statement_expr);

The same happens when using, e.g., __builtin_offsetof.

It'll happen in many places, all of which will need to be changed with a check for GNUMode (for GNU extensions). I'd be happy to review and apply such a patch, if someone feels like tackling this.

  - Doug

Douglas Gregor wrote:

There seems to be a problem in the handling of diagnostic for GNU
extensions: some warnings are produced even though the -std=gnu89 option
is specified.

We probably have quite a few of these problems, because many of these extension diagnostics were written before we distinguished between the different kinds of extensions (e.g., Microsoft vs. GNU), so they conflate "is an extension diagnostic" with "is a GNU extension.

$ cat aaa.c
int foo() {
  return ({2+3;});
}

$ clang-cc -std=gnu89 -pedantic aaa.c
aaa.c:2:11: warning: use of GNU statement expression extension
  return ({2+3;});
          ^
1 diagnostic generated.
$

The fix for this issue would be to change 1311 of ParseExpr.cpp from

    Diag(Tok, diag::ext_gnu_statement_expr);

to

  if (!getLang().GNUMode)
    Diag(Tok, diag::ext_gnu_statement_expr);

The same happens when using, e.g., __builtin_offsetof.

It'll happen in many places, all of which will need to be changed with a check for GNUMode (for GNU extensions). I'd be happy to review and apply such a patch, if someone feels like tackling this.

    - Doug

OK, I think we will make a pass on these,
trying to be as systematic as possible.

Cheers,
Enea Zaffanella.

There seems to be a problem in the handling of diagnostic for GNU
extensions: some warnings are produced even though the -std=gnu89
option

The fix for this issue would be to change 1311 of ParseExpr.cpp from

    Diag(Tok, diag::ext_gnu_statement_expr);

to

  if (!getLang().GNUMode)
    Diag(Tok, diag::ext_gnu_statement_expr);

Instead of checking for gnu mode, can we have a diagnostic group for all such diagnostics
and ignore them in -std=gnu89 mode?

- Fariborz

That is a great idea!

  - Doug

I think it's worth noting that our behavior matches gcc here... what
exactly were you expecting?

-Eli

Right, my understanding is that -pedantic emits warnings vs the base language (c89 in this case) not vs "gnu89".

-Chris

Eli Friedman wrote:

Initially, I misread it and was assuming that gnu89 and gnu99 were
considered to be "standards", as much as c89 and c99. Then I realized that
each of them is just a "dialect of a standard". Under this interpretation,
as far as diagnostic is concerned, there should be no difference at all
between
-std=c89 -pedantic
and
-std=gnu89 -pedantic

Is that the intended behavior?

That's what we implement, and it isn't by accident, if that's what
you're asking. Clang Compiler User’s Manual — Clang 18.0.0git documentation is
a complete list of the differences between the modes.

If it is ... then it still sounds a bit strange to me. In particular, what
would then be the reason for allowing a combination such as
-std=gnu89 -pedantic-errors
?

Basically just copying gcc... you're right, it isn't really a useful
set of options.

The issue here is that arguably, almost everything which we print a
warning for with -pedantic is a GNU extension, since they're
violations of the standard and implemented by gcc. Also, I'm not sure
what we would gain by classifying extension warnings into GNU
extensions and "generic" extensions.

-Eli

Well, we also support some Microsoft extensions and OpenCL constructs. One could imagine keeping these separate, so that users could call Clang in a GCC-like mode, Microsoft-like mode, or whatever.

  • Doug

Okay... so then a GNU extension would be anything we don't want in
msvc-like mode? That's a reasonable classification, I guess. I doubt
anyone would want the set of warnings which are not GNU extensions
using that classification scheme, though.

-Eli

A GNU extension is something that GNU supports and isn't part of the base language. Same deal with Microsoft extensions, and it's natural that some extensions will be available in both modes.

  - Doug

So a GNU extension any diagnostic currently classified as Extension
right now, plus the? Okay, but that makes the whole thing seem
orthogonal to this discussion...

-Eli

We have a tiny number of Extensions that aren't GNU extensions, e.g., ext_ellipsis_exception_spec (a Microsoft extension) and ext_explicit_instantiation_after_specialization (a C++0x extension that's benign in C++98 mode).

But, since the vast majority of Extensions and ExtWarns are for GNU, it's probably easier just to deal with these oddballs in the code.

  - Doug