Skip to content
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

[Clang] ++this with a dependent this is accepted when it’s not instantiated #92439

Open
Sirraide opened this issue May 16, 2024 · 31 comments
Open
Labels
accepts-invalid clang:frontend Language frontend issues, e.g. anything involving "Sema"

Comments

@Sirraide
Copy link
Contributor

This code compiles, unless we instantiate and call f(). This doesn’t seem right to me because, irrespective of what the type of e.g. this ends up being, it’s a prvalue, and we can’t increment that.

template <typename T>
struct S : T {
    auto t() -> S*;
    void f() { 
        ++reinterpret_cast<S*>(4);
        ++this;
        ++t(); 
    }
};

Imo we should diagnose this earlier if that is feasible. GCC also suffers from the same problem, which caused ++this as a typo for ++*this to go unnoticed in a libstdc++ header because the template containing it was never instantiated by libstdc++. MSVC also accepts this code. Is this a bug or a standards defect? Because I don’t see a situation where ++this would be semantically valid.

CC @AaronBallman, @cor3ntin, @erichkeane

@Sirraide Sirraide added clang:frontend Language frontend issues, e.g. anything involving "Sema" accepts-invalid labels May 16, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented May 16, 2024

@llvm/issue-subscribers-clang-frontend

Author: None (Sirraide)

This code compiles, unless we instantiate and call `f()`. This doesn’t seem right to me because, irrespective of what the type of e.g. `this` ends up being, it’s a prvalue, and we can’t increment that.
template &lt;typename T&gt;
struct S : T {
    auto t() -&gt; S*;
    void f() { 
        ++reinterpret_cast&lt;S*&gt;(4);
        ++this;
        ++t(); 
    }
};

Imo we should diagnose this earlier if that is feasible. GCC also suffers from the same problem, which caused ++this as a typo for ++*this to go unnoticed in a libstdc++ header because the template containing it was never instantiated by libstdc++. MSVC also accepts this code. Is this a bug or a standards defect? Because I don’t see a situation where ++this would be semantically valid.

CC @AaronBallman, @cor3ntin, @erichkeane

@Sirraide Sirraide changed the title [Clang] ++this is accepted when it’s not instantiated [Clang] ++this with a dependent this is accepted when it’s not instantiated May 16, 2024
@Sirraide
Copy link
Contributor Author

More examples; these are even worse imo (compiles if S is dependent):

S s;
++s++;
s++++;

@Sirraide
Copy link
Contributor Author

Actually, those could make sense if the postfix ++ operator is overloaded to return an lvalue, but if S is a pointer type then this should definitely be ill-formed.

@davidstone
Copy link
Contributor

Overall, this seems like a good suggestion. Unfortunately, it's a bit more complicated than this, I think.

1595988 is a recent commit that partially added the behavior you are requesting (and is the reason you needed to add in the base class to get the code to get accepted). However, that change is what revealed the bug in libstdc++ when compiling with clang, which means that as of right now, clang cannot compile the most recently released version of libstdc++. I'm not really sure how we want to proceed based on that.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115119 is the associated libstdc++ bug.

@erichkeane
Copy link
Collaborator

Ooof, yeah, we probably DO have to accept the ++this in at least the libstdc++ case. I'd rather we do the absolute hackiest thing possible though.

One thought would be to do this as a 'Warn-as-default-error' for a while, so that 'system headers' don't catch it.

@shafik
Copy link
Collaborator

shafik commented May 16, 2024

Worth noting, no implementation diagnoses this: https://godbolt.org/z/zssdnMe8G

I guess this is IFNDR, so diagnosing it eventually, is fine.

@Sirraide
Copy link
Contributor Author

Sirraide commented May 17, 2024

that change is what revealed the bug in libstdc++ when compiling with clang

Yeah, the libstdc++ bug is also also how I noticed this bug.

One thought would be to do this as a 'Warn-as-default-error' for a while

A warning would probably also work if you feel that making this an error would be too disruptive (for what it’s worth, I had to manually edit the libstdc++ header in question on my system to get things compiling again), but imo we should definitely issue some sort of diagnostic for this, because there is no situation where ++this isn’t a bug.

Worth noting, no implementation diagnoses this: https://godbolt.org/z/zssdnMe8G

Imo it’s worth pointing out though that the only reason the libstdc++ bug wasn’t caught earlier is because no-one diagnoses this.

I guess this is IFNDR, so diagnosing it eventually, is fine.

Just because I’m curious, where in the standard does it say that, because I only remember this always being a prvalue, but I’m not sure if that still applies if it is dependent.

@erichkeane
Copy link
Collaborator

