diff options
Diffstat (limited to 'clang/lib/CodeGen/CGCXX.cpp')
-rw-r--r-- | clang/lib/CodeGen/CGCXX.cpp | 16 |
1 files changed, 15 insertions, 1 deletions
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp index af499427387..0744b79d45d 100644 --- a/clang/lib/CodeGen/CGCXX.cpp +++ b/clang/lib/CodeGen/CGCXX.cpp @@ -198,6 +198,20 @@ RValue CodeGenFunction::EmitCXXMemberCall(const CXXMethodDecl *MD, Callee, Args, MD); } +/// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given +/// expr can be devirtualized. +static bool canDevirtualizeMemberFunctionCalls(const Expr *Base) { + if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) { + if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) { + // This is a record decl. We know the type and can devirtualize it. + return VD->getType()->isRecordType(); + } + } + + // We can't devirtualize the call. + return false; +} + RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { if (isa<BinaryOperator>(CE->getCallee())) return EmitCXXMemberPointerCallExpr(CE); @@ -235,7 +249,7 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE) { // because then we know what the type is. llvm::Value *Callee; if (MD->isVirtual() && !ME->hasQualifier() && - !ME->getBase()->getType()->isRecordType()) + !canDevirtualizeMemberFunctionCalls(ME->getBase())) Callee = BuildVirtualCall(MD, This, Ty); else if (const CXXDestructorDecl *Destructor = dyn_cast<CXXDestructorDecl>(MD)) |