clang-tools  10.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 
21  Location = Location.getLocWithOffset(-1);
22  if (Location.isInvalid())
23  return Token;
24 
25  auto StartOfFile = SM.getLocForStartOfFile(SM.getFileID(Location));
26  while (Location != StartOfFile) {
27  Location = Lexer::GetBeginningOfToken(Location, SM, LangOpts);
28  if (!Lexer::getRawToken(Location, Token, SM, LangOpts) &&
29  (!SkipComments || !Token.is(tok::comment))) {
30  break;
31  }
32  Location = Location.getLocWithOffset(-1);
33  }
34  return Token;
35 }
36 
37 SourceLocation findPreviousTokenStart(SourceLocation Start,
38  const SourceManager &SM,
39  const LangOptions &LangOpts) {
40  if (Start.isInvalid() || Start.isMacroID())
41  return SourceLocation();
42 
43  SourceLocation BeforeStart = Start.getLocWithOffset(-1);
44  if (BeforeStart.isInvalid() || BeforeStart.isMacroID())
45  return SourceLocation();
46 
47  return Lexer::GetBeginningOfToken(BeforeStart, SM, LangOpts);
48 }
49 
50 SourceLocation findPreviousTokenKind(SourceLocation Start,
51  const SourceManager &SM,
52  const LangOptions &LangOpts,
53  tok::TokenKind TK) {
54  if (Start.isInvalid() || Start.isMacroID())
55  return SourceLocation();
56 
57  while (true) {
58  SourceLocation L = findPreviousTokenStart(Start, SM, LangOpts);
59  if (L.isInvalid() || L.isMacroID())
60  return SourceLocation();
61 
62  Token T;
63  if (Lexer::getRawToken(L, T, SM, LangOpts, /*IgnoreWhiteSpace=*/true))
64  return SourceLocation();
65 
66  if (T.is(TK))
67  return T.getLocation();
68 
69  Start = L;
70  }
71 }
72 
73 SourceLocation findNextTerminator(SourceLocation Start, const SourceManager &SM,
74  const LangOptions &LangOpts) {
75  return findNextAnyTokenKind(Start, SM, LangOpts, tok::comma, tok::semi);
76 }
77 
78 Optional<Token> findNextTokenSkippingComments(SourceLocation Start,
79  const SourceManager &SM,
80  const LangOptions &LangOpts) {
81  Optional<Token> CurrentToken;
82  do {
83  CurrentToken = Lexer::findNextToken(Start, SM, LangOpts);
84  } while (CurrentToken && CurrentToken->is(tok::comment));
85  return CurrentToken;
86 }
87 
89  const SourceManager &SM,
90  const LangOptions &LangOpts) {
91  assert(Range.isValid() && "Invalid Range for relexing provided");
92  SourceLocation Loc = Range.getBegin();
93 
94  while (Loc < Range.getEnd()) {
95  if (Loc.isMacroID())
96  return true;
97 
98  llvm::Optional<Token> Tok = Lexer::findNextToken(Loc, SM, LangOpts);
99 
100  if (!Tok)
101  return true;
102 
103  if (Tok->is(tok::hash))
104  return true;
105 
106  Loc = Lexer::getLocForEndOfToken(Loc, 0, SM, LangOpts).getLocWithOffset(1);
107  }
108 
109  return false;
110 }
111 
112 llvm::Optional<Token> getQualifyingToken(tok::TokenKind TK,
113  CharSourceRange Range,
114  const ASTContext &Context,
115  const SourceManager &SM) {
116  assert((TK == tok::kw_const || TK == tok::kw_volatile ||
117  TK == tok::kw_restrict) &&
118  "TK is not a qualifier keyword");
119  std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Range.getBegin());
120  StringRef File = SM.getBufferData(LocInfo.first);
121  Lexer RawLexer(SM.getLocForStartOfFile(LocInfo.first), Context.getLangOpts(),
122  File.begin(), File.data() + LocInfo.second, File.end());
123  llvm::Optional<Token> LastMatchBeforeTemplate;
124  llvm::Optional<Token> LastMatchAfterTemplate;
125  bool SawTemplate = false;
126  Token Tok;
127  while (!RawLexer.LexFromRawLexer(Tok) &&
128  Range.getEnd() != Tok.getLocation() &&
129  !SM.isBeforeInTranslationUnit(Range.getEnd(), Tok.getLocation())) {
130  if (Tok.is(tok::raw_identifier)) {
131  IdentifierInfo &Info = Context.Idents.get(
132  StringRef(SM.getCharacterData(Tok.getLocation()), Tok.getLength()));
133  Tok.setIdentifierInfo(&Info);
134  Tok.setKind(Info.getTokenID());
135  }
136  if (Tok.is(tok::less))
137  SawTemplate = true;
138  else if (Tok.isOneOf(tok::greater, tok::greatergreater))
139  LastMatchAfterTemplate = None;
140  else if (Tok.is(TK)) {
141  if (SawTemplate)
142  LastMatchAfterTemplate = Tok;
143  else
144  LastMatchBeforeTemplate = Tok;
145  }
146  }
147  return LastMatchAfterTemplate != None ? LastMatchAfterTemplate
148  : LastMatchBeforeTemplate;
149 }
150 } // namespace lexer
151 } // namespace utils
152 } // namespace tidy
153 } // 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:88
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:73
SourceLocation findNextAnyTokenKind(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts, TokenKind TK, TokenKinds... TKs)
Definition: LexerUtils.h:62
Optional< Token > findNextTokenSkippingComments(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition: LexerUtils.cpp:78
SourceLocation findPreviousTokenStart(SourceLocation Start, const SourceManager &SM, const LangOptions &LangOpts)
Definition: LexerUtils.cpp:37
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:50
llvm::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...
Definition: LexerUtils.cpp:112