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