diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1899,51 +1899,48 @@ } namespace { - const Expr *skipImplicitTemporary(const Expr *E) { - // Skip through reference binding to temporary. - if (auto *Materialize = dyn_cast(E)) - E = Materialize->getSubExpr(); +// Skip over implicit nodes produced as part of semantic analysis. +// Designed for use with IgnoreExprNodes. +Expr *ignoreImplicitSemaNodes(Expr *E) { + if (auto *Materialize = dyn_cast(E)) + return Materialize->getSubExpr(); - // Skip any temporary bindings; they're implicit. - if (auto *Binder = dyn_cast(E)) - E = Binder->getSubExpr(); + if (auto *Binder = dyn_cast(E)) + return Binder->getSubExpr(); - return E; - } + return E; } +} // namespace Expr *CastExpr::getSubExprAsWritten() { const Expr *SubExpr = nullptr; - const CastExpr *E = this; - do { - SubExpr = skipImplicitTemporary(E->getSubExpr()); + + for (const CastExpr *E = this; E; E = dyn_cast(SubExpr)) { + SubExpr = IgnoreExprNodes(E->getSubExpr(), ignoreImplicitSemaNodes); // Conversions by constructor and conversion functions have a // subexpression describing the call; strip it off. - if (E->getCastKind() == CK_ConstructorConversion) - SubExpr = - skipImplicitTemporary(cast(SubExpr->IgnoreImplicit())->getArg(0)); - else if (E->getCastKind() == CK_UserDefinedConversion) { + if (E->getCastKind() == CK_ConstructorConversion) { + SubExpr = IgnoreExprNodes( + cast(SubExpr->IgnoreImplicit())->getArg(0), + ignoreImplicitSemaNodes); + } else if (E->getCastKind() == CK_UserDefinedConversion) { SubExpr = SubExpr->IgnoreImplicit(); - assert((isa(SubExpr) || - isa(SubExpr)) && + assert((isa(SubExpr) || isa(SubExpr)) && "Unexpected SubExpr for CK_UserDefinedConversion."); if (auto *MCE = dyn_cast(SubExpr)) SubExpr = MCE->getImplicitObjectArgument(); } + } - // If the subexpression we're left with is an implicit cast, look - // through that, too. - } while ((E = dyn_cast(SubExpr))); - - return const_cast(SubExpr); + return const_cast(SubExpr); } NamedDecl *CastExpr::getConversionFunction() const { const Expr *SubExpr = nullptr; for (const CastExpr *E = this; E; E = dyn_cast(SubExpr)) { - SubExpr = skipImplicitTemporary(E->getSubExpr()); + SubExpr = IgnoreExprNodes(E->getSubExpr(), ignoreImplicitSemaNodes); if (E->getCastKind() == CK_ConstructorConversion) return cast(SubExpr)->getConstructor();