A warning would probably also work if you feel that making this an error would be too disruptive (for what it’s worth, I had to manually edit the libstdc++ header in question on my system to get things compiling again), but imo we should definitely issue some sort of diagnostic for this, because there is no situation where ++this isn’t a bug.

I think we HAVE to here unfortunately, we can't really fail to compile past versions of libstdc++ for a long while.

Imo it’s worth pointing out though that the only reason the libstdc++ bug wasn’t caught earlier is because no-one diagnoses this.

100%

Just because I’m curious, where in the standard does it say that, because I only remember this always being a prvalue, but I’m not sure if that still applies if it is dependent.

Not going to look it up now, but ++this isn't ill-formed, NDR. Its that diagnosing in an uninstantiated template is NDR.

@Sirraide
Copy link
Contributor Author

I think we HAVE to here unfortunately, we can't really fail to compile past versions of libstdc++ for a long while.

I don’t know how long this has been in libstdc++ (though it will be fixed as soon as version 1.14.2 is released), but yeah, that’s true; in that case it does seem like making it an error that’s a warning by default is probably the way to go.

Its that diagnosing in an uninstantiated template is NDR.

Ah, I see, that makes sense.

@erichkeane
Copy link
Collaborator

I lied, I looked it up:
https://eel.is/c++draft/temp#res.general-6

And referenced here: https://eel.is/c++draft/temp#inst-example-11

@Sirraide
Copy link
Contributor Author

I lied, I looked it up: https://eel.is/c++draft/temp#res.general-6

And referenced here: https://eel.is/c++draft/temp#inst-example-11

Good to know. Thanks!

@sdkrystian
Copy link
Member

FWIW, it's only in the GCC 14.1 release -- the containing file was added in January.

@shafik
Copy link
Collaborator

shafik commented May 17, 2024

I lied, I looked it up: https://eel.is/c++draft/temp#res.general-6

And referenced here: https://eel.is/c++draft/temp#inst-example-11

Apologies, I should have quoted it earlier but that was I was referring to. Thank you for quoting it!

@pinskia
Copy link

pinskia commented May 19, 2024

GCC also suffers from the same problem

GCC issue was filed as https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115121 .

@sdkrystian
Copy link
Member

sdkrystian commented May 19, 2024

Also, clang will diagnose ++this with or without a dependent base class. Clang assertions trunk was just a bit behind clang trunk on godbolt :)

@Sirraide
Copy link
Contributor Author

Also, clang will diagnose ++this with or without a dependent base class. Clang assertions trunk was just a bit behind clang trunk on godbolt :)

Ah I see; I thought it was weird that it didn’t already do that given that your pr, from what I remember at least, addresses pretty much exactly this.

Also, if it’s only in GCC 14.1, I think it might be fine for us to keep this as-is? Provided that 14.2 is released and shipped before Clang 19, that is. I find it unlikely that anyone would find themselves stuck on GCC 14.1 specifically as opposed to 14.X, which is the only situation in which this would get problematic.

@erichkeane
Copy link
Collaborator

Ah, huh... I didn't realize this only applies to a single sub-release of libstdc++. I think then I'd be OK leaving it as an error as long as a 14.2 release happens 'soon' enough for us to not cross.

@AaronBallman : You should probably comment here too

@AaronBallman
Copy link
Collaborator

I would recommend we follow the potentially breaking changes policy; basically: start a thread on discourse about the issue (with the appropriate label), tag vendors for awareness, and let's see if we can get away with leaving it as an error rather than working around the issue for libstdc++. One potential concern would be whether that version of libstdc++ will be in any LTS releases; if that happens, I think we will have to work around it somehow.

@erichkeane
Copy link
Collaborator

I would recommend we follow the potentially breaking changes policy; basically: start a thread on discourse about the issue (with the appropriate label), tag vendors for awareness, and let's see if we can get away with leaving it as an error rather than working around the issue for libstdc++. One potential concern would be whether that version of libstdc++ will be in any LTS releases; if that happens, I think we will have to work around it somehow.

I agree! @Sirraide or @sdkrystian : would you two be able to get a post together on discourse that explains all of this? It seems this applies to 14.1 only, and if that hits an LTS that gets brought up there, we should put in SOME Sort of hack to fix to permit this.

@Sirraide
Copy link
Contributor Author

would you two be able to get a post together on discourse that explains all of this?

Sure, I’ll do that later today/tomorrow probably; this situation is fairly straight-forward to explain, so it shouldn’t take too long.

@sdkrystian If you’d like I can put it in a google doc and send you a link if you want to take a look at it before we put it on Discourse.

tag vendors for awareness,

I’d appreciate it if someone could help me w/ that because I’m not sure who I should tag about this candidly.

