forked from OSchip/llvm-project
118 lines
4.1 KiB
C++
118 lines
4.1 KiB
C++
//===- unittest/Tooling/CastExprTest.cpp ----------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "TestVisitor.h"
|
|
|
|
using namespace clang;
|
|
|
|
namespace {
|
|
|
|
struct CastExprVisitor : TestVisitor<CastExprVisitor> {
|
|
std::function<void(ExplicitCastExpr *)> OnExplicitCast;
|
|
std::function<void(CastExpr *)> OnCast;
|
|
|
|
bool VisitExplicitCastExpr(ExplicitCastExpr *Expr) {
|
|
if (OnExplicitCast)
|
|
OnExplicitCast(Expr);
|
|
return true;
|
|
}
|
|
|
|
bool VisitCastExpr(CastExpr *Expr) {
|
|
if (OnCast)
|
|
OnCast(Expr);
|
|
return true;
|
|
}
|
|
};
|
|
|
|
TEST(CastExprTest, GetSubExprAsWrittenThroughMaterializedTemporary) {
|
|
CastExprVisitor Visitor;
|
|
Visitor.OnExplicitCast = [](ExplicitCastExpr *Expr) {
|
|
auto Sub = Expr->getSubExprAsWritten();
|
|
EXPECT_TRUE(isa<DeclRefExpr>(Sub))
|
|
<< "Expected DeclRefExpr, but saw " << Sub->getStmtClassName();
|
|
};
|
|
Visitor.runOver("struct S1 {};\n"
|
|
"struct S2 { operator S1(); };\n"
|
|
"S1 f(S2 s) { return static_cast<S1>(s); }\n");
|
|
}
|
|
|
|
// Verify that getSubExprAsWritten looks through a ConstantExpr in a scenario
|
|
// like
|
|
//
|
|
// CXXFunctionalCastExpr functional cast to struct S <ConstructorConversion>
|
|
// `-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<IntegerLiteral>(Sub))
|
|
<< "Expected IntegerLiteral, but saw " << Sub->getStmtClassName();
|
|
};
|
|
Visitor.runOver("struct S { consteval S(int) {} };\n"
|
|
"S f() { return S(0); }\n",
|
|
CastExprVisitor::Lang_CXX2a);
|
|
}
|
|
|
|
// Verify that getConversionFunction looks through a ConstantExpr for implicit
|
|
// constructor conversions (https://github.com/llvm/llvm-project/issues/53044):
|
|
//
|
|
// `-ImplicitCastExpr 'X' <ConstructorConversion>
|
|
// `-ConstantExpr 'X'
|
|
// |-value: Struct
|
|
// `-CXXConstructExpr 'X' 'void (const char *)'
|
|
// `-ImplicitCastExpr 'const char *' <ArrayToPointerDecay>
|
|
// `-StringLiteral 'const char [7]' lvalue "foobar"
|
|
TEST(CastExprTest, GetCtorConversionFunctionThroughConstantExpr) {
|
|
CastExprVisitor Visitor;
|
|
Visitor.OnCast = [](CastExpr *Expr) {
|
|
if (Expr->getCastKind() == CK_ConstructorConversion) {
|
|
auto *Conv = Expr->getConversionFunction();
|
|
EXPECT_TRUE(isa<CXXConstructorDecl>(Conv))
|
|
<< "Expected CXXConstructorDecl, but saw " << Conv->getDeclKindName();
|
|
}
|
|
};
|
|
Visitor.runOver("struct X { consteval X(const char *) {} };\n"
|
|
"void f() { X x = \"foobar\"; }\n",
|
|
CastExprVisitor::Lang_CXX2a);
|
|
}
|
|
|
|
// Verify that getConversionFunction looks through a ConstantExpr for implicit
|
|
// user-defined conversions.
|
|
//
|
|
// `-ImplicitCastExpr 'const char *' <UserDefinedConversion>
|
|
// `-ConstantExpr 'const char *'
|
|
// |-value: LValue
|
|
// `-CXXMemberCallExpr 'const char *'
|
|
// `-MemberExpr '<bound member function type>' .operator const char *
|
|
// `-DeclRefExpr 'const X' lvalue Var 'x' 'const X'
|
|
TEST(CastExprTest, GetUserDefinedConversionFunctionThroughConstantExpr) {
|
|
CastExprVisitor Visitor;
|
|
Visitor.OnCast = [](CastExpr *Expr) {
|
|
if (Expr->getCastKind() == CK_UserDefinedConversion) {
|
|
auto *Conv = Expr->getConversionFunction();
|
|
EXPECT_TRUE(isa<CXXMethodDecl>(Conv))
|
|
<< "Expected CXXMethodDecl, but saw " << Conv->getDeclKindName();
|
|
}
|
|
};
|
|
Visitor.runOver("struct X {\n"
|
|
" consteval operator const char *() const {\n"
|
|
" return nullptr;\n"
|
|
" }\n"
|
|
"};\n"
|
|
"const char *f() {\n"
|
|
" constexpr X x;\n"
|
|
" return x;\n"
|
|
"}\n",
|
|
CastExprVisitor::Lang_CXX2a);
|
|
}
|
|
|
|
} // namespace
|