[cfe-commits] r159326 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
Rafael Espindola
rafael.espindola at gmail.com
Wed Jun 27 18:56:38 PDT 2012
Author: rafael
Date: Wed Jun 27 20:56:38 2012
New Revision: 159326
URL: http://llvm.org/viewvc/llvm-project?rev=159326&view=rev
Log:
Fix another issue with devirtualizing calls to final methods by passing them
the correct this pointer. There is some potential for sharing a bit more
code with canDevirtualizeMemberFunctionCalls, but that can be done in an
independent patch.
Modified:
cfe/trunk/include/clang/AST/Expr.h
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/lib/CodeGen/CGExprCXX.cpp
cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
Modified: cfe/trunk/include/clang/AST/Expr.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Expr.h?rev=159326&r1=159325&r2=159326&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/Expr.h (original)
+++ cfe/trunk/include/clang/AST/Expr.h Wed Jun 27 20:56:38 2012
@@ -634,6 +634,13 @@
/// ParenExpr or CastExprs, returning their operand.
Expr *IgnoreParenNoopCasts(ASTContext &Ctx) LLVM_READONLY;
+ /// Ignore parentheses and derived-to-base casts.
+ Expr *ignoreParenBaseCasts() LLVM_READONLY;
+
+ const Expr *ignoreParenBaseCasts() const LLVM_READONLY {
+ return const_cast<Expr*>(this)->ignoreParenBaseCasts();
+ }
+
/// \brief Determine whether this expression is a default function argument.
///
/// Default arguments are implicitly generated in the abstract syntax tree
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=159326&r1=159325&r2=159326&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Wed Jun 27 20:56:38 2012
@@ -34,21 +34,7 @@
using namespace clang;
const CXXRecordDecl *Expr::getBestDynamicClassType() const {
- const Expr *E = this;
-
- while (true) {
- E = E->IgnoreParens();
- if (const CastExpr *CE = dyn_cast<CastExpr>(E)) {
- if (CE->getCastKind() == CK_DerivedToBase ||
- CE->getCastKind() == CK_UncheckedDerivedToBase ||
- CE->getCastKind() == CK_NoOp) {
- E = CE->getSubExpr();
- continue;
- }
- }
-
- break;
- }
+ const Expr *E = ignoreParenBaseCasts();
QualType DerivedType = E->getType();
if (const PointerType *PTy = DerivedType->getAs<PointerType>())
@@ -2231,7 +2217,27 @@
}
return E;
}
-
+
+Expr *Expr::ignoreParenBaseCasts() {
+ Expr *E = this;
+ while (true) {
+ if (ParenExpr *P = dyn_cast<ParenExpr>(E)) {
+ E = P->getSubExpr();
+ continue;
+ }
+ if (CastExpr *CE = dyn_cast<CastExpr>(E)) {
+ if (CE->getCastKind() == CK_DerivedToBase ||
+ CE->getCastKind() == CK_UncheckedDerivedToBase ||
+ CE->getCastKind() == CK_NoOp) {
+ E = CE->getSubExpr();
+ continue;
+ }
+ }
+
+ return E;
+ }
+}
+
Expr *Expr::IgnoreParenImpCasts() {
Expr *E = this;
while (true) {
Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=159326&r1=159325&r2=159326&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Wed Jun 27 20:56:38 2012
@@ -172,11 +172,21 @@
}
// Compute the object pointer.
+ const Expr *Base = ME->getBase();
+ bool CanUseVirtualCall = MD->isVirtual() && !ME->hasQualifier();
+ bool Devirtualize = CanUseVirtualCall &&
+ canDevirtualizeMemberFunctionCalls(getContext(), Base, MD);
+
+ const Expr *Inner = Base;
+ if (Devirtualize)
+ Inner = Base->ignoreParenBaseCasts();
+
llvm::Value *This;
if (ME->isArrow())
- This = EmitScalarExpr(ME->getBase());
+ This = EmitScalarExpr(Inner);
else
- This = EmitLValue(ME->getBase()).getAddress();
+ This = EmitLValue(Inner).getAddress();
+
if (MD->isTrivial()) {
if (isa<CXXDestructorDecl>(MD)) return RValue::get(0);
@@ -223,11 +233,8 @@
//
// We also don't emit a virtual call if the base expression has a record type
// because then we know what the type is.
- const Expr *Base = ME->getBase();
- bool UseVirtualCall = MD->isVirtual() && !ME->hasQualifier()
- && !canDevirtualizeMemberFunctionCalls(getContext(),
- Base, MD);
- const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType();
+ bool UseVirtualCall = CanUseVirtualCall && !Devirtualize;
+ const CXXRecordDecl *MostDerivedClassDecl = Inner->getBestDynamicClassType();
llvm::Value *Callee;
if (const CXXDestructorDecl *Dtor = dyn_cast<CXXDestructorDecl>(MD)) {
@@ -238,7 +245,7 @@
MD->isVirtual() &&
ME->hasQualifier())
Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), Ty);
- else if (ME->hasQualifier())
+ else if (!Devirtualize)
Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty);
else {
const CXXMethodDecl *DM =
@@ -258,7 +265,7 @@
MD->isVirtual() &&
ME->hasQualifier())
Callee = BuildAppleKextVirtualCall(MD, ME->getQualifier(), Ty);
- else if (ME->hasQualifier())
+ else if (!Devirtualize)
Callee = CGM.GetAddrOfFunction(MD, Ty);
else {
const CXXMethodDecl *DerivedMethod =
Modified: cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp?rev=159326&r1=159325&r2=159326&view=diff
==============================================================================
--- cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp (original)
+++ cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp Wed Jun 27 20:56:38 2012
@@ -107,3 +107,29 @@
static_cast<A*>(d)->~A();
}
}
+
+namespace Test7 {
+ struct foo {
+ virtual void g() {}
+ };
+
+ struct bar {
+ virtual int f() { return 0; }
+ };
+
+ struct zed final : public foo, public bar {
+ int z;
+ virtual int f() {return z;}
+ };
+
+ // CHECK: define i32 @_ZN5Test71fEPNS_3zedE
+ int f(zed *z) {
+ // CHECK: alloca
+ // CHECK-NEXT: store
+ // CHECK-NEXT: load
+ // CHECK-NEXT: bitcast
+ // CHECK-NEXT: call {{.*}} @_ZN5Test73zed1fEv
+ // CHECK-NEXT: ret
+ return static_cast<bar*>(z)->f();
+ }
+}
More information about the cfe-commits
mailing list