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 
MSVCUndecoratedNameParser(llvm::StringRef name)13 MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) {
14   // Global ctor and dtor are global functions.
15   if (name.contains("dynamic initializer for") ||
16       name.contains("dynamic atexit destructor for")) {
17     m_specifiers.emplace_back(name, 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(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(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(name.take_front(i - 1),
69                                 name.slice(last_base_start, i - 1));
70 
71       last_base_start = i + 1;
72       break;
73     default:
74       break;
75     }
76   }
77 
78   m_specifiers.emplace_back(name, name.drop_front(last_base_start));
79 }
80 
IsMSVCUndecoratedName(llvm::StringRef name)81 bool MSVCUndecoratedNameParser::IsMSVCUndecoratedName(llvm::StringRef name) {
82   return name.contains('`');
83 }
84 
ExtractContextAndIdentifier(llvm::StringRef name,llvm::StringRef & context,llvm::StringRef & identifier)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 
DropScope(llvm::StringRef name)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