10#include "clang/Basic/SourceManager.h"
17std::pair<std::optional<Token>, SourceLocation>
19 const LangOptions &LangOpts,
bool SkipComments) {
20 const std::optional<Token> Tok =
21 Lexer::findPreviousToken(
Location, SM, LangOpts, !SkipComments);
24 return {*Tok, Lexer::GetBeginningOfToken(Tok->getLocation(), SM, LangOpts)};
26 return {std::nullopt, SourceLocation()};
30 const SourceManager &SM,
31 const LangOptions &LangOpts,
39 const SourceManager &SM,
40 const LangOptions &LangOpts) {
41 if (Start.isInvalid() || Start.isMacroID())
44 const SourceLocation BeforeStart = Start.getLocWithOffset(-1);
45 if (BeforeStart.isInvalid() || BeforeStart.isMacroID())
48 return Lexer::GetBeginningOfToken(BeforeStart, SM, LangOpts);
52 const SourceManager &SM,
53 const LangOptions &LangOpts,
55 if (Start.isInvalid() || Start.isMacroID())
60 if (L.isInvalid() || L.isMacroID())
64 if (Lexer::getRawToken(L, T, SM, LangOpts,
true))
68 return T.getLocation();
75 const LangOptions &LangOpts) {
80 const SourceManager &SM,
81 const LangOptions &LangOpts) {
82 assert(Range.isValid() &&
"Invalid Range for relexing provided");
83 SourceLocation Loc = Range.getBegin();
85 while (Loc <= Range.getEnd()) {
94 if (Tok->is(tok::hash))
97 Loc = Tok->getLocation();
104enum class CommentCollectionMode { AllComments, TrailingComments };
107static std::vector<CommentToken>
109 const LangOptions &LangOpts,
110 CommentCollectionMode Mode) {
111 std::vector<CommentToken> Comments;
112 if (Range.isInvalid())
115 const CharSourceRange FileRange =
116 Lexer::makeFileCharRange(Range, SM, LangOpts);
117 if (FileRange.isInvalid())
120 const std::pair<FileID, unsigned> BeginLoc =
121 SM.getDecomposedLoc(FileRange.getBegin());
122 const std::pair<FileID, unsigned> EndLoc =
123 SM.getDecomposedLoc(FileRange.getEnd());
125 if (BeginLoc.first != EndLoc.first)
128 bool Invalid =
false;
129 const StringRef Buffer = SM.getBufferData(BeginLoc.first, &Invalid);
133 const char *StrData = Buffer.data() + BeginLoc.second;
135 Lexer TheLexer(SM.getLocForStartOfFile(BeginLoc.first), LangOpts,
136 Buffer.begin(), StrData, Buffer.end());
139 TheLexer.SetCommentRetentionState(
true);
143 if (TheLexer.LexFromRawLexer(Tok))
145 if (Tok.is(tok::eof) || Tok.getLocation() == FileRange.getEnd() ||
146 SM.isBeforeInTranslationUnit(FileRange.getEnd(), Tok.getLocation()))
149 if (Tok.is(tok::comment)) {
150 const std::pair<FileID, unsigned> CommentLoc =
151 SM.getDecomposedLoc(Tok.getLocation());
152 assert(CommentLoc.first == BeginLoc.first);
155 StringRef(Buffer.begin() + CommentLoc.second, Tok.getLength()),
157 }
else if (Mode == CommentCollectionMode::TrailingComments) {
169 const SourceManager &SM,
170 const LangOptions &LangOpts) {
172 CommentCollectionMode::AllComments);
175std::vector<CommentToken>
177 const LangOptions &LangOpts) {
179 CommentCollectionMode::TrailingComments);
184 const LangOptions &LangOpts,
185 llvm::function_ref<
bool(
const Token &)> Pred) {
186 if (Range.isInvalid())
191 const CharSourceRange FileRange =
192 Lexer::makeFileCharRange(Range, SM, LangOpts);
193 if (FileRange.isInvalid())
196 const auto [BeginFID, BeginOffset] =
197 SM.getDecomposedLoc(FileRange.getBegin());
198 const auto [EndFID, EndOffset] = SM.getDecomposedLoc(FileRange.getEnd());
199 if (BeginFID != EndFID || BeginOffset > EndOffset)
202 bool Invalid =
false;
203 const StringRef Buffer = SM.getBufferData(BeginFID, &Invalid);
207 const char *LexStart = Buffer.data() + BeginOffset;
210 Lexer TheLexer(SM.getLocForStartOfFile(BeginFID), LangOpts, Buffer.begin(),
211 LexStart, Buffer.end());
212 TheLexer.SetCommentRetentionState(
true);
216 if (TheLexer.LexFromRawLexer(Tok))
219 if (Tok.is(tok::eof) || Tok.getLocation() == FileRange.getEnd() ||
220 SM.isBeforeInTranslationUnit(FileRange.getEnd(), Tok.getLocation()))
227 if (TheLexer.LexFromRawLexer(NextTok))
231 return CharSourceRange::getCharRange(Tok.getLocation(),
232 NextTok.getLocation());
237 CharSourceRange Range,
238 const ASTContext &Context,
239 const SourceManager &SM) {
240 assert((TK == tok::kw_const || TK == tok::kw_volatile ||
241 TK == tok::kw_restrict) &&
242 "TK is not a qualifier keyword");
243 const std::pair<FileID, unsigned> LocInfo =
244 SM.getDecomposedLoc(Range.getBegin());
245 const StringRef File = SM.getBufferData(LocInfo.first);
246 Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
247 File.begin(), File.data() + LocInfo.second, File.end());
248 std::optional<Token> LastMatchBeforeTemplate;
249 std::optional<Token> LastMatchAfterTemplate;
250 bool SawTemplate =
false;
252 while (!RawLexer.LexFromRawLexer(Tok) &&
253 Range.getEnd() != Tok.getLocation() &&
254 !SM.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation())) {
255 if (Tok.is(tok::raw_identifier)) {
256 IdentifierInfo &Info = Context.Idents.get(
257 StringRef(SM.getCharacterData(Tok.getLocation()), Tok.getLength()));
258 Tok.setIdentifierInfo(&Info);
259 Tok.setKind(Info.getTokenID());
261 if (Tok.is(tok::less)) {
263 }
else if (Tok.isOneOf(tok::greater, tok::greatergreater)) {
264 LastMatchAfterTemplate = std::nullopt;
265 }
else if (Tok.is(TK)) {
267 LastMatchAfterTemplate = Tok;
269 LastMatchBeforeTemplate = Tok;
272 return LastMatchAfterTemplate != std::nullopt ? LastMatchAfterTemplate
273 : LastMatchBeforeTemplate;
277 return isa<CompoundStmt, DeclStmt, NullStmt>(S);
281 return isa<Expr, DoStmt, ReturnStmt, BreakStmt, ContinueStmt, GotoStmt,
288 const SourceManager &SM,
289 const LangOptions &LangOpts) {
290 if (EndLoc.isMacroID()) {
296 const SourceLocation SpellingLoc = SM.getSpellingLoc(EndLoc);
297 std::optional<Token> NextTok =
302 if (NextTok && NextTok->is(tok::TokenKind::semi)) {
305 return NextTok->getLocation();
313 std::optional<Token> NextTok =
317 if (NextTok && NextTok->is(tok::TokenKind::semi))
318 return NextTok->getLocation();
324 const LangOptions &LangOpts) {
325 const Stmt *LastChild = &S;
328 for (
const Stmt *Child : LastChild->children())
335 return S.getEndLoc();
339 const SourceManager &SM) {
343 const LangOptions &LangOpts =
FuncDecl->getLangOpts();
345 if (
FuncDecl->getNumParams() == 0) {
349 SourceLocation CurrentLocation =
FuncDecl->getBeginLoc();
350 while (!Lexer::getRawToken(CurrentLocation, CurrentToken, SM, LangOpts,
352 if (CurrentToken.is(tok::r_paren))
353 return CurrentLocation.getLocWithOffset(1);
355 CurrentLocation = CurrentToken.getEndLoc();
364 const SourceLocation NoexceptLoc =
366 if (NoexceptLoc.isValid())
367 return Lexer::findLocationAfterToken(
368 NoexceptLoc, tok::r_paren, SM, LangOpts,
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.
std::vector< CommentToken > getTrailingCommentsInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Returns comment tokens found in the given range. If a non-comment token is encountered,...
SourceLocation findNextAnyTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, TokenKind TK, TokenKinds... TKs)
std::optional< Token > findNextTokenSkippingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
SourceLocation findPreviousTokenStart(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
static SourceLocation getSemicolonAfterStmtEndLoc(const SourceLocation &EndLoc, const SourceManager &SM, const LangOptions &LangOpts)
CharSourceRange findTokenTextInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, llvm::function_ref< bool(const Token &)> Pred)
Returns source range of the first token in Range matching Pred. The returned char range starts at the...
static bool breakAndReturnEndPlus1Token(const Stmt &S)
static bool breakAndReturnEnd(const Stmt &S)
std::vector< CommentToken > getCommentsInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts)
Returns all comment tokens found in the given range.
static std::vector< CommentToken > collectCommentsInRange(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, CommentCollectionMode Mode)
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...
static constexpr const char FuncDecl[]