-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
CastExpr conversion function decl is sometimes corrupt #53044
Comments
I believe the issue is with
|
@drec357 Thank you! I can confirm that inlining those two functions into
makes both c++17 and c++20 behave as expected. I'm trying to really understand why we get a zero declkind, though...? Is it because without assertions, the LLVM RTTI just blindly reinterprets the |
On Jan 6, 2022, at 4:30 PM, Kim Gräsman ***@***.***> wrote:
@drec357 <https://github.com/drec357> Thank you!
I can confirm that inlining those two functions into
static NamedDecl *
my_get_conversion_function(CastExpr *expr) {
// Skip implicit temporary stuffsies
const Expr *SubExpr = nullptr;
for (const CastExpr *E = expr; E; E = dyn_cast<ImplicitCastExpr>(SubExpr)) {
// Skip through reference binding to temporary.
if (auto *Materialize = dyn_cast<MaterializeTemporaryExpr>(E->getSubExpr()))
SubExpr = Materialize->getSubExpr();
else if (auto *Binder = dyn_cast<CXXBindTemporaryExpr>(E->getSubExpr()))
SubExpr = Binder->getSubExpr();
else if (auto *Constant = dyn_cast<ConstantExpr>(E->getSubExpr()))
SubExpr = Constant->getSubExpr();
else
SubExpr = E->getSubExpr();
if (E->getCastKind() == CK_ConstructorConversion)
return cast<CXXConstructExpr>(SubExpr)->getConstructor();
if (E->getCastKind() == CK_UserDefinedConversion) {
if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SubExpr))
return MCE->getMethodDecl();
}
}
return nullptr;
}
makes both c++17 and c++20 behave as expected.
I'm trying to really understand why we get a zero declkind, though...? Is it because without assertions, the LLVM RTTI just blindly reinterprets the ConstantExpr as a CXXConstructExpr?
I believe without assertions the `cast<CXXConstructExpr>(SubExpr)` will always succeed and the program will access bad data until it goes off the rails. Incorrect DeclKinds, StmtClasses etc. are usually where this happens I suppose, since the chances random data matches the kind expected in a certain context are slim.
… —
Reply to this email directly, view it on GitHub <#53044 (comment)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AB56JNUWNLMNQT7CBPK5M4TUUYCW5ANCNFSM5LMW4E2A>.
Triage notifications on the go with GitHub Mobile for iOS <https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675> or Android <https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub>.
You are receiving this because you were mentioned.
|
Right, makes sense. I was a bit surprised it got that far, but With that additional context, I've been able to reduce the problematic input to:
This can be provoked using
The JSON AST dumper also calls I'm not quite sure how to turn that into a lit test. |
I suppose a case could be made for this to be a |
I have just uploaded a patch for this at https://reviews.llvm.org/D117391 (which depends on a clang-reformat in https://reviews.llvm.org/D117390). @drec357 I'll add you as reviewer, I hope you don't mind. |
When a consteval function is called, its call-expression is wrapped in a ConstantExpr in the Clang AST. There's an upstream bug [1] where Clang doesn't account for that when searching the AST for a cast-expression's potential user-defined conversion function, leading to an assertion failure or a crash. Reimplement GetConversionFunction so it works in this case. This can safely be reverted when the upstream bug is fixed. [1] llvm/llvm-project#53044
When a consteval function is called, its call-expression is wrapped in a ConstantExpr in the Clang AST. There's an upstream bug [1] where Clang doesn't account for that when searching the AST for a cast-expression's potential user-defined conversion function, leading to an assertion failure or a crash. Reimplement GetConversionFunction so it works in this case. This can safely be reverted when the upstream bug is fixed. [1] llvm/llvm-project#53044
When a consteval function is called, its call-expression is wrapped in a ConstantExpr in the Clang AST. There's an upstream bug [1] where Clang doesn't account for that when searching the AST for a cast-expression's potential user-defined conversion function, leading to an assertion failure or a crash. Reimplement GetConversionFunction so it works in this case. This can safely be reverted when the upstream bug is fixed. [1] llvm/llvm-project#53044
Full-expressions are Sema-generated implicit nodes that cover constant-expressions and expressions-with-cleanup for temporaries. Ignore those as part of implicit-ignore, and also remove too-aggressive IgnoreImplicit (which includes nested ImplicitCastExprs, for example) on unpacked sub-expressions. Add some unittests to demonstrate that RecursiveASTVisitor sees through ConstantExpr nodes correctly. Adjust cxx2a-consteval test to cover diagnostics for nested consteval expressions that were previously missed. Fixes bug #53044.
@AaronBallman Thanks for helping land this! I'd like to reintegrate and double-check this with |
@llvm/issue-subscribers-clang-frontend |
Issue is indeed fixed as of 403d7d8. Is there a procedure for closing, or should I just hit the button? |
The procedure is to link to the git hash for the commit with the fix and close. I'll let you do the honors for this one given it was your fix (thanks again!). :-) |
Thanks, closing! |
When a consteval function is called, its call-expression is wrapped in a ConstantExpr in the Clang AST. There's an upstream bug [1] where Clang doesn't account for that when searching the AST for a cast-expression's potential user-defined conversion function, leading to an assertion failure or a crash. Reimplement GetConversionFunction so it works in this case. This can safely be reverted when the upstream bug is fixed. [1] llvm/llvm-project#53044
This is a problem that surfaced in IWYU recently.
I'm pretty sure it's difficult to provoke it in the compiler proper, since
CastExpr::getConversionFunction
is only called in a single place, for diagnostics. Tools built on Clang tooling and the recursive AST visitor can fall victim to it, however.I have only been able to reproduce it on plain source code (not preprocessed), and only in conjunction with the fmt library (https://github.com/fmtlib/fmt). Attached is a minimal RAV tool and instructions to reproduce.
What makes me think this is somewhat critical is that
CastExpr::getConversionFunction
returns anAccessSpecDecl
in this scenario, which breaks all sorts of AST and LLVM RTTI invariants. I suspect we're looking at garbage data for some reason. I have tried building ubsan+asan-instrumented LLVM/Clang, but without being able to track anything down.Repro project: ravrepro.tar.gz.
Thankful for any ideas, let me know if I can add more information.
References:
The text was updated successfully, but these errors were encountered: