-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[clang] Improve nested name specifier AST representation #147835
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
Conversation
This feels like a regression, unless you think the bug is elsewhere and the assert just catches it now: #156458 (comment) |
"And on that day, every maintainer of a nontrivial clang fork cried out to the sky in unison." |
The tests started failing after the following PR was merged: llvm#147835 rdar://159140646
The tests started failing after the following PR was merged: llvm#147835 rdar://159140646
@mizvekov there is one more instance of a clang crash that we are encountering during our testing at google. Here is the reproducer https://godbolt.org/z/jfeW9d9Ts. Please take a look. |
For convenience copying the code and clang stdout here:
|
And a bit cleaned up (https://godbolt.org/z/q9fGPj54d):
|
FWIW that crash is pre-existing, this PR just adds another way to reproduce it. Here is a reproducer for clang-21, using Typedefs instead of RecordTypes to induce the problem: https://compiler-explorer.com/z/E89P31brT class A;
using B = A;
using T = void(__attribute__((swift_async_context)) B *);
T R;
using B = A;
void fa(__attribute__((swift_async_context)) B *);
bool f() {
return R == fa;
} |
This fixes an assumption that the ExtInfo for two same function types would have referential equality. This should compare these ExtInfos by value instead. The bug is pre-existing to #147835, but that PR adds another way to reproduce it.
) This fixes an assumption that the ExtInfo for two same function types would have referential equality. This should compare these ExtInfos by value instead. The bug is pre-existing to #147835, but that PR adds another way to reproduce it.
@joanahalili @alexfh that's fixed in #157925 |
…tInfo (#157925) This fixes an assumption that the ExtInfo for two same function types would have referential equality. This should compare these ExtInfos by value instead. The bug is pre-existing to llvm/llvm-project#147835, but that PR adds another way to reproduce it.
On a positive note, we just updated Chromium's toolchain and saw a 5% reduction in build time, which I'm assuming is due to this change :-) |
This fixes a regression introduced in #147835 When parsing a lambda where the call operator has a late parsed attribute, we would try to build a 'this' type for the lambda, but in a lambda 'this' never refers to the lambda class itself. This late parsed attribute can be added implicitly by the -ftrapping-math flag. This patch patch makes it so CXXThisScopeRAII ignores lambdas. This became observable in #147835 because that made clang lazily create tag types, and it removed a workaround for a lambda dependency bug where any previously created tag type for the lambda is dicarded after its dependency is recalculated. But the 'this' scope created above would defeat this laziness and create the lambda type too soon, before its dependency was updated. Since this regression was never released, there are no release notes. Fixes #161657
This fixes a regression introduced in #147835 When parsing a lambda where the call operator has a late parsed attribute, we would try to build a 'this' type for the lambda, but in a lambda 'this' never refers to the lambda class itself. This late parsed attribute can be added implicitly by the -ftrapping-math flag. This patch patch makes it so CXXThisScopeRAII ignores lambdas. This became observable in #147835 because that made clang lazily create tag types, and it removed a workaround for a lambda dependency bug where any previously created tag type for the lambda is discarded after its dependency is recalculated. But the 'this' scope created above would defeat this laziness and create the lambda type too soon, before its dependency was updated. Since this regression was never released, there are no release notes. Fixes #161657
…161765) This fixes a regression introduced in llvm#147835 When parsing a lambda where the call operator has a late parsed attribute, we would try to build a 'this' type for the lambda, but in a lambda 'this' never refers to the lambda class itself. This late parsed attribute can be added implicitly by the -ftrapping-math flag. This patch patch makes it so CXXThisScopeRAII ignores lambdas. This became observable in llvm#147835 because that made clang lazily create tag types, and it removed a workaround for a lambda dependency bug where any previously created tag type for the lambda is discarded after its dependency is recalculated. But the 'this' scope created above would defeat this laziness and create the lambda type too soon, before its dependency was updated. Since this regression was never released, there are no release notes. Fixes llvm#161657
…161765) This fixes a regression introduced in llvm#147835 When parsing a lambda where the call operator has a late parsed attribute, we would try to build a 'this' type for the lambda, but in a lambda 'this' never refers to the lambda class itself. This late parsed attribute can be added implicitly by the -ftrapping-math flag. This patch patch makes it so CXXThisScopeRAII ignores lambdas. This became observable in llvm#147835 because that made clang lazily create tag types, and it removed a workaround for a lambda dependency bug where any previously created tag type for the lambda is discarded after its dependency is recalculated. But the 'this' scope created above would defeat this laziness and create the lambda type too soon, before its dependency was updated. Since this regression was never released, there are no release notes. Fixes llvm#161657
Hello, did these changes modify the semantics of |
I think the documentation is right and matches what's happening. Sounds like you want to get the beginning of the range as something like: if (auto TL = NNSL->getAsTypeLoc())
return TL.getNonPrefixBeginLoc();
else
return NNSL->getLocalBeginLoc(); I didn't add a helper for this because there was just a single user in the llvm codebase using this pattern. |
Just my two cents. I think the term "local" is ambiguous, and my mental model has always been that it refers to the last specifier in a qualified name. This seems to have been the behavior, and the public API doc implies it. This recent change seems to break that model and introduces behavior that feels inconsistent:
This difference is confusing. While I understand the reasoning behind the internal implementation, API users aren't likely to be aware of it, and the "last piece" model seems more intuitive. If this new behavior is intended, could we update the comments for |
Yeah, all except one user of I propose adding a note about this in the documentation, add a new helper which does what |
This is a major change on how we represent nested name qualifications in the AST.
This patch offers a great performance benefit.
It greatly improves compilation time for stdexec. For one datapoint, for
test_on2.cpp
in that project, which is the slowest compiling test, this patch improves-c
compilation time by about 7.2%, with the-fsyntax-only
improvement being at ~12%.This has great results on compile-time-tracker as well:

This patch also further enables other optimziations in the future, and will reduce the performance impact of template specialization resugaring when that lands.
It has some other miscelaneous drive-by fixes.
About the review: Yes the patch is huge, sorry about that. Part of the reason is that I started by the nested name specifier part, before the ElaboratedType part, but that had a huge performance downside, as ElaboratedType is a big performance hog. I didn't have the steam to go back and change the patch after the fact.
There is also a lot of internal API changes, and it made sense to remove ElaboratedType in one go, versus removing it from one type at a time, as that would present much more churn to the users. Also, the nested name specifier having a different API avoids missing changes related to how prefixes work now, which could make existing code compile but not work.
How to review: The important changes are all in
clang/include/clang/AST
andclang/lib/AST
, with also important changes inclang/lib/Sema/TreeTransform.h
.The rest and bulk of the changes are mostly consequences of the changes in API.
PS: TagType::getDecl is renamed to
getOriginalDecl
in this patch, just for easier to rebasing. I plan to rename it back after this lands.Fixes #136624
Fixes #43179
Fixes #68670
Fixes #92757