SOME Sort of hack to fix to permit this

One possible hack would quite literally be to allow this only in that exact function (template), but I’m not sure how easy or difficult it would be to implement that candidly. Should I mention that option in the RFC, or would you say that it’s not a good idea?

@sdkrystian
Copy link
Member

If you’d like I can put it in a google doc and send you a link if you want to take a look at it before we put it on Discourse.

Please do, thanks!

@Sirraide
Copy link
Contributor Author

@sdkrystian Alright, I’ve sent an invite to the email on your github profile

@AaronBallman, @erichkeane I’d send you an invite as well, but I’m candidly not sure what email address(es) to send it to...

@cor3ntin
Copy link
Contributor

I talked to @jwakely, Distributions are actively backporting the fix.

The changes is going to affect

  • People who compile/use libstdc++ 14.1.0 from source
  • A few distros that have deployed GCC 14 and not yet deployed the fix. (Fedora is impacted but will be fixed this week, and debian is impacted but should have the fix soon)

So the situation seems fairly transient, and I am not sure it warrants a long standing hack
(on the flip side, the hack should be fairly minimal so i would not be opposed to it if it helps a few people)

@Sirraide
Copy link
Contributor Author

Thanks, that’s good to know. Do we still want to make a Discourse post about this? If so, then we should definitely include this information there.

@jwakely
Copy link
Contributor

jwakely commented May 21, 2024

To be a little more precise, the buggy libstdc++ header is currently in (at least):

Fedora 40 and rawhide, Gentoo, Arch Linux, Debian unstable (sid), and I think it's in Mageia and OpenMandriva based on rpmfind.net. I don't think Ubuntu is affected.

Fedora should have the fix in a couple of days and Gentoo already has the fix in testing. I don't know about the others.

As Corentin said, it of course also affects anybody with a self-built GCC 14.1.0 who's also using Clang trunk. If they built it themselves, they can probably also patch it themselves (or update to the most recent 14.1.1 snapshot which has the fix).

@cor3ntin
Copy link
Contributor

Thanks, that’s good to know. Do we still want to make a Discourse post about this? If so, then we should definitely include this information there.

Let me have a chat with Aaron tomorrow

@jwakely
Copy link
Contributor

jwakely commented May 21, 2024

One potential concern would be whether that version of libstdc++ will be in any LTS releases

Nobody is going to build an LTS distro on the first release from the gcc-14 branch and then never update to a later 14.x, that would be extremely silly. I know of at least one distro that will use GCC 14.x long term, but it won't be stuck on 14.1.0 forever.

@AaronBallman
Copy link
Collaborator

Thank you for the details @jwakely!

Given that the changes are in Clang 19 (not 18) and the libstdc++ issue is already fixed and should hopefully be rolled out to many folks by the time Clang 19 ships, we can hopefully get away with not adding a workaround to Clang.

Thanks, that’s good to know. Do we still want to make a Discourse post about this?

We might as well still alert users to the fact that this situation exists, but perhaps it's not worth a Discourse post -- maybe we should list it under "C++ Specific Potentially Breaking Changes` in the release notes with a mention of impact on libstdc++ with a code example showing what error the user is likely to see, and that users should get an updated version of libstdc++ with the fix applied

@Sirraide
Copy link
Contributor Author

we should list it under "C++ Specific Potentially Breaking Changes` in the release notes with a mention of impact on libstdc++ with a code example showing what error the user is likely to see

Alright, I’ll do that then unless anyone else thinks we should make a discourse post.

@sdkrystian Looks like we won’t need that post after all, but thanks for the help anyway!

@Sirraide Sirraide self-assigned this May 22, 2024
Sirraide added a commit that referenced this issue May 22, 2024
Adding a release note about this as discussed in #92439. 

---------

Co-authored-by: cor3ntin <corentinjabot@gmail.com>
@Sirraide
Copy link
Contributor Author

A release note has been added; as pointed out by @cor3ntin, I’m leaving this issue open because there are a few cases mentioned here that still aren’t diagnosed. He also suggested adding a fix-it for this, so I’ve opened an issue for that as well.

@Sirraide Sirraide removed their assignment May 22, 2024
@Sirraide
Copy link
Contributor Author

(Unassigning myself again because that was mainly to add the release note)

jameshu15869 pushed a commit to jameshu15869/llvm-project that referenced this issue May 31, 2024
Adding a release note about this as discussed in llvm#92439. 

---------

Co-authored-by: cor3ntin <corentinjabot@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepts-invalid clang:frontend Language frontend issues, e.g. anything involving "Sema"
Projects
None yet
Development

No branches or pull requests

10 participants