clang-tools  9.0.0
LexerUtils.cpp
Go to the documentation of this file.
1 //===--- LexerUtils.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 
9 #include "LexerUtils.h"
10 
11 namespace clang {
12 namespace tidy {
13 namespace utils {
14 namespace lexer {
15 
16 Token getPreviousToken(SourceLocation Location, const SourceManager &SM,
17  const LangOptions &LangOpts, bool SkipComments) {
18  Token Token;
19  Token.setKind(tok::unknown);
20  Location = Location.getLocWithOffset(-1);
21  auto StartOfFile = SM.getLocForStartOfFile(SM.getFileID(Location));
22  while (Location != StartOfFile) {
23  Location = Lexer::GetBeginningOfToken(Location, SM, LangOpts);
24  if (!Lexer::getRawToken(Location, Token, SM, LangOpts) &&
25  (!SkipComments || !Token.is(tok::comment))) {
26  break;
27  }
28  Location = Location.getLocWithOffset(-1);
29  }
30  return Token;
31 }
32 
33 SourceLocation findPreviousTokenStart(SourceLocation Start,
34  const SourceManager &SM,
35  const LangOptions &LangOpts) {
36  if (Start.isInvalid() || Start.isMacroID())
37  return SourceLocation();
38 
39  SourceLocation BeforeStart = Start.getLocWithOffset(-1);
40  if (BeforeStart.isInvalid() || BeforeStart.isMacroID())
41  return SourceLocation();
42 
43  return Lexer::GetBeginningOfToken(BeforeStart, SM, LangOpts);
44 }
45 
46 SourceLocation findPreviousTokenKind(SourceLocation Start,
47  const SourceManager &SM,
48  const LangOptions &LangOpts,
49  tok::TokenKind TK) {
50  while (true) {
51  SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
52  if (L.isInvalid() || L.isMacroID())
53  return SourceLocation();
54 
55  Token T;
56  if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
57  return SourceLocation();
58 
59  if (T.is(TK))
60  return T.getLocation();
61 
62  Start = L;
63  }
64 }
65 
66 SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM,
67  const LangOptions &LangOpts) {
68  return findNextAnyTokenKind(Start, SM, LangOpts, tok::comma, tok::semi);
69 }
70 
72  const SourceManager &SM,
73  const LangOptions &LangOpts) {
74  assert(Range.isValid() && "Invalid Range for relexing provided");
75  SourceLocation Loc = Range.getBegin();
76 
77  while (Loc < Range.getEnd()) {
78  if (Loc.isMacroID())
79  return true;
80 
81  llvm::Optional<Token> Tok = Lexer::findNextToken(Loc, SM, LangOpts);
82 
83  if (!Tok)
84  return true;
85 
86  if (Tok->is(tok::hash))
87  return true;
88 
89  Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts).getLocWithOffset(1);
90  }
91 
92  return false;
93 }
94 
95 llvm::Optional<Token> getConstQualifyingToken(CharSourceRange Range,
96  const ASTContext &Context,
97  const SourceManager &SM) {
98  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getBegin());
99  StringRef File = SM.getBufferData(LocInfo.first);
100  Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
101  File.begin(), File.data() + LocInfo.second, File.end());
102  llvm::Optional<Token> FirstConstTok;
103  Token LastTokInRange;
104  Token Tok;
105  while (!RawLexer.LexFromRawLexer(Tok) &&
106  Range.getEnd() != Tok.getLocation() &&
107  !SM.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation())) {
108  if (Tok.is(tok::raw_identifier)) {
109  IdentifierInfo &Info = Context.Idents.get(
110  StringRef(SM.getCharacterData(Tok.getLocation()), Tok.getLength()));
111  Tok.setIdentifierInfo(&Info);
112  Tok.setKind(Info.getTokenID());
113  }
114  if (Tok.is(tok::kw_const) && !FirstConstTok)
115  FirstConstTok = Tok;
116  LastTokInRange = Tok;
117  }
118  // If the last token in the range is a `const`, then it const qualifies the
119  // type. Otherwise, the first `const` token, if any, is the qualifier.
120  return LastTokInRange.is(tok::kw_const) ? LastTokInRange : FirstConstTok;
121 }
122 } // namespace lexer
123 } // namespace utils
124 } // namespace tidy
125 } // namespace clang
SourceLocation Loc
&#39;#&#39; location in the include directive
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, a pre-processor directive or failure to retrieve the next token is found, otherwise true.
Definition: LexerUtils.cpp:71
Token getPreviousToken(SourceLocation Location, const SourceManager &SM, const LangOptions &LangOpts, bool SkipComments)
Returns previous token or tok::unknown if not found.
Definition: LexerUtils.cpp:16
SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition: LexerUtils.cpp:66
SourceLocation findNextAnyTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, TokenKind TK, TokenKinds... TKs)
Definition: LexerUtils.h:59
llvm::Optional< Token > getConstQualifyingToken(CharSourceRange Range, const ASTContext &Context, const SourceManager &SM)
Assuming that Range spans a const-qualified type, returns the const token in Range that is responsibl...
Definition: LexerUtils.cpp:95
SourceLocation findPreviousTokenStart(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition: LexerUtils.cpp:33
FunctionInfo Info
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
CharSourceRange Range
SourceRange for the file name.
SourceLocation findPreviousTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, tok::TokenKind TK)
Definition: LexerUtils.cpp:46