[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang / unittests / Tooling / CastExprTest.cpp
blobeab23a5a98e5d519b253a0f5e5a996665e570561
1 //===- unittest/Tooling/CastExprTest.cpp ----------------------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
9 #include "TestVisitor.h"
11 using namespace clang;
13 namespace {
15 struct CastExprVisitor : TestVisitor<CastExprVisitor> {
16 std::function<void(ExplicitCastExpr *)> OnExplicitCast;
17 std::function<void(CastExpr *)> OnCast;
19 bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) {
20 if (OnExplicitCast)
21 OnExplicitCast(Expr);
22 return true;
25 bool VisitCastExpr(CastExpr *Expr) {
26 if (OnCast)
27 OnCast(Expr);
28 return true;
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
45 // like
47 // CXXFunctionalCastExpr functional cast to struct S <ConstructorConversion>
48 // `-ConstantExpr 'S'
49 // |-value: Struct
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>
68 // `-ConstantExpr 'X'
69 // |-value: Struct
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 *'
92 // |-value: LValue
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"
107 " return nullptr;\n"
108 " }\n"
109 "};\n"
110 "const char *f() {\n"
111 " constexpr X x;\n"
112 " return x;\n"
113 "}\n",
114 CastExprVisitor::Lang_CXX2a);
117 } // namespace