diff options
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); |