SetLongJmpCheck.cpp 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. //===--- SetLongJmpCheck.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 "SetLongJmpCheck.h"
  9. #include "clang/AST/ASTContext.h"
  10. #include "clang/ASTMatchers/ASTMatchFinder.h"
  11. #include "clang/Frontend/CompilerInstance.h"
  12. #include "clang/Lex/PPCallbacks.h"
  13. #include "clang/Lex/Preprocessor.h"
  14. using namespace clang::ast_matchers;
  15. namespace clang::tidy::cert {
  16. namespace {
  17. const char DiagWording[] =
  18. "do not call %0; consider using exception handling instead";
  19. class SetJmpMacroCallbacks : public PPCallbacks {
  20. SetLongJmpCheck &Check;
  21. public:
  22. explicit SetJmpMacroCallbacks(SetLongJmpCheck &Check) : Check(Check) {}
  23. void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
  24. SourceRange Range, const MacroArgs *Args) override {
  25. const auto *II = MacroNameTok.getIdentifierInfo();
  26. if (!II)
  27. return;
  28. if (II->getName() == "setjmp")
  29. Check.diag(Range.getBegin(), DiagWording) << II;
  30. }
  31. };
  32. } // namespace
  33. void SetLongJmpCheck::registerPPCallbacks(const SourceManager &SM,
  34. Preprocessor *PP,
  35. Preprocessor *ModuleExpanderPP) {
  36. // Per [headers]p5, setjmp must be exposed as a macro instead of a function,
  37. // despite the allowance in C for setjmp to also be an extern function.
  38. PP->addPPCallbacks(std::make_unique<SetJmpMacroCallbacks>(*this));
  39. }
  40. void SetLongJmpCheck::registerMatchers(MatchFinder *Finder) {
  41. // In case there is an implementation that happens to define setjmp as a
  42. // function instead of a macro, this will also catch use of it. However, we
  43. // are primarily searching for uses of longjmp.
  44. Finder->addMatcher(
  45. callExpr(callee(functionDecl(hasAnyName("setjmp", "longjmp"))))
  46. .bind("expr"),
  47. this);
  48. }
  49. void SetLongJmpCheck::check(const MatchFinder::MatchResult &Result) {
  50. const auto *E = Result.Nodes.getNodeAs<CallExpr>("expr");
  51. diag(E->getExprLoc(), DiagWording) << cast<NamedDecl>(E->getCalleeDecl());
  52. }
  53. } // namespace clang::tidy::cert