summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorStephan Bergmann <sbergman@redhat.com>2017-06-27 08:19:09 +0000
committerStephan Bergmann <sbergman@redhat.com>2017-06-27 08:19:09 +0000
commitf31b0dc473c4b25ab6abf127c6c9a54a5c444b74 (patch)
treede6df5d32014ea6c33544452453a80a4aac45e02 /clang/lib/AST/Expr.cpp
parent2315d83333c862b2afb27cf28f7174ed015234c7 (diff)
downloadbcm5719-llvm-f31b0dc473c4b25ab6abf127c6c9a54a5c444b74.tar.gz
bcm5719-llvm-f31b0dc473c4b25ab6abf127c6c9a54a5c444b74.zip
Make CastExpr::getSubExprAsWritten look through implicit temporary under CK_ConstructorConversion
With struct S1 {}; struct S2 { operator S1(); }; S1 f(S2 s) { return static_cast<S1>(s); } the static_cast expr is CXXStaticCastExpr 0x... 'struct S1' static_cast<struct S1> <ConstructorConversion> `-CXXConstructExpr 0x... 'struct S1' 'void (struct S1 &&) noexcept' elidable `-MaterializeTemporaryExpr 0x... 'struct S1' xvalue `-ImplicitCastExpr 0x... 'struct S1' <UserDefinedConversion> `-CXXMemberCallExpr 0x... 'struct S1' `-MemberExpr 0x... '<bound member function type>' .operator S1 0x... `-DeclRefExpr 0x... 'struct S2' lvalue ParmVar 0x... 's' 'struct S2' getSubExprAsWritten used to return the MaterializeTemporaryExpr (of type S1) under the CXXConstructExpr, instead of unwinding further to the DeclRefExpr (of type S2) at the bottom. Differential Revision: https://reviews.llvm.org/D22128 llvm-svn: 306377
Diffstat (limited to 'clang/lib/AST/Expr.cpp')
-rw-r--r--clang/lib/AST/Expr.cpp29
1 files changed, 18 insertions, 11 deletions
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index c21cd3f65bd..afc7fa8ea09 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -1641,25 +1641,32 @@ const char *CastExpr::getCastKindName() const {
llvm_unreachable("Unhandled cast kind!");
}
+namespace {
+ Expr *skipImplicitTemporary(Expr *expr) {
+ // Skip through reference binding to temporary.
+ if (MaterializeTemporaryExpr *Materialize
+ = dyn_cast<MaterializeTemporaryExpr>(expr))
+ expr = Materialize->GetTemporaryExpr();
+
+ // Skip any temporary bindings; they're implicit.
+ if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(expr))
+ expr = Binder->getSubExpr();
+
+ return expr;
+ }
+}
+
Expr *CastExpr::getSubExprAsWritten() {
Expr *SubExpr = nullptr;
CastExpr *E = this;
do {
- SubExpr = E->getSubExpr();
+ SubExpr = skipImplicitTemporary(E->getSubExpr());
- // Skip through reference binding to temporary.
- if (MaterializeTemporaryExpr *Materialize
- = dyn_cast<MaterializeTemporaryExpr>(SubExpr))
- SubExpr = Materialize->GetTemporaryExpr();
-
- // Skip any temporary bindings; they're implicit.
- if (CXXBindTemporaryExpr *Binder = dyn_cast<CXXBindTemporaryExpr>(SubExpr))
- SubExpr = Binder->getSubExpr();
-
// Conversions by constructor and conversion functions have a
// subexpression describing the call; strip it off.
if (E->getCastKind() == CK_ConstructorConversion)
- SubExpr = cast<CXXConstructExpr>(SubExpr)->getArg(0);
+ SubExpr =
+ skipImplicitTemporary(cast<CXXConstructExpr>(SubExpr)->getArg(0));
else if (E->getCastKind() == CK_UserDefinedConversion) {
assert((isa<CXXMemberCallExpr>(SubExpr) ||
isa<BlockExpr>(SubExpr)) &&
OpenPOWER on IntegriCloud