clang-tools 23.0.0git
LexerUtils.h
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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
9#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXERUTILS_H
10#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXERUTILS_H
11
12#include "clang/AST/ASTContext.h"
13#include "clang/Basic/TokenKinds.h"
14#include "clang/Lex/Lexer.h"
15#include <optional>
16#include <utility>
17
18namespace clang {
19
20class Stmt;
21
22namespace tidy::utils::lexer {
23
24/// Returns previous token or ``std::nullopt`` if not found.
25std::optional<Token> getPreviousToken(SourceLocation Location,
26 const SourceManager &SM,
27 const LangOptions &LangOpts,
28 bool SkipComments = true);
29
30std::pair<std::optional<Token>, SourceLocation>
31getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM,
32 const LangOptions &LangOpts, bool SkipComments = true);
33
34SourceLocation findPreviousTokenStart(SourceLocation Start,
35 const SourceManager &SM,
36 const LangOptions &LangOpts);
37
38SourceLocation findPreviousTokenKind(SourceLocation Start,
39 const SourceManager &SM,
40 const LangOptions &LangOpts,
41 tok::TokenKind TK);
42
43SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM,
44 const LangOptions &LangOpts);
45
46template <typename TokenKind, typename... TokenKinds>
47SourceLocation findPreviousAnyTokenKind(SourceLocation Start,
48 const SourceManager &SM,
49 const LangOptions &LangOpts,
50 TokenKind TK, TokenKinds... TKs) {
51 if (Start.isInvalid() || Start.isMacroID())
52 return {};
53 while (true) {
54 const SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
55 if (L.isInvalid() || L.isMacroID())
56 return {};
57
58 Token T;
59 // Returning 'true' is used to signal failure to retrieve the token.
60 if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
61 return {};
62
63 if (T.isOneOf(TK, TKs...))
64 return T.getLocation();
65
66 Start = L;
67 }
68}
69
70template <typename TokenKind, typename... TokenKinds>
71SourceLocation findNextAnyTokenKind(SourceLocation Start,
72 const SourceManager &SM,
73 const LangOptions &LangOpts, TokenKind TK,
74 TokenKinds... TKs) {
75 while (true) {
76 std::optional<Token> CurrentToken =
77 Lexer::findNextToken(Start, SM, LangOpts);
78
79 if (!CurrentToken)
80 return {};
81
82 const Token PotentialMatch = *CurrentToken;
83 if (PotentialMatch.isOneOf(TK, TKs...))
84 return PotentialMatch.getLocation();
85
86 // If we reach the end of the file, and eof is not the target token, we stop
87 // the loop, otherwise we will get infinite loop (findNextToken will return
88 // eof on eof).
89 if (PotentialMatch.is(tok::eof))
90 return {};
91 Start = PotentialMatch.getLastLoc();
92 }
93}
94
95// Finds next token, possibly a comment.
96inline std::optional<Token>
97findNextTokenIncludingComments(SourceLocation Start, const SourceManager &SM,
98 const LangOptions &LangOpts) {
99 return Lexer::findNextToken(Start, SM, LangOpts, true);
100}
101
102// Finds next token that's not a comment.
103inline std::optional<Token>
104findNextTokenSkippingComments(SourceLocation Start, const SourceManager &SM,
105 const LangOptions &LangOpts) {
106 return Lexer::findNextToken(Start, SM, LangOpts, false);
107}
108
109/// Re-lex the provide \p Range and return \c false if either a macro spans
110/// multiple tokens, a pre-processor directive or failure to retrieve the
111/// next token is found, otherwise \c true.
112bool rangeContainsExpansionsOrDirectives(SourceRange Range,
113 const SourceManager &SM,
114 const LangOptions &LangOpts);
115
116/// Assuming that ``Range`` spans a CVR-qualified type, returns the
117/// token in ``Range`` that is responsible for the qualification. ``Range``
118/// must be valid with respect to ``SM``. Returns ``std::nullopt`` if no
119/// qualifying tokens are found.
120/// \note: doesn't support member function qualifiers.
121std::optional<Token> getQualifyingToken(tok::TokenKind TK,
122 CharSourceRange Range,
123 const ASTContext &Context,
124 const SourceManager &SM);
125
126/// Stmt->getEndLoc does not always behave the same way depending on Token type.
127/// See implementation for exceptions.
128SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM,
129 const LangOptions &LangOpts);
130
131/// For a given FunctionDecl returns the location where you would need to place
132/// the noexcept specifier.
133SourceLocation getLocationForNoexceptSpecifier(const FunctionDecl *FuncDecl,
134 const SourceManager &SM);
135
136} // namespace tidy::utils::lexer
137} // namespace clang
138
139#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_UTILS_LEXERUTILS_H
std::pair< std::optional< Token >, SourceLocation > getPreviousTokenAndStart(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments)
SourceLocation getLocationForNoexceptSpecifier(const FunctionDecl *FuncDecl, const SourceManager &SM)
For a given FunctionDecl returns the location where you would need to place the noexcept specifier.
SourceLocation getUnifiedEndLoc(const Stmt &S, const SourceManager &SM, const LangOptions &LangOpts)
Stmt->getEndLoc does not always behave the same way depending on Token type.
bool rangeContainsExpansionsOrDirectives(SourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Re-lex the provide Range and return false if either a macro spans multiple tokens,...
SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
std::optional< Token > getPreviousToken(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments)
Returns previous token or std::nullopt if not found.
SourceLocation findNextAnyTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, TokenKind TK, TokenKinds... TKs)
Definition LexerUtils.h:71
std::optional< Token > findNextTokenSkippingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition LexerUtils.h:104
SourceLocation findPreviousTokenStart(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
SourceLocation findPreviousTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, tok::TokenKind TK)
std::optional< Token > getQualifyingToken(tok::TokenKind TK, CharSourceRange Range, const ASTContext &Context, const SourceManager &SM)
Assuming that Range spans a CVR-qualified type, returns the token in Range that is responsible for th...
std::optional< Token > findNextTokenIncludingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition LexerUtils.h:97
SourceLocation findPreviousAnyTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, TokenKind TK, TokenKinds... TKs)
Definition LexerUtils.h:47
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static constexpr const char FuncDecl[]