summaryrefslogtreecommitdiffstats
path: root/clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp')
-rw-r--r--clang-tools-extra/clang-tidy/modernize/UseNoexceptCheck.cpp114
1 files changed, 114 insertions, 0 deletions
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..a38274ebbd2
--- /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
+ : 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
OpenPOWER on IntegriCloud