1 //===--- ThrowKeywordMissingCheck.cpp - clang-tidy-------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "ThrowKeywordMissingCheck.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/ASTMatchers/ASTMatchFinder.h"
13 
14 using namespace clang::ast_matchers;
15 
16 namespace clang {
17 namespace tidy {
18 namespace bugprone {
19 
20 void ThrowKeywordMissingCheck::registerMatchers(MatchFinder *Finder) {
21   if (!getLangOpts().CPlusPlus)
22     return;
23 
24   auto CtorInitializerList =
25       cxxConstructorDecl(hasAnyConstructorInitializer(anything()));
26 
27   Finder->addMatcher(
28       expr(anyOf(cxxFunctionalCastExpr(), cxxBindTemporaryExpr(),
29                  cxxTemporaryObjectExpr()),
30            hasType(cxxRecordDecl(
31                isSameOrDerivedFrom(matchesName("[Ee]xception|EXCEPTION")))),
32            unless(anyOf(hasAncestor(stmt(
33                             anyOf(cxxThrowExpr(), callExpr(), returnStmt()))),
34                         hasAncestor(varDecl()),
35                         allOf(hasAncestor(CtorInitializerList),
36                               unless(hasAncestor(cxxCatchStmt()))))))
37           .bind("temporary-exception-not-thrown"),
38       this);
39 }
40 
41 void ThrowKeywordMissingCheck::check(const MatchFinder::MatchResult &Result) {
42   const auto *TemporaryExpr =
43       Result.Nodes.getNodeAs<Expr>("temporary-exception-not-thrown");
44 
45   diag(TemporaryExpr->getLocStart(), "suspicious exception object created but "
46                                      "not thrown; did you mean 'throw %0'?")
47       << TemporaryExpr->getType().getBaseTypeIdentifier()->getName();
48 }
49 
50 } // namespace bugprone
51 } // namespace tidy
52 } // namespace clang
53