[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
2017-06-08 22:04:16 +08:00
|
|
|
//===--- UseNoexceptCheck.cpp - clang-tidy---------------------------------===//
|
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
[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
2017-06-08 22:04:16 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#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.");
|
2018-05-03 11:59:50 +08:00
|
|
|
bool IsNoThrow = FnTy->isNothrow();
|
[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
2017-06-08 22:04:16 +08:00
|
|
|
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
|