ExceptionBaseclassCheck.cpp 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. //===--- ExceptionBaseclassCheck.cpp - clang-tidy--------------------------===//
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "ExceptionBaseclassCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. using namespace clang::ast_matchers;
  12. namespace clang::tidy::hicpp {
  13. void ExceptionBaseclassCheck::registerMatchers(MatchFinder *Finder) {
  14. Finder->addMatcher(
  15. cxxThrowExpr(
  16. unless(has(expr(anyOf(isTypeDependent(), isValueDependent())))),
  17. // The thrown value is not derived from 'std::exception'.
  18. has(expr(unless(
  19. hasType(qualType(hasCanonicalType(hasDeclaration(cxxRecordDecl(
  20. isSameOrDerivedFrom(hasName("::std::exception")))))))))),
  21. // This condition is always true, but will bind to the
  22. // template value if the thrown type is templated.
  23. anyOf(has(expr(
  24. hasType(substTemplateTypeParmType().bind("templ_type")))),
  25. anything()),
  26. // Bind to the declaration of the type of the value that
  27. // is thrown. 'anything()' is necessary to always succeed
  28. // in the 'eachOf' because builtin types are not
  29. // 'namedDecl'.
  30. eachOf(has(expr(hasType(namedDecl().bind("decl")))), anything()))
  31. .bind("bad_throw"),
  32. this);
  33. }
  34. void ExceptionBaseclassCheck::check(const MatchFinder::MatchResult &Result) {
  35. const auto *BadThrow = Result.Nodes.getNodeAs<CXXThrowExpr>("bad_throw");
  36. assert(BadThrow && "Did not match the throw expression");
  37. diag(BadThrow->getSubExpr()->getBeginLoc(), "throwing an exception whose "
  38. "type %0 is not derived from "
  39. "'std::exception'")
  40. << BadThrow->getSubExpr()->getType() << BadThrow->getSourceRange();
  41. if (const auto *Template =
  42. Result.Nodes.getNodeAs<SubstTemplateTypeParmType>("templ_type"))
  43. diag(BadThrow->getSubExpr()->getBeginLoc(),
  44. "type %0 is a template instantiation of %1", DiagnosticIDs::Note)
  45. << BadThrow->getSubExpr()->getType()
  46. << Template->getReplacedParameter();
  47. if (const auto *TypeDecl = Result.Nodes.getNodeAs<NamedDecl>("decl"))
  48. diag(TypeDecl->getBeginLoc(), "type defined here", DiagnosticIDs::Note);
  49. }
  50. } // namespace clang::tidy::hicpp