1 //===--- ExceptionBaseclassCheck.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 "ExceptionBaseclassCheck.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 hicpp { 19 20 void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) { 21 if (!getLangOpts().CPlusPlus) 22 return; 23 24 Finder->addMatcher( 25 cxxThrowExpr(allOf(has(expr(unless(hasType(qualType(hasCanonicalType( 26 hasDeclaration(cxxRecordDecl(isSameOrDerivedFrom( 27 hasName("std::exception")))))))))), 28 has(expr(unless(cxxUnresolvedConstructExpr()))), 29 eachOf(has(expr(hasType(namedDecl().bind("decl")))), 30 anything()))) 31 .bind("bad_throw"), 32 this); 33 } 34 35 void ExceptionBaseclassCheck::check(const MatchFinder::MatchResult &Result) { 36 const auto *BadThrow = Result.Nodes.getNodeAs<CXXThrowExpr>("bad_throw"); 37 38 diag(BadThrow->getSubExpr()->getBeginLoc(), "throwing an exception whose " 39 "type %0 is not derived from " 40 "'std::exception'") 41 << BadThrow->getSubExpr()->getType() << BadThrow->getSourceRange(); 42 43 const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl"); 44 if (TypeDecl != nullptr) 45 diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note); 46 } 47 48 } // namespace hicpp 49 } // namespace tidy 50 } // namespace clang 51