15ffd83dbSDimitry Andric //===-- CPlusPlusNameParser.cpp -------------------------------------------===//
2*0b57cec5SDimitry Andric //
3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0b57cec5SDimitry Andric //
7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8*0b57cec5SDimitry Andric 
9*0b57cec5SDimitry Andric #include "CPlusPlusNameParser.h"
10*0b57cec5SDimitry Andric 
11*0b57cec5SDimitry Andric #include "clang/Basic/IdentifierTable.h"
12bdd1243dSDimitry Andric #include "clang/Basic/TokenKinds.h"
13*0b57cec5SDimitry Andric #include "llvm/ADT/StringMap.h"
14*0b57cec5SDimitry Andric #include "llvm/Support/Threading.h"
15bdd1243dSDimitry Andric #include <optional>
16*0b57cec5SDimitry Andric 
17*0b57cec5SDimitry Andric using namespace lldb;
18*0b57cec5SDimitry Andric using namespace lldb_private;
19*0b57cec5SDimitry Andric using ParsedFunction = lldb_private::CPlusPlusNameParser::ParsedFunction;
20*0b57cec5SDimitry Andric using ParsedName = lldb_private::CPlusPlusNameParser::ParsedName;
21*0b57cec5SDimitry Andric namespace tok = clang::tok;
22*0b57cec5SDimitry Andric 
23bdd1243dSDimitry Andric std::optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() {
24*0b57cec5SDimitry Andric   m_next_token_index = 0;
25bdd1243dSDimitry Andric   std::optional<ParsedFunction> result(std::nullopt);
26*0b57cec5SDimitry Andric 
27*0b57cec5SDimitry Andric   // Try to parse the name as function without a return type specified e.g.
28*0b57cec5SDimitry Andric   // main(int, char*[])
29*0b57cec5SDimitry Andric   {
30*0b57cec5SDimitry Andric     Bookmark start_position = SetBookmark();
31*0b57cec5SDimitry Andric     result = ParseFunctionImpl(false);
32*0b57cec5SDimitry Andric     if (result && !HasMoreTokens())
33*0b57cec5SDimitry Andric       return result;
34*0b57cec5SDimitry Andric   }
35*0b57cec5SDimitry Andric 
36*0b57cec5SDimitry Andric   // Try to parse the name as function with function pointer return type e.g.
37*0b57cec5SDimitry Andric   // void (*get_func(const char*))()
38*0b57cec5SDimitry Andric   result = ParseFuncPtr(true);
39*0b57cec5SDimitry Andric   if (result)
40*0b57cec5SDimitry Andric     return result;
41*0b57cec5SDimitry Andric 
42*0b57cec5SDimitry Andric   // Finally try to parse the name as a function with non-function return type
43*0b57cec5SDimitry Andric   // e.g. int main(int, char*[])
44*0b57cec5SDimitry Andric   result = ParseFunctionImpl(true);
45*0b57cec5SDimitry Andric   if (HasMoreTokens())
46bdd1243dSDimitry Andric     return std::nullopt;
47*0b57cec5SDimitry Andric   return result;
48*0b57cec5SDimitry Andric }
49*0b57cec5SDimitry Andric 
50bdd1243dSDimitry Andric std::optional<ParsedName> CPlusPlusNameParser::ParseAsFullName() {
51*0b57cec5SDimitry Andric   m_next_token_index = 0;
52bdd1243dSDimitry Andric   std::optional<ParsedNameRanges> name_ranges = ParseFullNameImpl();
53*0b57cec5SDimitry Andric   if (!name_ranges)
54bdd1243dSDimitry Andric     return std::nullopt;
55*0b57cec5SDimitry Andric   if (HasMoreTokens())
56bdd1243dSDimitry Andric     return std::nullopt;
57*0b57cec5SDimitry Andric   ParsedName result;
58bdd1243dSDimitry Andric   result.basename = GetTextForRange(name_ranges->basename_range);
59bdd1243dSDimitry Andric   result.context = GetTextForRange(name_ranges->context_range);
60*0b57cec5SDimitry Andric   return result;
61*0b57cec5SDimitry Andric }
62*0b57cec5SDimitry Andric 
63*0b57cec5SDimitry Andric bool CPlusPlusNameParser::HasMoreTokens() {
64*0b57cec5SDimitry Andric   return m_next_token_index < m_tokens.size();
65*0b57cec5SDimitry Andric }
66*0b57cec5SDimitry Andric 
67*0b57cec5SDimitry Andric void CPlusPlusNameParser::Advance() { ++m_next_token_index; }
68*0b57cec5SDimitry Andric 
69*0b57cec5SDimitry Andric void CPlusPlusNameParser::TakeBack() { --m_next_token_index; }
70*0b57cec5SDimitry Andric 
71*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeToken(tok::TokenKind kind) {
72*0b57cec5SDimitry Andric   if (!HasMoreTokens())
73*0b57cec5SDimitry Andric     return false;
74*0b57cec5SDimitry Andric 
75*0b57cec5SDimitry Andric   if (!Peek().is(kind))
76*0b57cec5SDimitry Andric     return false;
77*0b57cec5SDimitry Andric 
78*0b57cec5SDimitry Andric   Advance();
79*0b57cec5SDimitry Andric   return true;
80*0b57cec5SDimitry Andric }
81*0b57cec5SDimitry Andric 
82*0b57cec5SDimitry Andric template <typename... Ts> bool CPlusPlusNameParser::ConsumeToken(Ts... kinds) {
83*0b57cec5SDimitry Andric   if (!HasMoreTokens())
84*0b57cec5SDimitry Andric     return false;
85*0b57cec5SDimitry Andric 
86*0b57cec5SDimitry Andric   if (!Peek().isOneOf(kinds...))
87*0b57cec5SDimitry Andric     return false;
88*0b57cec5SDimitry Andric 
89*0b57cec5SDimitry Andric   Advance();
90*0b57cec5SDimitry Andric   return true;
91*0b57cec5SDimitry Andric }
92*0b57cec5SDimitry Andric 
93*0b57cec5SDimitry Andric CPlusPlusNameParser::Bookmark CPlusPlusNameParser::SetBookmark() {
94*0b57cec5SDimitry Andric   return Bookmark(m_next_token_index);
95*0b57cec5SDimitry Andric }
96*0b57cec5SDimitry Andric 
97*0b57cec5SDimitry Andric size_t CPlusPlusNameParser::GetCurrentPosition() { return m_next_token_index; }
98*0b57cec5SDimitry Andric 
99*0b57cec5SDimitry Andric clang::Token &CPlusPlusNameParser::Peek() {
100*0b57cec5SDimitry Andric   assert(HasMoreTokens());
101*0b57cec5SDimitry Andric   return m_tokens[m_next_token_index];
102*0b57cec5SDimitry Andric }
103*0b57cec5SDimitry Andric 
104bdd1243dSDimitry Andric std::optional<ParsedFunction>
105*0b57cec5SDimitry Andric CPlusPlusNameParser::ParseFunctionImpl(bool expect_return_type) {
106*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
107bdd1243dSDimitry Andric 
108bdd1243dSDimitry Andric   ParsedFunction result;
109*0b57cec5SDimitry Andric   if (expect_return_type) {
110bdd1243dSDimitry Andric     size_t return_start = GetCurrentPosition();
111*0b57cec5SDimitry Andric     // Consume return type if it's expected.
112bdd1243dSDimitry Andric     if (!ConsumeToken(tok::kw_auto) && !ConsumeTypename())
113bdd1243dSDimitry Andric       return std::nullopt;
114bdd1243dSDimitry Andric 
115bdd1243dSDimitry Andric     size_t return_end = GetCurrentPosition();
116bdd1243dSDimitry Andric     result.return_type = GetTextForRange(Range(return_start, return_end));
117*0b57cec5SDimitry Andric   }
118*0b57cec5SDimitry Andric 
119*0b57cec5SDimitry Andric   auto maybe_name = ParseFullNameImpl();
120*0b57cec5SDimitry Andric   if (!maybe_name) {
121bdd1243dSDimitry Andric     return std::nullopt;
122*0b57cec5SDimitry Andric   }
123*0b57cec5SDimitry Andric 
124*0b57cec5SDimitry Andric   size_t argument_start = GetCurrentPosition();
125*0b57cec5SDimitry Andric   if (!ConsumeArguments()) {
126bdd1243dSDimitry Andric     return std::nullopt;
127*0b57cec5SDimitry Andric   }
128*0b57cec5SDimitry Andric 
129*0b57cec5SDimitry Andric   size_t qualifiers_start = GetCurrentPosition();
130*0b57cec5SDimitry Andric   SkipFunctionQualifiers();
131*0b57cec5SDimitry Andric   size_t end_position = GetCurrentPosition();
132*0b57cec5SDimitry Andric 
133bdd1243dSDimitry Andric   result.name.basename = GetTextForRange(maybe_name->basename_range);
134bdd1243dSDimitry Andric   result.name.context = GetTextForRange(maybe_name->context_range);
135*0b57cec5SDimitry Andric   result.arguments = GetTextForRange(Range(argument_start, qualifiers_start));
136*0b57cec5SDimitry Andric   result.qualifiers = GetTextForRange(Range(qualifiers_start, end_position));
137*0b57cec5SDimitry Andric   start_position.Remove();
138*0b57cec5SDimitry Andric   return result;
139*0b57cec5SDimitry Andric }
140*0b57cec5SDimitry Andric 
141bdd1243dSDimitry Andric std::optional<ParsedFunction>
142*0b57cec5SDimitry Andric CPlusPlusNameParser::ParseFuncPtr(bool expect_return_type) {
143bdd1243dSDimitry Andric   // This function parses a function definition
144bdd1243dSDimitry Andric   // that returns a pointer type.
145bdd1243dSDimitry Andric   // E.g., double (*(*func(long))(int))(float)
146bdd1243dSDimitry Andric 
147bdd1243dSDimitry Andric   // Step 1:
148bdd1243dSDimitry Andric   // Remove the return type of the innermost
149bdd1243dSDimitry Andric   // function pointer type.
150bdd1243dSDimitry Andric   //
151bdd1243dSDimitry Andric   // Leaves us with:
152bdd1243dSDimitry Andric   //   (*(*func(long))(int))(float)
153*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
154*0b57cec5SDimitry Andric   if (expect_return_type) {
155*0b57cec5SDimitry Andric     // Consume return type.
156*0b57cec5SDimitry Andric     if (!ConsumeTypename())
157bdd1243dSDimitry Andric       return std::nullopt;
158*0b57cec5SDimitry Andric   }
159*0b57cec5SDimitry Andric 
160bdd1243dSDimitry Andric   // Step 2:
161bdd1243dSDimitry Andric   //
162bdd1243dSDimitry Andric   // Skip a pointer and parenthesis pair.
163bdd1243dSDimitry Andric   //
164bdd1243dSDimitry Andric   // Leaves us with:
165bdd1243dSDimitry Andric   //   (*func(long))(int))(float)
166*0b57cec5SDimitry Andric   if (!ConsumeToken(tok::l_paren))
167bdd1243dSDimitry Andric     return std::nullopt;
168*0b57cec5SDimitry Andric   if (!ConsumePtrsAndRefs())
169bdd1243dSDimitry Andric     return std::nullopt;
170*0b57cec5SDimitry Andric 
171bdd1243dSDimitry Andric   // Step 3:
172bdd1243dSDimitry Andric   //
173bdd1243dSDimitry Andric   // Consume inner function name. This will fail unless
174bdd1243dSDimitry Andric   // we stripped all the pointers on the left hand side
175bdd1243dSDimitry Andric   // of the funciton name.
176*0b57cec5SDimitry Andric   {
177*0b57cec5SDimitry Andric     Bookmark before_inner_function_pos = SetBookmark();
178*0b57cec5SDimitry Andric     auto maybe_inner_function_name = ParseFunctionImpl(false);
179*0b57cec5SDimitry Andric     if (maybe_inner_function_name)
180*0b57cec5SDimitry Andric       if (ConsumeToken(tok::r_paren))
181*0b57cec5SDimitry Andric         if (ConsumeArguments()) {
182*0b57cec5SDimitry Andric           SkipFunctionQualifiers();
183*0b57cec5SDimitry Andric           start_position.Remove();
184*0b57cec5SDimitry Andric           before_inner_function_pos.Remove();
185*0b57cec5SDimitry Andric           return maybe_inner_function_name;
186*0b57cec5SDimitry Andric         }
187*0b57cec5SDimitry Andric   }
188*0b57cec5SDimitry Andric 
189bdd1243dSDimitry Andric   // Step 4:
190bdd1243dSDimitry Andric   //
191bdd1243dSDimitry Andric   // Parse the remaining string as a function pointer again.
192bdd1243dSDimitry Andric   // This time don't consume the inner-most typename since
193bdd1243dSDimitry Andric   // we're left with pointers only. This will strip another
194bdd1243dSDimitry Andric   // layer of pointers until we're left with the innermost
195bdd1243dSDimitry Andric   // function name/argument. I.e., func(long))(int))(float)
196bdd1243dSDimitry Andric   //
197bdd1243dSDimitry Andric   // Once we successfully stripped all pointers and gotten
198bdd1243dSDimitry Andric   // the innermost function name from ParseFunctionImpl above,
199bdd1243dSDimitry Andric   // we consume a single ')' and the arguments '(...)' that follows.
200bdd1243dSDimitry Andric   //
201bdd1243dSDimitry Andric   // Leaves us with:
202bdd1243dSDimitry Andric   //   )(float)
203bdd1243dSDimitry Andric   //
204bdd1243dSDimitry Andric   // This is the remnant of the outer function pointers' arguments.
205bdd1243dSDimitry Andric   // Unwinding the recursive calls will remove the remaining
206bdd1243dSDimitry Andric   // arguments.
207*0b57cec5SDimitry Andric   auto maybe_inner_function_ptr_name = ParseFuncPtr(false);
208*0b57cec5SDimitry Andric   if (maybe_inner_function_ptr_name)
209*0b57cec5SDimitry Andric     if (ConsumeToken(tok::r_paren))
210*0b57cec5SDimitry Andric       if (ConsumeArguments()) {
211*0b57cec5SDimitry Andric         SkipFunctionQualifiers();
212*0b57cec5SDimitry Andric         start_position.Remove();
213*0b57cec5SDimitry Andric         return maybe_inner_function_ptr_name;
214*0b57cec5SDimitry Andric       }
215bdd1243dSDimitry Andric 
216bdd1243dSDimitry Andric   return std::nullopt;
217*0b57cec5SDimitry Andric }
218*0b57cec5SDimitry Andric 
219*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeArguments() {
220*0b57cec5SDimitry Andric   return ConsumeBrackets(tok::l_paren, tok::r_paren);
221*0b57cec5SDimitry Andric }
222*0b57cec5SDimitry Andric 
223*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeTemplateArgs() {
224*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
225*0b57cec5SDimitry Andric   if (!HasMoreTokens() || Peek().getKind() != tok::less)
226*0b57cec5SDimitry Andric     return false;
227*0b57cec5SDimitry Andric   Advance();
228*0b57cec5SDimitry Andric 
229*0b57cec5SDimitry Andric   // Consuming template arguments is a bit trickier than consuming function
230*0b57cec5SDimitry Andric   // arguments, because '<' '>' brackets are not always trivially balanced. In
231*0b57cec5SDimitry Andric   // some rare cases tokens '<' and '>' can appear inside template arguments as
232*0b57cec5SDimitry Andric   // arithmetic or shift operators not as template brackets. Examples:
233*0b57cec5SDimitry Andric   // std::enable_if<(10u)<(64), bool>
234*0b57cec5SDimitry Andric   //           f<A<operator<(X,Y)::Subclass>>
235*0b57cec5SDimitry Andric   // Good thing that compiler makes sure that really ambiguous cases of '>'
236*0b57cec5SDimitry Andric   // usage should be enclosed within '()' brackets.
237*0b57cec5SDimitry Andric   int template_counter = 1;
238*0b57cec5SDimitry Andric   bool can_open_template = false;
239*0b57cec5SDimitry Andric   while (HasMoreTokens() && template_counter > 0) {
240*0b57cec5SDimitry Andric     tok::TokenKind kind = Peek().getKind();
241*0b57cec5SDimitry Andric     switch (kind) {
242*0b57cec5SDimitry Andric     case tok::greatergreater:
243*0b57cec5SDimitry Andric       template_counter -= 2;
244*0b57cec5SDimitry Andric       can_open_template = false;
245*0b57cec5SDimitry Andric       Advance();
246*0b57cec5SDimitry Andric       break;
247*0b57cec5SDimitry Andric     case tok::greater:
248*0b57cec5SDimitry Andric       --template_counter;
249*0b57cec5SDimitry Andric       can_open_template = false;
250*0b57cec5SDimitry Andric       Advance();
251*0b57cec5SDimitry Andric       break;
252*0b57cec5SDimitry Andric     case tok::less:
253*0b57cec5SDimitry Andric       // '<' is an attempt to open a subteamplte
254*0b57cec5SDimitry Andric       // check if parser is at the point where it's actually possible,
255*0b57cec5SDimitry Andric       // otherwise it's just a part of an expression like 'sizeof(T)<(10)'. No
256*0b57cec5SDimitry Andric       // need to do the same for '>' because compiler actually makes sure that
257*0b57cec5SDimitry Andric       // '>' always surrounded by brackets to avoid ambiguity.
258*0b57cec5SDimitry Andric       if (can_open_template)
259*0b57cec5SDimitry Andric         ++template_counter;
260*0b57cec5SDimitry Andric       can_open_template = false;
261*0b57cec5SDimitry Andric       Advance();
262*0b57cec5SDimitry Andric       break;
263*0b57cec5SDimitry Andric     case tok::kw_operator: // C++ operator overloading.
264*0b57cec5SDimitry Andric       if (!ConsumeOperator())
265*0b57cec5SDimitry Andric         return false;
266*0b57cec5SDimitry Andric       can_open_template = true;
267*0b57cec5SDimitry Andric       break;
268*0b57cec5SDimitry Andric     case tok::raw_identifier:
269*0b57cec5SDimitry Andric       can_open_template = true;
270*0b57cec5SDimitry Andric       Advance();
271*0b57cec5SDimitry Andric       break;
272*0b57cec5SDimitry Andric     case tok::l_square:
273bdd1243dSDimitry Andric       // Handle templates tagged with an ABI tag.
274bdd1243dSDimitry Andric       // An example demangled/prettified version is:
275bdd1243dSDimitry Andric       //   func[abi:tag1][abi:tag2]<type[abi:tag3]>(int)
276bdd1243dSDimitry Andric       if (ConsumeAbiTag())
277bdd1243dSDimitry Andric         can_open_template = true;
278bdd1243dSDimitry Andric       else if (ConsumeBrackets(tok::l_square, tok::r_square))
279*0b57cec5SDimitry Andric         can_open_template = false;
280bdd1243dSDimitry Andric       else
281bdd1243dSDimitry Andric         return false;
282*0b57cec5SDimitry Andric       break;
283*0b57cec5SDimitry Andric     case tok::l_paren:
284*0b57cec5SDimitry Andric       if (!ConsumeArguments())
285*0b57cec5SDimitry Andric         return false;
286*0b57cec5SDimitry Andric       can_open_template = false;
287*0b57cec5SDimitry Andric       break;
288*0b57cec5SDimitry Andric     default:
289*0b57cec5SDimitry Andric       can_open_template = false;
290*0b57cec5SDimitry Andric       Advance();
291*0b57cec5SDimitry Andric       break;
292*0b57cec5SDimitry Andric     }
293*0b57cec5SDimitry Andric   }
294*0b57cec5SDimitry Andric 
295*0b57cec5SDimitry Andric   if (template_counter != 0) {
296*0b57cec5SDimitry Andric     return false;
297*0b57cec5SDimitry Andric   }
298*0b57cec5SDimitry Andric   start_position.Remove();
299*0b57cec5SDimitry Andric   return true;
300*0b57cec5SDimitry Andric }
301*0b57cec5SDimitry Andric 
302bdd1243dSDimitry Andric bool CPlusPlusNameParser::ConsumeAbiTag() {
303bdd1243dSDimitry Andric   Bookmark start_position = SetBookmark();
304bdd1243dSDimitry Andric   if (!ConsumeToken(tok::l_square))
305bdd1243dSDimitry Andric     return false;
306bdd1243dSDimitry Andric 
307bdd1243dSDimitry Andric   if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
308bdd1243dSDimitry Andric       Peek().getRawIdentifier() == "abi")
309bdd1243dSDimitry Andric     Advance();
310bdd1243dSDimitry Andric   else
311bdd1243dSDimitry Andric     return false;
312bdd1243dSDimitry Andric 
313bdd1243dSDimitry Andric   if (!ConsumeToken(tok::colon))
314bdd1243dSDimitry Andric     return false;
315bdd1243dSDimitry Andric 
316bdd1243dSDimitry Andric   // Consume the actual tag string (and allow some special characters)
317bdd1243dSDimitry Andric   while (ConsumeToken(tok::raw_identifier, tok::comma, tok::period,
318bdd1243dSDimitry Andric                       tok::numeric_constant))
319bdd1243dSDimitry Andric     ;
320bdd1243dSDimitry Andric 
321bdd1243dSDimitry Andric   if (!ConsumeToken(tok::r_square))
322bdd1243dSDimitry Andric     return false;
323bdd1243dSDimitry Andric 
324bdd1243dSDimitry Andric   start_position.Remove();
325bdd1243dSDimitry Andric   return true;
326bdd1243dSDimitry Andric }
327bdd1243dSDimitry Andric 
328*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeAnonymousNamespace() {
329*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
330*0b57cec5SDimitry Andric   if (!ConsumeToken(tok::l_paren)) {
331*0b57cec5SDimitry Andric     return false;
332*0b57cec5SDimitry Andric   }
333*0b57cec5SDimitry Andric   constexpr llvm::StringLiteral g_anonymous("anonymous");
334*0b57cec5SDimitry Andric   if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
335*0b57cec5SDimitry Andric       Peek().getRawIdentifier() == g_anonymous) {
336*0b57cec5SDimitry Andric     Advance();
337*0b57cec5SDimitry Andric   } else {
338*0b57cec5SDimitry Andric     return false;
339*0b57cec5SDimitry Andric   }
340*0b57cec5SDimitry Andric 
341*0b57cec5SDimitry Andric   if (!ConsumeToken(tok::kw_namespace)) {
342*0b57cec5SDimitry Andric     return false;
343*0b57cec5SDimitry Andric   }
344*0b57cec5SDimitry Andric 
345*0b57cec5SDimitry Andric   if (!ConsumeToken(tok::r_paren)) {
346*0b57cec5SDimitry Andric     return false;
347*0b57cec5SDimitry Andric   }
348*0b57cec5SDimitry Andric   start_position.Remove();
349*0b57cec5SDimitry Andric   return true;
350*0b57cec5SDimitry Andric }
351*0b57cec5SDimitry Andric 
352*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeLambda() {
353*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
354*0b57cec5SDimitry Andric   if (!ConsumeToken(tok::l_brace)) {
355*0b57cec5SDimitry Andric     return false;
356*0b57cec5SDimitry Andric   }
357*0b57cec5SDimitry Andric   constexpr llvm::StringLiteral g_lambda("lambda");
358*0b57cec5SDimitry Andric   if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
359*0b57cec5SDimitry Andric       Peek().getRawIdentifier() == g_lambda) {
360*0b57cec5SDimitry Andric     // Put the matched brace back so we can use ConsumeBrackets
361*0b57cec5SDimitry Andric     TakeBack();
362*0b57cec5SDimitry Andric   } else {
363*0b57cec5SDimitry Andric     return false;
364*0b57cec5SDimitry Andric   }
365*0b57cec5SDimitry Andric 
366*0b57cec5SDimitry Andric   if (!ConsumeBrackets(tok::l_brace, tok::r_brace)) {
367*0b57cec5SDimitry Andric     return false;
368*0b57cec5SDimitry Andric   }
369*0b57cec5SDimitry Andric 
370*0b57cec5SDimitry Andric   start_position.Remove();
371*0b57cec5SDimitry Andric   return true;
372*0b57cec5SDimitry Andric }
373*0b57cec5SDimitry Andric 
374*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeBrackets(tok::TokenKind left,
375*0b57cec5SDimitry Andric                                           tok::TokenKind right) {
376*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
377*0b57cec5SDimitry Andric   if (!HasMoreTokens() || Peek().getKind() != left)
378*0b57cec5SDimitry Andric     return false;
379*0b57cec5SDimitry Andric   Advance();
380*0b57cec5SDimitry Andric 
381*0b57cec5SDimitry Andric   int counter = 1;
382*0b57cec5SDimitry Andric   while (HasMoreTokens() && counter > 0) {
383*0b57cec5SDimitry Andric     tok::TokenKind kind = Peek().getKind();
384*0b57cec5SDimitry Andric     if (kind == right)
385*0b57cec5SDimitry Andric       --counter;
386*0b57cec5SDimitry Andric     else if (kind == left)
387*0b57cec5SDimitry Andric       ++counter;
388*0b57cec5SDimitry Andric     Advance();
389*0b57cec5SDimitry Andric   }
390*0b57cec5SDimitry Andric 
391*0b57cec5SDimitry Andric   assert(counter >= 0);
392*0b57cec5SDimitry Andric   if (counter > 0) {
393*0b57cec5SDimitry Andric     return false;
394*0b57cec5SDimitry Andric   }
395*0b57cec5SDimitry Andric   start_position.Remove();
396*0b57cec5SDimitry Andric   return true;
397*0b57cec5SDimitry Andric }
398*0b57cec5SDimitry Andric 
399*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeOperator() {
400*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
401*0b57cec5SDimitry Andric   if (!ConsumeToken(tok::kw_operator))
402*0b57cec5SDimitry Andric     return false;
403*0b57cec5SDimitry Andric 
404*0b57cec5SDimitry Andric   if (!HasMoreTokens()) {
405*0b57cec5SDimitry Andric     return false;
406*0b57cec5SDimitry Andric   }
407*0b57cec5SDimitry Andric 
408*0b57cec5SDimitry Andric   const auto &token = Peek();
4095ffd83dbSDimitry Andric 
4105ffd83dbSDimitry Andric   // When clang generates debug info it adds template parameters to names.
4115ffd83dbSDimitry Andric   // Since clang doesn't add a space between the name and the template parameter
4125ffd83dbSDimitry Andric   // in some cases we are not generating valid C++ names e.g.:
4135ffd83dbSDimitry Andric   //
4145ffd83dbSDimitry Andric   //   operator<<A::B>
4155ffd83dbSDimitry Andric   //
4165ffd83dbSDimitry Andric   // In some of these cases we will not parse them correctly. This fixes the
4175ffd83dbSDimitry Andric   // issue by detecting this case and inserting tok::less in place of
4185ffd83dbSDimitry Andric   // tok::lessless and returning successfully that we consumed the operator.
4195ffd83dbSDimitry Andric   if (token.getKind() == tok::lessless) {
4205ffd83dbSDimitry Andric     // Make sure we have more tokens before attempting to look ahead one more.
4215ffd83dbSDimitry Andric     if (m_next_token_index + 1 < m_tokens.size()) {
4225ffd83dbSDimitry Andric       // Look ahead two tokens.
4235ffd83dbSDimitry Andric       clang::Token n_token = m_tokens[m_next_token_index + 1];
4245ffd83dbSDimitry Andric       // If we find ( or < then this is indeed operator<< no need for fix.
4255ffd83dbSDimitry Andric       if (n_token.getKind() != tok::l_paren && n_token.getKind() != tok::less) {
4265ffd83dbSDimitry Andric         clang::Token tmp_tok;
4275ffd83dbSDimitry Andric         tmp_tok.startToken();
4285ffd83dbSDimitry Andric         tmp_tok.setLength(1);
4295ffd83dbSDimitry Andric         tmp_tok.setLocation(token.getLocation().getLocWithOffset(1));
4305ffd83dbSDimitry Andric         tmp_tok.setKind(tok::less);
4315ffd83dbSDimitry Andric 
4325ffd83dbSDimitry Andric         m_tokens[m_next_token_index] = tmp_tok;
4335ffd83dbSDimitry Andric 
4345ffd83dbSDimitry Andric         start_position.Remove();
4355ffd83dbSDimitry Andric         return true;
4365ffd83dbSDimitry Andric       }
4375ffd83dbSDimitry Andric     }
4385ffd83dbSDimitry Andric   }
4395ffd83dbSDimitry Andric 
440*0b57cec5SDimitry Andric   switch (token.getKind()) {
441*0b57cec5SDimitry Andric   case tok::kw_new:
442*0b57cec5SDimitry Andric   case tok::kw_delete:
443*0b57cec5SDimitry Andric     // This is 'new' or 'delete' operators.
444*0b57cec5SDimitry Andric     Advance();
445*0b57cec5SDimitry Andric     // Check for array new/delete.
446*0b57cec5SDimitry Andric     if (HasMoreTokens() && Peek().is(tok::l_square)) {
447*0b57cec5SDimitry Andric       // Consume the '[' and ']'.
448*0b57cec5SDimitry Andric       if (!ConsumeBrackets(tok::l_square, tok::r_square))
449*0b57cec5SDimitry Andric         return false;
450*0b57cec5SDimitry Andric     }
451*0b57cec5SDimitry Andric     break;
452*0b57cec5SDimitry Andric 
453*0b57cec5SDimitry Andric #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly)  \
454*0b57cec5SDimitry Andric   case tok::Token:                                                             \
455*0b57cec5SDimitry Andric     Advance();                                                                 \
456*0b57cec5SDimitry Andric     break;
457*0b57cec5SDimitry Andric #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
458*0b57cec5SDimitry Andric #include "clang/Basic/OperatorKinds.def"
459*0b57cec5SDimitry Andric #undef OVERLOADED_OPERATOR
460*0b57cec5SDimitry Andric #undef OVERLOADED_OPERATOR_MULTI
461*0b57cec5SDimitry Andric 
462*0b57cec5SDimitry Andric   case tok::l_paren:
463*0b57cec5SDimitry Andric     // Call operator consume '(' ... ')'.
464*0b57cec5SDimitry Andric     if (ConsumeBrackets(tok::l_paren, tok::r_paren))
465*0b57cec5SDimitry Andric       break;
466*0b57cec5SDimitry Andric     return false;
467*0b57cec5SDimitry Andric 
468*0b57cec5SDimitry Andric   case tok::l_square:
469*0b57cec5SDimitry Andric     // This is a [] operator.
470*0b57cec5SDimitry Andric     // Consume the '[' and ']'.
471*0b57cec5SDimitry Andric     if (ConsumeBrackets(tok::l_square, tok::r_square))
472*0b57cec5SDimitry Andric       break;
473*0b57cec5SDimitry Andric     return false;
474*0b57cec5SDimitry Andric 
475*0b57cec5SDimitry Andric   default:
476*0b57cec5SDimitry Andric     // This might be a cast operator.
477*0b57cec5SDimitry Andric     if (ConsumeTypename())
478*0b57cec5SDimitry Andric       break;
479*0b57cec5SDimitry Andric     return false;
480*0b57cec5SDimitry Andric   }
481*0b57cec5SDimitry Andric   start_position.Remove();
482*0b57cec5SDimitry Andric   return true;
483*0b57cec5SDimitry Andric }
484*0b57cec5SDimitry Andric 
485*0b57cec5SDimitry Andric void CPlusPlusNameParser::SkipTypeQualifiers() {
486*0b57cec5SDimitry Andric   while (ConsumeToken(tok::kw_const, tok::kw_volatile))
487*0b57cec5SDimitry Andric     ;
488*0b57cec5SDimitry Andric }
489*0b57cec5SDimitry Andric 
490*0b57cec5SDimitry Andric void CPlusPlusNameParser::SkipFunctionQualifiers() {
491*0b57cec5SDimitry Andric   while (ConsumeToken(tok::kw_const, tok::kw_volatile, tok::amp, tok::ampamp))
492*0b57cec5SDimitry Andric     ;
493*0b57cec5SDimitry Andric }
494*0b57cec5SDimitry Andric 
495*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeBuiltinType() {
496*0b57cec5SDimitry Andric   bool result = false;
497*0b57cec5SDimitry Andric   bool continue_parsing = true;
498*0b57cec5SDimitry Andric   // Built-in types can be made of a few keywords like 'unsigned long long
499*0b57cec5SDimitry Andric   // int'. This function consumes all built-in type keywords without checking
500*0b57cec5SDimitry Andric   // if they make sense like 'unsigned char void'.
501*0b57cec5SDimitry Andric   while (continue_parsing && HasMoreTokens()) {
502*0b57cec5SDimitry Andric     switch (Peek().getKind()) {
503*0b57cec5SDimitry Andric     case tok::kw_short:
504*0b57cec5SDimitry Andric     case tok::kw_long:
505*0b57cec5SDimitry Andric     case tok::kw___int64:
506*0b57cec5SDimitry Andric     case tok::kw___int128:
507*0b57cec5SDimitry Andric     case tok::kw_signed:
508*0b57cec5SDimitry Andric     case tok::kw_unsigned:
509*0b57cec5SDimitry Andric     case tok::kw_void:
510*0b57cec5SDimitry Andric     case tok::kw_char:
511*0b57cec5SDimitry Andric     case tok::kw_int:
512*0b57cec5SDimitry Andric     case tok::kw_half:
513*0b57cec5SDimitry Andric     case tok::kw_float:
514*0b57cec5SDimitry Andric     case tok::kw_double:
515*0b57cec5SDimitry Andric     case tok::kw___float128:
516*0b57cec5SDimitry Andric     case tok::kw_wchar_t:
517*0b57cec5SDimitry Andric     case tok::kw_bool:
518*0b57cec5SDimitry Andric     case tok::kw_char16_t:
519*0b57cec5SDimitry Andric     case tok::kw_char32_t:
520*0b57cec5SDimitry Andric       result = true;
521*0b57cec5SDimitry Andric       Advance();
522*0b57cec5SDimitry Andric       break;
523*0b57cec5SDimitry Andric     default:
524*0b57cec5SDimitry Andric       continue_parsing = false;
525*0b57cec5SDimitry Andric       break;
526*0b57cec5SDimitry Andric     }
527*0b57cec5SDimitry Andric   }
528*0b57cec5SDimitry Andric   return result;
529*0b57cec5SDimitry Andric }
530*0b57cec5SDimitry Andric 
531*0b57cec5SDimitry Andric void CPlusPlusNameParser::SkipPtrsAndRefs() {
532*0b57cec5SDimitry Andric   // Ignoring result.
533*0b57cec5SDimitry Andric   ConsumePtrsAndRefs();
534*0b57cec5SDimitry Andric }
535*0b57cec5SDimitry Andric 
536*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumePtrsAndRefs() {
537*0b57cec5SDimitry Andric   bool found = false;
538*0b57cec5SDimitry Andric   SkipTypeQualifiers();
539*0b57cec5SDimitry Andric   while (ConsumeToken(tok::star, tok::amp, tok::ampamp, tok::kw_const,
540*0b57cec5SDimitry Andric                       tok::kw_volatile)) {
541*0b57cec5SDimitry Andric     found = true;
542*0b57cec5SDimitry Andric     SkipTypeQualifiers();
543*0b57cec5SDimitry Andric   }
544*0b57cec5SDimitry Andric   return found;
545*0b57cec5SDimitry Andric }
546*0b57cec5SDimitry Andric 
547*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeDecltype() {
548*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
549*0b57cec5SDimitry Andric   if (!ConsumeToken(tok::kw_decltype))
550*0b57cec5SDimitry Andric     return false;
551*0b57cec5SDimitry Andric 
552*0b57cec5SDimitry Andric   if (!ConsumeArguments())
553*0b57cec5SDimitry Andric     return false;
554*0b57cec5SDimitry Andric 
555*0b57cec5SDimitry Andric   start_position.Remove();
556*0b57cec5SDimitry Andric   return true;
557*0b57cec5SDimitry Andric }
558*0b57cec5SDimitry Andric 
559*0b57cec5SDimitry Andric bool CPlusPlusNameParser::ConsumeTypename() {
560*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
561*0b57cec5SDimitry Andric   SkipTypeQualifiers();
562*0b57cec5SDimitry Andric   if (!ConsumeBuiltinType() && !ConsumeDecltype()) {
563*0b57cec5SDimitry Andric     if (!ParseFullNameImpl())
564*0b57cec5SDimitry Andric       return false;
565*0b57cec5SDimitry Andric   }
566*0b57cec5SDimitry Andric   SkipPtrsAndRefs();
567*0b57cec5SDimitry Andric   start_position.Remove();
568*0b57cec5SDimitry Andric   return true;
569*0b57cec5SDimitry Andric }
570*0b57cec5SDimitry Andric 
571bdd1243dSDimitry Andric std::optional<CPlusPlusNameParser::ParsedNameRanges>
572*0b57cec5SDimitry Andric CPlusPlusNameParser::ParseFullNameImpl() {
573*0b57cec5SDimitry Andric   // Name parsing state machine.
574*0b57cec5SDimitry Andric   enum class State {
575*0b57cec5SDimitry Andric     Beginning,       // start of the name
576*0b57cec5SDimitry Andric     AfterTwoColons,  // right after ::
577*0b57cec5SDimitry Andric     AfterIdentifier, // right after alphanumerical identifier ([a-z0-9_]+)
578*0b57cec5SDimitry Andric     AfterTemplate,   // right after template brackets (<something>)
579*0b57cec5SDimitry Andric     AfterOperator,   // right after name of C++ operator
580*0b57cec5SDimitry Andric   };
581*0b57cec5SDimitry Andric 
582*0b57cec5SDimitry Andric   Bookmark start_position = SetBookmark();
583*0b57cec5SDimitry Andric   State state = State::Beginning;
584*0b57cec5SDimitry Andric   bool continue_parsing = true;
585bdd1243dSDimitry Andric   std::optional<size_t> last_coloncolon_position;
586*0b57cec5SDimitry Andric 
587*0b57cec5SDimitry Andric   while (continue_parsing && HasMoreTokens()) {
588*0b57cec5SDimitry Andric     const auto &token = Peek();
589*0b57cec5SDimitry Andric     switch (token.getKind()) {
590*0b57cec5SDimitry Andric     case tok::raw_identifier: // Just a name.
591*0b57cec5SDimitry Andric       if (state != State::Beginning && state != State::AfterTwoColons) {
592*0b57cec5SDimitry Andric         continue_parsing = false;
593*0b57cec5SDimitry Andric         break;
594*0b57cec5SDimitry Andric       }
595*0b57cec5SDimitry Andric       Advance();
596*0b57cec5SDimitry Andric       state = State::AfterIdentifier;
597*0b57cec5SDimitry Andric       break;
598bdd1243dSDimitry Andric     case tok::l_square: {
599bdd1243dSDimitry Andric       // Handles types or functions that were tagged
600bdd1243dSDimitry Andric       // with, e.g.,
601bdd1243dSDimitry Andric       //   [[gnu::abi_tag("tag1","tag2")]] func()
602bdd1243dSDimitry Andric       // and demangled/prettified into:
603bdd1243dSDimitry Andric       //   func[abi:tag1][abi:tag2]()
604bdd1243dSDimitry Andric 
605bdd1243dSDimitry Andric       // ABI tags only appear after a method or type name
606bdd1243dSDimitry Andric       const bool valid_state =
607bdd1243dSDimitry Andric           state == State::AfterIdentifier || state == State::AfterOperator;
608bdd1243dSDimitry Andric       if (!valid_state || !ConsumeAbiTag()) {
609bdd1243dSDimitry Andric         continue_parsing = false;
610bdd1243dSDimitry Andric       }
611bdd1243dSDimitry Andric 
612bdd1243dSDimitry Andric       break;
613bdd1243dSDimitry Andric     }
614*0b57cec5SDimitry Andric     case tok::l_paren: {
615*0b57cec5SDimitry Andric       if (state == State::Beginning || state == State::AfterTwoColons) {
616*0b57cec5SDimitry Andric         // (anonymous namespace)
617*0b57cec5SDimitry Andric         if (ConsumeAnonymousNamespace()) {
618*0b57cec5SDimitry Andric           state = State::AfterIdentifier;
619*0b57cec5SDimitry Andric           break;
620*0b57cec5SDimitry Andric         }
621*0b57cec5SDimitry Andric       }
622*0b57cec5SDimitry Andric 
623*0b57cec5SDimitry Andric       // Type declared inside a function 'func()::Type'
624*0b57cec5SDimitry Andric       if (state != State::AfterIdentifier && state != State::AfterTemplate &&
625*0b57cec5SDimitry Andric           state != State::AfterOperator) {
626*0b57cec5SDimitry Andric         continue_parsing = false;
627*0b57cec5SDimitry Andric         break;
628*0b57cec5SDimitry Andric       }
629*0b57cec5SDimitry Andric       Bookmark l_paren_position = SetBookmark();
630*0b57cec5SDimitry Andric       // Consume the '(' ... ') [const]'.
631*0b57cec5SDimitry Andric       if (!ConsumeArguments()) {
632*0b57cec5SDimitry Andric         continue_parsing = false;
633*0b57cec5SDimitry Andric         break;
634*0b57cec5SDimitry Andric       }
635*0b57cec5SDimitry Andric       SkipFunctionQualifiers();
636*0b57cec5SDimitry Andric 
637*0b57cec5SDimitry Andric       // Consume '::'
638*0b57cec5SDimitry Andric       size_t coloncolon_position = GetCurrentPosition();
639*0b57cec5SDimitry Andric       if (!ConsumeToken(tok::coloncolon)) {
640*0b57cec5SDimitry Andric         continue_parsing = false;
641*0b57cec5SDimitry Andric         break;
642*0b57cec5SDimitry Andric       }
643*0b57cec5SDimitry Andric       l_paren_position.Remove();
644*0b57cec5SDimitry Andric       last_coloncolon_position = coloncolon_position;
645*0b57cec5SDimitry Andric       state = State::AfterTwoColons;
646*0b57cec5SDimitry Andric       break;
647*0b57cec5SDimitry Andric     }
648*0b57cec5SDimitry Andric     case tok::l_brace:
649*0b57cec5SDimitry Andric       if (state == State::Beginning || state == State::AfterTwoColons) {
650*0b57cec5SDimitry Andric         if (ConsumeLambda()) {
651*0b57cec5SDimitry Andric           state = State::AfterIdentifier;
652*0b57cec5SDimitry Andric           break;
653*0b57cec5SDimitry Andric         }
654*0b57cec5SDimitry Andric       }
655*0b57cec5SDimitry Andric       continue_parsing = false;
656*0b57cec5SDimitry Andric       break;
657*0b57cec5SDimitry Andric     case tok::coloncolon: // Type nesting delimiter.
658*0b57cec5SDimitry Andric       if (state != State::Beginning && state != State::AfterIdentifier &&
659*0b57cec5SDimitry Andric           state != State::AfterTemplate) {
660*0b57cec5SDimitry Andric         continue_parsing = false;
661*0b57cec5SDimitry Andric         break;
662*0b57cec5SDimitry Andric       }
663*0b57cec5SDimitry Andric       last_coloncolon_position = GetCurrentPosition();
664*0b57cec5SDimitry Andric       Advance();
665*0b57cec5SDimitry Andric       state = State::AfterTwoColons;
666*0b57cec5SDimitry Andric       break;
667*0b57cec5SDimitry Andric     case tok::less: // Template brackets.
668*0b57cec5SDimitry Andric       if (state != State::AfterIdentifier && state != State::AfterOperator) {
669*0b57cec5SDimitry Andric         continue_parsing = false;
670*0b57cec5SDimitry Andric         break;
671*0b57cec5SDimitry Andric       }
672*0b57cec5SDimitry Andric       if (!ConsumeTemplateArgs()) {
673*0b57cec5SDimitry Andric         continue_parsing = false;
674*0b57cec5SDimitry Andric         break;
675*0b57cec5SDimitry Andric       }
676*0b57cec5SDimitry Andric       state = State::AfterTemplate;
677*0b57cec5SDimitry Andric       break;
678*0b57cec5SDimitry Andric     case tok::kw_operator: // C++ operator overloading.
679*0b57cec5SDimitry Andric       if (state != State::Beginning && state != State::AfterTwoColons) {
680*0b57cec5SDimitry Andric         continue_parsing = false;
681*0b57cec5SDimitry Andric         break;
682*0b57cec5SDimitry Andric       }
683*0b57cec5SDimitry Andric       if (!ConsumeOperator()) {
684*0b57cec5SDimitry Andric         continue_parsing = false;
685*0b57cec5SDimitry Andric         break;
686*0b57cec5SDimitry Andric       }
687*0b57cec5SDimitry Andric       state = State::AfterOperator;
688*0b57cec5SDimitry Andric       break;
689*0b57cec5SDimitry Andric     case tok::tilde: // Destructor.
690*0b57cec5SDimitry Andric       if (state != State::Beginning && state != State::AfterTwoColons) {
691*0b57cec5SDimitry Andric         continue_parsing = false;
692*0b57cec5SDimitry Andric         break;
693*0b57cec5SDimitry Andric       }
694*0b57cec5SDimitry Andric       Advance();
695*0b57cec5SDimitry Andric       if (ConsumeToken(tok::raw_identifier)) {
696*0b57cec5SDimitry Andric         state = State::AfterIdentifier;
697*0b57cec5SDimitry Andric       } else {
698*0b57cec5SDimitry Andric         TakeBack();
699*0b57cec5SDimitry Andric         continue_parsing = false;
700*0b57cec5SDimitry Andric       }
701*0b57cec5SDimitry Andric       break;
702*0b57cec5SDimitry Andric     default:
703*0b57cec5SDimitry Andric       continue_parsing = false;
704*0b57cec5SDimitry Andric       break;
705*0b57cec5SDimitry Andric     }
706*0b57cec5SDimitry Andric   }
707*0b57cec5SDimitry Andric 
708*0b57cec5SDimitry Andric   if (state == State::AfterIdentifier || state == State::AfterOperator ||
709*0b57cec5SDimitry Andric       state == State::AfterTemplate) {
710*0b57cec5SDimitry Andric     ParsedNameRanges result;
711*0b57cec5SDimitry Andric     if (last_coloncolon_position) {
712bdd1243dSDimitry Andric       result.context_range =
713bdd1243dSDimitry Andric           Range(start_position.GetSavedPosition(), *last_coloncolon_position);
714*0b57cec5SDimitry Andric       result.basename_range =
715bdd1243dSDimitry Andric           Range(*last_coloncolon_position + 1, GetCurrentPosition());
716*0b57cec5SDimitry Andric     } else {
717*0b57cec5SDimitry Andric       result.basename_range =
718*0b57cec5SDimitry Andric           Range(start_position.GetSavedPosition(), GetCurrentPosition());
719*0b57cec5SDimitry Andric     }
720*0b57cec5SDimitry Andric     start_position.Remove();
721*0b57cec5SDimitry Andric     return result;
722*0b57cec5SDimitry Andric   } else {
723bdd1243dSDimitry Andric     return std::nullopt;
724*0b57cec5SDimitry Andric   }
725*0b57cec5SDimitry Andric }
726*0b57cec5SDimitry Andric 
727*0b57cec5SDimitry Andric llvm::StringRef CPlusPlusNameParser::GetTextForRange(const Range &range) {
728*0b57cec5SDimitry Andric   if (range.empty())
729*0b57cec5SDimitry Andric     return llvm::StringRef();
730*0b57cec5SDimitry Andric   assert(range.begin_index < range.end_index);
731*0b57cec5SDimitry Andric   assert(range.begin_index < m_tokens.size());
732*0b57cec5SDimitry Andric   assert(range.end_index <= m_tokens.size());
733*0b57cec5SDimitry Andric   clang::Token &first_token = m_tokens[range.begin_index];
734*0b57cec5SDimitry Andric   clang::Token &last_token = m_tokens[range.end_index - 1];
735*0b57cec5SDimitry Andric   clang::SourceLocation start_loc = first_token.getLocation();
736*0b57cec5SDimitry Andric   clang::SourceLocation end_loc = last_token.getLocation();
737*0b57cec5SDimitry Andric   unsigned start_pos = start_loc.getRawEncoding();
738*0b57cec5SDimitry Andric   unsigned end_pos = end_loc.getRawEncoding() + last_token.getLength();
739*0b57cec5SDimitry Andric   return m_text.take_front(end_pos).drop_front(start_pos);
740*0b57cec5SDimitry Andric }
741*0b57cec5SDimitry Andric 
742*0b57cec5SDimitry Andric static const clang::LangOptions &GetLangOptions() {
743*0b57cec5SDimitry Andric   static clang::LangOptions g_options;
744*0b57cec5SDimitry Andric   static llvm::once_flag g_once_flag;
745*0b57cec5SDimitry Andric   llvm::call_once(g_once_flag, []() {
746*0b57cec5SDimitry Andric     g_options.LineComment = true;
747*0b57cec5SDimitry Andric     g_options.C99 = true;
748*0b57cec5SDimitry Andric     g_options.C11 = true;
749*0b57cec5SDimitry Andric     g_options.CPlusPlus = true;
750*0b57cec5SDimitry Andric     g_options.CPlusPlus11 = true;
751*0b57cec5SDimitry Andric     g_options.CPlusPlus14 = true;
752*0b57cec5SDimitry Andric     g_options.CPlusPlus17 = true;
753*0b57cec5SDimitry Andric   });
754*0b57cec5SDimitry Andric   return g_options;
755*0b57cec5SDimitry Andric }
756*0b57cec5SDimitry Andric 
757*0b57cec5SDimitry Andric static const llvm::StringMap<tok::TokenKind> &GetKeywordsMap() {
758*0b57cec5SDimitry Andric   static llvm::StringMap<tok::TokenKind> g_map{
759*0b57cec5SDimitry Andric #define KEYWORD(Name, Flags) {llvm::StringRef(#Name), tok::kw_##Name},
760*0b57cec5SDimitry Andric #include "clang/Basic/TokenKinds.def"
761*0b57cec5SDimitry Andric #undef KEYWORD
762*0b57cec5SDimitry Andric   };
763*0b57cec5SDimitry Andric   return g_map;
764*0b57cec5SDimitry Andric }
765*0b57cec5SDimitry Andric 
766*0b57cec5SDimitry Andric void CPlusPlusNameParser::ExtractTokens() {
767*0b57cec5SDimitry Andric   if (m_text.empty())
768*0b57cec5SDimitry Andric     return;
769*0b57cec5SDimitry Andric   clang::Lexer lexer(clang::SourceLocation(), GetLangOptions(), m_text.data(),
770*0b57cec5SDimitry Andric                      m_text.data(), m_text.data() + m_text.size());
771*0b57cec5SDimitry Andric   const auto &kw_map = GetKeywordsMap();
772*0b57cec5SDimitry Andric   clang::Token token;
773*0b57cec5SDimitry Andric   for (lexer.LexFromRawLexer(token); !token.is(clang::tok::eof);
774*0b57cec5SDimitry Andric        lexer.LexFromRawLexer(token)) {
775*0b57cec5SDimitry Andric     if (token.is(clang::tok::raw_identifier)) {
776*0b57cec5SDimitry Andric       auto it = kw_map.find(token.getRawIdentifier());
777*0b57cec5SDimitry Andric       if (it != kw_map.end()) {
778*0b57cec5SDimitry Andric         token.setKind(it->getValue());
779*0b57cec5SDimitry Andric       }
780*0b57cec5SDimitry Andric     }
781*0b57cec5SDimitry Andric 
782*0b57cec5SDimitry Andric     m_tokens.push_back(token);
783*0b57cec5SDimitry Andric   }
784*0b57cec5SDimitry Andric }
785