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"
12a633ee6eSEugene Zemtsov #include "llvm/ADT/StringMap.h"
13a633ee6eSEugene Zemtsov #include "llvm/Support/Threading.h"
14a633ee6eSEugene Zemtsov
15a633ee6eSEugene Zemtsov using namespace lldb;
16a633ee6eSEugene Zemtsov using namespace lldb_private;
17a633ee6eSEugene Zemtsov using llvm::Optional;
18a633ee6eSEugene Zemtsov using llvm::None;
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()23a633ee6eSEugene Zemtsov Optional<ParsedFunction> CPlusPlusNameParser::ParseAsFunctionDefinition() {
24a633ee6eSEugene Zemtsov m_next_token_index = 0;
25a633ee6eSEugene Zemtsov Optional<ParsedFunction> result(None);
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())
46a633ee6eSEugene Zemtsov return None;
47a633ee6eSEugene Zemtsov return result;
48a633ee6eSEugene Zemtsov }
49a633ee6eSEugene Zemtsov
ParseAsFullName()50a633ee6eSEugene Zemtsov Optional<ParsedName> CPlusPlusNameParser::ParseAsFullName() {
51a633ee6eSEugene Zemtsov m_next_token_index = 0;
52a633ee6eSEugene Zemtsov Optional<ParsedNameRanges> name_ranges = ParseFullNameImpl();
53a633ee6eSEugene Zemtsov if (!name_ranges)
54a633ee6eSEugene Zemtsov return None;
55a633ee6eSEugene Zemtsov if (HasMoreTokens())
56a633ee6eSEugene Zemtsov return None;
57a633ee6eSEugene Zemtsov ParsedName result;
58*5cff5142SKazu Hirata result.basename = GetTextForRange(name_ranges.value().basename_range);
59*5cff5142SKazu Hirata result.context = GetTextForRange(name_ranges.value().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
104a633ee6eSEugene Zemtsov Optional<ParsedFunction>
ParseFunctionImpl(bool expect_return_type)105a633ee6eSEugene Zemtsov CPlusPlusNameParser::ParseFunctionImpl(bool expect_return_type) {
106a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
107a633ee6eSEugene Zemtsov if (expect_return_type) {
108a633ee6eSEugene Zemtsov // Consume return type if it's expected.
109a633ee6eSEugene Zemtsov if (!ConsumeTypename())
110a633ee6eSEugene Zemtsov return None;
111a633ee6eSEugene Zemtsov }
112a633ee6eSEugene Zemtsov
113a633ee6eSEugene Zemtsov auto maybe_name = ParseFullNameImpl();
114a633ee6eSEugene Zemtsov if (!maybe_name) {
115a633ee6eSEugene Zemtsov return None;
116a633ee6eSEugene Zemtsov }
117a633ee6eSEugene Zemtsov
118a633ee6eSEugene Zemtsov size_t argument_start = GetCurrentPosition();
119a633ee6eSEugene Zemtsov if (!ConsumeArguments()) {
120a633ee6eSEugene Zemtsov return None;
121a633ee6eSEugene Zemtsov }
122a633ee6eSEugene Zemtsov
123a633ee6eSEugene Zemtsov size_t qualifiers_start = GetCurrentPosition();
124a633ee6eSEugene Zemtsov SkipFunctionQualifiers();
125a633ee6eSEugene Zemtsov size_t end_position = GetCurrentPosition();
126a633ee6eSEugene Zemtsov
127a633ee6eSEugene Zemtsov ParsedFunction result;
128*5cff5142SKazu Hirata result.name.basename = GetTextForRange(maybe_name.value().basename_range);
129*5cff5142SKazu Hirata result.name.context = GetTextForRange(maybe_name.value().context_range);
130a633ee6eSEugene Zemtsov result.arguments = GetTextForRange(Range(argument_start, qualifiers_start));
131a633ee6eSEugene Zemtsov result.qualifiers = GetTextForRange(Range(qualifiers_start, end_position));
132a633ee6eSEugene Zemtsov start_position.Remove();
133a633ee6eSEugene Zemtsov return result;
134a633ee6eSEugene Zemtsov }
135a633ee6eSEugene Zemtsov
136a633ee6eSEugene Zemtsov Optional<ParsedFunction>
ParseFuncPtr(bool expect_return_type)137a633ee6eSEugene Zemtsov CPlusPlusNameParser::ParseFuncPtr(bool expect_return_type) {
138a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
139a633ee6eSEugene Zemtsov if (expect_return_type) {
140a633ee6eSEugene Zemtsov // Consume return type.
141a633ee6eSEugene Zemtsov if (!ConsumeTypename())
142a633ee6eSEugene Zemtsov return None;
143a633ee6eSEugene Zemtsov }
144a633ee6eSEugene Zemtsov
145a633ee6eSEugene Zemtsov if (!ConsumeToken(tok::l_paren))
146a633ee6eSEugene Zemtsov return None;
147a633ee6eSEugene Zemtsov if (!ConsumePtrsAndRefs())
148a633ee6eSEugene Zemtsov return None;
149a633ee6eSEugene Zemtsov
150a633ee6eSEugene Zemtsov {
151a633ee6eSEugene Zemtsov Bookmark before_inner_function_pos = SetBookmark();
152a633ee6eSEugene Zemtsov auto maybe_inner_function_name = ParseFunctionImpl(false);
153a633ee6eSEugene Zemtsov if (maybe_inner_function_name)
154a633ee6eSEugene Zemtsov if (ConsumeToken(tok::r_paren))
155a633ee6eSEugene Zemtsov if (ConsumeArguments()) {
156a633ee6eSEugene Zemtsov SkipFunctionQualifiers();
157a633ee6eSEugene Zemtsov start_position.Remove();
158a633ee6eSEugene Zemtsov before_inner_function_pos.Remove();
159a633ee6eSEugene Zemtsov return maybe_inner_function_name;
160a633ee6eSEugene Zemtsov }
161a633ee6eSEugene Zemtsov }
162a633ee6eSEugene Zemtsov
163a633ee6eSEugene Zemtsov auto maybe_inner_function_ptr_name = ParseFuncPtr(false);
164a633ee6eSEugene Zemtsov if (maybe_inner_function_ptr_name)
165a633ee6eSEugene Zemtsov if (ConsumeToken(tok::r_paren))
166a633ee6eSEugene Zemtsov if (ConsumeArguments()) {
167a633ee6eSEugene Zemtsov SkipFunctionQualifiers();
168a633ee6eSEugene Zemtsov start_position.Remove();
169a633ee6eSEugene Zemtsov return maybe_inner_function_ptr_name;
170a633ee6eSEugene Zemtsov }
171a633ee6eSEugene Zemtsov return None;
172a633ee6eSEugene Zemtsov }
173a633ee6eSEugene Zemtsov
ConsumeArguments()174a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeArguments() {
175a633ee6eSEugene Zemtsov return ConsumeBrackets(tok::l_paren, tok::r_paren);
176a633ee6eSEugene Zemtsov }
177a633ee6eSEugene Zemtsov
ConsumeTemplateArgs()178a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeTemplateArgs() {
179a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
180a633ee6eSEugene Zemtsov if (!HasMoreTokens() || Peek().getKind() != tok::less)
181a633ee6eSEugene Zemtsov return false;
182a633ee6eSEugene Zemtsov Advance();
183a633ee6eSEugene Zemtsov
184a633ee6eSEugene Zemtsov // Consuming template arguments is a bit trickier than consuming function
18505097246SAdrian Prantl // arguments, because '<' '>' brackets are not always trivially balanced. In
18605097246SAdrian Prantl // some rare cases tokens '<' and '>' can appear inside template arguments as
18705097246SAdrian Prantl // arithmetic or shift operators not as template brackets. Examples:
18805097246SAdrian Prantl // std::enable_if<(10u)<(64), bool>
189a633ee6eSEugene Zemtsov // f<A<operator<(X,Y)::Subclass>>
19005097246SAdrian Prantl // Good thing that compiler makes sure that really ambiguous cases of '>'
19105097246SAdrian Prantl // usage should be enclosed within '()' brackets.
192a633ee6eSEugene Zemtsov int template_counter = 1;
193a633ee6eSEugene Zemtsov bool can_open_template = false;
194a633ee6eSEugene Zemtsov while (HasMoreTokens() && template_counter > 0) {
195a633ee6eSEugene Zemtsov tok::TokenKind kind = Peek().getKind();
196a633ee6eSEugene Zemtsov switch (kind) {
197a633ee6eSEugene Zemtsov case tok::greatergreater:
198a633ee6eSEugene Zemtsov template_counter -= 2;
199a633ee6eSEugene Zemtsov can_open_template = false;
200a633ee6eSEugene Zemtsov Advance();
201a633ee6eSEugene Zemtsov break;
202a633ee6eSEugene Zemtsov case tok::greater:
203a633ee6eSEugene Zemtsov --template_counter;
204a633ee6eSEugene Zemtsov can_open_template = false;
205a633ee6eSEugene Zemtsov Advance();
206a633ee6eSEugene Zemtsov break;
207a633ee6eSEugene Zemtsov case tok::less:
208a633ee6eSEugene Zemtsov // '<' is an attempt to open a subteamplte
209a633ee6eSEugene Zemtsov // check if parser is at the point where it's actually possible,
21005097246SAdrian Prantl // otherwise it's just a part of an expression like 'sizeof(T)<(10)'. No
21105097246SAdrian Prantl // need to do the same for '>' because compiler actually makes sure that
21205097246SAdrian Prantl // '>' always surrounded by brackets to avoid ambiguity.
213a633ee6eSEugene Zemtsov if (can_open_template)
214a633ee6eSEugene Zemtsov ++template_counter;
215a633ee6eSEugene Zemtsov can_open_template = false;
216a633ee6eSEugene Zemtsov Advance();
217a633ee6eSEugene Zemtsov break;
218a633ee6eSEugene Zemtsov case tok::kw_operator: // C++ operator overloading.
219a633ee6eSEugene Zemtsov if (!ConsumeOperator())
220a633ee6eSEugene Zemtsov return false;
221a633ee6eSEugene Zemtsov can_open_template = true;
222a633ee6eSEugene Zemtsov break;
223a633ee6eSEugene Zemtsov case tok::raw_identifier:
224a633ee6eSEugene Zemtsov can_open_template = true;
225a633ee6eSEugene Zemtsov Advance();
226a633ee6eSEugene Zemtsov break;
227a633ee6eSEugene Zemtsov case tok::l_square:
228a633ee6eSEugene Zemtsov if (!ConsumeBrackets(tok::l_square, tok::r_square))
229a633ee6eSEugene Zemtsov return false;
230a633ee6eSEugene Zemtsov can_open_template = false;
231a633ee6eSEugene Zemtsov break;
232a633ee6eSEugene Zemtsov case tok::l_paren:
233a633ee6eSEugene Zemtsov if (!ConsumeArguments())
234a633ee6eSEugene Zemtsov return false;
235a633ee6eSEugene Zemtsov can_open_template = false;
236a633ee6eSEugene Zemtsov break;
237a633ee6eSEugene Zemtsov default:
238a633ee6eSEugene Zemtsov can_open_template = false;
239a633ee6eSEugene Zemtsov Advance();
240a633ee6eSEugene Zemtsov break;
241a633ee6eSEugene Zemtsov }
242a633ee6eSEugene Zemtsov }
243a633ee6eSEugene Zemtsov
2449e916e5eSEugene Zemtsov if (template_counter != 0) {
245a633ee6eSEugene Zemtsov return false;
246a633ee6eSEugene Zemtsov }
247a633ee6eSEugene Zemtsov start_position.Remove();
248a633ee6eSEugene Zemtsov return true;
249a633ee6eSEugene Zemtsov }
250a633ee6eSEugene Zemtsov
ConsumeAnonymousNamespace()251a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeAnonymousNamespace() {
252a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
253a633ee6eSEugene Zemtsov if (!ConsumeToken(tok::l_paren)) {
254a633ee6eSEugene Zemtsov return false;
255a633ee6eSEugene Zemtsov }
256a633ee6eSEugene Zemtsov constexpr llvm::StringLiteral g_anonymous("anonymous");
257a633ee6eSEugene Zemtsov if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
258a633ee6eSEugene Zemtsov Peek().getRawIdentifier() == g_anonymous) {
259a633ee6eSEugene Zemtsov Advance();
260a633ee6eSEugene Zemtsov } else {
261a633ee6eSEugene Zemtsov return false;
262a633ee6eSEugene Zemtsov }
263a633ee6eSEugene Zemtsov
264a633ee6eSEugene Zemtsov if (!ConsumeToken(tok::kw_namespace)) {
265a633ee6eSEugene Zemtsov return false;
266a633ee6eSEugene Zemtsov }
267a633ee6eSEugene Zemtsov
268a633ee6eSEugene Zemtsov if (!ConsumeToken(tok::r_paren)) {
269a633ee6eSEugene Zemtsov return false;
270a633ee6eSEugene Zemtsov }
271a633ee6eSEugene Zemtsov start_position.Remove();
272a633ee6eSEugene Zemtsov return true;
273a633ee6eSEugene Zemtsov }
274a633ee6eSEugene Zemtsov
ConsumeLambda()275055e65f0SJim Ingham bool CPlusPlusNameParser::ConsumeLambda() {
276055e65f0SJim Ingham Bookmark start_position = SetBookmark();
277055e65f0SJim Ingham if (!ConsumeToken(tok::l_brace)) {
278055e65f0SJim Ingham return false;
279055e65f0SJim Ingham }
280055e65f0SJim Ingham constexpr llvm::StringLiteral g_lambda("lambda");
281055e65f0SJim Ingham if (HasMoreTokens() && Peek().is(tok::raw_identifier) &&
282055e65f0SJim Ingham Peek().getRawIdentifier() == g_lambda) {
283055e65f0SJim Ingham // Put the matched brace back so we can use ConsumeBrackets
284055e65f0SJim Ingham TakeBack();
285055e65f0SJim Ingham } else {
286055e65f0SJim Ingham return false;
287055e65f0SJim Ingham }
288055e65f0SJim Ingham
289055e65f0SJim Ingham if (!ConsumeBrackets(tok::l_brace, tok::r_brace)) {
290055e65f0SJim Ingham return false;
291055e65f0SJim Ingham }
292055e65f0SJim Ingham
293055e65f0SJim Ingham start_position.Remove();
294055e65f0SJim Ingham return true;
295055e65f0SJim Ingham }
296055e65f0SJim Ingham
ConsumeBrackets(tok::TokenKind left,tok::TokenKind right)297a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeBrackets(tok::TokenKind left,
298a633ee6eSEugene Zemtsov tok::TokenKind right) {
299a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
300a633ee6eSEugene Zemtsov if (!HasMoreTokens() || Peek().getKind() != left)
301a633ee6eSEugene Zemtsov return false;
302a633ee6eSEugene Zemtsov Advance();
303a633ee6eSEugene Zemtsov
304a633ee6eSEugene Zemtsov int counter = 1;
305a633ee6eSEugene Zemtsov while (HasMoreTokens() && counter > 0) {
306a633ee6eSEugene Zemtsov tok::TokenKind kind = Peek().getKind();
307a633ee6eSEugene Zemtsov if (kind == right)
308a633ee6eSEugene Zemtsov --counter;
309a633ee6eSEugene Zemtsov else if (kind == left)
310a633ee6eSEugene Zemtsov ++counter;
311a633ee6eSEugene Zemtsov Advance();
312a633ee6eSEugene Zemtsov }
313a633ee6eSEugene Zemtsov
314a633ee6eSEugene Zemtsov assert(counter >= 0);
315a633ee6eSEugene Zemtsov if (counter > 0) {
316a633ee6eSEugene Zemtsov return false;
317a633ee6eSEugene Zemtsov }
318a633ee6eSEugene Zemtsov start_position.Remove();
319a633ee6eSEugene Zemtsov return true;
320a633ee6eSEugene Zemtsov }
321a633ee6eSEugene Zemtsov
ConsumeOperator()322a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeOperator() {
323a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
324a633ee6eSEugene Zemtsov if (!ConsumeToken(tok::kw_operator))
325a633ee6eSEugene Zemtsov return false;
326a633ee6eSEugene Zemtsov
327a633ee6eSEugene Zemtsov if (!HasMoreTokens()) {
328a633ee6eSEugene Zemtsov return false;
329a633ee6eSEugene Zemtsov }
330a633ee6eSEugene Zemtsov
331a633ee6eSEugene Zemtsov const auto &token = Peek();
3328016d61eSshafik
3338016d61eSshafik // When clang generates debug info it adds template parameters to names.
3348016d61eSshafik // Since clang doesn't add a space between the name and the template parameter
3358016d61eSshafik // in some cases we are not generating valid C++ names e.g.:
3368016d61eSshafik //
3378016d61eSshafik // operator<<A::B>
3388016d61eSshafik //
3398016d61eSshafik // In some of these cases we will not parse them correctly. This fixes the
3408016d61eSshafik // issue by detecting this case and inserting tok::less in place of
3418016d61eSshafik // tok::lessless and returning successfully that we consumed the operator.
3428016d61eSshafik if (token.getKind() == tok::lessless) {
3438016d61eSshafik // Make sure we have more tokens before attempting to look ahead one more.
3448016d61eSshafik if (m_next_token_index + 1 < m_tokens.size()) {
3458016d61eSshafik // Look ahead two tokens.
3468016d61eSshafik clang::Token n_token = m_tokens[m_next_token_index + 1];
3478016d61eSshafik // If we find ( or < then this is indeed operator<< no need for fix.
3488016d61eSshafik if (n_token.getKind() != tok::l_paren && n_token.getKind() != tok::less) {
3498016d61eSshafik clang::Token tmp_tok;
3503806b380SBenjamin Kramer tmp_tok.startToken();
3518016d61eSshafik tmp_tok.setLength(1);
3528016d61eSshafik tmp_tok.setLocation(token.getLocation().getLocWithOffset(1));
3538016d61eSshafik tmp_tok.setKind(tok::less);
3548016d61eSshafik
3558016d61eSshafik m_tokens[m_next_token_index] = tmp_tok;
3568016d61eSshafik
3578016d61eSshafik start_position.Remove();
3588016d61eSshafik return true;
3598016d61eSshafik }
3608016d61eSshafik }
3618016d61eSshafik }
3628016d61eSshafik
363a633ee6eSEugene Zemtsov switch (token.getKind()) {
364a633ee6eSEugene Zemtsov case tok::kw_new:
365a633ee6eSEugene Zemtsov case tok::kw_delete:
366a633ee6eSEugene Zemtsov // This is 'new' or 'delete' operators.
367a633ee6eSEugene Zemtsov Advance();
368a633ee6eSEugene Zemtsov // Check for array new/delete.
369a633ee6eSEugene Zemtsov if (HasMoreTokens() && Peek().is(tok::l_square)) {
370a633ee6eSEugene Zemtsov // Consume the '[' and ']'.
371a633ee6eSEugene Zemtsov if (!ConsumeBrackets(tok::l_square, tok::r_square))
372a633ee6eSEugene Zemtsov return false;
373a633ee6eSEugene Zemtsov }
374a633ee6eSEugene Zemtsov break;
375a633ee6eSEugene Zemtsov
376a633ee6eSEugene Zemtsov #define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \
377a633ee6eSEugene Zemtsov case tok::Token: \
378a633ee6eSEugene Zemtsov Advance(); \
379a633ee6eSEugene Zemtsov break;
380a633ee6eSEugene Zemtsov #define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemberOnly)
381a633ee6eSEugene Zemtsov #include "clang/Basic/OperatorKinds.def"
382a633ee6eSEugene Zemtsov #undef OVERLOADED_OPERATOR
383a633ee6eSEugene Zemtsov #undef OVERLOADED_OPERATOR_MULTI
384a633ee6eSEugene Zemtsov
385a633ee6eSEugene Zemtsov case tok::l_paren:
386a633ee6eSEugene Zemtsov // Call operator consume '(' ... ')'.
387a633ee6eSEugene Zemtsov if (ConsumeBrackets(tok::l_paren, tok::r_paren))
388a633ee6eSEugene Zemtsov break;
389a633ee6eSEugene Zemtsov return false;
390a633ee6eSEugene Zemtsov
391a633ee6eSEugene Zemtsov case tok::l_square:
392a633ee6eSEugene Zemtsov // This is a [] operator.
393a633ee6eSEugene Zemtsov // Consume the '[' and ']'.
394a633ee6eSEugene Zemtsov if (ConsumeBrackets(tok::l_square, tok::r_square))
395a633ee6eSEugene Zemtsov break;
396a633ee6eSEugene Zemtsov return false;
397a633ee6eSEugene Zemtsov
398a633ee6eSEugene Zemtsov default:
399a633ee6eSEugene Zemtsov // This might be a cast operator.
400a633ee6eSEugene Zemtsov if (ConsumeTypename())
401a633ee6eSEugene Zemtsov break;
402a633ee6eSEugene Zemtsov return false;
403a633ee6eSEugene Zemtsov }
404a633ee6eSEugene Zemtsov start_position.Remove();
405a633ee6eSEugene Zemtsov return true;
406a633ee6eSEugene Zemtsov }
407a633ee6eSEugene Zemtsov
SkipTypeQualifiers()408a633ee6eSEugene Zemtsov void CPlusPlusNameParser::SkipTypeQualifiers() {
409a633ee6eSEugene Zemtsov while (ConsumeToken(tok::kw_const, tok::kw_volatile))
410a633ee6eSEugene Zemtsov ;
411a633ee6eSEugene Zemtsov }
412a633ee6eSEugene Zemtsov
SkipFunctionQualifiers()413a633ee6eSEugene Zemtsov void CPlusPlusNameParser::SkipFunctionQualifiers() {
414a633ee6eSEugene Zemtsov while (ConsumeToken(tok::kw_const, tok::kw_volatile, tok::amp, tok::ampamp))
415a633ee6eSEugene Zemtsov ;
416a633ee6eSEugene Zemtsov }
417a633ee6eSEugene Zemtsov
ConsumeBuiltinType()418a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeBuiltinType() {
419a633ee6eSEugene Zemtsov bool result = false;
420a633ee6eSEugene Zemtsov bool continue_parsing = true;
42105097246SAdrian Prantl // Built-in types can be made of a few keywords like 'unsigned long long
42205097246SAdrian Prantl // int'. This function consumes all built-in type keywords without checking
42305097246SAdrian Prantl // if they make sense like 'unsigned char void'.
424a633ee6eSEugene Zemtsov while (continue_parsing && HasMoreTokens()) {
425a633ee6eSEugene Zemtsov switch (Peek().getKind()) {
426a633ee6eSEugene Zemtsov case tok::kw_short:
427a633ee6eSEugene Zemtsov case tok::kw_long:
428a633ee6eSEugene Zemtsov case tok::kw___int64:
429a633ee6eSEugene Zemtsov case tok::kw___int128:
430a633ee6eSEugene Zemtsov case tok::kw_signed:
431a633ee6eSEugene Zemtsov case tok::kw_unsigned:
432a633ee6eSEugene Zemtsov case tok::kw_void:
433a633ee6eSEugene Zemtsov case tok::kw_char:
434a633ee6eSEugene Zemtsov case tok::kw_int:
435a633ee6eSEugene Zemtsov case tok::kw_half:
436a633ee6eSEugene Zemtsov case tok::kw_float:
437a633ee6eSEugene Zemtsov case tok::kw_double:
438a633ee6eSEugene Zemtsov case tok::kw___float128:
439a633ee6eSEugene Zemtsov case tok::kw_wchar_t:
440a633ee6eSEugene Zemtsov case tok::kw_bool:
441a633ee6eSEugene Zemtsov case tok::kw_char16_t:
442a633ee6eSEugene Zemtsov case tok::kw_char32_t:
443a633ee6eSEugene Zemtsov result = true;
444a633ee6eSEugene Zemtsov Advance();
445a633ee6eSEugene Zemtsov break;
446a633ee6eSEugene Zemtsov default:
447a633ee6eSEugene Zemtsov continue_parsing = false;
448a633ee6eSEugene Zemtsov break;
449a633ee6eSEugene Zemtsov }
450a633ee6eSEugene Zemtsov }
451a633ee6eSEugene Zemtsov return result;
452a633ee6eSEugene Zemtsov }
453a633ee6eSEugene Zemtsov
SkipPtrsAndRefs()454a633ee6eSEugene Zemtsov void CPlusPlusNameParser::SkipPtrsAndRefs() {
455a633ee6eSEugene Zemtsov // Ignoring result.
456a633ee6eSEugene Zemtsov ConsumePtrsAndRefs();
457a633ee6eSEugene Zemtsov }
458a633ee6eSEugene Zemtsov
ConsumePtrsAndRefs()459a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumePtrsAndRefs() {
460a633ee6eSEugene Zemtsov bool found = false;
461a633ee6eSEugene Zemtsov SkipTypeQualifiers();
462a633ee6eSEugene Zemtsov while (ConsumeToken(tok::star, tok::amp, tok::ampamp, tok::kw_const,
463a633ee6eSEugene Zemtsov tok::kw_volatile)) {
464a633ee6eSEugene Zemtsov found = true;
465a633ee6eSEugene Zemtsov SkipTypeQualifiers();
466a633ee6eSEugene Zemtsov }
467a633ee6eSEugene Zemtsov return found;
468a633ee6eSEugene Zemtsov }
469a633ee6eSEugene Zemtsov
ConsumeDecltype()470a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeDecltype() {
471a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
472a633ee6eSEugene Zemtsov if (!ConsumeToken(tok::kw_decltype))
473a633ee6eSEugene Zemtsov return false;
474a633ee6eSEugene Zemtsov
475a633ee6eSEugene Zemtsov if (!ConsumeArguments())
476a633ee6eSEugene Zemtsov return false;
477a633ee6eSEugene Zemtsov
478a633ee6eSEugene Zemtsov start_position.Remove();
479a633ee6eSEugene Zemtsov return true;
480a633ee6eSEugene Zemtsov }
481a633ee6eSEugene Zemtsov
ConsumeTypename()482a633ee6eSEugene Zemtsov bool CPlusPlusNameParser::ConsumeTypename() {
483a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
484a633ee6eSEugene Zemtsov SkipTypeQualifiers();
485a633ee6eSEugene Zemtsov if (!ConsumeBuiltinType() && !ConsumeDecltype()) {
486a633ee6eSEugene Zemtsov if (!ParseFullNameImpl())
487a633ee6eSEugene Zemtsov return false;
488a633ee6eSEugene Zemtsov }
489a633ee6eSEugene Zemtsov SkipPtrsAndRefs();
490a633ee6eSEugene Zemtsov start_position.Remove();
491a633ee6eSEugene Zemtsov return true;
492a633ee6eSEugene Zemtsov }
493a633ee6eSEugene Zemtsov
494a633ee6eSEugene Zemtsov Optional<CPlusPlusNameParser::ParsedNameRanges>
ParseFullNameImpl()495a633ee6eSEugene Zemtsov CPlusPlusNameParser::ParseFullNameImpl() {
496a633ee6eSEugene Zemtsov // Name parsing state machine.
497a633ee6eSEugene Zemtsov enum class State {
498a633ee6eSEugene Zemtsov Beginning, // start of the name
499a633ee6eSEugene Zemtsov AfterTwoColons, // right after ::
500a633ee6eSEugene Zemtsov AfterIdentifier, // right after alphanumerical identifier ([a-z0-9_]+)
501a633ee6eSEugene Zemtsov AfterTemplate, // right after template brackets (<something>)
502a633ee6eSEugene Zemtsov AfterOperator, // right after name of C++ operator
503a633ee6eSEugene Zemtsov };
504a633ee6eSEugene Zemtsov
505a633ee6eSEugene Zemtsov Bookmark start_position = SetBookmark();
506a633ee6eSEugene Zemtsov State state = State::Beginning;
507a633ee6eSEugene Zemtsov bool continue_parsing = true;
508a633ee6eSEugene Zemtsov Optional<size_t> last_coloncolon_position = None;
509a633ee6eSEugene Zemtsov
510a633ee6eSEugene Zemtsov while (continue_parsing && HasMoreTokens()) {
511a633ee6eSEugene Zemtsov const auto &token = Peek();
512a633ee6eSEugene Zemtsov switch (token.getKind()) {
513a633ee6eSEugene Zemtsov case tok::raw_identifier: // Just a name.
514a633ee6eSEugene Zemtsov if (state != State::Beginning && state != State::AfterTwoColons) {
515a633ee6eSEugene Zemtsov continue_parsing = false;
516a633ee6eSEugene Zemtsov break;
517a633ee6eSEugene Zemtsov }
518a633ee6eSEugene Zemtsov Advance();
519a633ee6eSEugene Zemtsov state = State::AfterIdentifier;
520a633ee6eSEugene Zemtsov break;
521a633ee6eSEugene Zemtsov case tok::l_paren: {
522a633ee6eSEugene Zemtsov if (state == State::Beginning || state == State::AfterTwoColons) {
523a633ee6eSEugene Zemtsov // (anonymous namespace)
524a633ee6eSEugene Zemtsov if (ConsumeAnonymousNamespace()) {
525a633ee6eSEugene Zemtsov state = State::AfterIdentifier;
526a633ee6eSEugene Zemtsov break;
527a633ee6eSEugene Zemtsov }
528a633ee6eSEugene Zemtsov }
529a633ee6eSEugene Zemtsov
530a633ee6eSEugene Zemtsov // Type declared inside a function 'func()::Type'
531a633ee6eSEugene Zemtsov if (state != State::AfterIdentifier && state != State::AfterTemplate &&
532a633ee6eSEugene Zemtsov state != State::AfterOperator) {
533a633ee6eSEugene Zemtsov continue_parsing = false;
534a633ee6eSEugene Zemtsov break;
535a633ee6eSEugene Zemtsov }
536a633ee6eSEugene Zemtsov Bookmark l_paren_position = SetBookmark();
537a633ee6eSEugene Zemtsov // Consume the '(' ... ') [const]'.
538a633ee6eSEugene Zemtsov if (!ConsumeArguments()) {
539a633ee6eSEugene Zemtsov continue_parsing = false;
540a633ee6eSEugene Zemtsov break;
541a633ee6eSEugene Zemtsov }
542a633ee6eSEugene Zemtsov SkipFunctionQualifiers();
543a633ee6eSEugene Zemtsov
544a633ee6eSEugene Zemtsov // Consume '::'
545a633ee6eSEugene Zemtsov size_t coloncolon_position = GetCurrentPosition();
546a633ee6eSEugene Zemtsov if (!ConsumeToken(tok::coloncolon)) {
547a633ee6eSEugene Zemtsov continue_parsing = false;
548a633ee6eSEugene Zemtsov break;
549a633ee6eSEugene Zemtsov }
550a633ee6eSEugene Zemtsov l_paren_position.Remove();
551a633ee6eSEugene Zemtsov last_coloncolon_position = coloncolon_position;
552a633ee6eSEugene Zemtsov state = State::AfterTwoColons;
553a633ee6eSEugene Zemtsov break;
554a633ee6eSEugene Zemtsov }
555055e65f0SJim Ingham case tok::l_brace:
556055e65f0SJim Ingham if (state == State::Beginning || state == State::AfterTwoColons) {
557055e65f0SJim Ingham if (ConsumeLambda()) {
558055e65f0SJim Ingham state = State::AfterIdentifier;
559055e65f0SJim Ingham break;
560055e65f0SJim Ingham }
561055e65f0SJim Ingham }
562055e65f0SJim Ingham continue_parsing = false;
563055e65f0SJim Ingham break;
564a633ee6eSEugene Zemtsov case tok::coloncolon: // Type nesting delimiter.
565a633ee6eSEugene Zemtsov if (state != State::Beginning && state != State::AfterIdentifier &&
566a633ee6eSEugene Zemtsov state != State::AfterTemplate) {
567a633ee6eSEugene Zemtsov continue_parsing = false;
568a633ee6eSEugene Zemtsov break;
569a633ee6eSEugene Zemtsov }
570a633ee6eSEugene Zemtsov last_coloncolon_position = GetCurrentPosition();
571a633ee6eSEugene Zemtsov Advance();
572a633ee6eSEugene Zemtsov state = State::AfterTwoColons;
573a633ee6eSEugene Zemtsov break;
574a633ee6eSEugene Zemtsov case tok::less: // Template brackets.
575a633ee6eSEugene Zemtsov if (state != State::AfterIdentifier && state != State::AfterOperator) {
576a633ee6eSEugene Zemtsov continue_parsing = false;
577a633ee6eSEugene Zemtsov break;
578a633ee6eSEugene Zemtsov }
579a633ee6eSEugene Zemtsov if (!ConsumeTemplateArgs()) {
580a633ee6eSEugene Zemtsov continue_parsing = false;
581a633ee6eSEugene Zemtsov break;
582a633ee6eSEugene Zemtsov }
583a633ee6eSEugene Zemtsov state = State::AfterTemplate;
584a633ee6eSEugene Zemtsov break;
585a633ee6eSEugene Zemtsov case tok::kw_operator: // C++ operator overloading.
586a633ee6eSEugene Zemtsov if (state != State::Beginning && state != State::AfterTwoColons) {
587a633ee6eSEugene Zemtsov continue_parsing = false;
588a633ee6eSEugene Zemtsov break;
589a633ee6eSEugene Zemtsov }
590a633ee6eSEugene Zemtsov if (!ConsumeOperator()) {
591a633ee6eSEugene Zemtsov continue_parsing = false;
592a633ee6eSEugene Zemtsov break;
593a633ee6eSEugene Zemtsov }
594a633ee6eSEugene Zemtsov state = State::AfterOperator;
595a633ee6eSEugene Zemtsov break;
596a633ee6eSEugene Zemtsov case tok::tilde: // Destructor.
597a633ee6eSEugene Zemtsov if (state != State::Beginning && state != State::AfterTwoColons) {
598a633ee6eSEugene Zemtsov continue_parsing = false;
599a633ee6eSEugene Zemtsov break;
600a633ee6eSEugene Zemtsov }
601a633ee6eSEugene Zemtsov Advance();
602a633ee6eSEugene Zemtsov if (ConsumeToken(tok::raw_identifier)) {
603a633ee6eSEugene Zemtsov state = State::AfterIdentifier;
604a633ee6eSEugene Zemtsov } else {
605a633ee6eSEugene Zemtsov TakeBack();
606a633ee6eSEugene Zemtsov continue_parsing = false;
607a633ee6eSEugene Zemtsov }
608a633ee6eSEugene Zemtsov break;
609a633ee6eSEugene Zemtsov default:
610a633ee6eSEugene Zemtsov continue_parsing = false;
611a633ee6eSEugene Zemtsov break;
612a633ee6eSEugene Zemtsov }
613a633ee6eSEugene Zemtsov }
614a633ee6eSEugene Zemtsov
615a633ee6eSEugene Zemtsov if (state == State::AfterIdentifier || state == State::AfterOperator ||
616a633ee6eSEugene Zemtsov state == State::AfterTemplate) {
617a633ee6eSEugene Zemtsov ParsedNameRanges result;
618a633ee6eSEugene Zemtsov if (last_coloncolon_position) {
6193b7c3a65SKazu Hirata result.context_range = Range(start_position.GetSavedPosition(),
620*5cff5142SKazu Hirata last_coloncolon_position.value());
621a633ee6eSEugene Zemtsov result.basename_range =
622*5cff5142SKazu Hirata Range(last_coloncolon_position.value() + 1, GetCurrentPosition());
623a633ee6eSEugene Zemtsov } else {
624a633ee6eSEugene Zemtsov result.basename_range =
625a633ee6eSEugene Zemtsov Range(start_position.GetSavedPosition(), GetCurrentPosition());
626a633ee6eSEugene Zemtsov }
627a633ee6eSEugene Zemtsov start_position.Remove();
628a633ee6eSEugene Zemtsov return result;
629a633ee6eSEugene Zemtsov } else {
630a633ee6eSEugene Zemtsov return None;
631a633ee6eSEugene Zemtsov }
632a633ee6eSEugene Zemtsov }
633a633ee6eSEugene Zemtsov
GetTextForRange(const Range & range)634a633ee6eSEugene Zemtsov llvm::StringRef CPlusPlusNameParser::GetTextForRange(const Range &range) {
635a633ee6eSEugene Zemtsov if (range.empty())
636a633ee6eSEugene Zemtsov return llvm::StringRef();
637a633ee6eSEugene Zemtsov assert(range.begin_index < range.end_index);
638a633ee6eSEugene Zemtsov assert(range.begin_index < m_tokens.size());
639a633ee6eSEugene Zemtsov assert(range.end_index <= m_tokens.size());
640a633ee6eSEugene Zemtsov clang::Token &first_token = m_tokens[range.begin_index];
641a633ee6eSEugene Zemtsov clang::Token &last_token = m_tokens[range.end_index - 1];
642a633ee6eSEugene Zemtsov clang::SourceLocation start_loc = first_token.getLocation();
643a633ee6eSEugene Zemtsov clang::SourceLocation end_loc = last_token.getLocation();
644a633ee6eSEugene Zemtsov unsigned start_pos = start_loc.getRawEncoding();
645a633ee6eSEugene Zemtsov unsigned end_pos = end_loc.getRawEncoding() + last_token.getLength();
646a633ee6eSEugene Zemtsov return m_text.take_front(end_pos).drop_front(start_pos);
647a633ee6eSEugene Zemtsov }
648a633ee6eSEugene Zemtsov
GetLangOptions()649a633ee6eSEugene Zemtsov static const clang::LangOptions &GetLangOptions() {
650a633ee6eSEugene Zemtsov static clang::LangOptions g_options;
651a633ee6eSEugene Zemtsov static llvm::once_flag g_once_flag;
652a633ee6eSEugene Zemtsov llvm::call_once(g_once_flag, []() {
653a633ee6eSEugene Zemtsov g_options.LineComment = true;
654a633ee6eSEugene Zemtsov g_options.C99 = true;
655a633ee6eSEugene Zemtsov g_options.C11 = true;
656a633ee6eSEugene Zemtsov g_options.CPlusPlus = true;
657a633ee6eSEugene Zemtsov g_options.CPlusPlus11 = true;
658a633ee6eSEugene Zemtsov g_options.CPlusPlus14 = true;
65905b618e3SAaron Ballman g_options.CPlusPlus17 = true;
660a633ee6eSEugene Zemtsov });
661a633ee6eSEugene Zemtsov return g_options;
662a633ee6eSEugene Zemtsov }
663a633ee6eSEugene Zemtsov
GetKeywordsMap()664a633ee6eSEugene Zemtsov static const llvm::StringMap<tok::TokenKind> &GetKeywordsMap() {
665a633ee6eSEugene Zemtsov static llvm::StringMap<tok::TokenKind> g_map{
666a633ee6eSEugene Zemtsov #define KEYWORD(Name, Flags) {llvm::StringRef(#Name), tok::kw_##Name},
667a633ee6eSEugene Zemtsov #include "clang/Basic/TokenKinds.def"
668a633ee6eSEugene Zemtsov #undef KEYWORD
669a633ee6eSEugene Zemtsov };
670a633ee6eSEugene Zemtsov return g_map;
671a633ee6eSEugene Zemtsov }
672a633ee6eSEugene Zemtsov
ExtractTokens()673a633ee6eSEugene Zemtsov void CPlusPlusNameParser::ExtractTokens() {
6744a585a3eSAdrian Prantl if (m_text.empty())
6754a585a3eSAdrian Prantl return;
676a633ee6eSEugene Zemtsov clang::Lexer lexer(clang::SourceLocation(), GetLangOptions(), m_text.data(),
677a633ee6eSEugene Zemtsov m_text.data(), m_text.data() + m_text.size());
678a633ee6eSEugene Zemtsov const auto &kw_map = GetKeywordsMap();
679a633ee6eSEugene Zemtsov clang::Token token;
680a633ee6eSEugene Zemtsov for (lexer.LexFromRawLexer(token); !token.is(clang::tok::eof);
681a633ee6eSEugene Zemtsov lexer.LexFromRawLexer(token)) {
682a633ee6eSEugene Zemtsov if (token.is(clang::tok::raw_identifier)) {
683a633ee6eSEugene Zemtsov auto it = kw_map.find(token.getRawIdentifier());
684a633ee6eSEugene Zemtsov if (it != kw_map.end()) {
685a633ee6eSEugene Zemtsov token.setKind(it->getValue());
686a633ee6eSEugene Zemtsov }
687a633ee6eSEugene Zemtsov }
688a633ee6eSEugene Zemtsov
689a633ee6eSEugene Zemtsov m_tokens.push_back(token);
690a633ee6eSEugene Zemtsov }
691a633ee6eSEugene Zemtsov }
692