diff options
| author | Matthias Gehre <M.Gehre@gmx.de> | 2015-10-12 20:46:53 +0000 |
|---|---|---|
| committer | Matthias Gehre <M.Gehre@gmx.de> | 2015-10-12 20:46:53 +0000 |
| commit | a704d4bb27354a7ee54b8672808ebae9c13ba806 (patch) | |
| tree | ef26f8682ed42ef1f8dca6930dda6725796bc22f /clang-tools-extra/clang-tidy/cppcoreguidelines | |
| parent | 8ebfb60efa77062d12a3ecc804b8b52737b7ac1c (diff) | |
| download | bcm5719-llvm-a704d4bb27354a7ee54b8672808ebae9c13ba806.tar.gz bcm5719-llvm-a704d4bb27354a7ee54b8672808ebae9c13ba806.zip | |
[clang-tidy] add check cppcoreguidelines-pro-type-static-cast-downcast
Summary:
This check flags all usages of static_cast, where a base class is casted
to a derived class.
In those cases, a fixit is provided to convert the cast to a
dynamic_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.
This rule is part of the "Type safety" profile of the C++ Core
Guidelines, see
https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md#-type2-dont-use-static_cast-downcasts-use-dynamic_cast-instead
Depends on D13313
Reviewers: alexfh, sbenza, bkramer, aaron.ballman
Subscribers: cfe-commits
Differential Revision: http://reviews.llvm.org/D13368
llvm-svn: 250098
Diffstat (limited to 'clang-tools-extra/clang-tidy/cppcoreguidelines')
4 files changed, 89 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt index 5a83b3fef08..d35b9a56f94 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_library(clangTidyCppCoreGuidelinesModule CppCoreGuidelinesTidyModule.cpp ProTypeConstCastCheck.cpp ProTypeReinterpretCastCheck.cpp + ProTypeStaticCastDowncastCheck.cpp LINK_LIBS clangAST diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp index 130eabe29f1..358bd6ec8fd 100644 --- a/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/CppCoreGuidelinesTidyModule.cpp @@ -12,6 +12,7 @@ #include "../ClangTidyModuleRegistry.h" #include "ProTypeConstCastCheck.h" #include "ProTypeReinterpretCastCheck.h" +#include "ProTypeStaticCastDowncastCheck.h" namespace clang { namespace tidy { @@ -25,6 +26,8 @@ public: "cppcoreguidelines-pro-type-const-cast"); CheckFactories.registerCheck<ProTypeReinterpretCastCheck>( "cppcoreguidelines-pro-type-reinterpret-cast"); + CheckFactories.registerCheck<ProTypeStaticCastDowncastCheck>( + "cppcoreguidelines-pro-type-static-cast-downcast"); } }; diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp new file mode 100644 index 00000000000..0033e4ed9d3 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.cpp @@ -0,0 +1,52 @@ +//===--- ProTypeStaticCastDowncastCheck.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 "ProTypeStaticCastDowncastCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { + +void ProTypeStaticCastDowncastCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus) + return; + + Finder->addMatcher( + cxxStaticCastExpr(unless(isInTemplateInstantiation())).bind("cast"), + this); +} + +void ProTypeStaticCastDowncastCheck::check(const MatchFinder::MatchResult &Result) { + const auto *MatchedCast = Result.Nodes.getNodeAs<CXXStaticCastExpr>("cast"); + if (MatchedCast->getCastKind() != CK_BaseToDerived) + return; + + QualType SourceType = MatchedCast->getSubExpr()->getType(); + const auto *SourceDecl = SourceType->getPointeeCXXRecordDecl(); + if (!SourceDecl) // The cast is from object to reference + SourceDecl = SourceType->getAsCXXRecordDecl(); + if (!SourceDecl) + return; + + if (SourceDecl->isPolymorphic()) + diag(MatchedCast->getOperatorLoc(), + "do not use static_cast to downcast from a base to a derived class; " + "use dynamic_cast instead") + << FixItHint::CreateReplacement(MatchedCast->getOperatorLoc(), + "dynamic_cast"); + else + diag(MatchedCast->getOperatorLoc(), + "do not use static_cast to downcast from a base to a derived class"); +} + +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h new file mode 100644 index 00000000000..02de48ae957 --- /dev/null +++ b/clang-tools-extra/clang-tidy/cppcoreguidelines/ProTypeStaticCastDowncastCheck.h @@ -0,0 +1,33 @@ +//===--- ProTypeStaticCastDowncastCheck.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_STATIC_CAST_DOWNCAST_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CPPCOREGUIDELINES_PRO_TYPE_STATIC_CAST_DOWNCAST_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { + +/// Checks for usages of static_cast, where a base class is downcasted to a derived class. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/cppcoreguidelines-pro-type-static-cast-downcast.html +class ProTypeStaticCastDowncastCheck : public ClangTidyCheck { +public: + ProTypeStaticCastDowncastCheck(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_STATIC_CAST_DOWNCAST_H |

