xref: /llvm-project/clang-tools-extra/clang-tidy/performance/NoexceptFunctionBaseCheck.cpp (revision 845618cf69e89313084a4e93f8ff31d8e6ea4499)
1*845618cfSAMS21 //===--- NoexceptFunctionCheck.cpp - clang-tidy ---------------------------===//
2*845618cfSAMS21 //
3*845618cfSAMS21 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*845618cfSAMS21 // See https://llvm.org/LICENSE.txt for license information.
5*845618cfSAMS21 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*845618cfSAMS21 //
7*845618cfSAMS21 //===----------------------------------------------------------------------===//
8*845618cfSAMS21 
9*845618cfSAMS21 #include "NoexceptFunctionBaseCheck.h"
10*845618cfSAMS21 #include "../utils/LexerUtils.h"
11*845618cfSAMS21 #include "clang/AST/ASTContext.h"
12*845618cfSAMS21 #include "clang/AST/Decl.h"
13*845618cfSAMS21 #include "clang/ASTMatchers/ASTMatchFinder.h"
14*845618cfSAMS21 
15*845618cfSAMS21 using namespace clang::ast_matchers;
16*845618cfSAMS21 
17*845618cfSAMS21 namespace clang::tidy::performance {
18*845618cfSAMS21 
check(const MatchFinder::MatchResult & Result)19*845618cfSAMS21 void NoexceptFunctionBaseCheck::check(const MatchFinder::MatchResult &Result) {
20*845618cfSAMS21   const auto *FuncDecl = Result.Nodes.getNodeAs<FunctionDecl>(BindFuncDeclName);
21*845618cfSAMS21   assert(FuncDecl);
22*845618cfSAMS21 
23*845618cfSAMS21   if (SpecAnalyzer.analyze(FuncDecl) !=
24*845618cfSAMS21       utils::ExceptionSpecAnalyzer::State::Throwing)
25*845618cfSAMS21     return;
26*845618cfSAMS21 
27*845618cfSAMS21   // Don't complain about nothrow(false), but complain on nothrow(expr)
28*845618cfSAMS21   // where expr evaluates to false.
29*845618cfSAMS21   const auto *ProtoType = FuncDecl->getType()->castAs<FunctionProtoType>();
30*845618cfSAMS21   const Expr *NoexceptExpr = ProtoType->getNoexceptExpr();
31*845618cfSAMS21   if (NoexceptExpr) {
32*845618cfSAMS21     NoexceptExpr = NoexceptExpr->IgnoreImplicit();
33*845618cfSAMS21     if (!isa<CXXBoolLiteralExpr>(NoexceptExpr))
34*845618cfSAMS21       reportNoexceptEvaluatedToFalse(FuncDecl, NoexceptExpr);
35*845618cfSAMS21     return;
36*845618cfSAMS21   }
37*845618cfSAMS21 
38*845618cfSAMS21   auto Diag = reportMissingNoexcept(FuncDecl);
39*845618cfSAMS21 
40*845618cfSAMS21   // Add FixIt hints.
41*845618cfSAMS21   const SourceManager &SM = *Result.SourceManager;
42*845618cfSAMS21 
43*845618cfSAMS21   const SourceLocation NoexceptLoc =
44*845618cfSAMS21       utils::lexer::getLocationForNoexceptSpecifier(FuncDecl, SM);
45*845618cfSAMS21   if (NoexceptLoc.isValid())
46*845618cfSAMS21     Diag << FixItHint::CreateInsertion(NoexceptLoc, " noexcept ");
47*845618cfSAMS21 }
48*845618cfSAMS21 
49*845618cfSAMS21 } // namespace clang::tidy::performance
50