[clang] [Clang] Allow devirtualization involving array subscripts with constant indices when the pointee type is known (PR #207540)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Jul 11 07:54:09 PDT 2026
https://github.com/AZero13 updated https://github.com/llvm/llvm-project/pull/207540
>From 668e98a459f5f9ce65fb6438874b51acee61968b Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sat, 4 Jul 2026 16:41:32 -0400
Subject: [PATCH 1/2] [Clang] Allow devirtualization involving array subscripts
with constant indices when the pointee type is known
By C++1z [expr.add]/6, if the array element type and the pointee type are not similar, behavior is undefined.
---
clang/lib/AST/DeclCXX.cpp | 14 ++++++++++++++
.../devirtualize-virtual-function-calls.cpp | 4 ++--
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/clang/lib/AST/DeclCXX.cpp b/clang/lib/AST/DeclCXX.cpp
index e7e0f75fdc84d..eb010b5d43718 100644
--- a/clang/lib/AST/DeclCXX.cpp
+++ b/clang/lib/AST/DeclCXX.cpp
@@ -2600,6 +2600,20 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
}
}
+ // We can devirtualize calls on an object accessed by an array subscript
+ // expression with a non-zero index. A pointer to the base of an array must
+ // point to an object of the array element type, so the dynamic type of the
+ // element can't be a derived class. A single object is considered to be an
+ // array of one element, so p[0] could still be a derived object, but p[N]
+ // for N != 0 cannot.
+ if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(Base)) {
+ Expr::EvalResult Result;
+ if (ASE->getIdx()->EvaluateAsInt(Result, getASTContext())) {
+ if (Result.Val.getInt() != 0)
+ return DevirtualizedMethod;
+ }
+ }
+
// We can't devirtualize the call.
return nullptr;
}
diff --git a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
index b50881db63e05..9851b88ebffcd 100644
--- a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
+++ b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
@@ -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
+ // 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 %
+ // CHECK: call void @_ZN1A1fEv
p[1].f();
}
>From 43374f8925b40b4d390700332ffa3c3248cec3fd Mon Sep 17 00:00:00 2001
From: AZero13 <gfunni234 at gmail.com>
Date: Sat, 11 Jul 2026 10:54:01 -0400
Subject: [PATCH 2/2] Update
clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
Co-authored-by: Aaron Ballman <aaron at aaronballman.com>
---
clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
index 9851b88ebffcd..ea9d5a5920c1d 100644
--- a/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
+++ b/clang/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
@@ -92,7 +92,7 @@ void fd(D d, XD xd, D *p) {
// CHECK: call void %
p[0].f();
- // We can devirtualize this, by C++1z [expr.add]/6 (if the array
+ // We can devirtualize this, by C++17 [expr.add]/6 (if the array
// element type and the pointee type are not similar, behavior is undefined).
// CHECK: call void @_ZN1A1fEv
p[1].f();
More information about the cfe-commits
mailing list