reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
//===-- MSVCUndecoratedNameParser.cpp ---------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "MSVCUndecoratedNameParser.h"

#include <stack>

MSVCUndecoratedNameParser::MSVCUndecoratedNameParser(llvm::StringRef name) {
  std::size_t last_base_start = 0;

  std::stack<std::size_t> stack;
  unsigned int open_angle_brackets = 0;
  for (size_t i = 0; i < name.size(); i++) {
    switch (name[i]) {
    case '<':
      // Do not treat `operator<' and `operator<<' as templates
      // (sometimes they represented as `<' and `<<' in the name).
      if (i == last_base_start ||
          (i == last_base_start + 1 && name[last_base_start] == '<'))
        break;

      stack.push(i);
      open_angle_brackets++;

      break;
    case '>':
      if (!stack.empty() && name[stack.top()] == '<') {
        open_angle_brackets--;
        stack.pop();
      }

      break;
    case '`':
      stack.push(i);

      break;
    case '\'':
      while (!stack.empty()) {
        std::size_t top = stack.top();
        if (name[top] == '<')
          open_angle_brackets--;

        stack.pop();

        if (name[top] == '`')
          break;
      }

      break;
    case ':':
      if (open_angle_brackets)
        break;
      if (i == 0 || name[i - 1] != ':')
        break;

      m_specifiers.emplace_back(name.take_front(i - 1),
                                name.slice(last_base_start, i - 1));

      last_base_start = i + 1;
      break;
    default:
      break;
    }
  }

  m_specifiers.emplace_back(name, name.drop_front(last_base_start));
}

bool MSVCUndecoratedNameParser::IsMSVCUndecoratedName(llvm::StringRef name) {
  return name.find('`') != llvm::StringRef::npos;
}

bool MSVCUndecoratedNameParser::ExtractContextAndIdentifier(
    llvm::StringRef name, llvm::StringRef &context,
    llvm::StringRef &identifier) {
  MSVCUndecoratedNameParser parser(name);
  llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();

  std::size_t count = specs.size();
  identifier = count > 0 ? specs[count - 1].GetBaseName() : "";
  context = count > 1 ? specs[count - 2].GetFullName() : "";

  return count;
}

llvm::StringRef MSVCUndecoratedNameParser::DropScope(llvm::StringRef name) {
  MSVCUndecoratedNameParser parser(name);
  llvm::ArrayRef<MSVCUndecoratedNameSpecifier> specs = parser.GetSpecifiers();
  if (specs.empty())
    return "";

  return specs[specs.size() - 1].GetBaseName();
}