clang-tools 6.0.0

ProTypeCstyleCastCheck.cpp
Go to the documentation of this file.
1 //===--- ProTypeCstyleCastCheck.cpp - clang-tidy---------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "ProTypeCstyleCastCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 #include "clang/Lex/Lexer.h"
14
15 using namespace clang::ast_matchers;
16
17 namespace clang {
18 namespace tidy {
19 namespace cppcoreguidelines {
20
21 static bool needsConstCast(QualType SourceType, QualType DestType) {
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())
28 return true;
29 }
30 return false;
31 }
32
33 void ProTypeCstyleCastCheck::registerMatchers(MatchFinder *Finder) {
34 if (!getLangOpts().CPlusPlus)
35 return;
36
37 Finder->addMatcher(
38 cStyleCastExpr(unless(isInTemplateInstantiation())).bind("cast"), this);
39 }
40
41 void ProTypeCstyleCastCheck::check(const MatchFinder::MatchResult &Result) {
42 const auto *MatchedCast = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
43
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->getLocStart(),
50 "do not use C-style cast to convert between unrelated types");
51 return;
52 }
53
54 QualType SourceType = MatchedCast->getSubExpr()->getType();
55
56 if (MatchedCast->getCastKind() == CK_BaseToDerived) {
57 const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl();
58 if (!SourceDecl) // The cast is from object to reference.
59 SourceDecl = SourceType->getAsCXXRecordDecl();
60 if (!SourceDecl)
61 return;
62
63 if (SourceDecl->isPolymorphic()) {
64 // Leave type spelling exactly as it was (unlike
65 // getTypeAsWritten().getAsString() which would spell enum types 'enum
66 // X').
67 StringRef DestTypeString = Lexer::getSourceText(
68 CharSourceRange::getTokenRange(
69 MatchedCast->getLParenLoc().getLocWithOffset(1),
70 MatchedCast->getRParenLoc().getLocWithOffset(-1)),
71 *Result.SourceManager, getLangOpts());
72
73 auto diag_builder = diag(
74 MatchedCast->getLocStart(),
75 "do not use C-style cast to downcast from a base to a derived class; "
76 "use dynamic_cast instead");
77
78 const Expr *SubExpr =
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->getLocEnd(), 0,
85 *Result.SourceManager, getLangOpts()),
86 ")");
87 }
88 auto ParenRange = CharSourceRange::getTokenRange(
89 MatchedCast->getLParenLoc(), MatchedCast->getRParenLoc());
90 diag_builder << FixItHint::CreateReplacement(ParenRange, CastText);
91 } else {
92 diag(
93 MatchedCast->getLocStart(),
94 "do not use C-style cast to downcast from a base to a derived class");
95 }
96 return;
97 }
98
99 if (MatchedCast->getCastKind() == CK_NoOp &&
100 needsConstCast(SourceType, MatchedCast->getType())) {
101 diag(MatchedCast->getLocStart(),
102 "do not use C-style cast to cast away constness");
103 }
104 }
105
106 } // namespace cppcoreguidelines
107 } // namespace tidy
108 } // namespace clang
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
ProTypeCstyleCastCheck.h
clang::tidy::cppcoreguidelines::needsConstCast
static bool needsConstCast(QualType SourceType, QualType DestType)
Definition: ProTypeCstyleCastCheck.cpp:21
clang
Definition: AndroidTidyModule.cpp:28