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