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