xref: /llvm-project/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp (revision 89cd0e8c267f57004a734c94ff15c6bd0facf646)
180814287SRaphael Isemann //===-- CPlusPlusNameParser.cpp -------------------------------------------===//
2a633ee6eSEugene Zemtsov //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a633ee6eSEugene Zemtsov //
7a633ee6eSEugene Zemtsov //===----------------------------------------------------------------------===//
8a633ee6eSEugene Zemtsov 
9a633ee6eSEugene Zemtsov #include "CPlusPlusNameParser.h"
10a633ee6eSEugene Zemtsov 
11a633ee6eSEugene Zemtsov #include "clang/Basic/IdentifierTable.h"
12a4561d93SMichael Buch #include "clang/Basic/TokenKinds.h"
13a633ee6eSEugene Zemtsov #include "llvm/ADT/StringMap.h"
14a633ee6eSEugene Zemtsov #include "llvm/Support/Threading.h"
15f190ce62SKazu Hirata #include <optional>
16a633ee6eSEugene Zemtsov 
17a633ee6eSEugene Zemtsov using namespace lldb;
18a633ee6eSEugene Zemtsov using namespace lldb_private;
19a633ee6eSEugene Zemtsov using ParsedFunction = lldb_private::CPlusPlusNameParser::ParsedFunction;
20a633ee6eSEugene Zemtsov using ParsedName = lldb_private::CPlusPlusNameParser::ParsedName;
21a633ee6eSEugene Zemtsov namespace tok = clang::tok;
22a633ee6eSEugene Zemtsov 
ParseAsFunctionDefinition()232fe83274SKazu Hirata std::optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() {
24a633ee6eSEugene Zemtsov   m_next_token_index = 0;
252fe83274SKazu Hirata   std::optional<ParsedFunction> result(std::nullopt);
26a633ee6eSEugene Zemtsov 
2705097246SAdrian Prantl   // Try to parse the name as function without a return type specified e.g.
2805097246SAdrian Prantl   // main(int, char*[])
29a633ee6eSEugene Zemtsov   {
30a633ee6eSEugene Zemtsov     Bookmark start_position = SetBookmark();
31a633ee6eSEugene Zemtsov     result = ParseFunctionImpl(false);
32a633ee6eSEugene Zemtsov     if (result && !HasMoreTokens())
33a633ee6eSEugene Zemtsov       return result;
34a633ee6eSEugene Zemtsov   }
35a633ee6eSEugene Zemtsov 
3605097246SAdrian Prantl   // Try to parse the name as function with function pointer return type e.g.
3705097246SAdrian Prantl   // void (*get_func(const char*))()
38a633ee6eSEugene Zemtsov   result = ParseFuncPtr(true);
39a633ee6eSEugene Zemtsov   if (result)
40a633ee6eSEugene Zemtsov     return result;
41a633ee6eSEugene Zemtsov 
42a633ee6eSEugene Zemtsov   // Finally try to parse the name as a function with non-function return type
43a633ee6eSEugene Zemtsov   // e.g. int main(int, char*[])
44a633ee6eSEugene Zemtsov   result = ParseFunctionImpl(true);
45a633ee6eSEugene Zemtsov   if (HasMoreTokens())
46343523d0SKazu Hirata     return std::nullopt;
47a633ee6eSEugene Zemtsov   return result;
48a633ee6eSEugene Zemtsov }
49a633ee6eSEugene Zemtsov 
ParseAsFullName()502fe83274SKazu Hirata std::optional<ParsedName> CPlusPlusNameParser::ParseAsFullName() {
51a633ee6eSEugene Zemtsov   m_next_token_index = 0;
522fe83274SKazu Hirata   std::optional<ParsedNameRanges> name_ranges = ParseFullNameImpl();
53a633ee6eSEugene Zemtsov   if (!name_ranges)
54343523d0SKazu Hirata     return std::nullopt;
55a633ee6eSEugene Zemtsov   if (HasMoreTokens())
56343523d0SKazu Hirata     return std::nullopt;
57a633ee6eSEugene Zemtsov   ParsedName result;
58f43886e7SFangrui Song   result.basename = GetTextForRange(name_ranges->basename_range);
59f43886e7SFangrui Song   result.context = GetTextForRange(name_ranges->context_range);
60a633ee6eSEugene Zemtsov   return result;
61a633ee6eSEugene Zemtsov }
62a633ee6eSEugene Zemtsov 
HasMoreTokens()63a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::HasMoreTokens() {
64a633ee6eSEugene Zemtsov   return m_next_token_index < m_tokens.size();
65a633ee6eSEugene Zemtsov }
66a633ee6eSEugene Zemtsov 
Advance()67a633ee6eSEugene Zemtsov void CPlusPlusNameParser::Advance() { ++m_next_token_index; }
68a633ee6eSEugene Zemtsov 
TakeBack()69a633ee6eSEugene Zemtsov void CPlusPlusNameParser::TakeBack() { --m_next_token_index; }
70a633ee6eSEugene Zemtsov 
ConsumeToken(tok::TokenKind kind)71a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeToken(tok::TokenKind kind) {
72a633ee6eSEugene Zemtsov   if (!HasMoreTokens())
73a633ee6eSEugene Zemtsov     return false;
74a633ee6eSEugene Zemtsov 
75a633ee6eSEugene Zemtsov   if (!Peek().is(kind))
76a633ee6eSEugene Zemtsov     return false;
77a633ee6eSEugene Zemtsov 
78a633ee6eSEugene Zemtsov   Advance();
79a633ee6eSEugene Zemtsov   return true;
80a633ee6eSEugene Zemtsov }
81a633ee6eSEugene Zemtsov 
ConsumeToken(Ts...kinds)82a633ee6eSEugene Zemtsov template <typename... Ts> bool CPlusPlusNameParser::ConsumeToken(Ts... kinds) {
83a633ee6eSEugene Zemtsov   if (!HasMoreTokens())
84a633ee6eSEugene Zemtsov     return false;
85a633ee6eSEugene Zemtsov 
86a633ee6eSEugene Zemtsov   if (!Peek().isOneOf(kinds...))
87a633ee6eSEugene Zemtsov     return false;
88a633ee6eSEugene Zemtsov 
89a633ee6eSEugene Zemtsov   Advance();
90a633ee6eSEugene Zemtsov   return true;
91a633ee6eSEugene Zemtsov }
92a633ee6eSEugene Zemtsov 
SetBookmark()93a633ee6eSEugene Zemtsov CPlusPlusNameParser::Bookmark CPlusPlusNameParser::SetBookmark() {
94a633ee6eSEugene Zemtsov   return Bookmark(m_next_token_index);
95a633ee6eSEugene Zemtsov }
96a633ee6eSEugene Zemtsov 
GetCurrentPosition()97a633ee6eSEugene Zemtsov size_t CPlusPlusNameParser::GetCurrentPosition() { return m_next_token_index; }
98a633ee6eSEugene Zemtsov 
Peek()99a633ee6eSEugene Zemtsov clang::Token &CPlusPlusNameParser::Peek() {
100a633ee6eSEugene Zemtsov   assert(HasMoreTokens());
101a633ee6eSEugene Zemtsov   return m_tokens[m_next_token_index];
102a633ee6eSEugene Zemtsov }
103a633ee6eSEugene Zemtsov 
1042fe83274SKazu Hirata std::optional<ParsedFunction>
ParseFunctionImpl(bool expect_return_type)105a633ee6eSEugene Zemtsov CPlusPlusNameParser::ParseFunctionImpl(bool expect_return_type) {
106a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
10776f34ed2SMichael Buch 
10876f34ed2SMichael Buch   ParsedFunction result;
109a633ee6eSEugene Zemtsov   if (expect_return_type) {
11076f34ed2SMichael Buch     size_t return_start = GetCurrentPosition();
111a633ee6eSEugene Zemtsov     // Consume return type if it's expected.
112a4561d93SMichael Buch     if (!ConsumeToken(tok::kw_auto) && !ConsumeTypename())
113343523d0SKazu Hirata       return std::nullopt;
11476f34ed2SMichael Buch 
11576f34ed2SMichael Buch     size_t return_end = GetCurrentPosition();
11676f34ed2SMichael Buch     result.return_type = GetTextForRange(Range(return_start, return_end));
117a633ee6eSEugene Zemtsov   }
118a633ee6eSEugene Zemtsov 
119a633ee6eSEugene Zemtsov   auto maybe_name = ParseFullNameImpl();
120a633ee6eSEugene Zemtsov   if (!maybe_name) {
121343523d0SKazu Hirata     return std::nullopt;
122a633ee6eSEugene Zemtsov   }
123a633ee6eSEugene Zemtsov 
124a633ee6eSEugene Zemtsov   size_t argument_start = GetCurrentPosition();
125a633ee6eSEugene Zemtsov   if (!ConsumeArguments()) {
126343523d0SKazu Hirata     return std::nullopt;
127a633ee6eSEugene Zemtsov   }
128a633ee6eSEugene Zemtsov 
129a633ee6eSEugene Zemtsov   size_t qualifiers_start = GetCurrentPosition();
130a633ee6eSEugene Zemtsov   SkipFunctionQualifiers();
131a633ee6eSEugene Zemtsov   size_t end_position = GetCurrentPosition();
132a633ee6eSEugene Zemtsov 
133f43886e7SFangrui Song   result.name.basename = GetTextForRange(maybe_name->basename_range);
134f43886e7SFangrui Song   result.name.context = GetTextForRange(maybe_name->context_range);
135a633ee6eSEugene Zemtsov   result.arguments = GetTextForRange(Range(argument_start, qualifiers_start));
136a633ee6eSEugene Zemtsov   result.qualifiers = GetTextForRange(Range(qualifiers_start, end_position));
137a633ee6eSEugene Zemtsov   start_position.Remove();
138a633ee6eSEugene Zemtsov   return result;
139a633ee6eSEugene Zemtsov }
140a633ee6eSEugene Zemtsov 
1412fe83274SKazu Hirata std::optional<ParsedFunction>
ParseFuncPtr(bool expect_return_type)142a633ee6eSEugene Zemtsov CPlusPlusNameParser::ParseFuncPtr(bool expect_return_type) {
14376f34ed2SMichael Buch   // This function parses a function definition
14476f34ed2SMichael Buch   // that returns a pointer type.
14576f34ed2SMichael Buch   // E.g., double (*(*func(long))(int))(float)
14676f34ed2SMichael Buch 
14776f34ed2SMichael Buch   // Step 1:
14876f34ed2SMichael Buch   // Remove the return type of the innermost
14976f34ed2SMichael Buch   // function pointer type.
15076f34ed2SMichael Buch   //
15176f34ed2SMichael Buch   // Leaves us with:
15276f34ed2SMichael Buch   //   (*(*func(long))(int))(float)
153a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
154a633ee6eSEugene Zemtsov   if (expect_return_type) {
155a633ee6eSEugene Zemtsov     // Consume return type.
156a633ee6eSEugene Zemtsov     if (!ConsumeTypename())
157343523d0SKazu Hirata       return std::nullopt;
158a633ee6eSEugene Zemtsov   }
159a633ee6eSEugene Zemtsov 
16076f34ed2SMichael Buch   // Step 2:
16176f34ed2SMichael Buch   //
16276f34ed2SMichael Buch   // Skip a pointer and parenthesis pair.
16376f34ed2SMichael Buch   //
16476f34ed2SMichael Buch   // Leaves us with:
16576f34ed2SMichael Buch   //   (*func(long))(int))(float)
166a633ee6eSEugene Zemtsov   if (!ConsumeToken(tok::l_paren))
167343523d0SKazu Hirata     return std::nullopt;
168a633ee6eSEugene Zemtsov   if (!ConsumePtrsAndRefs())
169343523d0SKazu Hirata     return std::nullopt;
170a633ee6eSEugene Zemtsov 
17176f34ed2SMichael Buch   // Step 3:
17276f34ed2SMichael Buch   //
17376f34ed2SMichael Buch   // Consume inner function name. This will fail unless
17476f34ed2SMichael Buch   // we stripped all the pointers on the left hand side
1759aae408dSYuanfang Chen   // of the function name.
176a633ee6eSEugene Zemtsov   {
177a633ee6eSEugene Zemtsov     Bookmark before_inner_function_pos = SetBookmark();
178a633ee6eSEugene Zemtsov     auto maybe_inner_function_name = ParseFunctionImpl(false);
179a633ee6eSEugene Zemtsov     if (maybe_inner_function_name)
180a633ee6eSEugene Zemtsov       if (ConsumeToken(tok::r_paren))
181a633ee6eSEugene Zemtsov         if (ConsumeArguments()) {
182a633ee6eSEugene Zemtsov           SkipFunctionQualifiers();
183a633ee6eSEugene Zemtsov           start_position.Remove();
184a633ee6eSEugene Zemtsov           before_inner_function_pos.Remove();
185a633ee6eSEugene Zemtsov           return maybe_inner_function_name;
186a633ee6eSEugene Zemtsov         }
187a633ee6eSEugene Zemtsov   }
188a633ee6eSEugene Zemtsov 
18976f34ed2SMichael Buch   // Step 4:
19076f34ed2SMichael Buch   //
19176f34ed2SMichael Buch   // Parse the remaining string as a function pointer again.
19276f34ed2SMichael Buch   // This time don't consume the inner-most typename since
19376f34ed2SMichael Buch   // we're left with pointers only. This will strip another
19476f34ed2SMichael Buch   // layer of pointers until we're left with the innermost
19576f34ed2SMichael Buch   // function name/argument. I.e., func(long))(int))(float)
19676f34ed2SMichael Buch   //
19776f34ed2SMichael Buch   // Once we successfully stripped all pointers and gotten
19876f34ed2SMichael Buch   // the innermost function name from ParseFunctionImpl above,
19976f34ed2SMichael Buch   // we consume a single ')' and the arguments '(...)' that follows.
20076f34ed2SMichael Buch   //
20176f34ed2SMichael Buch   // Leaves us with:
20276f34ed2SMichael Buch   //   )(float)
20376f34ed2SMichael Buch   //
20476f34ed2SMichael Buch   // This is the remnant of the outer function pointers' arguments.
20576f34ed2SMichael Buch   // Unwinding the recursive calls will remove the remaining
20676f34ed2SMichael Buch   // arguments.
207a633ee6eSEugene Zemtsov   auto maybe_inner_function_ptr_name = ParseFuncPtr(false);
208a633ee6eSEugene Zemtsov   if (maybe_inner_function_ptr_name)
209a633ee6eSEugene Zemtsov     if (ConsumeToken(tok::r_paren))
210a633ee6eSEugene Zemtsov       if (ConsumeArguments()) {
211a633ee6eSEugene Zemtsov         SkipFunctionQualifiers();
212a633ee6eSEugene Zemtsov         start_position.Remove();
213a633ee6eSEugene Zemtsov         return maybe_inner_function_ptr_name;
214a633ee6eSEugene Zemtsov       }
21576f34ed2SMichael Buch 
216343523d0SKazu Hirata   return std::nullopt;
217a633ee6eSEugene Zemtsov }
218a633ee6eSEugene Zemtsov 
ConsumeArguments()219a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeArguments() {
220a633ee6eSEugene Zemtsov   return ConsumeBrackets(tok::l_paren, tok::r_paren);
221a633ee6eSEugene Zemtsov }
222a633ee6eSEugene Zemtsov 
ConsumeTemplateArgs()223a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeTemplateArgs() {
224a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
225a633ee6eSEugene Zemtsov   if (!HasMoreTokens() || Peek().getKind() != tok::less)
226a633ee6eSEugene Zemtsov     return false;
227a633ee6eSEugene Zemtsov   Advance();
228a633ee6eSEugene Zemtsov 
229a633ee6eSEugene Zemtsov   // Consuming template arguments is a bit trickier than consuming function
23005097246SAdrian Prantl   // arguments, because '<' '>' brackets are not always trivially balanced. In
23105097246SAdrian Prantl   // some rare cases tokens '<' and '>' can appear inside template arguments as
23205097246SAdrian Prantl   // arithmetic or shift operators not as template brackets. Examples:
23305097246SAdrian Prantl   // std::enable_if<(10u)<(64), bool>
234a633ee6eSEugene Zemtsov   //           f<A<operator<(X,Y)::Subclass>>
23505097246SAdrian Prantl   // Good thing that compiler makes sure that really ambiguous cases of '>'
23605097246SAdrian Prantl   // usage should be enclosed within '()' brackets.
237a633ee6eSEugene Zemtsov   int template_counter = 1;
238a633ee6eSEugene Zemtsov   bool can_open_template = false;
239a633ee6eSEugene Zemtsov   while (HasMoreTokens() && template_counter > 0) {
240a633ee6eSEugene Zemtsov     tok::TokenKind kind = Peek().getKind();
241a633ee6eSEugene Zemtsov     switch (kind) {
242a633ee6eSEugene Zemtsov     case tok::greatergreater:
243a633ee6eSEugene Zemtsov       template_counter -= 2;
244a633ee6eSEugene Zemtsov       can_open_template = false;
245a633ee6eSEugene Zemtsov       Advance();
246a633ee6eSEugene Zemtsov       break;
247a633ee6eSEugene Zemtsov     case tok::greater:
248a633ee6eSEugene Zemtsov       --template_counter;
249a633ee6eSEugene Zemtsov       can_open_template = false;
250a633ee6eSEugene Zemtsov       Advance();
251a633ee6eSEugene Zemtsov       break;
252a633ee6eSEugene Zemtsov     case tok::less:
253a633ee6eSEugene Zemtsov       // '<' is an attempt to open a subteamplte
254a633ee6eSEugene Zemtsov       // check if parser is at the point where it's actually possible,
25505097246SAdrian Prantl       // otherwise it's just a part of an expression like 'sizeof(T)<(10)'. No
25605097246SAdrian Prantl       // need to do the same for '>' because compiler actually makes sure that
25705097246SAdrian Prantl       // '>' always surrounded by brackets to avoid ambiguity.
258a633ee6eSEugene Zemtsov       if (can_open_template)
259a633ee6eSEugene Zemtsov         ++template_counter;
260a633ee6eSEugene Zemtsov       can_open_template = false;
261a633ee6eSEugene Zemtsov       Advance();
262a633ee6eSEugene Zemtsov       break;
263a633ee6eSEugene Zemtsov     case tok::kw_operator: // C++ operator overloading.
264a633ee6eSEugene Zemtsov       if (!ConsumeOperator())
265a633ee6eSEugene Zemtsov         return false;
266a633ee6eSEugene Zemtsov       can_open_template = true;
267a633ee6eSEugene Zemtsov       break;
268a633ee6eSEugene Zemtsov     case tok::raw_identifier:
269a633ee6eSEugene Zemtsov       can_open_template = true;
270a633ee6eSEugene Zemtsov       Advance();
271a633ee6eSEugene Zemtsov       break;
272a633ee6eSEugene Zemtsov     case tok::l_square:
2733cc98845SMichael Buch       // Handle templates tagged with an ABI tag.
2743cc98845SMichael Buch       // An example demangled/prettified version is:
2753cc98845SMichael Buch       //   func[abi:tag1][abi:tag2]<type[abi:tag3]>(int)
2763cc98845SMichael Buch       if (ConsumeAbiTag())
2773cc98845SMichael Buch         can_open_template = true;
2783cc98845SMichael Buch       else if (ConsumeBrackets(tok::l_square, tok::r_square))
279a633ee6eSEugene Zemtsov         can_open_template = false;
2803cc98845SMichael Buch       else
2813cc98845SMichael Buch         return false;
282a633ee6eSEugene Zemtsov       break;
283a633ee6eSEugene Zemtsov     case tok::l_paren:
284a633ee6eSEugene Zemtsov       if (!ConsumeArguments())
285a633ee6eSEugene Zemtsov         return false;
286a633ee6eSEugene Zemtsov       can_open_template = false;
287a633ee6eSEugene Zemtsov       break;
288a633ee6eSEugene Zemtsov     default:
289a633ee6eSEugene Zemtsov       can_open_template = false;
290a633ee6eSEugene Zemtsov       Advance();
291a633ee6eSEugene Zemtsov       break;
292a633ee6eSEugene Zemtsov     }
293a633ee6eSEugene Zemtsov   }
294a633ee6eSEugene Zemtsov 
2959e916e5eSEugene Zemtsov   if (template_counter != 0) {
296a633ee6eSEugene Zemtsov     return false;
297a633ee6eSEugene Zemtsov   }
298a633ee6eSEugene Zemtsov   start_position.Remove();
299a633ee6eSEugene Zemtsov   return true;
300a633ee6eSEugene Zemtsov }
301a633ee6eSEugene Zemtsov 
ConsumeAbiTag()3023cc98845SMichael Buch bool CPlusPlusNameParser::ConsumeAbiTag() {
3033cc98845SMichael Buch   Bookmark start_position = SetBookmark();
3043cc98845SMichael Buch   if (!ConsumeToken(tok::l_square))
3053cc98845SMichael Buch     return false;
3063cc98845SMichael Buch 
3073cc98845SMichael Buch   if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
3083cc98845SMichael Buch       Peek().getRawIdentifier() == "abi")
3093cc98845SMichael Buch     Advance();
3103cc98845SMichael Buch   else
3113cc98845SMichael Buch     return false;
3123cc98845SMichael Buch 
3133cc98845SMichael Buch   if (!ConsumeToken(tok::colon))
3143cc98845SMichael Buch     return false;
3153cc98845SMichael Buch 
3163cc98845SMichael Buch   // Consume the actual tag string (and allow some special characters)
3173cc98845SMichael Buch   while (ConsumeToken(tok::raw_identifier, tok::comma, tok::period,
3183cc98845SMichael Buch                       tok::numeric_constant))
3193cc98845SMichael Buch     ;
3203cc98845SMichael Buch 
3213cc98845SMichael Buch   if (!ConsumeToken(tok::r_square))
3223cc98845SMichael Buch     return false;
3233cc98845SMichael Buch 
3243cc98845SMichael Buch   start_position.Remove();
3253cc98845SMichael Buch   return true;
3263cc98845SMichael Buch }
3273cc98845SMichael Buch 
ConsumeAnonymousNamespace()328a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeAnonymousNamespace() {
329a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
330a633ee6eSEugene Zemtsov   if (!ConsumeToken(tok::l_paren)) {
331a633ee6eSEugene Zemtsov     return false;
332a633ee6eSEugene Zemtsov   }
333a633ee6eSEugene Zemtsov   constexpr llvm::StringLiteral g_anonymous("anonymous");
334a633ee6eSEugene Zemtsov   if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
335a633ee6eSEugene Zemtsov       Peek().getRawIdentifier() == g_anonymous) {
336a633ee6eSEugene Zemtsov     Advance();
337a633ee6eSEugene Zemtsov   } else {
338a633ee6eSEugene Zemtsov     return false;
339a633ee6eSEugene Zemtsov   }
340a633ee6eSEugene Zemtsov 
341a633ee6eSEugene Zemtsov   if (!ConsumeToken(tok::kw_namespace)) {
342a633ee6eSEugene Zemtsov     return false;
343a633ee6eSEugene Zemtsov   }
344a633ee6eSEugene Zemtsov 
345a633ee6eSEugene Zemtsov   if (!ConsumeToken(tok::r_paren)) {
346a633ee6eSEugene Zemtsov     return false;
347a633ee6eSEugene Zemtsov   }
348a633ee6eSEugene Zemtsov   start_position.Remove();
349a633ee6eSEugene Zemtsov   return true;
350a633ee6eSEugene Zemtsov }
351a633ee6eSEugene Zemtsov 
ConsumeLambda()352055e65f0SJim Ingham bool CPlusPlusNameParser::ConsumeLambda() {
353055e65f0SJim Ingham   Bookmark start_position = SetBookmark();
354055e65f0SJim Ingham   if (!ConsumeToken(tok::l_brace)) {
355055e65f0SJim Ingham     return false;
356055e65f0SJim Ingham   }
357055e65f0SJim Ingham   constexpr llvm::StringLiteral g_lambda("lambda");
358055e65f0SJim Ingham   if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
359055e65f0SJim Ingham       Peek().getRawIdentifier() == g_lambda) {
360055e65f0SJim Ingham     // Put the matched brace back so we can use ConsumeBrackets
361055e65f0SJim Ingham     TakeBack();
362055e65f0SJim Ingham   } else {
363055e65f0SJim Ingham     return false;
364055e65f0SJim Ingham   }
365055e65f0SJim Ingham 
366055e65f0SJim Ingham   if (!ConsumeBrackets(tok::l_brace, tok::r_brace)) {
367055e65f0SJim Ingham     return false;
368055e65f0SJim Ingham   }
369055e65f0SJim Ingham 
370055e65f0SJim Ingham   start_position.Remove();
371055e65f0SJim Ingham   return true;
372055e65f0SJim Ingham }
373055e65f0SJim Ingham 
ConsumeBrackets(tok::TokenKind left,tok::TokenKind right)374a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeBrackets(tok::TokenKind left,
375a633ee6eSEugene Zemtsov                                           tok::TokenKind right) {
376a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
377a633ee6eSEugene Zemtsov   if (!HasMoreTokens() || Peek().getKind() != left)
378a633ee6eSEugene Zemtsov     return false;
379a633ee6eSEugene Zemtsov   Advance();
380a633ee6eSEugene Zemtsov 
381a633ee6eSEugene Zemtsov   int counter = 1;
382a633ee6eSEugene Zemtsov   while (HasMoreTokens() && counter > 0) {
383a633ee6eSEugene Zemtsov     tok::TokenKind kind = Peek().getKind();
384a633ee6eSEugene Zemtsov     if (kind == right)
385a633ee6eSEugene Zemtsov       --counter;
386a633ee6eSEugene Zemtsov     else if (kind == left)
387a633ee6eSEugene Zemtsov       ++counter;
388a633ee6eSEugene Zemtsov     Advance();
389a633ee6eSEugene Zemtsov   }
390a633ee6eSEugene Zemtsov 
391a633ee6eSEugene Zemtsov   assert(counter >= 0);
392a633ee6eSEugene Zemtsov   if (counter > 0) {
393a633ee6eSEugene Zemtsov     return false;
394a633ee6eSEugene Zemtsov   }
395a633ee6eSEugene Zemtsov   start_position.Remove();
396a633ee6eSEugene Zemtsov   return true;
397a633ee6eSEugene Zemtsov }
398a633ee6eSEugene Zemtsov 
ConsumeOperator()399a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeOperator() {
400a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
401a633ee6eSEugene Zemtsov   if (!ConsumeToken(tok::kw_operator))
402a633ee6eSEugene Zemtsov     return false;
403a633ee6eSEugene Zemtsov 
404a633ee6eSEugene Zemtsov   if (!HasMoreTokens()) {
405a633ee6eSEugene Zemtsov     return false;
406a633ee6eSEugene Zemtsov   }
407a633ee6eSEugene Zemtsov 
408a633ee6eSEugene Zemtsov   const auto &token = Peek();
4098016d61eSshafik 
4108016d61eSshafik   // When clang generates debug info it adds template parameters to names.
4118016d61eSshafik   // Since clang doesn't add a space between the name and the template parameter
4128016d61eSshafik   // in some cases we are not generating valid C++ names e.g.:
4138016d61eSshafik   //
4148016d61eSshafik   //   operator<<A::B>
4158016d61eSshafik   //
4168016d61eSshafik   // In some of these cases we will not parse them correctly. This fixes the
4178016d61eSshafik   // issue by detecting this case and inserting tok::less in place of
4188016d61eSshafik   // tok::lessless and returning successfully that we consumed the operator.
4198016d61eSshafik   if (token.getKind() == tok::lessless) {
4208016d61eSshafik     // Make sure we have more tokens before attempting to look ahead one more.
4218016d61eSshafik     if (m_next_token_index + 1 < m_tokens.size()) {
4228016d61eSshafik       // Look ahead two tokens.
4238016d61eSshafik       clang::Token n_token = m_tokens[m_next_token_index + 1];
4248016d61eSshafik       // If we find ( or < then this is indeed operator<< no need for fix.
4258016d61eSshafik       if (n_token.getKind() != tok::l_paren && n_token.getKind() != tok::less) {
4268016d61eSshafik         clang::Token tmp_tok;
4273806b380SBenjamin Kramer         tmp_tok.startToken();
4288016d61eSshafik         tmp_tok.setLength(1);
4298016d61eSshafik         tmp_tok.setLocation(token.getLocation().getLocWithOffset(1));
4308016d61eSshafik         tmp_tok.setKind(tok::less);
4318016d61eSshafik 
4328016d61eSshafik         m_tokens[m_next_token_index] = tmp_tok;
4338016d61eSshafik 
4348016d61eSshafik         start_position.Remove();
4358016d61eSshafik         return true;
4368016d61eSshafik       }
4378016d61eSshafik     }
4388016d61eSshafik   }
4398016d61eSshafik 
440a633ee6eSEugene Zemtsov   switch (token.getKind()) {
441a633ee6eSEugene Zemtsov   case tok::kw_new:
442a633ee6eSEugene Zemtsov   case tok::kw_delete:
443a633ee6eSEugene Zemtsov     // This is 'new' or 'delete' operators.
444a633ee6eSEugene Zemtsov     Advance();
445a633ee6eSEugene Zemtsov     // Check for array new/delete.
446a633ee6eSEugene Zemtsov     if (HasMoreTokens() && Peek().is(tok::l_square)) {
447a633ee6eSEugene Zemtsov       // Consume the '[' and ']'.
448a633ee6eSEugene Zemtsov       if (!ConsumeBrackets(tok::l_square, tok::r_square))
449a633ee6eSEugene Zemtsov         return false;
450a633ee6eSEugene Zemtsov     }
451a633ee6eSEugene Zemtsov     break;
452a633ee6eSEugene Zemtsov 
453a633ee6eSEugene Zemtsov #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly)  \
454a633ee6eSEugene Zemtsov   case tok::Token:                                                             \
455a633ee6eSEugene Zemtsov     Advance();                                                                 \
456a633ee6eSEugene Zemtsov     break;
457a633ee6eSEugene Zemtsov #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
458a633ee6eSEugene Zemtsov #include "clang/Basic/OperatorKinds.def"
459a633ee6eSEugene Zemtsov #undef OVERLOADED_OPERATOR
460a633ee6eSEugene Zemtsov #undef OVERLOADED_OPERATOR_MULTI
461a633ee6eSEugene Zemtsov 
462a633ee6eSEugene Zemtsov   case tok::l_paren:
463a633ee6eSEugene Zemtsov     // Call operator consume '(' ... ')'.
464a633ee6eSEugene Zemtsov     if (ConsumeBrackets(tok::l_paren, tok::r_paren))
465a633ee6eSEugene Zemtsov       break;
466a633ee6eSEugene Zemtsov     return false;
467a633ee6eSEugene Zemtsov 
468a633ee6eSEugene Zemtsov   case tok::l_square:
469a633ee6eSEugene Zemtsov     // This is a [] operator.
470a633ee6eSEugene Zemtsov     // Consume the '[' and ']'.
471a633ee6eSEugene Zemtsov     if (ConsumeBrackets(tok::l_square, tok::r_square))
472a633ee6eSEugene Zemtsov       break;
473a633ee6eSEugene Zemtsov     return false;
474a633ee6eSEugene Zemtsov 
475a633ee6eSEugene Zemtsov   default:
476a633ee6eSEugene Zemtsov     // This might be a cast operator.
477a633ee6eSEugene Zemtsov     if (ConsumeTypename())
478a633ee6eSEugene Zemtsov       break;
479a633ee6eSEugene Zemtsov     return false;
480a633ee6eSEugene Zemtsov   }
481a633ee6eSEugene Zemtsov   start_position.Remove();
482a633ee6eSEugene Zemtsov   return true;
483a633ee6eSEugene Zemtsov }
484a633ee6eSEugene Zemtsov 
SkipTypeQualifiers()485a633ee6eSEugene Zemtsov void CPlusPlusNameParser::SkipTypeQualifiers() {
486a633ee6eSEugene Zemtsov   while (ConsumeToken(tok::kw_const, tok::kw_volatile))
487a633ee6eSEugene Zemtsov     ;
488a633ee6eSEugene Zemtsov }
489a633ee6eSEugene Zemtsov 
SkipFunctionQualifiers()490a633ee6eSEugene Zemtsov void CPlusPlusNameParser::SkipFunctionQualifiers() {
491a633ee6eSEugene Zemtsov   while (ConsumeToken(tok::kw_const, tok::kw_volatile, tok::amp, tok::ampamp))
492a633ee6eSEugene Zemtsov     ;
493a633ee6eSEugene Zemtsov }
494a633ee6eSEugene Zemtsov 
ConsumeBuiltinType()495a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeBuiltinType() {
496a633ee6eSEugene Zemtsov   bool result = false;
497a633ee6eSEugene Zemtsov   bool continue_parsing = true;
49805097246SAdrian Prantl   // Built-in types can be made of a few keywords like 'unsigned long long
49905097246SAdrian Prantl   // int'. This function consumes all built-in type keywords without checking
50005097246SAdrian Prantl   // if they make sense like 'unsigned char void'.
501a633ee6eSEugene Zemtsov   while (continue_parsing && HasMoreTokens()) {
502a633ee6eSEugene Zemtsov     switch (Peek().getKind()) {
503a633ee6eSEugene Zemtsov     case tok::kw_short:
504a633ee6eSEugene Zemtsov     case tok::kw_long:
505a633ee6eSEugene Zemtsov     case tok::kw___int64:
506a633ee6eSEugene Zemtsov     case tok::kw___int128:
507a633ee6eSEugene Zemtsov     case tok::kw_signed:
508a633ee6eSEugene Zemtsov     case tok::kw_unsigned:
509a633ee6eSEugene Zemtsov     case tok::kw_void:
510a633ee6eSEugene Zemtsov     case tok::kw_char:
511a633ee6eSEugene Zemtsov     case tok::kw_int:
512a633ee6eSEugene Zemtsov     case tok::kw_half:
513a633ee6eSEugene Zemtsov     case tok::kw_float:
514a633ee6eSEugene Zemtsov     case tok::kw_double:
515a633ee6eSEugene Zemtsov     case tok::kw___float128:
516a633ee6eSEugene Zemtsov     case tok::kw_wchar_t:
517a633ee6eSEugene Zemtsov     case tok::kw_bool:
518a633ee6eSEugene Zemtsov     case tok::kw_char16_t:
519a633ee6eSEugene Zemtsov     case tok::kw_char32_t:
520a633ee6eSEugene Zemtsov       result = true;
521a633ee6eSEugene Zemtsov       Advance();
522a633ee6eSEugene Zemtsov       break;
523a633ee6eSEugene Zemtsov     default:
524a633ee6eSEugene Zemtsov       continue_parsing = false;
525a633ee6eSEugene Zemtsov       break;
526a633ee6eSEugene Zemtsov     }
527a633ee6eSEugene Zemtsov   }
528a633ee6eSEugene Zemtsov   return result;
529a633ee6eSEugene Zemtsov }
530a633ee6eSEugene Zemtsov 
SkipPtrsAndRefs()531a633ee6eSEugene Zemtsov void CPlusPlusNameParser::SkipPtrsAndRefs() {
532a633ee6eSEugene Zemtsov   // Ignoring result.
533a633ee6eSEugene Zemtsov   ConsumePtrsAndRefs();
534a633ee6eSEugene Zemtsov }
535a633ee6eSEugene Zemtsov 
ConsumePtrsAndRefs()536a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumePtrsAndRefs() {
537a633ee6eSEugene Zemtsov   bool found = false;
538a633ee6eSEugene Zemtsov   SkipTypeQualifiers();
539a633ee6eSEugene Zemtsov   while (ConsumeToken(tok::star, tok::amp, tok::ampamp, tok::kw_const,
540a633ee6eSEugene Zemtsov                       tok::kw_volatile)) {
541a633ee6eSEugene Zemtsov     found = true;
542a633ee6eSEugene Zemtsov     SkipTypeQualifiers();
543a633ee6eSEugene Zemtsov   }
544a633ee6eSEugene Zemtsov   return found;
545a633ee6eSEugene Zemtsov }
546a633ee6eSEugene Zemtsov 
ConsumeDecltype()547a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeDecltype() {
548a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
549a633ee6eSEugene Zemtsov   if (!ConsumeToken(tok::kw_decltype))
550a633ee6eSEugene Zemtsov     return false;
551a633ee6eSEugene Zemtsov 
552a633ee6eSEugene Zemtsov   if (!ConsumeArguments())
553a633ee6eSEugene Zemtsov     return false;
554a633ee6eSEugene Zemtsov 
555a633ee6eSEugene Zemtsov   start_position.Remove();
556a633ee6eSEugene Zemtsov   return true;
557a633ee6eSEugene Zemtsov }
558a633ee6eSEugene Zemtsov 
ConsumeTypename()559a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeTypename() {
560a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
561a633ee6eSEugene Zemtsov   SkipTypeQualifiers();
562a633ee6eSEugene Zemtsov   if (!ConsumeBuiltinType() && !ConsumeDecltype()) {
563a633ee6eSEugene Zemtsov     if (!ParseFullNameImpl())
564a633ee6eSEugene Zemtsov       return false;
565a633ee6eSEugene Zemtsov   }
566a633ee6eSEugene Zemtsov   SkipPtrsAndRefs();
567a633ee6eSEugene Zemtsov   start_position.Remove();
568a633ee6eSEugene Zemtsov   return true;
569a633ee6eSEugene Zemtsov }
570a633ee6eSEugene Zemtsov 
5712fe83274SKazu Hirata std::optional<CPlusPlusNameParser::ParsedNameRanges>
ParseFullNameImpl()572a633ee6eSEugene Zemtsov CPlusPlusNameParser::ParseFullNameImpl() {
573a633ee6eSEugene Zemtsov   // Name parsing state machine.
574a633ee6eSEugene Zemtsov   enum class State {
575a633ee6eSEugene Zemtsov     Beginning,       // start of the name
576a633ee6eSEugene Zemtsov     AfterTwoColons,  // right after ::
577a633ee6eSEugene Zemtsov     AfterIdentifier, // right after alphanumerical identifier ([a-z0-9_]+)
578a633ee6eSEugene Zemtsov     AfterTemplate,   // right after template brackets (<something>)
579a633ee6eSEugene Zemtsov     AfterOperator,   // right after name of C++ operator
580a633ee6eSEugene Zemtsov   };
581a633ee6eSEugene Zemtsov 
582a633ee6eSEugene Zemtsov   Bookmark start_position = SetBookmark();
583a633ee6eSEugene Zemtsov   State state = State::Beginning;
584a633ee6eSEugene Zemtsov   bool continue_parsing = true;
5852fe83274SKazu Hirata   std::optional<size_t> last_coloncolon_position;
586a633ee6eSEugene Zemtsov 
587a633ee6eSEugene Zemtsov   while (continue_parsing && HasMoreTokens()) {
588a633ee6eSEugene Zemtsov     const auto &token = Peek();
589a633ee6eSEugene Zemtsov     switch (token.getKind()) {
590a633ee6eSEugene Zemtsov     case tok::raw_identifier: // Just a name.
591a633ee6eSEugene Zemtsov       if (state != State::Beginning && state != State::AfterTwoColons) {
592a633ee6eSEugene Zemtsov         continue_parsing = false;
593a633ee6eSEugene Zemtsov         break;
594a633ee6eSEugene Zemtsov       }
595a633ee6eSEugene Zemtsov       Advance();
596a633ee6eSEugene Zemtsov       state = State::AfterIdentifier;
597a633ee6eSEugene Zemtsov       break;
5983cc98845SMichael Buch     case tok::l_square: {
5993cc98845SMichael Buch       // Handles types or functions that were tagged
6003cc98845SMichael Buch       // with, e.g.,
6013cc98845SMichael Buch       //   [[gnu::abi_tag("tag1","tag2")]] func()
6023cc98845SMichael Buch       // and demangled/prettified into:
6033cc98845SMichael Buch       //   func[abi:tag1][abi:tag2]()
6043cc98845SMichael Buch 
6053cc98845SMichael Buch       // ABI tags only appear after a method or type name
6063cc98845SMichael Buch       const bool valid_state =
6073cc98845SMichael Buch           state == State::AfterIdentifier || state == State::AfterOperator;
6083cc98845SMichael Buch       if (!valid_state || !ConsumeAbiTag()) {
6093cc98845SMichael Buch         continue_parsing = false;
6103cc98845SMichael Buch       }
6113cc98845SMichael Buch 
6123cc98845SMichael Buch       break;
6133cc98845SMichael Buch     }
614a633ee6eSEugene Zemtsov     case tok::l_paren: {
615a633ee6eSEugene Zemtsov       if (state == State::Beginning || state == State::AfterTwoColons) {
616a633ee6eSEugene Zemtsov         // (anonymous namespace)
617a633ee6eSEugene Zemtsov         if (ConsumeAnonymousNamespace()) {
618a633ee6eSEugene Zemtsov           state = State::AfterIdentifier;
619a633ee6eSEugene Zemtsov           break;
620a633ee6eSEugene Zemtsov         }
621a633ee6eSEugene Zemtsov       }
622a633ee6eSEugene Zemtsov 
623a633ee6eSEugene Zemtsov       // Type declared inside a function 'func()::Type'
624a633ee6eSEugene Zemtsov       if (state != State::AfterIdentifier && state != State::AfterTemplate &&
625a633ee6eSEugene Zemtsov           state != State::AfterOperator) {
626a633ee6eSEugene Zemtsov         continue_parsing = false;
627a633ee6eSEugene Zemtsov         break;
628a633ee6eSEugene Zemtsov       }
629a633ee6eSEugene Zemtsov       Bookmark l_paren_position = SetBookmark();
630a633ee6eSEugene Zemtsov       // Consume the '(' ... ') [const]'.
631a633ee6eSEugene Zemtsov       if (!ConsumeArguments()) {
632a633ee6eSEugene Zemtsov         continue_parsing = false;
633a633ee6eSEugene Zemtsov         break;
634a633ee6eSEugene Zemtsov       }
635a633ee6eSEugene Zemtsov       SkipFunctionQualifiers();
636a633ee6eSEugene Zemtsov 
637a633ee6eSEugene Zemtsov       // Consume '::'
638a633ee6eSEugene Zemtsov       size_t coloncolon_position = GetCurrentPosition();
639a633ee6eSEugene Zemtsov       if (!ConsumeToken(tok::coloncolon)) {
640a633ee6eSEugene Zemtsov         continue_parsing = false;
641a633ee6eSEugene Zemtsov         break;
642a633ee6eSEugene Zemtsov       }
643a633ee6eSEugene Zemtsov       l_paren_position.Remove();
644a633ee6eSEugene Zemtsov       last_coloncolon_position = coloncolon_position;
645a633ee6eSEugene Zemtsov       state = State::AfterTwoColons;
646a633ee6eSEugene Zemtsov       break;
647a633ee6eSEugene Zemtsov     }
648055e65f0SJim Ingham     case tok::l_brace:
649055e65f0SJim Ingham       if (state == State::Beginning || state == State::AfterTwoColons) {
650055e65f0SJim Ingham         if (ConsumeLambda()) {
651055e65f0SJim Ingham           state = State::AfterIdentifier;
652055e65f0SJim Ingham           break;
653055e65f0SJim Ingham         }
654055e65f0SJim Ingham       }
655055e65f0SJim Ingham       continue_parsing = false;
656055e65f0SJim Ingham       break;
657a633ee6eSEugene Zemtsov     case tok::coloncolon: // Type nesting delimiter.
658a633ee6eSEugene Zemtsov       if (state != State::Beginning && state != State::AfterIdentifier &&
659a633ee6eSEugene Zemtsov           state != State::AfterTemplate) {
660a633ee6eSEugene Zemtsov         continue_parsing = false;
661a633ee6eSEugene Zemtsov         break;
662a633ee6eSEugene Zemtsov       }
663a633ee6eSEugene Zemtsov       last_coloncolon_position = GetCurrentPosition();
664a633ee6eSEugene Zemtsov       Advance();
665a633ee6eSEugene Zemtsov       state = State::AfterTwoColons;
666a633ee6eSEugene Zemtsov       break;
667a633ee6eSEugene Zemtsov     case tok::less: // Template brackets.
668a633ee6eSEugene Zemtsov       if (state != State::AfterIdentifier && state != State::AfterOperator) {
669a633ee6eSEugene Zemtsov         continue_parsing = false;
670a633ee6eSEugene Zemtsov         break;
671a633ee6eSEugene Zemtsov       }
672a633ee6eSEugene Zemtsov       if (!ConsumeTemplateArgs()) {
673a633ee6eSEugene Zemtsov         continue_parsing = false;
674a633ee6eSEugene Zemtsov         break;
675a633ee6eSEugene Zemtsov       }
676a633ee6eSEugene Zemtsov       state = State::AfterTemplate;
677a633ee6eSEugene Zemtsov       break;
678a633ee6eSEugene Zemtsov     case tok::kw_operator: // C++ operator overloading.
679a633ee6eSEugene Zemtsov       if (state != State::Beginning && state != State::AfterTwoColons) {
680a633ee6eSEugene Zemtsov         continue_parsing = false;
681a633ee6eSEugene Zemtsov         break;
682a633ee6eSEugene Zemtsov       }
683a633ee6eSEugene Zemtsov       if (!ConsumeOperator()) {
684a633ee6eSEugene Zemtsov         continue_parsing = false;
685a633ee6eSEugene Zemtsov         break;
686a633ee6eSEugene Zemtsov       }
687a633ee6eSEugene Zemtsov       state = State::AfterOperator;
688a633ee6eSEugene Zemtsov       break;
689a633ee6eSEugene Zemtsov     case tok::tilde: // Destructor.
690a633ee6eSEugene Zemtsov       if (state != State::Beginning && state != State::AfterTwoColons) {
691a633ee6eSEugene Zemtsov         continue_parsing = false;
692a633ee6eSEugene Zemtsov         break;
693a633ee6eSEugene Zemtsov       }
694a633ee6eSEugene Zemtsov       Advance();
695a633ee6eSEugene Zemtsov       if (ConsumeToken(tok::raw_identifier)) {
696a633ee6eSEugene Zemtsov         state = State::AfterIdentifier;
697a633ee6eSEugene Zemtsov       } else {
698a633ee6eSEugene Zemtsov         TakeBack();
699a633ee6eSEugene Zemtsov         continue_parsing = false;
700a633ee6eSEugene Zemtsov       }
701a633ee6eSEugene Zemtsov       break;
702a633ee6eSEugene Zemtsov     default:
703a633ee6eSEugene Zemtsov       continue_parsing = false;
704a633ee6eSEugene Zemtsov       break;
705a633ee6eSEugene Zemtsov     }
706a633ee6eSEugene Zemtsov   }
707a633ee6eSEugene Zemtsov 
708a633ee6eSEugene Zemtsov   if (state == State::AfterIdentifier || state == State::AfterOperator ||
709a633ee6eSEugene Zemtsov       state == State::AfterTemplate) {
710a633ee6eSEugene Zemtsov     ParsedNameRanges result;
711a633ee6eSEugene Zemtsov     if (last_coloncolon_position) {
712f43886e7SFangrui Song       result.context_range =
713f43886e7SFangrui Song           Range(start_position.GetSavedPosition(), *last_coloncolon_position);
714a633ee6eSEugene Zemtsov       result.basename_range =
715f43886e7SFangrui Song           Range(*last_coloncolon_position + 1, GetCurrentPosition());
716a633ee6eSEugene Zemtsov     } else {
717a633ee6eSEugene Zemtsov       result.basename_range =
718a633ee6eSEugene Zemtsov           Range(start_position.GetSavedPosition(), GetCurrentPosition());
719a633ee6eSEugene Zemtsov     }
720a633ee6eSEugene Zemtsov     start_position.Remove();
721a633ee6eSEugene Zemtsov     return result;
722a633ee6eSEugene Zemtsov   } else {
723343523d0SKazu Hirata     return std::nullopt;
724a633ee6eSEugene Zemtsov   }
725a633ee6eSEugene Zemtsov }
726a633ee6eSEugene Zemtsov 
GetTextForRange(const Range & range)727a633ee6eSEugene Zemtsov llvm::StringRef CPlusPlusNameParser::GetTextForRange(const Range &range) {
728a633ee6eSEugene Zemtsov   if (range.empty())
729a633ee6eSEugene Zemtsov     return llvm::StringRef();
730a633ee6eSEugene Zemtsov   assert(range.begin_index < range.end_index);
731a633ee6eSEugene Zemtsov   assert(range.begin_index < m_tokens.size());
732a633ee6eSEugene Zemtsov   assert(range.end_index <= m_tokens.size());
733a633ee6eSEugene Zemtsov   clang::Token &first_token = m_tokens[range.begin_index];
734a633ee6eSEugene Zemtsov   clang::Token &last_token = m_tokens[range.end_index - 1];
735a633ee6eSEugene Zemtsov   clang::SourceLocation start_loc = first_token.getLocation();
736a633ee6eSEugene Zemtsov   clang::SourceLocation end_loc = last_token.getLocation();
737a633ee6eSEugene Zemtsov   unsigned start_pos = start_loc.getRawEncoding();
738a633ee6eSEugene Zemtsov   unsigned end_pos = end_loc.getRawEncoding() + last_token.getLength();
739a633ee6eSEugene Zemtsov   return m_text.take_front(end_pos).drop_front(start_pos);
740a633ee6eSEugene Zemtsov }
741a633ee6eSEugene Zemtsov 
GetLangOptions()742a633ee6eSEugene Zemtsov static const clang::LangOptions &GetLangOptions() {
743a633ee6eSEugene Zemtsov   static clang::LangOptions g_options;
744a633ee6eSEugene Zemtsov   static llvm::once_flag g_once_flag;
745a633ee6eSEugene Zemtsov   llvm::call_once(g_once_flag, []() {
746a633ee6eSEugene Zemtsov     g_options.LineComment = true;
747a633ee6eSEugene Zemtsov     g_options.C99 = true;
748a633ee6eSEugene Zemtsov     g_options.C11 = true;
749a633ee6eSEugene Zemtsov     g_options.CPlusPlus = true;
750a633ee6eSEugene Zemtsov     g_options.CPlusPlus11 = true;
751a633ee6eSEugene Zemtsov     g_options.CPlusPlus14 = true;
75205b618e3SAaron Ballman     g_options.CPlusPlus17 = true;
753*89cd0e8cSMichael Buch     g_options.CPlusPlus20 = true;
754a633ee6eSEugene Zemtsov   });
755a633ee6eSEugene Zemtsov   return g_options;
756a633ee6eSEugene Zemtsov }
757a633ee6eSEugene Zemtsov 
GetKeywordsMap()758a633ee6eSEugene Zemtsov static const llvm::StringMap<tok::TokenKind> &GetKeywordsMap() {
759a633ee6eSEugene Zemtsov   static llvm::StringMap<tok::TokenKind> g_map{
760a633ee6eSEugene Zemtsov #define KEYWORD(Name, Flags) {llvm::StringRef(#Name), tok::kw_##Name},
761a633ee6eSEugene Zemtsov #include "clang/Basic/TokenKinds.def"
762a633ee6eSEugene Zemtsov #undef KEYWORD
763a633ee6eSEugene Zemtsov   };
764a633ee6eSEugene Zemtsov   return g_map;
765a633ee6eSEugene Zemtsov }
766a633ee6eSEugene Zemtsov 
ExtractTokens()767a633ee6eSEugene Zemtsov void CPlusPlusNameParser::ExtractTokens() {
7684a585a3eSAdrian Prantl   if (m_text.empty())
7694a585a3eSAdrian Prantl     return;
770a633ee6eSEugene Zemtsov   clang::Lexer lexer(clang::SourceLocation(), GetLangOptions(), m_text.data(),
771a633ee6eSEugene Zemtsov                      m_text.data(), m_text.data() + m_text.size());
772a633ee6eSEugene Zemtsov   const auto &kw_map = GetKeywordsMap();
773a633ee6eSEugene Zemtsov   clang::Token token;
774a633ee6eSEugene Zemtsov   for (lexer.LexFromRawLexer(token); !token.is(clang::tok::eof);
775a633ee6eSEugene Zemtsov        lexer.LexFromRawLexer(token)) {
776a633ee6eSEugene Zemtsov     if (token.is(clang::tok::raw_identifier)) {
777a633ee6eSEugene Zemtsov       auto it = kw_map.find(token.getRawIdentifier());
778a633ee6eSEugene Zemtsov       if (it != kw_map.end()) {
779a633ee6eSEugene Zemtsov         token.setKind(it->getValue());
780a633ee6eSEugene Zemtsov       }
781a633ee6eSEugene Zemtsov     }
782a633ee6eSEugene Zemtsov 
783a633ee6eSEugene Zemtsov     m_tokens.push_back(token);
784a633ee6eSEugene Zemtsov   }
785a633ee6eSEugene Zemtsov }
786