118 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "TestVisitor.h"10 11using namespace clang;12 13namespace {14 15struct CastExprVisitor : TestVisitor {16 std::function<void(ExplicitCastExpr *)> OnExplicitCast;17 std::function<void(CastExpr *)> OnCast;18 19 bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) override {20 if (OnExplicitCast)21 OnExplicitCast(Expr);22 return true;23 }24 25 bool VisitCastExpr(CastExpr *Expr) override {26 if (OnCast)27 OnCast(Expr);28 return true;29 }30};31 32TEST(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();38 };39 Visitor.runOver("struct S1 {};\n"40 "struct S2 { operator S1(); };\n"41 "S1 f(S2 s) { return static_cast<S1>(s); }\n");42}43 44// Verify that getSubExprAsWritten looks through a ConstantExpr in a scenario45// like46//47// CXXFunctionalCastExpr functional cast to struct S <ConstructorConversion>48// `-ConstantExpr 'S'49// |-value: Struct50// `-CXXConstructExpr 'S' 'void (int)'51// `-IntegerLiteral 'int' 052TEST(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();58 };59 Visitor.runOver("struct S { consteval S(int) {} };\n"60 "S f() { return S(0); }\n",61 CastExprVisitor::Lang_CXX2a);62}63 64// Verify that getConversionFunction looks through a ConstantExpr for implicit65// constructor conversions (https://github.com/llvm/llvm-project/issues/53044):66//67// `-ImplicitCastExpr 'X' <ConstructorConversion>68// `-ConstantExpr 'X'69// |-value: Struct70// `-CXXConstructExpr 'X' 'void (const char *)'71// `-ImplicitCastExpr 'const char *' <ArrayToPointerDecay>72// `-StringLiteral 'const char [7]' lvalue "foobar"73TEST(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();80 }81 };82 Visitor.runOver("struct X { consteval X(const char *) {} };\n"83 "void f() { X x = \"foobar\"; }\n",84 CastExprVisitor::Lang_CXX2a);85}86 87// Verify that getConversionFunction looks through a ConstantExpr for implicit88// user-defined conversions.89//90// `-ImplicitCastExpr 'const char *' <UserDefinedConversion>91// `-ConstantExpr 'const char *'92// |-value: LValue93// `-CXXMemberCallExpr 'const char *'94// `-MemberExpr '<bound member function type>' .operator const char *95// `-DeclRefExpr 'const X' lvalue Var 'x' 'const X'96TEST(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();103 }104 };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);115}116 117} // namespace118