-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[clang] Deprecation warnings in system headers are silenced when the deprecated entity is used indirectly #134425
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
CC @erichkeane as well |
This is a bit of a mess... We typically just suppress ALL warnings inside of system headers, so that you guys don't break folks with things they can't fix. This is obviously an exception to this for obvious reasons (where you wanted it to be shown). Your last bullet sounds onerous/too much work to be valuable. But none of the others really solve the problem without harming others. We could special case deprecated perhaps, but that seems awkward, as you could then never use 'deprecated' for internal APIs. The pragma idea causing a 'special' verison of deprecated (vs a special version of deprecated) to be marked up isn't that bad, it could mark the DeprecatedAttr node to 'always' diagnose, but that requires some additional 'specialiness' in our diagnostics engine. I'll have to think about this.. this is funky. |
Not sure how revelant it is but GCC has -Wsystem-headers. |
I wonder if there is a way in Clang to track whether an instantiation is trigged by user code or if it happens within a system header. E.g. whether |
We don't necessarily have that because the instantiation might be caused by different code, and now just being re-referenced, so it would only be triggered on the FIRST instantiation (though, if none of the headers DO this referencing, we could perhaps diagnose). That said, I suspect looking back to the whole template stack to figure out if we should diagnose could very well be a very unfortunate behavior, as a lot of 'deprecated, but only for internal use' kinda diagnostics would end up firing everywhere (or even, diagnostics you don't want happening in the header, like the REST of our warnings). |
Can we mark the forward declaration of It looks like clang tries to see where the template instantiation originated from in
|
This reproduces the problem: $ cat fw.h
$ cat char_traits.h
$ cat string.h
$ cat string.cpp
$ clang++ -std=c++20 string.cpp -c |
A while back, we marked
std::char_traits<not-a-character-type>
as deprecated (see #72694 and the related history). We then removed it in LLVM 19 after thinking we had provided users with a reasonable deprecation period of 6 months for such a small thing. And that was the case, with a major caveat.Indeed, Clang <= 17 failed to surface deprecation warnings for things in system headers, so that the following would actually not issue any diagnostic:
That was fixed in Clang 18 in #70353 (thanks to @cor3ntin!). In Clang 18 and above, the code above does warn. Based on that, we went ahead and removed
std::char_traits<not-a-character-type>
in LLVM 19, thinking we had provided one release of deprecation. However, the following code never warned and still doesn't warn:Even though
basic_string<long>
instantiateschar_traits<long>
, I guess the issue is that the instantiation ofchar_traits<long>
itself is happening from a system header, not user code, and as a result we don't warn on it.IMO, that's broken. That means that we effectively shipped #72694 without giving any advance notice to people because nobody instantiates
char_traits
directly, everybody instantiatesbasic_string
andbasic_string_view
. When I did my sanity testing before landing #72694, I must have usedchar_traits
(because that's what we were deprecating and that's what didn't work before @cor3ntin 's fix), but that wasn't enough.I'm not sure how to best fix that, but at the moment we seem to basically not have a good story for deprecating things located in system headers. I'm going to throw a few potential solutions out there:
pragma
that allows headers to change Clang's behavior diagnostics-wise? It always felt like a big hammer to disallow any and all warnings coming from system headers without giving them the choice to decide for themselves.basic_string<long>
,basic_string_view<long>
,basic_istream<long>
and the other 150 APIs that can end up instantiatingchar_traits<long>
as deprecated. I think that would be really challenging and error prone, but I could imagine the argument being made. If that's the direction we want to take, then we'd need a way to easily mark specific specializations as deprecated. Today the only way to do this would be to provide an explicit instantiation of all the types that we want to deprecate (e.g.basic_istream<long>
,basic_istream<unsigned char>
, etc.) and duplicate their implementation while marking them as deprecated. So if we think that's philosophically the right way to go, we should try to find a way that makes it technically feasible.I'm eager to see what other folks think!
CC @AaronBallman for awareness
The text was updated successfully, but these errors were encountered: