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