diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index a274bf37a407..94b6adf489fe 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -1765,7 +1765,7 @@ Expr *CastExpr::getSubExprAsWritten() { // subexpression describing the call; strip it off. if (E->getCastKind() == CK_ConstructorConversion) SubExpr = - skipImplicitTemporary(cast(SubExpr)->getArg(0)); + skipImplicitTemporary(cast(SubExpr->IgnoreImplicit())->getArg(0)); else if (E->getCastKind() == CK_UserDefinedConversion) { assert((isa(SubExpr) || isa(SubExpr)) && diff --git a/clang/unittests/Tooling/CastExprTest.cpp b/clang/unittests/Tooling/CastExprTest.cpp index a9e78d2155b4..cda963a6a897 100644 --- a/clang/unittests/Tooling/CastExprTest.cpp +++ b/clang/unittests/Tooling/CastExprTest.cpp @@ -34,4 +34,24 @@ TEST(CastExprTest, GetSubExprAsWrittenThroughMaterializedTemporary) { "S1 f(S2 s) { return static_cast(s); }\n"); } +// Verify that getSubExprAsWritten looks through a ConstantExpr in a scenario +// like +// +// CXXFunctionalCastExpr functional cast to struct S +// `-ConstantExpr 'S' +// |-value: Struct +// `-CXXConstructExpr 'S' 'void (int)' +// `-IntegerLiteral 'int' 0 +TEST(CastExprTest, GetSubExprAsWrittenThroughConstantExpr) { + CastExprVisitor Visitor; + Visitor.OnExplicitCast = [](ExplicitCastExpr *Expr) { + auto *Sub = Expr->getSubExprAsWritten(); + EXPECT_TRUE(isa(Sub)) + << "Expected IntegerLiteral, but saw " << Sub->getStmtClassName(); + }; + Visitor.runOver("struct S { consteval S(int) {} };\n" + "S f() { return S(0); }\n", + CastExprVisitor::Lang_CXX2a); +} + }