clang-tools 3.8.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
20 static bool needsConstCast(QualType SourceType, QualType DestType) {
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())
27 return true;
28 }
29 return false;
30 }
31
32 void ProTypeCstyleCastCheck::registerMatchers(MatchFinder *Finder) {
33 if (!getLangOpts().CPlusPlus)
34 return;
35
36 Finder->addMatcher(
37 cStyleCastExpr(unless(isInTemplateInstantiation())).bind("cast"), this);
38 }
39
40 void ProTypeCstyleCastCheck::check(const MatchFinder::MatchResult &Result) {
41 const auto *MatchedCast = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
42
43 if (MatchedCast->getCastKind() == CK_BitCast ||
44 MatchedCast->getCastKind() == CK_LValueBitCast ||
45 MatchedCast->getCastKind() == CK_IntegralToPointer ||
46 MatchedCast->getCastKind() == CK_PointerToIntegral ||
47 MatchedCast->getCastKind() == CK_ReinterpretMemberPointer) {
48 diag(MatchedCast->getLocStart(),
49 "do not use C-style cast to convert between unrelated types");
50 return;
51 }
52
53 QualType SourceType = MatchedCast->getSubExpr()->getType();
54
55 if (MatchedCast->getCastKind() == CK_BaseToDerived) {
56 const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl();
57 if (!SourceDecl) // The cast is from object to reference.
58 SourceDecl = SourceType->getAsCXXRecordDecl();
59 if (!SourceDecl)
60 return;
61
62 if (SourceDecl->isPolymorphic()) {
63 // Leave type spelling exactly as it was (unlike
64 // getTypeAsWritten().getAsString() which would spell enum types 'enum
65 // X').
66 StringRef DestTypeString = Lexer::getSourceText(
67 CharSourceRange::getTokenRange(
68 MatchedCast->getLParenLoc().getLocWithOffset(1),
69 MatchedCast->getRParenLoc().getLocWithOffset(-1)),
70 *Result.SourceManager, Result.Context->getLangOpts());
71
72 auto diag_builder = diag(
73 MatchedCast->getLocStart(),
74 "do not use C-style cast to downcast from a base to a derived class; "
75 "use dynamic_cast instead");
76
77 const Expr *SubExpr =
78 MatchedCast->getSubExprAsWritten()->IgnoreImpCasts();
79 std::string CastText = ("dynamic_cast<" + DestTypeString + ">").str();
80 if (!isa<ParenExpr>(SubExpr)) {
81 CastText.push_back('(');
82 diag_builder << FixItHint::CreateInsertion(
83 Lexer::getLocForEndOfToken(SubExpr->getLocEnd(), 0,
84 *Result.SourceManager,
85 Result.Context->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 tidy
107 } // namespace clang
clang::tidy::needsConstCast
static bool needsConstCast(QualType SourceType, QualType DestType)
Definition: ProTypeCstyleCastCheck.cpp:20
Finder
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:188
ProTypeCstyleCastCheck.h
Result
const NamedDecl * Result
Definition: USRFinder.cpp:121