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 | // Global ctor and dtor are global functions. |
15 | if (name.contains(Other: "dynamic initializer for") || |
16 | name.contains(Other: "dynamic atexit destructor for")) { |
17 | m_specifiers.emplace_back(args&: name, args&: name); |
18 | return; |
19 | } |
20 | |
21 | std::size_t last_base_start = 0; |
22 | |
23 | std::stack<std::size_t> stack; |
24 | unsigned int open_angle_brackets = 0; |
25 | for (size_t i = 0; i < name.size(); i++) { |
26 | switch (name[i]) { |
27 | case '<': |
28 | // Do not treat `operator<' and `operator<<' as templates |
29 | // (sometimes they represented as `<' and `<<' in the name). |
30 | if (i == last_base_start || |
31 | (i == last_base_start + 1 && name[last_base_start] == '<')) |
32 | break; |
33 | |
34 | stack.push(x: i); |
35 | open_angle_brackets++; |
36 | |
37 | break; |
38 | case '>': |
39 | if (!stack.empty() && name[stack.top()] == '<') { |
40 | open_angle_brackets--; |
41 | stack.pop(); |
42 | } |
43 | |
44 | break; |
45 | case '`': |
46 | stack.push(x: i); |
47 | |
48 | break; |
49 | case '\'': |
50 | while (!stack.empty()) { |
51 | std::size_t top = stack.top(); |
52 | if (name[top] == '<') |
53 | open_angle_brackets--; |
54 | |
55 | stack.pop(); |
56 | |
57 | if (name[top] == '`') |
58 | break; |
59 | } |
60 | |
61 | break; |
62 | case ':': |
63 | if (open_angle_brackets) |
64 | break; |
65 | if (i == 0 || name[i - 1] != ':') |
66 | break; |
67 | |
68 | m_specifiers.emplace_back(args: name.take_front(N: i - 1), |
69 | args: name.slice(Start: last_base_start, End: i - 1)); |
70 | |
71 | last_base_start = i + 1; |
72 | break; |
73 | default: |
74 | break; |
75 | } |
76 | } |
77 | |
78 | m_specifiers.emplace_back(args&: name, args: name.drop_front(N: last_base_start)); |
79 | } |
80 | |
81 | bool MSVCUndecoratedNameParser::IsMSVCUndecoratedName(llvm::StringRef name) { |
82 | return name.contains(C: '`'); |
83 | } |
84 | |
85 | bool MSVCUndecoratedNameParser::ExtractContextAndIdentifier( |
86 | llvm::StringRef name, llvm::StringRef &context, |
87 | llvm::StringRef &identifier) { |
88 | MSVCUndecoratedNameParser parser(name); |
89 | llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); |
90 | |
91 | std::size_t count = specs.size(); |
92 | identifier = count > 0 ? specs[count - 1].GetBaseName() : ""; |
93 | context = count > 1 ? specs[count - 2].GetFullName() : ""; |
94 | |
95 | return count; |
96 | } |
97 | |
98 | llvm::StringRef MSVCUndecoratedNameParser::DropScope(llvm::StringRef name) { |
99 | MSVCUndecoratedNameParser parser(name); |
100 | llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers(); |
101 | if (specs.empty()) |
102 | return ""; |
103 | |
104 | return specs[specs.size() - 1].GetBaseName(); |
105 | } |
106 |