summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/cppcoreguidelines
diff options
context:
space:
mode:
authorMatthias Gehre <M.Gehre@gmx.de>2015-11-08 21:10:39 +0000
committerMatthias Gehre <M.Gehre@gmx.de>2015-11-08 21:10:39 +0000
commiteeb71758cc32933863a8f165c1a63c517fd9283a (patch)
tree470284cd44e5ecce4db918dd097e91ccb265cc19 /clang-tools-extra/clang-tidy/cppcoreguidelines
parentf85ad0411f1dcec5a1da1958c2663a50e8c2748b (diff)
downloadbcm5719-llvm-eeb71758cc32933863a8f165c1a63c517fd9283a.tar.gz
bcm5719-llvm-eeb71758cc32933863a8f165c1a63c517fd9283a.zip
[clang-tidy] add new check cppcoreguidelines-pro-type-cstyle-cast
Summary: This check flags all use of c-style casts that perform a static_cast downcast, const_cast, or reinterpret_cast. Use of these casts can violate type safety and cause the program to access a variable that is actually of type X to be accessed as if it were of an unrelated type Z. Note that a C-style (T)expression cast means to perform the first of the following that is possible: a const_cast, a static_cast, a static_cast followed by a const_cast, a reinterpret_cast, or a reinterpret_cast followed by a const_cast. This rule bans (T)expression only when used to perform an unsafe cast. This rule is part of the "Type safety" profile of the C++ Core Guidelines, see https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-type4-dont-use-c-style-texpression-casts-that-would-perform-a-static_cast-downcast-const_cast-or-reinterpret_cast. Reviewers: alexfh, sbenza, bkramer, aaron.ballman Subscribers: cfe-commits Differential Revision: http://reviews.llvm.org/D14096 llvm-svn: 252425
Diffstat (limited to 'clang-tools-extra/clang-tidy/cppcoreguidelines')
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt1
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp3
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp107
-rw-r--r--clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h34
4 files changed, 145 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
index 506a90741ba..3bf729cbd10 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt
@@ -5,6 +5,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule
ProBoundsArrayToPointerDecayCheck.cpp
ProBoundsPointerArithmeticCheck.cpp
ProTypeConstCastCheck.cpp
+ ProTypeCstyleCastCheck.cpp
ProTypeReinterpretCastCheck.cpp
ProTypeStaticCastDowncastCheck.cpp
ProTypeUnionAccessCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
index d77954b51a1..1ef55da14ab 100644
--- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp
@@ -14,6 +14,7 @@
#include "ProBoundsArrayToPointerDecayCheck.h"
#include "ProBoundsPointerArithmeticCheck.h"
#include "ProTypeConstCastCheck.h"
+#include "ProTypeCstyleCastCheck.h"
#include "ProTypeReinterpretCastCheck.h"
#include "ProTypeStaticCastDowncastCheck.h"
#include "ProTypeUnionAccessCheck.h"
@@ -33,6 +34,8 @@ public:
"cppcoreguidelines-pro-bounds-pointer-arithmetic");
CheckFactories.registerCheck<ProTypeConstCastCheck>(
"cppcoreguidelines-pro-type-const-cast");
+ CheckFactories.registerCheck<ProTypeCstyleCastCheck>(
+ "cppcoreguidelines-pro-type-cstyle-cast");
CheckFactories.registerCheck<ProTypeReinterpretCastCheck>(
"cppcoreguidelines-pro-type-reinterpret-cast");
CheckFactories.registerCheck<ProTypeStaticCastDowncastCheck>(
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
new file mode 100644
index 00000000000..542dd854c43
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.cpp
@@ -0,0 +1,107 @@
+//===--- ProTypeCstyleCastCheck.cpp - clang-tidy---------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProTypeCstyleCastCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang {
+namespace tidy {
+
+static bool needsConstCast(QualType SourceType, QualType DestType) {
+ SourceType = SourceType.getNonReferenceType();
+ DestType = DestType.getNonReferenceType();
+ while (SourceType->isPointerType() && DestType->isPointerType()) {
+ SourceType = SourceType->getPointeeType();
+ DestType = DestType->getPointeeType();
+ if (SourceType.isConstQualified() && !DestType.isConstQualified())
+ return true;
+ }
+ return false;
+}
+
+void ProTypeCstyleCastCheck::registerMatchers(MatchFinder *Finder) {
+ if (!getLangOpts().CPlusPlus)
+ return;
+
+ Finder->addMatcher(
+ cStyleCastExpr(unless(isInTemplateInstantiation())).bind("cast"), this);
+}
+
+void ProTypeCstyleCastCheck::check(const MatchFinder::MatchResult &Result) {
+ const auto *MatchedCast = Result.Nodes.getNodeAs<CStyleCastExpr>("cast");
+
+ if (MatchedCast->getCastKind() == CK_BitCast ||
+ MatchedCast->getCastKind() == CK_LValueBitCast ||
+ MatchedCast->getCastKind() == CK_IntegralToPointer ||
+ MatchedCast->getCastKind() == CK_PointerToIntegral ||
+ MatchedCast->getCastKind() == CK_ReinterpretMemberPointer) {
+ diag(MatchedCast->getLocStart(),
+ "do not use C-style cast to convert between unrelated types");
+ return;
+ }
+
+ QualType SourceType = MatchedCast->getSubExpr()->getType();
+
+ if (MatchedCast->getCastKind() == CK_BaseToDerived) {
+ const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl();
+ if (!SourceDecl) // The cast is from object to reference.
+ SourceDecl = SourceType->getAsCXXRecordDecl();
+ if (!SourceDecl)
+ return;
+
+ if (SourceDecl->isPolymorphic()) {
+ // Leave type spelling exactly as it was (unlike
+ // getTypeAsWritten().getAsString() which would spell enum types 'enum
+ // X').
+ StringRef DestTypeString = Lexer::getSourceText(
+ CharSourceRange::getTokenRange(
+ MatchedCast->getLParenLoc().getLocWithOffset(1),
+ MatchedCast->getRParenLoc().getLocWithOffset(-1)),
+ *Result.SourceManager, Result.Context->getLangOpts());
+
+ auto diag_builder = diag(
+ MatchedCast->getLocStart(),
+ "do not use C-style cast to downcast from a base to a derived class; "
+ "use dynamic_cast instead");
+
+ const Expr *SubExpr =
+ MatchedCast->getSubExprAsWritten()->IgnoreImpCasts();
+ std::string CastText = ("dynamic_cast<" + DestTypeString + ">").str();
+ if (!isa<ParenExpr>(SubExpr)) {
+ CastText.push_back('(');
+ diag_builder << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(SubExpr->getLocEnd(), 0,
+ *Result.SourceManager,
+ Result.Context->getLangOpts()),
+ ")");
+ }
+ auto ParenRange = CharSourceRange::getTokenRange(
+ MatchedCast->getLParenLoc(), MatchedCast->getRParenLoc());
+ diag_builder << FixItHint::CreateReplacement(ParenRange, CastText);
+ } else {
+ diag(
+ MatchedCast->getLocStart(),
+ "do not use C-style cast to downcast from a base to a derived class");
+ }
+ return;
+ }
+
+ if (MatchedCast->getCastKind() == CK_NoOp &&
+ needsConstCast(SourceType, MatchedCast->getType())) {
+ diag(MatchedCast->getLocStart(),
+ "do not use C-style cast to cast away constness");
+ }
+}
+
+} // namespace tidy
+} // namespace clang
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h
new file mode 100644
index 00000000000..f85be87d93b
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeCstyleCastCheck.h
@@ -0,0 +1,34 @@
+//===--- ProTypeCstyleCastCheck.h - clang-tidy-------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_CSTYLE_CAST_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_CSTYLE_CAST_H
+
+#include "../ClangTidy.h"
+
+namespace clang {
+namespace tidy {
+
+/// This check flags all use of C-style casts that perform a static_cast
+/// downcast, const_cast, or reinterpret_cast.
+///
+/// For the user-facing documentation see:
+/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-cstyle-cast.html
+class ProTypeCstyleCastCheck : public ClangTidyCheck {
+public:
+ ProTypeCstyleCastCheck(StringRef Name, ClangTidyContext *Context)
+ : ClangTidyCheck(Name, Context) {}
+ void registerMatchers(ast_matchers::MatchFinder *Finder) override;
+ void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
+};
+
+} // namespace tidy
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_CSTYLE_CAST_H
OpenPOWER on IntegriCloud