1 //===- unittest/Tooling/CastExprTest.cpp ----------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "TestVisitor.h"
11 using namespace clang
;
15 struct CastExprVisitor
: TestVisitor
<CastExprVisitor
> {
16 std::function
<void(ExplicitCastExpr
*)> OnExplicitCast
;
17 std::function
<void(CastExpr
*)> OnCast
;
19 bool VisitExplicitCastExpr(ExplicitCastExpr
*Expr
) {
25 bool VisitCastExpr(CastExpr
*Expr
) {
32 TEST(CastExprTest
, GetSubExprAsWrittenThroughMaterializedTemporary
) {
33 CastExprVisitor Visitor
;
34 Visitor
.OnExplicitCast
= [](ExplicitCastExpr
*Expr
) {
35 auto Sub
= Expr
->getSubExprAsWritten();
36 EXPECT_TRUE(isa
<DeclRefExpr
>(Sub
))
37 << "Expected DeclRefExpr, but saw " << Sub
->getStmtClassName();
39 Visitor
.runOver("struct S1 {};\n"
40 "struct S2 { operator S1(); };\n"
41 "S1 f(S2 s) { return static_cast<S1>(s); }\n");
44 // Verify that getSubExprAsWritten looks through a ConstantExpr in a scenario
47 // CXXFunctionalCastExpr functional cast to struct S <ConstructorConversion>
50 // `-CXXConstructExpr 'S' 'void (int)'
51 // `-IntegerLiteral 'int' 0
52 TEST(CastExprTest
, GetSubExprAsWrittenThroughConstantExpr
) {
53 CastExprVisitor Visitor
;
54 Visitor
.OnExplicitCast
= [](ExplicitCastExpr
*Expr
) {
55 auto *Sub
= Expr
->getSubExprAsWritten();
56 EXPECT_TRUE(isa
<IntegerLiteral
>(Sub
))
57 << "Expected IntegerLiteral, but saw " << Sub
->getStmtClassName();
59 Visitor
.runOver("struct S { consteval S(int) {} };\n"
60 "S f() { return S(0); }\n",
61 CastExprVisitor::Lang_CXX2a
);
64 // Verify that getConversionFunction looks through a ConstantExpr for implicit
65 // constructor conversions (https://github.com/llvm/llvm-project/issues/53044):
67 // `-ImplicitCastExpr 'X' <ConstructorConversion>
70 // `-CXXConstructExpr 'X' 'void (const char *)'
71 // `-ImplicitCastExpr 'const char *' <ArrayToPointerDecay>
72 // `-StringLiteral 'const char [7]' lvalue "foobar"
73 TEST(CastExprTest
, GetCtorConversionFunctionThroughConstantExpr
) {
74 CastExprVisitor Visitor
;
75 Visitor
.OnCast
= [](CastExpr
*Expr
) {
76 if (Expr
->getCastKind() == CK_ConstructorConversion
) {
77 auto *Conv
= Expr
->getConversionFunction();
78 EXPECT_TRUE(isa
<CXXConstructorDecl
>(Conv
))
79 << "Expected CXXConstructorDecl, but saw " << Conv
->getDeclKindName();
82 Visitor
.runOver("struct X { consteval X(const char *) {} };\n"
83 "void f() { X x = \"foobar\"; }\n",
84 CastExprVisitor::Lang_CXX2a
);
87 // Verify that getConversionFunction looks through a ConstantExpr for implicit
88 // user-defined conversions.
90 // `-ImplicitCastExpr 'const char *' <UserDefinedConversion>
91 // `-ConstantExpr 'const char *'
93 // `-CXXMemberCallExpr 'const char *'
94 // `-MemberExpr '<bound member function type>' .operator const char *
95 // `-DeclRefExpr 'const X' lvalue Var 'x' 'const X'
96 TEST(CastExprTest
, GetUserDefinedConversionFunctionThroughConstantExpr
) {
97 CastExprVisitor Visitor
;
98 Visitor
.OnCast
= [](CastExpr
*Expr
) {
99 if (Expr
->getCastKind() == CK_UserDefinedConversion
) {
100 auto *Conv
= Expr
->getConversionFunction();
101 EXPECT_TRUE(isa
<CXXMethodDecl
>(Conv
))
102 << "Expected CXXMethodDecl, but saw " << Conv
->getDeclKindName();
105 Visitor
.runOver("struct X {\n"
106 " consteval operator const char *() const {\n"
110 "const char *f() {\n"
114 CastExprVisitor::Lang_CXX2a
);