10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
18 namespace cppcoreguidelines {
21 SourceType = SourceType.getNonReferenceType();
22 DestType = DestType.getNonReferenceType();
23 while (SourceType->isPointerType() && DestType->isPointerType()) {
24 SourceType = SourceType->getPointeeType();
25 DestType = DestType->getPointeeType();
26 if (SourceType.isConstQualified() && !DestType.isConstQualified())
32 void ProTypeCstyleCastCheck::registerMatchers(MatchFinder *Finder) {
34 cStyleCastExpr(unless(isInTemplateInstantiation())).bind(
"cast"),
this);
38 const auto *MatchedCast = Result.Nodes.getNodeAs<CStyleCastExpr>(
"cast");
40 if (MatchedCast->getCastKind() == CK_BitCast ||
41 MatchedCast->getCastKind() == CK_LValueBitCast ||
42 MatchedCast->getCastKind() == CK_IntegralToPointer ||
43 MatchedCast->getCastKind() == CK_PointerToIntegral ||
44 MatchedCast->getCastKind() == CK_ReinterpretMemberPointer) {
45 diag(MatchedCast->getBeginLoc(),
46 "do not use C-style cast to convert between unrelated types");
50 QualType SourceType = MatchedCast->getSubExpr()->getType();
52 if (MatchedCast->getCastKind() == CK_BaseToDerived) {
53 const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl();
55 SourceDecl = SourceType->getAsCXXRecordDecl();
59 if (SourceDecl->isPolymorphic()) {
64 CharSourceRange::getTokenRange(
65 MatchedCast->getLParenLoc().getLocWithOffset(1),
66 MatchedCast->getRParenLoc().getLocWithOffset(-1)),
67 *Result.SourceManager, getLangOpts());
69 auto DiagBuilder = diag(
70 MatchedCast->getBeginLoc(),
71 "do not use C-style cast to downcast from a base to a derived class; "
72 "use dynamic_cast instead");
75 MatchedCast->getSubExprAsWritten()->IgnoreImpCasts();
76 std::string CastText = (
"dynamic_cast<" + DestTypeString +
">").str();
77 if (!isa<ParenExpr>(SubExpr)) {
78 CastText.push_back(
'(');
79 DiagBuilder << FixItHint::CreateInsertion(
80 Lexer::getLocForEndOfToken(SubExpr->getEndLoc(), 0,
81 *Result.SourceManager, getLangOpts()),
84 auto ParenRange = CharSourceRange::getTokenRange(
85 MatchedCast->getLParenLoc(), MatchedCast->getRParenLoc());
86 DiagBuilder << FixItHint::CreateReplacement(ParenRange, CastText);
89 MatchedCast->getBeginLoc(),
90 "do not use C-style cast to downcast from a base to a derived class");
95 if (MatchedCast->getCastKind() == CK_NoOp &&
97 diag(MatchedCast->getBeginLoc(),
98 "do not use C-style cast to cast away constness");