diff options
author | John McCall <rjmccall@apple.com> | 2010-09-15 10:14:12 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-09-15 10:14:12 +0000 |
commit | 558d2abc7f9fd6801cc7677200992313ae90b5d8 (patch) | |
tree | 7624495cd37a259daceff9065f500f9522cbd775 /lib/AST/Expr.cpp | |
parent | 8f3b834471b158d65d490e3458fa16ba659ec105 (diff) |
one piece of code is responsible for the lifetime of every aggregate
slot. The easiest way to do that was to bundle up the information
we care about for aggregate slots into a new structure which demands
that its creators at least consider the question.
I could probably be convinced that the ObjC 'needs GC' bit should
be rolled into this structure.
Implement generalized copy elision. The main obstacle here is that
IR-generation must be much more careful about making sure that exactly
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@113962 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r-- | lib/AST/Expr.cpp | 55 |
1 files changed, 20 insertions, 35 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp index c9dae17f80..4e65b9c339 100644 --- a/lib/AST/Expr.cpp +++ b/lib/AST/Expr.cpp @@ -1648,46 +1648,31 @@ static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) { return E; } -const Expr *Expr::getTemporaryObject() const { - const Expr *E = skipTemporaryBindingsAndNoOpCasts(this); - - // A cast can produce a temporary object. The object's construction - // is represented as a CXXConstructExpr. - if (const CastExpr *Cast = dyn_cast<CastExpr>(E)) { - // Only user-defined and constructor conversions can produce - // temporary objects. - if (Cast->getCastKind() != CK_ConstructorConversion && - Cast->getCastKind() != CK_UserDefinedConversion) - return 0; - - // Strip off temporary bindings and no-op casts. - const Expr *Sub = skipTemporaryBindingsAndNoOpCasts(Cast->getSubExpr()); - - // If this is a constructor conversion, see if we have an object - // construction. - if (Cast->getCastKind() == CK_ConstructorConversion) - return dyn_cast<CXXConstructExpr>(Sub); - - // If this is a user-defined conversion, see if we have a call to - // a function that itself returns a temporary object. - if (Cast->getCastKind() == CK_UserDefinedConversion) - if (const CallExpr *CE = dyn_cast<CallExpr>(Sub)) - if (CE->getCallReturnType()->isRecordType()) - return CE; +/// isTemporaryObject - Determines if this expression produces a +/// temporary of the given class type. +bool Expr::isTemporaryObject(ASTContext &C, const CXXRecordDecl *TempTy) const { + if (!C.hasSameUnqualifiedType(getType(), C.getTypeDeclType(TempTy))) + return false; - return 0; - } + const Expr *E = skipTemporaryBindingsAndNoOpCasts(this); - // A call returning a class type returns a temporary. - if (const CallExpr *CE = dyn_cast<CallExpr>(E)) { - if (CE->getCallReturnType()->isRecordType()) - return CE; + // pr-values of class type are always temporaries. + if (!E->Classify(C).isPRValue()) return false; - return 0; + // Black-list implicit derived-to-base conversions, which are the + // only way we can get a pr-value of class type that doesn't refer + // to a temporary of that type. + if (isa<ImplicitCastExpr>(E)) { + switch (cast<ImplicitCastExpr>(E)->getCastKind()) { + case CK_DerivedToBase: + case CK_UncheckedDerivedToBase: + return false; + default: + break; + } } - // Explicit temporary object constructors create temporaries. - return dyn_cast<CXXTemporaryObjectExpr>(E); + return true; } /// hasAnyTypeDependentArguments - Determines if any of the expressions |