clang-tools  10.0.0git
ProTypeCstyleCastCheck.cpp
Go to the documentation of this file.
1 //===--- ProTypeCstyleCastCheck.cpp - clang-tidy---------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
10 #include "clang/AST/ASTContext.h"
11 #include "clang/ASTMatchers/ASTMatchFinder.h"
12 #include "clang/Lex/Lexer.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace cppcoreguidelines {
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->getBeginLoc(),
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(
68  MatchedCast->getLParenLoc().getLocWithOffset(1),
69  MatchedCast->getRParenLoc().getLocWithOffset(-1)),
70  *Result.SourceManager, getLangOpts());
71 
72  auto diag_builder = diag(
73  MatchedCast->getBeginLoc(),
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->getEndLoc(), 0,
84  *Result.SourceManager, getLangOpts()),
85  ")");
86  }
87  auto ParenRange = CharSourceRange::getTokenRange(
88  MatchedCast->getLParenLoc(), MatchedCast->getRParenLoc());
89  diag_builder << FixItHint::CreateReplacement(ParenRange, CastText);
90  } else {
91  diag(
92  MatchedCast->getBeginLoc(),
93  "do not use C-style cast to downcast from a base to a derived class");
94  }
95  return;
96  }
97 
98  if (MatchedCast->getCastKind() == CK_NoOp &&
99  needsConstCast(SourceType, MatchedCast->getType())) {
100  diag(MatchedCast->getBeginLoc(),
101  "do not use C-style cast to cast away constness");
102  }
103 }
104 
105 } // namespace cppcoreguidelines
106 } // namespace tidy
107 } // namespace clang
llvm::Optional< Range > getTokenRange(const SourceManager &SM, const LangOptions &LangOpts, SourceLocation TokLoc)
Returns the taken range at TokLoc.
Definition: SourceCode.cpp:227
static bool needsConstCast(QualType SourceType, QualType DestType)
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//