aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorRoman Divacky <rdivacky@FreeBSD.org>2010-04-03 07:51:34 +0000
committerRoman Divacky <rdivacky@FreeBSD.org>2010-04-03 07:51:34 +0000
commit2c56c396ce5990954f85194029eeb391bc3529ff (patch)
tree1e9c2f464daf7966d11aa31cf069fa1bc63fdb21 /lib/AST/Expr.cpp
parent11d2b2d2bb706fca0656f2760839721bb7f6cb6f (diff)
downloadsrc-2c56c396ce5990954f85194029eeb391bc3529ff.tar.gz
src-2c56c396ce5990954f85194029eeb391bc3529ff.zip
Update clang to r100285.
Notes
Notes: svn path=/vendor/clang/dist/; revision=206125
Diffstat (limited to 'lib/AST/Expr.cpp')
-rw-r--r--lib/AST/Expr.cpp65
1 files changed, 65 insertions, 0 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 6764612c80b6..ae4bc8c80128 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -1476,6 +1476,71 @@ bool Expr::isDefaultArgument() const {
return isa<CXXDefaultArgExpr>(E);
}
+/// \brief Skip over any no-op casts and any temporary-binding
+/// expressions.
+static const Expr *skipTemporaryBindingsAndNoOpCasts(const Expr *E) {
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() == CastExpr::CK_NoOp)
+ E = ICE->getSubExpr();
+ else
+ break;
+ }
+
+ while (const CXXBindTemporaryExpr *BE = dyn_cast<CXXBindTemporaryExpr>(E))
+ E = BE->getSubExpr();
+
+ while (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E)) {
+ if (ICE->getCastKind() == CastExpr::CK_NoOp)
+ E = ICE->getSubExpr();
+ else
+ break;
+ }
+
+ 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() != CastExpr::CK_ConstructorConversion &&
+ Cast->getCastKind() != CastExpr::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() == CastExpr::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() == CastExpr::CK_UserDefinedConversion)
+ if (const CallExpr *CE = dyn_cast<CallExpr>(Sub))
+ if (CE->getCallReturnType()->isRecordType())
+ return CE;
+
+ return 0;
+ }
+
+ // A call returning a class type returns a temporary.
+ if (const CallExpr *CE = dyn_cast<CallExpr>(E)) {
+ if (CE->getCallReturnType()->isRecordType())
+ return CE;
+
+ return 0;
+ }
+
+ // Explicit temporary object constructors create temporaries.
+ return dyn_cast<CXXTemporaryObjectExpr>(E);
+}
+
/// hasAnyTypeDependentArguments - Determines if any of the expressions
/// in Exprs is type-dependent.
bool Expr::hasAnyTypeDependentArguments(Expr** Exprs, unsigned NumExprs) {