Index: clang/lib/AST/Expr.cpp =================================================================== --- clang/lib/AST/Expr.cpp +++ clang/lib/AST/Expr.cpp @@ -1823,8 +1823,8 @@ // Conversions by constructor and conversion functions have a // subexpression describing the call; strip it off. if (E->getCastKind() == CK_ConstructorConversion) - SubExpr = - skipImplicitTemporary(cast(SubExpr)->getArg(0)); + SubExpr = skipImplicitTemporary( + cast(SubExpr->IgnoreImplicit())->getArg(0)); else if (E->getCastKind() == CK_UserDefinedConversion) { assert((isa(SubExpr) || isa(SubExpr)) && Index: clang/unittests/Tooling/CastExprTest.cpp =================================================================== --- clang/unittests/Tooling/CastExprTest.cpp +++ clang/unittests/Tooling/CastExprTest.cpp @@ -34,4 +34,23 @@ "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); +} }