brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · 6bd5485 Raw
107 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "UseNoexceptCheck.h"10#include "clang/AST/ASTContext.h"11#include "clang/Lex/Lexer.h"12 13using namespace clang::ast_matchers;14 15namespace clang::tidy::modernize {16 17namespace {18AST_MATCHER(NamedDecl, isValid) { return !Node.isInvalidDecl(); }19} // namespace20 21UseNoexceptCheck::UseNoexceptCheck(StringRef Name, ClangTidyContext *Context)22    : ClangTidyCheck(Name, Context),23      NoexceptMacro(Options.get("ReplacementString", "")),24      UseNoexceptFalse(Options.get("UseNoexceptFalse", true)) {}25 26void UseNoexceptCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {27  Options.store(Opts, "ReplacementString", NoexceptMacro);28  Options.store(Opts, "UseNoexceptFalse", UseNoexceptFalse);29}30 31void UseNoexceptCheck::registerMatchers(MatchFinder *Finder) {32  Finder->addMatcher(33      functionDecl(34          isValid(),35          hasTypeLoc(loc(functionProtoType(hasDynamicExceptionSpec()))),36          optionally(cxxMethodDecl(anyOf(hasAnyOverloadedOperatorName(37                                             "delete[]", "delete"),38                                         cxxDestructorDecl()))39                         .bind("del-dtor")))40          .bind("funcDecl"),41      this);42 43  Finder->addMatcher(44      parmVarDecl(anyOf(hasType(pointerType(pointee(parenType(innerType(45                            functionProtoType(hasDynamicExceptionSpec())))))),46                        hasType(memberPointerType(pointee(parenType(innerType(47                            functionProtoType(hasDynamicExceptionSpec()))))))))48          .bind("parmVarDecl"),49      this);50}51 52void UseNoexceptCheck::check(const MatchFinder::MatchResult &Result) {53  const FunctionProtoType *FnTy = nullptr;54  bool DtorOrOperatorDel = false;55  SourceRange Range;56 57  if (const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>("funcDecl")) {58    DtorOrOperatorDel = Result.Nodes.getNodeAs<FunctionDecl>("del-dtor");59    FnTy = FuncDecl->getType()->getAs<FunctionProtoType>();60    if (const auto *TSI = FuncDecl->getTypeSourceInfo())61      Range =62          TSI->getTypeLoc().castAs<FunctionTypeLoc>().getExceptionSpecRange();63  } else if (const auto *ParmDecl =64                 Result.Nodes.getNodeAs<ParmVarDecl>("parmVarDecl")) {65    FnTy = ParmDecl->getType()66               ->castAs<Type>()67               ->getPointeeType()68               ->getAs<FunctionProtoType>();69 70    if (const auto *TSI = ParmDecl->getTypeSourceInfo())71      Range = TSI->getTypeLoc()72                  .getNextTypeLoc()73                  .IgnoreParens()74                  .castAs<FunctionProtoTypeLoc>()75                  .getExceptionSpecRange();76  }77 78  assert(FnTy && "FunctionProtoType is null.");79  if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType()))80    return;81 82  assert(Range.isValid() && "Exception Source Range is invalid.");83 84  const CharSourceRange CRange = Lexer::makeFileCharRange(85      CharSourceRange::getTokenRange(Range), *Result.SourceManager,86      Result.Context->getLangOpts());87 88  const bool IsNoThrow = FnTy->isNothrow();89  const StringRef ReplacementStr =90      IsNoThrow ? NoexceptMacro.empty() ? "noexcept" : NoexceptMacro91      : NoexceptMacro.empty()92          ? (DtorOrOperatorDel || UseNoexceptFalse) ? "noexcept(false)" : ""93          : "";94 95  FixItHint FixIt;96  if ((IsNoThrow || NoexceptMacro.empty()) && CRange.isValid())97    FixIt = FixItHint::CreateReplacement(CRange, ReplacementStr);98 99  diag(Range.getBegin(), "dynamic exception specification '%0' is deprecated; "100                         "consider %select{using '%2'|removing it}1 instead")101      << Lexer::getSourceText(CRange, *Result.SourceManager,102                              Result.Context->getLangOpts())103      << ReplacementStr.empty() << ReplacementStr << FixIt;104}105 106} // namespace clang::tidy::modernize107