diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2013-08-25 22:46:27 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2013-08-25 22:46:27 +0000 |
commit | 7463ed7c89f487fe0290c16b04caa24ca496131e (patch) | |
tree | 19e8b5554d54fa57faf8426a150c3002feda45d7 /clang/lib/CodeGen/CGClass.cpp | |
parent | 0300813d6af5fe34768db5a6249c9d872ee1d9bc (diff) | |
download | llvm-7463ed7c89f487fe0290c16b04caa24ca496131e.zip llvm-7463ed7c89f487fe0290c16b04caa24ca496131e.tar.gz llvm-7463ed7c89f487fe0290c16b04caa24ca496131e.tar.bz2 |
CodeGen: Unify two implementations of canDevirtualizeMemberFunctionCall.
They were mostly copy&paste of each other, move it to CodeGenFunction. Of course
the two implementations have diverged over time; the one in CGExprCXX seems to
be the more modern one so I picked that one and moved it to CGClass which feels
like a better home for it. No intended functionality change.
llvm-svn: 189203
Diffstat (limited to 'clang/lib/CodeGen/CGClass.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGClass.cpp | 62 |
1 files changed, 18 insertions, 44 deletions
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 5c46c51..4eb27c3 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -1994,29 +1994,6 @@ llvm::Value *CodeGenFunction::GetVTablePtr(llvm::Value *This, return VTable; } -static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) { - const Expr *E = Base; - - 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; - } - - QualType DerivedType = E->getType(); - if (const PointerType *PTy = DerivedType->getAs<PointerType>()) - DerivedType = PTy->getPointeeType(); - - return cast<CXXRecordDecl>(DerivedType->castAs<RecordType>()->getDecl()); -} // FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do // quite what we want. @@ -2043,10 +2020,14 @@ static const Expr *skipNoOpCastsAndParens(const Expr *E) { } } -/// canDevirtualizeMemberFunctionCall - Checks whether the given virtual member -/// function call on the given expr can be devirtualized. -static bool canDevirtualizeMemberFunctionCall(const Expr *Base, - const CXXMethodDecl *MD) { +bool +CodeGenFunction::CanDevirtualizeMemberFunctionCall(const Expr *Base, + const CXXMethodDecl *MD) { + // When building with -fapple-kext, all calls must go through the vtable since + // the kernel linker can do runtime patching of vtables. + if (getLangOpts().AppleKext) + return false; + // If the most derived class is marked final, we know that no subclass can // override this member function and so we can devirtualize it. For example: // @@ -2057,7 +2038,7 @@ static bool canDevirtualizeMemberFunctionCall(const Expr *Base, // b->f(); // } // - const CXXRecordDecl *MostDerivedClassDecl = getMostDerivedClassDecl(Base); + const CXXRecordDecl *MostDerivedClassDecl = Base->getBestDynamicClassType(); if (MostDerivedClassDecl->hasAttr<FinalAttr>()) return true; @@ -2080,7 +2061,14 @@ static bool canDevirtualizeMemberFunctionCall(const Expr *Base, return false; } - + + // We can devirtualize calls on an object accessed by a class member access + // expression, since by C++11 [basic.life]p6 we know that it can't refer to + // a derived class object constructed in the same location. + if (const MemberExpr *ME = dyn_cast<MemberExpr>(Base)) + if (const ValueDecl *VD = dyn_cast<ValueDecl>(ME->getMemberDecl())) + return VD->getType()->isRecordType(); + // We can always devirtualize calls on temporary object expressions. if (isa<CXXConstructExpr>(Base)) return true; @@ -2097,20 +2085,6 @@ static bool canDevirtualizeMemberFunctionCall(const Expr *Base, return false; } -static bool UseVirtualCall(ASTContext &Context, - const CXXOperatorCallExpr *CE, - const CXXMethodDecl *MD) { - if (!MD->isVirtual()) - return false; - - // When building with -fapple-kext, all calls must go through the vtable since - // the kernel linker can do runtime patching of vtables. - if (Context.getLangOpts().AppleKext) - return true; - - return !canDevirtualizeMemberFunctionCall(CE->getArg(0), MD); -} - llvm::Value * CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E, const CXXMethodDecl *MD, @@ -2119,7 +2093,7 @@ CodeGenFunction::EmitCXXOperatorMemberCallee(const CXXOperatorCallExpr *E, CGM.getTypes().GetFunctionType( CGM.getTypes().arrangeCXXMethodDeclaration(MD)); - if (UseVirtualCall(getContext(), E, MD)) + if (MD->isVirtual() && !CanDevirtualizeMemberFunctionCall(E->getArg(0), MD)) return CGM.getCXXABI().getVirtualFunctionPointer(*this, MD, This, fnType); return CGM.GetAddrOfFunction(MD, fnType); |