rsmith added inline comments.

================
Comment at: clang/lib/Parse/ParseDeclCXX.cpp:874-876
+    if (!getLangOpts().CPlusPlus)
+      Diag(Tok, diag::warn_cxx_static_assert_in_c)
+          << FixItHint::CreateReplacement(Tok.getLocation(), "_Static_assert");
----------------
aaron.ballman wrote:
> rsmith wrote:
> > aaron.ballman wrote:
> > > aaron.ballman wrote:
> > > > rsmith wrote:
> > > > > I don't think this diagnostic is useful as-is: on Windows, including 
> > > > > `<assert.h>` doesn't help because it doesn't `#define static_assert`. 
> > > > > And people hitting this also can't switch to using `_Static_assert`, 
> > > > > because MSVC doesn't provide it, only `static_assert`.
> > > > > 
> > > > > If we want to warn here, we could perhaps check whether `<assert.h>` 
> > > > > has been included, but getting that check correct across PCH / 
> > > > > modules is not straightforward. (If we knew what include guard the 
> > > > > CRT's `assert.h` used (if any), I guess we could check whether that's 
> > > > > defined, but that'd be a bit of a hack.) But I'm somewhat inclined to 
> > > > > think we don't have a good way to distinguish between the good cases 
> > > > > and the bad ones, so we shouldn't warn. Hopefully MS will fix their 
> > > > > CRT at some point and we can stop providing this compatibility hack 
> > > > > entirely (or start warning on it by default).
> > > > Are you sure they don't support `_Static_assert` yet? I seem to be able 
> > > > to use it fine: https://godbolt.org/z/vG47he
> > > > 
> > > > That said, this does appear to be only available in newer versions of 
> > > > MSVC, so perhaps you're correct about the diagnostic being a bit 
> > > > unhelpful. My primary concern is that use of `static_assert` in C is a 
> > > > nonconforming extension and we default to `-fms-compatibility` on 
> > > > Windows when Clang is built by MSVC. So it's not difficult to 
> > > > accidentally run into this, but the only warning we give on it with 
> > > > `-Weverything -pedantic` is how it's not compatible with C++98.
> > > > 
> > > > WDYT?
> > > I suppose one option would be to look at what version of MSVC we're 
> > > trying to be compatible with to see if that's a version that supports 
> > > `/std:c11` and only emit this diagnostic in that case, but tbh, that 
> > > feels like it'll lead to confusing diagnostic behavior (esp given that we 
> > > default to ms compatibility mode silently when you build Clang with MSVC 
> > > on Windows).
> > > 
> > > Given that MSVC does support `_Static_assert` when you enable C11 or 
> > > later language mode, I'm inclined to warn on this construct by default.
> > > 
> > > WDYT?
> > Well, it's good to see that they've made progress, but it [looks 
> > like](https://godbolt.org/z/YfEhGW) their `<assert.h>` still doesn't 
> > `#define static_assert`, so I think we still don't have an actionable 
> > warning we can produce here. We can't reasonably tell people to include 
> > `<assert.h>` (as this patch does) because that doesn't work. And it doesn't 
> > seem reasonable to tell people to use `_Static_assert` instead, if they 
> > actually have included `<assert.h>`. (I don't think we want to encourage 
> > people to use `_Static_assert` instead of `<assert.h>` + `static_assert`.)
> > 
> > So I don't think MSVC adding support for `_Static_assert` really changes 
> > anything here -- until their `<assert.h>` works, or we find some good way 
> > to detect whether it was properly included, this warning will fire on both 
> > correct code and incorrect code, which doesn't seem all that useful.
> >  And it doesn't seem reasonable to tell people to use _Static_assert 
> > instead, if they actually have included <assert.h>. (I don't think we want 
> > to encourage people to use _Static_assert instead of <assert.h> + 
> > static_assert.)
> 
> Ideally, yes. But this isn't ideal -- we produce no diagnostic for this 
> nonconforming extension and that's causing pain in practice. As an example of 
> where I ran into this: I had a header file that was shared between C and 
> (mostly) C++ code and added a `static_assert` to it but forgot to add 
> `#include <assert.h>`. This compiled great in MSVC and clang-cl, but when 
> compiled with clang on CI is when I finally found the issue. e.g., like this: 
> https://godbolt.org/z/cs8YGb
> 
> If I had to pick between behaviors, I think I'd prefer pushing people towards 
> using `_Static_assert` even if `assert.h` is included over silently accepting 
> a nonconforming extension in pedantic mode.
> 
> Rather than trying to see what header guard was used by `<assert.h>`, 
> couldn't we assume that if `assert` is defined as a macro then `<assert.h>` 
> must have been included (or the user triggered UB and gets what they get)? So 
> the logic could be: only diagnose use of the `static_assert` (keyword) in C 
> mode if `assert` is not defined?
> 
> > We can't reasonably tell people to include <assert.h> (as this patch does) 
> > because that doesn't work.
> 
> But it does (as far as the user is concerned)? In MS compatibility mode, 
> `static_assert` is always accepted, so the include isn't strictly necessary 
> but isn't harmful either. Outside of MS compatibility mode, the include is 
> required to spell it `static_assert` because we won't treat it as a keyword. 
> If we go with the "only diagnose when `assert` is not defined as a macro" 
> approach, it would give us the desired behavior here.
> we produce no diagnostic for this nonconforming extension

Well, I'd argue that it's not a non-conforming extension so much as it's a 
different language mode that has different rules. We don't accept 
`static_assert` if `-fms-compatibility` is disabled. I don't think conformance 
to ISO C has any bearing here, because you're not compiling the input in ISO C 
mode.

> So the logic could be: only diagnose use of the `static_assert` (keyword) in 
> C mode if `assert` is not defined?

Interesting, I'd not considered that. I think that could work well enough.

This approach wouldn't work when compiling preprocessed output, though perhaps 
we could fix that too, by making the preprocessor implicitly inject a `#define 
static_assert _Static_assert` if it sees a `#define` of `assert` in MS 
compatibility mode. We'd need to keep the `static_assert` keyword around for 
compatibility with code that uses it without a suitable `#include`, but we 
could then warn on it unconditionally, as this patch does.

> > We can't reasonably tell people to include <assert.h> (as this patch does) 
> > because that doesn't work.
> But it does (as far as the user is concerned)?

As far as the user is concerned, if their source file already includes 
`<assert.h>` and they get a warning that says "you need to include 
`<assert.h>`", they would reasonably conclude that that's a compiler bug. I 
think we need to avoid that possibility.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D95396/new/

https://reviews.llvm.org/D95396

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to