180814287SRaphael Isemann //===-- MSVCUndecoratedNameParser.cpp -------------------------------------===//
2c1e530eeSAleksandr Urakov //
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
6c1e530eeSAleksandr Urakov //
7c1e530eeSAleksandr Urakov //===----------------------------------------------------------------------===//
8c1e530eeSAleksandr Urakov 
9c1e530eeSAleksandr Urakov #include "MSVCUndecoratedNameParser.h"
10c1e530eeSAleksandr Urakov 
11c1e530eeSAleksandr Urakov #include <stack>
12c1e530eeSAleksandr Urakov 
MSVCUndecoratedNameParser(llvm::StringRef name)13c1e530eeSAleksandr Urakov MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) {
14c1e530eeSAleksandr Urakov   std::size_t last_base_start = 0;
15c1e530eeSAleksandr Urakov 
16c1e530eeSAleksandr Urakov   std::stack<std::size_t> stack;
17c1e530eeSAleksandr Urakov   unsigned int open_angle_brackets = 0;
18c1e530eeSAleksandr Urakov   for (size_t i = 0; i < name.size(); i++) {
19c1e530eeSAleksandr Urakov     switch (name[i]) {
20c1e530eeSAleksandr Urakov     case '<':
21c1e530eeSAleksandr Urakov       // Do not treat `operator<' and `operator<<' as templates
22c1e530eeSAleksandr Urakov       // (sometimes they represented as `<' and `<<' in the name).
23c1e530eeSAleksandr Urakov       if (i == last_base_start ||
2498d9647dSBenjamin Kramer           (i == last_base_start + 1 && name[last_base_start] == '<'))
25c1e530eeSAleksandr Urakov         break;
26c1e530eeSAleksandr Urakov 
27c1e530eeSAleksandr Urakov       stack.push(i);
28c1e530eeSAleksandr Urakov       open_angle_brackets++;
29c1e530eeSAleksandr Urakov 
30c1e530eeSAleksandr Urakov       break;
31c1e530eeSAleksandr Urakov     case '>':
32c1e530eeSAleksandr Urakov       if (!stack.empty() && name[stack.top()] == '<') {
33c1e530eeSAleksandr Urakov         open_angle_brackets--;
34c1e530eeSAleksandr Urakov         stack.pop();
35c1e530eeSAleksandr Urakov       }
36c1e530eeSAleksandr Urakov 
37c1e530eeSAleksandr Urakov       break;
38c1e530eeSAleksandr Urakov     case '`':
39c1e530eeSAleksandr Urakov       stack.push(i);
40c1e530eeSAleksandr Urakov 
41c1e530eeSAleksandr Urakov       break;
42c1e530eeSAleksandr Urakov     case '\'':
43c1e530eeSAleksandr Urakov       while (!stack.empty()) {
44c1e530eeSAleksandr Urakov         std::size_t top = stack.top();
45c1e530eeSAleksandr Urakov         if (name[top] == '<')
46c1e530eeSAleksandr Urakov           open_angle_brackets--;
47c1e530eeSAleksandr Urakov 
48c1e530eeSAleksandr Urakov         stack.pop();
49c1e530eeSAleksandr Urakov 
50c1e530eeSAleksandr Urakov         if (name[top] == '`')
51c1e530eeSAleksandr Urakov           break;
52c1e530eeSAleksandr Urakov       }
53c1e530eeSAleksandr Urakov 
54c1e530eeSAleksandr Urakov       break;
55c1e530eeSAleksandr Urakov     case ':':
56c1e530eeSAleksandr Urakov       if (open_angle_brackets)
57c1e530eeSAleksandr Urakov         break;
58c1e530eeSAleksandr Urakov       if (i == 0 || name[i - 1] != ':')
59c1e530eeSAleksandr Urakov         break;
60c1e530eeSAleksandr Urakov 
61c1e530eeSAleksandr Urakov       m_specifiers.emplace_back(name.take_front(i - 1),
62c1e530eeSAleksandr Urakov                                 name.slice(last_base_start, i - 1));
63c1e530eeSAleksandr Urakov 
64c1e530eeSAleksandr Urakov       last_base_start = i + 1;
65c7f57aa8SEric Christopher       break;
66c1e530eeSAleksandr Urakov     default:
67c1e530eeSAleksandr Urakov       break;
68c1e530eeSAleksandr Urakov     }
69c1e530eeSAleksandr Urakov   }
70c1e530eeSAleksandr Urakov 
71c1e530eeSAleksandr Urakov   m_specifiers.emplace_back(name, name.drop_front(last_base_start));
72c1e530eeSAleksandr Urakov }
73c1e530eeSAleksandr Urakov 
IsMSVCUndecoratedName(llvm::StringRef name)74c1e530eeSAleksandr Urakov bool MSVCUndecoratedNameParser::IsMSVCUndecoratedName(llvm::StringRef name) {
75*4ba9d9c8SKazu Hirata   return name.contains('`');
76c1e530eeSAleksandr Urakov }
77c1e530eeSAleksandr Urakov 
ExtractContextAndIdentifier(llvm::StringRef name,llvm::StringRef & context,llvm::StringRef & identifier)78c1e530eeSAleksandr Urakov bool MSVCUndecoratedNameParser::ExtractContextAndIdentifier(
79c1e530eeSAleksandr Urakov     llvm::StringRef name, llvm::StringRef &context,
80c1e530eeSAleksandr Urakov     llvm::StringRef &identifier) {
81c1e530eeSAleksandr Urakov   MSVCUndecoratedNameParser parser(name);
82c1e530eeSAleksandr Urakov   llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
83c1e530eeSAleksandr Urakov 
84c1e530eeSAleksandr Urakov   std::size_t count = specs.size();
85c1e530eeSAleksandr Urakov   identifier = count > 0 ? specs[count - 1].GetBaseName() : "";
86c1e530eeSAleksandr Urakov   context = count > 1 ? specs[count - 2].GetFullName() : "";
87c1e530eeSAleksandr Urakov 
88c1e530eeSAleksandr Urakov   return count;
89c1e530eeSAleksandr Urakov }
90c1e530eeSAleksandr Urakov 
DropScope(llvm::StringRef name)91c1e530eeSAleksandr Urakov llvm::StringRef MSVCUndecoratedNameParser::DropScope(llvm::StringRef name) {
92c1e530eeSAleksandr Urakov   MSVCUndecoratedNameParser parser(name);
93c1e530eeSAleksandr Urakov   llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
94c1e530eeSAleksandr Urakov   if (specs.empty())
95c1e530eeSAleksandr Urakov     return "";
96c1e530eeSAleksandr Urakov 
97c1e530eeSAleksandr Urakov   return specs[specs.size() - 1].GetBaseName();
98c1e530eeSAleksandr Urakov }
99