UseUncaughtExceptionsCheck.cpp 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. //===--- UseUncaughtExceptionsCheck.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 "UseUncaughtExceptionsCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. #include "clang/Lex/Lexer.h"
  12. using namespace clang::ast_matchers;
  13. namespace clang::tidy::modernize {
  14. void UseUncaughtExceptionsCheck::registerMatchers(MatchFinder *Finder) {
  15. std::string MatchText = "::std::uncaught_exception";
  16. // Using declaration: warning and fix-it.
  17. Finder->addMatcher(
  18. usingDecl(hasAnyUsingShadowDecl(hasTargetDecl(hasName(MatchText))))
  19. .bind("using_decl"),
  20. this);
  21. // DeclRefExpr: warning, no fix-it.
  22. Finder->addMatcher(
  23. declRefExpr(to(functionDecl(hasName(MatchText))), unless(callExpr()))
  24. .bind("decl_ref_expr"),
  25. this);
  26. auto DirectCallToUncaughtException = callee(expr(ignoringImpCasts(
  27. declRefExpr(hasDeclaration(functionDecl(hasName(MatchText)))))));
  28. // CallExpr: warning, fix-it.
  29. Finder->addMatcher(callExpr(DirectCallToUncaughtException,
  30. unless(hasAncestor(initListExpr())))
  31. .bind("call_expr"),
  32. this);
  33. // CallExpr in initialisation list: warning, fix-it with avoiding narrowing
  34. // conversions.
  35. Finder->addMatcher(callExpr(DirectCallToUncaughtException,
  36. hasAncestor(initListExpr()))
  37. .bind("init_call_expr"),
  38. this);
  39. }
  40. void UseUncaughtExceptionsCheck::check(const MatchFinder::MatchResult &Result) {
  41. SourceLocation BeginLoc;
  42. SourceLocation EndLoc;
  43. const CallExpr *C = Result.Nodes.getNodeAs<CallExpr>("init_call_expr");
  44. bool WarnOnly = false;
  45. if (C) {
  46. BeginLoc = C->getBeginLoc();
  47. EndLoc = C->getEndLoc();
  48. } else if (const auto *E = Result.Nodes.getNodeAs<CallExpr>("call_expr")) {
  49. BeginLoc = E->getBeginLoc();
  50. EndLoc = E->getEndLoc();
  51. } else if (const auto *D =
  52. Result.Nodes.getNodeAs<DeclRefExpr>("decl_ref_expr")) {
  53. BeginLoc = D->getBeginLoc();
  54. EndLoc = D->getEndLoc();
  55. WarnOnly = true;
  56. } else {
  57. const auto *U = Result.Nodes.getNodeAs<UsingDecl>("using_decl");
  58. assert(U && "Null pointer, no node provided");
  59. BeginLoc = U->getNameInfo().getBeginLoc();
  60. EndLoc = U->getNameInfo().getEndLoc();
  61. }
  62. auto Diag = diag(BeginLoc, "'std::uncaught_exception' is deprecated, use "
  63. "'std::uncaught_exceptions' instead");
  64. if (!BeginLoc.isMacroID()) {
  65. StringRef Text =
  66. Lexer::getSourceText(CharSourceRange::getTokenRange(BeginLoc, EndLoc),
  67. *Result.SourceManager, getLangOpts());
  68. Text.consume_back("()");
  69. int TextLength = Text.size();
  70. if (WarnOnly) {
  71. return;
  72. }
  73. if (!C) {
  74. Diag << FixItHint::CreateInsertion(BeginLoc.getLocWithOffset(TextLength),
  75. "s");
  76. } else {
  77. Diag << FixItHint::CreateReplacement(C->getSourceRange(),
  78. "std::uncaught_exceptions() > 0");
  79. }
  80. }
  81. }
  82. } // namespace clang::tidy::modernize