diff options
| author | Alexander Kornienko <alexfh@google.com> | 2017-06-08 14:04:16 +0000 |
|---|---|---|
| committer | Alexander Kornienko <alexfh@google.com> | 2017-06-08 14:04:16 +0000 |
| commit | 08936e4740e5c4f47a11efe059353987ac7c0145 (patch) | |
| tree | 074573597942fd1370e379c5c32997faf79b21e7 /clang-tools-extra/clang-tidy | |
| parent | c3c721222d3ca702ebe14ebc487a7feced6c36c1 (diff) | |
| download | bcm5719-llvm-08936e4740e5c4f47a11efe059353987ac7c0145.tar.gz bcm5719-llvm-08936e4740e5c4f47a11efe059353987ac7c0145.zip | |
[clang-tidy] New checker to replace dynamic exception specifications
Summary:
New checker to replace dynamic exception
specifications
This is an alternative to D18575 which relied on reparsing the decl to
find the location of dynamic exception specifications, but couldn't
deal with preprocessor conditionals correctly without reparsing the
entire file.
This approach uses D20428 to find dynamic exception specification
locations and handles all cases correctly.
Reviewers: aaron.ballman, alexfh
Reviewed By: aaron.ballman, alexfh
Subscribers: xazax.hun, mgehre, malcolm.parsons, mgorny, JDevlieghere, cfe-commits, Eugene.Zelenko, etienneb
Patch by Don Hinton!
Differential Revision: https://reviews.llvm.org/D20693
llvm-svn: 304977
Diffstat (limited to 'clang-tools-extra/clang-tidy')
4 files changed, 166 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt index b2f45b65727..8058f52343c 100644 --- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt @@ -22,6 +22,7 @@ add_clang_library(clangTidyModernizeModule UseEmplaceCheck.cpp UseEqualsDefaultCheck.cpp UseEqualsDeleteCheck.cpp + UseNoexceptCheck.cpp UseNullptrCheck.cpp UseOverrideCheck.cpp UseTransparentFunctorsCheck.cpp diff --git a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp index de027249d2d..f8c50e0c439 100644 --- a/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp @@ -28,6 +28,7 @@ #include "UseEmplaceCheck.h" #include "UseEqualsDefaultCheck.h" #include "UseEqualsDeleteCheck.h" +#include "UseNoexceptCheck.h" #include "UseNullptrCheck.h" #include "UseOverrideCheck.h" #include "UseTransparentFunctorsCheck.h" @@ -69,6 +70,7 @@ public: CheckFactories.registerCheck<UseEqualsDefaultCheck>("modernize-use-equals-default"); CheckFactories.registerCheck<UseEqualsDeleteCheck>( "modernize-use-equals-delete"); + CheckFactories.registerCheck<UseNoexceptCheck>("modernize-use-noexcept"); CheckFactories.registerCheck<UseNullptrCheck>("modernize-use-nullptr"); CheckFactories.registerCheck<UseOverrideCheck>("modernize-use-override"); CheckFactories.registerCheck<UseTransparentFunctorsCheck>( diff --git a/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp new file mode 100644 index 00000000000..e32aef92143 --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp @@ -0,0 +1,114 @@ +//===--- UseNoexceptCheck.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 "UseNoexceptCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/Lex/Lexer.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace modernize { + +UseNoexceptCheck::UseNoexceptCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context), + NoexceptMacro(Options.get("ReplacementString", "")), + UseNoexceptFalse(Options.get("UseNoexceptFalse", true)) {} + +void UseNoexceptCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { + Options.store(Opts, "ReplacementString", NoexceptMacro); + Options.store(Opts, "UseNoexceptFalse", UseNoexceptFalse); +} + +void UseNoexceptCheck::registerMatchers(MatchFinder *Finder) { + if (!getLangOpts().CPlusPlus11) + return; + + Finder->addMatcher( + functionDecl( + cxxMethodDecl( + hasTypeLoc(loc(functionProtoType(hasDynamicExceptionSpec()))), + anyOf(hasOverloadedOperatorName("delete[]"), + hasOverloadedOperatorName("delete"), cxxDestructorDecl())) + .bind("del-dtor")) + .bind("funcDecl"), + this); + + Finder->addMatcher( + functionDecl( + hasTypeLoc(loc(functionProtoType(hasDynamicExceptionSpec()))), + unless(anyOf(hasOverloadedOperatorName("delete[]"), + hasOverloadedOperatorName("delete"), + cxxDestructorDecl()))) + .bind("funcDecl"), + this); + + Finder->addMatcher( + parmVarDecl(anyOf(hasType(pointerType(pointee(parenType(innerType( + functionProtoType(hasDynamicExceptionSpec())))))), + hasType(memberPointerType(pointee(parenType(innerType( + functionProtoType(hasDynamicExceptionSpec())))))))) + .bind("parmVarDecl"), + this); +} + +void UseNoexceptCheck::check(const MatchFinder::MatchResult &Result) { + const FunctionProtoType *FnTy = nullptr; + bool DtorOrOperatorDel = false; + SourceRange Range; + + if (const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("funcDecl")) { + DtorOrOperatorDel = Result.Nodes.getNodeAs<FunctionDecl>("del-dtor"); + FnTy = FuncDecl->getType()->getAs<FunctionProtoType>(); + if (const auto *TSI = FuncDecl->getTypeSourceInfo()) + Range = + TSI->getTypeLoc().castAs<FunctionTypeLoc>().getExceptionSpecRange(); + } else if (const auto *ParmDecl = + Result.Nodes.getNodeAs<ParmVarDecl>("parmVarDecl")) { + FnTy = ParmDecl->getType() + ->getAs<Type>() + ->getPointeeType() + ->getAs<FunctionProtoType>(); + + if (const auto *TSI = ParmDecl->getTypeSourceInfo()) + Range = TSI->getTypeLoc() + .getNextTypeLoc() + .IgnoreParens() + .castAs<FunctionProtoTypeLoc>() + .getExceptionSpecRange(); + } + CharSourceRange CRange = Lexer::makeFileCharRange( + CharSourceRange::getTokenRange(Range), *Result.SourceManager, + Result.Context->getLangOpts()); + + assert(FnTy && "FunctionProtoType is null."); + bool IsNoThrow = FnTy->isNothrow(*Result.Context); + StringRef ReplacementStr = + IsNoThrow + ? NoexceptMacro.empty() ? "noexcept" : NoexceptMacro.c_str() + : NoexceptMacro.empty() + ? (DtorOrOperatorDel || UseNoexceptFalse) ? "noexcept(false)" + : "" + : ""; + + FixItHint FixIt; + if ((IsNoThrow || NoexceptMacro.empty()) && CRange.isValid()) + FixIt = FixItHint::CreateReplacement(CRange, ReplacementStr); + + diag(Range.getBegin(), "dynamic exception specification '%0' is deprecated; " + "consider %select{using '%2'|removing it}1 instead") + << Lexer::getSourceText(CRange, *Result.SourceManager, + Result.Context->getLangOpts()) + << ReplacementStr.empty() << ReplacementStr << FixIt; +} + +} // namespace modernize +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.h b/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.h new file mode 100644 index 00000000000..4fbd0bdde07 --- /dev/null +++ b/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.h @@ -0,0 +1,49 @@ +//===--- UseNoexceptCheck.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_MODERNIZE_USE_NOEXCEPT_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H + +#include "../ClangTidy.h" + +namespace clang { +namespace tidy { +namespace modernize { + +/// \brief Replace dynamic exception specifications, with +/// `noexcept` (or user-defined macro) or `noexcept(false)`. +/// \code +/// void foo() throw(); +/// void bar() throw(int); +/// \endcode +/// Is converted to: +/// \code +/// void foo() ; +// void bar() noexcept(false); +/// \endcode +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/modernize-use-noexcept.html +class UseNoexceptCheck : public ClangTidyCheck { +public: + UseNoexceptCheck(StringRef Name, ClangTidyContext *Context); + void storeOptions(ClangTidyOptions::OptionMap &Opts) override; + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; + +private: + const std::string NoexceptMacro; + bool UseNoexceptFalse; +}; + +} // namespace modernize +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_MODERNIZE_USE_NOEXCEPT_H |

