From 0a7dd835184343ec9149277b668ecdc5d49fe8b0 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Sat, 27 Oct 2012 01:03:43 +0000 Subject: [PATCH] Move two helper functions to AST so that sema can use them. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166853 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/Expr.h | 56 +++++++++++++++++++ lib/AST/Expr.cpp | 69 +++++++++++++++++++++++ lib/CodeGen/CGExpr.cpp | 115 +-------------------------------------- 3 files changed, 127 insertions(+), 113 deletions(-) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 6171b12fe1..9b11e8e2db 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -34,6 +34,7 @@ namespace clang { class ASTContext; class APValue; + class CastExpr; class Decl; class IdentifierInfo; class ParmVarDecl; @@ -42,6 +43,7 @@ namespace clang { class BlockDecl; class CXXBaseSpecifier; class CXXOperatorCallExpr; + class MaterializeTemporaryExpr; class CXXMemberCallExpr; class ObjCPropertyRefExpr; class OpaqueValueExpr; @@ -49,6 +51,48 @@ namespace clang { /// \brief A simple array of base specifiers. typedef SmallVector CXXCastPath; +/// \brief An adjustment to be made to the temporary created when emitting a +/// reference binding, which accesses a particular subobject of that temporary. +struct SubobjectAdjustment { + enum { + DerivedToBaseAdjustment, + FieldAdjustment, + MemberPointerAdjustment + } Kind; + + union { + struct { + const CastExpr *BasePath; + const CXXRecordDecl *DerivedClass; + } DerivedToBase; + + FieldDecl *Field; + + struct { + const MemberPointerType *MPT; + Expr *RHS; + } Ptr; + }; + + SubobjectAdjustment(const CastExpr *BasePath, + const CXXRecordDecl *DerivedClass) + : Kind(DerivedToBaseAdjustment) { + DerivedToBase.BasePath = BasePath; + DerivedToBase.DerivedClass = DerivedClass; + } + + SubobjectAdjustment(FieldDecl *Field) + : Kind(FieldAdjustment) { + this->Field = Field; + } + + SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS) + : Kind(MemberPointerAdjustment) { + this->Ptr.MPT = MPT; + this->Ptr.RHS = RHS; + } +}; + /// Expr - This represents one expression. Note that Expr's are subclasses of /// Stmt. This allows an expression to be transparently used any place a Stmt /// is required. @@ -695,6 +739,18 @@ public: /// behavior if the object isn't dynamically of the derived type. const CXXRecordDecl *getBestDynamicClassType() const; + /// Walk outwards from an expression we want to bind a reference to and + /// find the expression whose lifetime needs to be extended. Record + /// the adjustments needed along the path. + const Expr * + skipRValueSubobjectAdjustments( + SmallVectorImpl &Adjustments) const; + + /// Skip irrelevant expressions to find what should be materialize for + /// binding with a reference. + const Expr * + findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const; + static bool classof(const Stmt *T) { return T->getStmtClass() >= firstExprConstant && T->getStmtClass() <= lastExprConstant; diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index 6f4c8e2637..4a8033f878 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -48,6 +48,75 @@ const CXXRecordDecl *Expr::getBestDynamicClassType() const { return cast(D); } +const Expr * +Expr::skipRValueSubobjectAdjustments( + SmallVectorImpl &Adjustments) const { + const Expr *E = this; + while (true) { + E = E->IgnoreParens(); + + if (const CastExpr *CE = dyn_cast(E)) { + if ((CE->getCastKind() == CK_DerivedToBase || + CE->getCastKind() == CK_UncheckedDerivedToBase) && + E->getType()->isRecordType()) { + E = CE->getSubExpr(); + CXXRecordDecl *Derived + = cast(E->getType()->getAs()->getDecl()); + Adjustments.push_back(SubobjectAdjustment(CE, Derived)); + continue; + } + + if (CE->getCastKind() == CK_NoOp) { + E = CE->getSubExpr(); + continue; + } + } else if (const MemberExpr *ME = dyn_cast(E)) { + if (!ME->isArrow() && ME->getBase()->isRValue()) { + assert(ME->getBase()->getType()->isRecordType()); + if (FieldDecl *Field = dyn_cast(ME->getMemberDecl())) { + E = ME->getBase(); + Adjustments.push_back(SubobjectAdjustment(Field)); + continue; + } + } + } else if (const BinaryOperator *BO = dyn_cast(E)) { + if (BO->isPtrMemOp()) { + assert(BO->getLHS()->isRValue()); + E = BO->getLHS(); + const MemberPointerType *MPT = + BO->getRHS()->getType()->getAs(); + Adjustments.push_back(SubobjectAdjustment(MPT, BO->getRHS())); + } + } + + // Nothing changed. + break; + } + return E; +} + +const Expr * +Expr::findMaterializedTemporary(const MaterializeTemporaryExpr *&MTE) const { + const Expr *E = this; + // Look through single-element init lists that claim to be lvalues. They're + // just syntactic wrappers in this case. + if (const InitListExpr *ILE = dyn_cast(E)) { + if (ILE->getNumInits() == 1 && ILE->isGLValue()) + E = ILE->getInit(0); + } + + // Look through expressions for materialized temporaries (for now). + if (const MaterializeTemporaryExpr *M + = dyn_cast(E)) { + MTE = M; + E = M->GetTemporaryExpr(); + } + + if (const CXXDefaultArgExpr *DAE = dyn_cast(E)) + E = DAE->getExpr(); + return E; +} + /// isKnownToHaveBooleanValue - Return true if this is an integer expression /// that is known to return 0 or 1. This happens for _Bool/bool expressions /// but also int expressions which are produced by things like comparisons in diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index d5d3a68b97..a26a0aa28a 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -157,50 +157,6 @@ void CodeGenFunction::EmitAnyExprToMem(const Expr *E, } } -namespace { -/// \brief An adjustment to be made to the temporary created when emitting a -/// reference binding, which accesses a particular subobject of that temporary. - struct SubobjectAdjustment { - enum { - DerivedToBaseAdjustment, - FieldAdjustment, - MemberPointerAdjustment - } Kind; - - union { - struct { - const CastExpr *BasePath; - const CXXRecordDecl *DerivedClass; - } DerivedToBase; - - FieldDecl *Field; - - struct { - const MemberPointerType *MPT; - Expr *RHS; - } Ptr; - }; - - SubobjectAdjustment(const CastExpr *BasePath, - const CXXRecordDecl *DerivedClass) - : Kind(DerivedToBaseAdjustment) { - DerivedToBase.BasePath = BasePath; - DerivedToBase.DerivedClass = DerivedClass; - } - - SubobjectAdjustment(FieldDecl *Field) - : Kind(FieldAdjustment) { - this->Field = Field; - } - - SubobjectAdjustment(const MemberPointerType *MPT, Expr *RHS) - : Kind(MemberPointerAdjustment) { - this->Ptr.MPT = MPT; - this->Ptr.RHS = RHS; - } - }; -} - static llvm::Value * CreateReferenceTemporary(CodeGenFunction &CGF, QualType Type, const NamedDecl *InitializedDecl) { @@ -227,73 +183,6 @@ CreateReferenceTemporary(CodeGenFunction &CGF, QualType Type, return CGF.CreateMemTemp(Type, "ref.tmp"); } -static const Expr * -findMaterializedTemporary(const Expr *E, const MaterializeTemporaryExpr *&MTE) { - // Look through single-element init lists that claim to be lvalues. They're - // just syntactic wrappers in this case. - if (const InitListExpr *ILE = dyn_cast(E)) { - if (ILE->getNumInits() == 1 && ILE->isGLValue()) - E = ILE->getInit(0); - } - - // Look through expressions for materialized temporaries (for now). - if (const MaterializeTemporaryExpr *M - = dyn_cast(E)) { - MTE = M; - E = M->GetTemporaryExpr(); - } - - if (const CXXDefaultArgExpr *DAE = dyn_cast(E)) - E = DAE->getExpr(); - return E; -} - -static const Expr * -skipRValueSubobjectAdjustments(const Expr *E, - SmallVectorImpl &Adjustments) { - while (true) { - E = E->IgnoreParens(); - - if (const CastExpr *CE = dyn_cast(E)) { - if ((CE->getCastKind() == CK_DerivedToBase || - CE->getCastKind() == CK_UncheckedDerivedToBase) && - E->getType()->isRecordType()) { - E = CE->getSubExpr(); - CXXRecordDecl *Derived - = cast(E->getType()->getAs()->getDecl()); - Adjustments.push_back(SubobjectAdjustment(CE, Derived)); - continue; - } - - if (CE->getCastKind() == CK_NoOp) { - E = CE->getSubExpr(); - continue; - } - } else if (const MemberExpr *ME = dyn_cast(E)) { - if (!ME->isArrow() && ME->getBase()->isRValue()) { - assert(ME->getBase()->getType()->isRecordType()); - if (FieldDecl *Field = dyn_cast(ME->getMemberDecl())) { - E = ME->getBase(); - Adjustments.push_back(SubobjectAdjustment(Field)); - continue; - } - } - } else if (const BinaryOperator *BO = dyn_cast(E)) { - if (BO->isPtrMemOp()) { - assert(BO->getLHS()->isRValue()); - E = BO->getLHS(); - const MemberPointerType *MPT = - BO->getRHS()->getType()->getAs(); - Adjustments.push_back(SubobjectAdjustment(MPT, BO->getRHS())); - } - } - - // Nothing changed. - break; - } - return E; -} - static llvm::Value * EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, llvm::Value *&ReferenceTemporary, @@ -301,7 +190,7 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, QualType &ObjCARCReferenceLifetimeType, const NamedDecl *InitializedDecl) { const MaterializeTemporaryExpr *M = NULL; - E = findMaterializedTemporary(E, M); + E = E->findMaterializedTemporary(M); // Objective-C++ ARC: // If we are binding a reference to a temporary that has ownership, we // need to perform retain/release operations on the temporary. @@ -391,7 +280,7 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E, } SmallVector Adjustments; - E = skipRValueSubobjectAdjustments(E, Adjustments); + E = E->skipRValueSubobjectAdjustments(Adjustments); if (const OpaqueValueExpr *opaque = dyn_cast(E)) if (opaque->getType()->isRecordType()) return CGF.EmitOpaqueValueLValue(opaque).getAddress(); -- 2.40.0