11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "clang/Lex/Lexer.h" 19 namespace cppcoreguidelines {
22 SourceType = SourceType.getNonReferenceType();
23 DestType = DestType.getNonReferenceType();
24 while (SourceType->isPointerType() && DestType->isPointerType()) {
25 SourceType = SourceType->getPointeeType();
26 DestType = DestType->getPointeeType();
27 if (SourceType.isConstQualified() && !DestType.isConstQualified())
33 void ProTypeCstyleCastCheck::registerMatchers(MatchFinder *Finder) {
34 if (!getLangOpts().CPlusPlus)
38 cStyleCastExpr(unless(isInTemplateInstantiation())).bind(
"cast"),
this);
41 void ProTypeCstyleCastCheck::check(
const MatchFinder::MatchResult &
Result) {
42 const auto *MatchedCast = Result.Nodes.getNodeAs<CStyleCastExpr>(
"cast");
44 if (MatchedCast->getCastKind() == CK_BitCast ||
45 MatchedCast->getCastKind() == CK_LValueBitCast ||
46 MatchedCast->getCastKind() == CK_IntegralToPointer ||
47 MatchedCast->getCastKind() == CK_PointerToIntegral ||
48 MatchedCast->getCastKind() == CK_ReinterpretMemberPointer) {
49 diag(MatchedCast->getBeginLoc(),
50 "do not use C-style cast to convert between unrelated types");
54 QualType SourceType = MatchedCast->getSubExpr()->getType();
56 if (MatchedCast->getCastKind() == CK_BaseToDerived) {
57 const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl();
59 SourceDecl = SourceType->getAsCXXRecordDecl();
63 if (SourceDecl->isPolymorphic()) {
67 StringRef DestTypeString = Lexer::getSourceText(
68 CharSourceRange::getTokenRange(
69 MatchedCast->getLParenLoc().getLocWithOffset(1),
70 MatchedCast->getRParenLoc().getLocWithOffset(-1)),
71 *Result.SourceManager, getLangOpts());
73 auto diag_builder = diag(
74 MatchedCast->getBeginLoc(),
75 "do not use C-style cast to downcast from a base to a derived class; " 76 "use dynamic_cast instead");
79 MatchedCast->getSubExprAsWritten()->IgnoreImpCasts();
80 std::string CastText = (
"dynamic_cast<" + DestTypeString +
">").str();
81 if (!isa<ParenExpr>(SubExpr)) {
82 CastText.push_back(
'(');
83 diag_builder << FixItHint::CreateInsertion(
84 Lexer::getLocForEndOfToken(SubExpr->getEndLoc(), 0,
85 *Result.SourceManager, getLangOpts()),
88 auto ParenRange = CharSourceRange::getTokenRange(
89 MatchedCast->getLParenLoc(), MatchedCast->getRParenLoc());
90 diag_builder << FixItHint::CreateReplacement(ParenRange, CastText);
93 MatchedCast->getBeginLoc(),
94 "do not use C-style cast to downcast from a base to a derived class");
99 if (MatchedCast->getCastKind() == CK_NoOp &&
101 diag(MatchedCast->getBeginLoc(),
102 "do not use C-style cast to cast away constness");
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
static bool needsConstCast(QualType SourceType, QualType DestType)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//