r306377 - Make CastExpr::getSubExprAsWritten look through implicit temporary under CK_ConstructorConversion
Stephan Bergmann via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 27 01:19:09 PDT 2017
Author: sberg
Date: Tue Jun 27 01:19:09 2017
New Revision: 306377
URL: http://llvm.org/viewvc/llvm-project?rev=306377&view=rev
Log:
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
Added:
cfe/trunk/unittests/Tooling/CastExprTest.cpp
Modified:
cfe/trunk/lib/AST/Expr.cpp
cfe/trunk/unittests/Tooling/CMakeLists.txt
Modified: cfe/trunk/lib/AST/Expr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/Expr.cpp?rev=306377&r1=306376&r2=306377&view=diff
==============================================================================
--- cfe/trunk/lib/AST/Expr.cpp (original)
+++ cfe/trunk/lib/AST/Expr.cpp Tue Jun 27 01:19:09 2017
@@ -1641,25 +1641,32 @@ const char *CastExpr::getCastKindName()
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)) &&
Modified: cfe/trunk/unittests/Tooling/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CMakeLists.txt?rev=306377&r1=306376&r2=306377&view=diff
==============================================================================
--- cfe/trunk/unittests/Tooling/CMakeLists.txt (original)
+++ cfe/trunk/unittests/Tooling/CMakeLists.txt Tue Jun 27 01:19:09 2017
@@ -11,6 +11,7 @@ if (MSVC)
endif()
add_clang_unittest(ToolingTests
+ CastExprTest.cpp
CommentHandlerTest.cpp
CompilationDatabaseTest.cpp
FixItTest.cpp
Added: cfe/trunk/unittests/Tooling/CastExprTest.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/Tooling/CastExprTest.cpp?rev=306377&view=auto
==============================================================================
--- cfe/trunk/unittests/Tooling/CastExprTest.cpp (added)
+++ cfe/trunk/unittests/Tooling/CastExprTest.cpp Tue Jun 27 01:19:09 2017
@@ -0,0 +1,38 @@
+//===- unittest/Tooling/CastExprTest.cpp ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+struct CastExprVisitor : TestVisitor<CastExprVisitor> {
+ std::function<void(ExplicitCastExpr *)> OnExplicitCast;
+
+ bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) {
+ if (OnExplicitCast)
+ OnExplicitCast(Expr);
+ return true;
+ }
+};
+
+TEST(CastExprTest, GetSubExprAsWrittenThroughMaterializedTemporary) {
+ CastExprVisitor Visitor;
+ Visitor.OnExplicitCast = [](ExplicitCastExpr *Expr) {
+ auto Sub = Expr->getSubExprAsWritten();
+ EXPECT_TRUE(isa<DeclRefExpr>(Sub))
+ << "Expected DeclRefExpr, but saw " << Sub->getStmtClassName();
+ };
+ Visitor.runOver("struct S1 {};\n"
+ "struct S2 { operator S1(); };\n"
+ "S1 f(S2 s) { return static_cast<S1>(s); }\n");
+}
+
+}
More information about the cfe-commits
mailing list