diff options
author | Anders Carlsson <andersca@mac.com> | 2011-04-10 18:20:53 +0000 |
---|---|---|
committer | Anders Carlsson <andersca@mac.com> | 2011-04-10 18:20:53 +0000 |
commit | cd0b32e73a66a20a8dab7a7f0ce963dc669f7c0a (patch) | |
tree | 0460db11e326216c85839a35be0c294452865a5e /lib/CodeGen/CGExprCXX.cpp | |
parent | b8bced0b75fa4188c91753d5a1de6d164af45450 (diff) |
Strip off parens and no-op casts when deciding if an expr can be devirtualized. Fixes the second half of PR9660.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129253 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGExprCXX.cpp')
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 777036bc3b..075fdc30a8 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -77,6 +77,31 @@ static const CXXRecordDecl *getMostDerivedClassDecl(const Expr *Base) { return cast<CXXRecordDecl>(DerivedType->castAs<RecordType>()->getDecl()); } +// FIXME: Ideally Expr::IgnoreParenNoopCasts should do this, but it doesn't do +// quite what we want. +static const Expr *skipNoOpCastsAndParens(const Expr *E) { + while (true) { + if (const ParenExpr *PE = dyn_cast<ParenExpr>(E)) { + E = PE->getSubExpr(); + continue; + } + + if (const CastExpr *CE = dyn_cast<CastExpr>(E)) { + if (CE->getCastKind() == CK_NoOp) { + E = CE->getSubExpr(); + continue; + } + } + if (const UnaryOperator *UO = dyn_cast<UnaryOperator>(E)) { + if (UO->getOpcode() == UO_Extension) { + E = UO->getSubExpr(); + continue; + } + } + return E; + } +} + /// canDevirtualizeMemberFunctionCalls - Checks whether virtual calls on given /// expr can be devirtualized. static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, @@ -112,6 +137,7 @@ static bool canDevirtualizeMemberFunctionCalls(ASTContext &Context, if (MD->getParent()->hasAttr<FinalAttr>()) return true; + Base = skipNoOpCastsAndParens(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. |