-
Notifications
You must be signed in to change notification settings - Fork 15.4k
[Clang] Allow devirtualization involving array subscripts with constant indices when the pointee type is known #130528
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1689,7 +1689,7 @@ static NamedDecl* getLambdaCallOperatorHelper(const CXXRecordDecl &RD) { | |
| // auto L = [](T) { }; // But A's call operator would want A's here. | ||
| // } | ||
| // | ||
| // Walk the call operator’s redecl chain to find the one that belongs | ||
| // Walk the call operator's redecl chain to find the one that belongs | ||
| // to this module. | ||
| // | ||
| // TODO: We need to fix this properly (see | ||
|
|
@@ -2465,6 +2465,27 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base, | |
| if (Base->isPRValue() && Base->getType()->isRecordType()) | ||
| return this; | ||
|
|
||
| // Handle array subscripts with constant indices when the pointee type is | ||
| // known | ||
| if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Base)) { | ||
| QualType BaseTy = ASE->getBase()->getType(); | ||
|
|
||
| // Check if it's a pointer to a record type | ||
| if (BaseTy->isPointerType() && BaseTy->getPointeeType()->isRecordType()) { | ||
| // For C++17 and later, we can devirtualize array access beyond p[0] | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't see the 'beyond [0]' in that standardeeze, can you better clarify it? Also, where are you checking for >0 here? It seems like you'd do this in every case? What is making this skip the 0 case? |
||
| // According to [expr.add]/6, if the array element type and the pointee | ||
| // type are not similar, behavior is undefined, so we can assume they are | ||
| // the same type | ||
| const ASTContext &Context = getParent()->getASTContext(); | ||
| const LangOptions &LangOpts = Context.getLangOpts(); | ||
| if (LangOpts.CPlusPlus17 && | ||
| ASE->getIdx()->isIntegerConstantExpr(Context)) { | ||
| // It's a constant index, so it's safe to devirtualize | ||
| return this; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // If we don't even know what we would call, we can't devirtualize. | ||
| const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType(); | ||
| if (!BestDynamicDecl) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -92,9 +92,9 @@ void fd(D d, XD xd, D *p) { | |
| // CHECK: call void % | ||
| p[0].f(); | ||
|
|
||
| // FIXME: We can devirtualize this, by C++1z [expr.add]/6 (if the array | ||
| // element type and the pointee type are not similar, behavior is undefined). | ||
| // CHECK: call void % | ||
| // By C++1z [expr.add]/6 (if the array element type and the pointee type | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't get the comment on 89: Why can we virtualize this but not that one? |
||
| // are not similar, behavior is undefined). | ||
| // CHECK: call void @_ZN1D1fEv | ||
| p[1].f(); | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unrelated change.