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