LexerUtils.h 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. //===--- LexerUtils.h - clang-tidy-------------------------------*- C++ -*-===//
  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. #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H
  9. #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H
  10. #include "clang/AST/ASTContext.h"
  11. #include "clang/Basic/TokenKinds.h"
  12. #include "clang/Lex/Lexer.h"
  13. #include <optional>
  14. namespace clang {
  15. class Stmt;
  16. namespace tidy::utils::lexer {
  17. /// Returns previous token or ``tok::unknown`` if not found.
  18. Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
  19. const LangOptions &LangOpts, bool SkipComments = true);
  20. SourceLocation findPreviousTokenStart(SourceLocation Start,
  21. const SourceManager &SM,
  22. const LangOptions &LangOpts);
  23. SourceLocation findPreviousTokenKind(SourceLocation Start,
  24. const SourceManager &SM,
  25. const LangOptions &LangOpts,
  26. tok::TokenKind TK);
  27. SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM,
  28. const LangOptions &LangOpts);
  29. template <typename TokenKind, typename... TokenKinds>
  30. SourceLocation findPreviousAnyTokenKind(SourceLocation Start,
  31. const SourceManager &SM,
  32. const LangOptions &LangOpts,
  33. TokenKind TK, TokenKinds... TKs) {
  34. if (Start.isInvalid() || Start.isMacroID())
  35. return SourceLocation();
  36. while (true) {
  37. SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
  38. if (L.isInvalid() || L.isMacroID())
  39. return SourceLocation();
  40. Token T;
  41. // Returning 'true' is used to signal failure to retrieve the token.
  42. if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
  43. return SourceLocation();
  44. if (T.isOneOf(TK, TKs...))
  45. return T.getLocation();
  46. Start = L;
  47. }
  48. }
  49. template <typename TokenKind, typename... TokenKinds>
  50. SourceLocation findNextAnyTokenKind(SourceLocation Start,
  51. const SourceManager &SM,
  52. const LangOptions &LangOpts, TokenKind TK,
  53. TokenKinds... TKs) {
  54. while (true) {
  55. std::optional<Token> CurrentToken =
  56. Lexer::findNextToken(Start, SM, LangOpts);
  57. if (!CurrentToken)
  58. return SourceLocation();
  59. Token PotentialMatch = *CurrentToken;
  60. if (PotentialMatch.isOneOf(TK, TKs...))
  61. return PotentialMatch.getLocation();
  62. // If we reach the end of the file, and eof is not the target token, we stop
  63. // the loop, otherwise we will get infinite loop (findNextToken will return
  64. // eof on eof).
  65. if (PotentialMatch.is(tok::eof))
  66. return SourceLocation();
  67. Start = PotentialMatch.getLastLoc();
  68. }
  69. }
  70. // Finds next token that's not a comment.
  71. std::optional<Token> findNextTokenSkippingComments(SourceLocation Start,
  72. const SourceManager &SM,
  73. const LangOptions &LangOpts);
  74. /// Re-lex the provide \p Range and return \c false if either a macro spans
  75. /// multiple tokens, a pre-processor directive or failure to retrieve the
  76. /// next token is found, otherwise \c true.
  77. bool rangeContainsExpansionsOrDirectives(SourceRange Range,
  78. const SourceManager &SM,
  79. const LangOptions &LangOpts);
  80. /// Assuming that ``Range`` spans a CVR-qualified type, returns the
  81. /// token in ``Range`` that is responsible for the qualification. ``Range``
  82. /// must be valid with respect to ``SM``. Returns ``std::nullopt`` if no
  83. /// qualifying tokens are found.
  84. /// \note: doesn't support member function qualifiers.
  85. std::optional<Token> getQualifyingToken(tok::TokenKind TK,
  86. CharSourceRange Range,
  87. const ASTContext &Context,
  88. const SourceManager &SM);
  89. /// Stmt->getEndLoc does not always behave the same way depending on Token type.
  90. /// See implementation for exceptions.
  91. SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM,
  92. const LangOptions &LangOpts);
  93. } // namespace tidy::utils::lexer
  94. } // namespace clang
  95. #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXER_UTILS_H