<commit_before>//===--- TypeDecoder.h - Decode mangled type names --------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file provides facilities to \c TypeDecoder, which decodes a mangled
// type name into a structured type representation.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_DEMANGLING_TYPEDECODER_H
#define SWIFT_DEMANGLING_TYPEDECODER_H

#include "swift/ABI/MetadataValues.h"
#include "swift/Demangling/Demangler.h"
#include "swift/Basic/LLVM.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Strings.h"
#include <vector>

namespace swift {
namespace Demangle {

/// Strip generic arguments from the "spine" of a context node, producing a
/// bare context to be used in (e.g.) forming nominal type descriptors.
NodePointer stripGenericArgsFromContextNode(NodePointer node,
                                            NodeFactory &factory);

/// Describe a function parameter, parameterized on the type
/// representation.
template <typename BuiltType>
class FunctionParam {
  StringRef Label;
  BuiltType Type;
  ParameterFlags Flags;

  FunctionParam(StringRef label, BuiltType type, ParameterFlags flags)
      : Label(label), Type(type), Flags(flags) {}

public:
  explicit FunctionParam() {}

  FunctionParam(BuiltType type) : Type(type) {}

  StringRef getLabel() const { return Label; }
  BuiltType getType() const { return Type; }
  ParameterFlags getFlags() const { return Flags; }

  void setLabel(StringRef label) { Label = label; }
  void setType(BuiltType type) { Type = type; }

  void setVariadic() { Flags = Flags.withVariadic(true); }
  void setAutoClosure() { Flags = Flags.withAutoClosure(true); }
  void setValueOwnership(ValueOwnership ownership) {
    Flags = Flags.withValueOwnership(ownership);
  }
  void setFlags(ParameterFlags flags) { Flags = flags; };

  FunctionParam withLabel(StringRef label) const {
    return FunctionParam(label, Type, Flags);
  }

  FunctionParam withType(BuiltType type) const {
    return FunctionParam(Label, type, Flags);
  }

  FunctionParam withFlags(ParameterFlags flags) const {
    return FunctionParam(Label, Type, flags);
  }
};


#if SWIFT_OBJC_INTEROP
/// For a mangled node that refers to an Objective-C class or protocol,
/// return the class or protocol name.
static inline Optional<StringRef> getObjCClassOrProtocolName(
    const Demangle::NodePointer &node) {
  if (node->getKind() != Demangle::Node::Kind::Class &&
      node->getKind() != Demangle::Node::Kind::Protocol)
    return None;

  if (node->getNumChildren() != 2)
    return None;

  // Check whether we have the __ObjC module.
  auto moduleNode = node->getChild(0);
  if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
      moduleNode->getText() != MANGLING_MODULE_OBJC)
    return None;

  // Check whether we have an identifier.
  auto nameNode = node->getChild(1);
  if (nameNode->getKind() != Demangle::Node::Kind::Identifier)
    return None;

  return nameNode->getText();
}
#endif

/// Decode a mangled type to construct an abstract type, forming such
/// types by invoking a custom builder.
template <typename BuilderType>
class TypeDecoder {
  using BuiltType = typename BuilderType::BuiltType;
  using BuiltNominalTypeDecl = typename BuilderType::BuiltNominalTypeDecl;
  using BuiltProtocolDecl = typename BuilderType::BuiltProtocolDecl;
  using NodeKind = Demangle::Node::Kind;

  BuilderType &Builder;

 public:
  explicit TypeDecoder(BuilderType &Builder)
    : Builder(Builder) {}

  /// Given a demangle tree, attempt to turn it into a type.
  BuiltType decodeMangledType(const Demangle::NodePointer &Node) {
    if (!Node) return BuiltType();

    using NodeKind = Demangle::Node::Kind;
    switch (Node->getKind()) {
    case NodeKind::Global:
      if (Node->getNumChildren() < 1)
        return BuiltType();

      return decodeMangledType(Node->getChild(0));
    case NodeKind::TypeMangling:
      if (Node->getNumChildren() < 1)
        return BuiltType();

      return decodeMangledType(Node->getChild(0));
    case NodeKind::Type:
      if (Node->getNumChildren() < 1)
        return BuiltType();

      return decodeMangledType(Node->getChild(0));
    case NodeKind::Class:
    {
#if SWIFT_OBJC_INTEROP
      if (auto mangledName = getObjCClassOrProtocolName(Node))
        return Builder.createObjCClassType(mangledName->str());
#endif
      LLVM_FALLTHROUGH;
    }
    case NodeKind::Enum:
    case NodeKind::Structure:
    case NodeKind::TypeAlias: // This can show up for imported Clang decls.
    case NodeKind::TypeSymbolicReference:
    {
      BuiltNominalTypeDecl typeDecl = BuiltNominalTypeDecl();
      BuiltType parent = BuiltType();
      if (!decodeMangledNominalType(Node, typeDecl, parent))
        return BuiltType();

      return Builder.createNominalType(typeDecl, parent);
    }
    case NodeKind::BoundGenericClass:
    {
#if SWIFT_OBJC_INTEROP
      if (Node->getNumChildren() == 2) {
        auto ChildNode = Node->getChild(0);
        if (ChildNode->getKind() == NodeKind::Type &&
            ChildNode->getNumChildren() > 0)
          ChildNode = ChildNode->getChild(0);

        if (auto mangledName = getObjCClassOrProtocolName(ChildNode))
          return Builder.createObjCClassType(mangledName->str());
      }
#endif
      LLVM_FALLTHROUGH;
    }
    case NodeKind::BoundGenericEnum:
    case NodeKind::BoundGenericStructure:
    case NodeKind::BoundGenericOtherNominalType: {
      if (Node->getNumChildren() < 2)
        return BuiltType();

      BuiltNominalTypeDecl typeDecl = BuiltNominalTypeDecl();
      BuiltType parent = BuiltType();
      if (!decodeMangledNominalType(Node->getChild(0), typeDecl, parent))
        return BuiltType();

      std::vector<BuiltType> args;

      const auto &genericArgs = Node->getChild(1);
      assert(genericArgs->getKind() == NodeKind::TypeList);

      for (auto genericArg : *genericArgs) {
        auto paramType = decodeMangledType(genericArg);
        if (!paramType)
          return BuiltType();<commit_msg>[Runtime] Minor future-proofing for demangling bound generic ObjC classes.<commit_after>//===--- TypeDecoder.h - Decode mangled type names --------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file provides facilities to \c TypeDecoder, which decodes a mangled
// type name into a structured type representation.
//
//===----------------------------------------------------------------------===//

#ifndef SWIFT_DEMANGLING_TYPEDECODER_H
#define SWIFT_DEMANGLING_TYPEDECODER_H

#include "swift/ABI/MetadataValues.h"
#include "swift/Demangling/Demangler.h"
#include "swift/Basic/LLVM.h"
#include "swift/Runtime/Unreachable.h"
#include "swift/Strings.h"
#include <vector>

namespace swift {
namespace Demangle {

/// Strip generic arguments from the "spine" of a context node, producing a
/// bare context to be used in (e.g.) forming nominal type descriptors.
NodePointer stripGenericArgsFromContextNode(NodePointer node,
                                            NodeFactory &factory);

/// Describe a function parameter, parameterized on the type
/// representation.
template <typename BuiltType>
class FunctionParam {
  StringRef Label;
  BuiltType Type;
  ParameterFlags Flags;

  FunctionParam(StringRef label, BuiltType type, ParameterFlags flags)
      : Label(label), Type(type), Flags(flags) {}

public:
  explicit FunctionParam() {}

  FunctionParam(BuiltType type) : Type(type) {}

  StringRef getLabel() const { return Label; }
  BuiltType getType() const { return Type; }
  ParameterFlags getFlags() const { return Flags; }

  void setLabel(StringRef label) { Label = label; }
  void setType(BuiltType type) { Type = type; }

  void setVariadic() { Flags = Flags.withVariadic(true); }
  void setAutoClosure() { Flags = Flags.withAutoClosure(true); }
  void setValueOwnership(ValueOwnership ownership) {
    Flags = Flags.withValueOwnership(ownership);
  }
  void setFlags(ParameterFlags flags) { Flags = flags; };

  FunctionParam withLabel(StringRef label) const {
    return FunctionParam(label, Type, Flags);
  }

  FunctionParam withType(BuiltType type) const {
    return FunctionParam(Label, type, Flags);
  }

  FunctionParam withFlags(ParameterFlags flags) const {
    return FunctionParam(Label, Type, flags);
  }
};


#if SWIFT_OBJC_INTEROP
/// For a mangled node that refers to an Objective-C class or protocol,
/// return the class or protocol name.
static inline Optional<StringRef> getObjCClassOrProtocolName(
    const Demangle::NodePointer &node) {
  if (node->getKind() != Demangle::Node::Kind::Class &&
      node->getKind() != Demangle::Node::Kind::Protocol)
    return None;

  if (node->getNumChildren() != 2)
    return None;

  // Check whether we have the __ObjC module.
  auto moduleNode = node->getChild(0);
  if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
      moduleNode->getText() != MANGLING_MODULE_OBJC)
    return None;

  // Check whether we have an identifier.
  auto nameNode = node->getChild(1);
  if (nameNode->getKind() != Demangle::Node::Kind::Identifier)
    return None;

  return nameNode->getText();
}
#endif

/// Decode a mangled type to construct an abstract type, forming such
/// types by invoking a custom builder.
template <typename BuilderType>
class TypeDecoder {
  using BuiltType = typename BuilderType::BuiltType;
  using BuiltNominalTypeDecl = typename BuilderType::BuiltNominalTypeDecl;
  using BuiltProtocolDecl = typename BuilderType::BuiltProtocolDecl;
  using NodeKind = Demangle::Node::Kind;

  BuilderType &Builder;

 public:
  explicit TypeDecoder(BuilderType &Builder)
    : Builder(Builder) {}

  /// Given a demangle tree, attempt to turn it into a type.
  BuiltType decodeMangledType(const Demangle::NodePointer &Node) {
    if (!Node) return BuiltType();

    using NodeKind = Demangle::Node::Kind;
    switch (Node->getKind()) {
    case NodeKind::Global:
      if (Node->getNumChildren() < 1)
        return BuiltType();

      return decodeMangledType(Node->getChild(0));
    case NodeKind::TypeMangling:
      if (Node->getNumChildren() < 1)
        return BuiltType();

      return decodeMangledType(Node->getChild(0));
    case NodeKind::Type:
      if (Node->getNumChildren() < 1)
        return BuiltType();

      return decodeMangledType(Node->getChild(0));
    case NodeKind::Class:
    {
#if SWIFT_OBJC_INTEROP
      if (auto mangledName = getObjCClassOrProtocolName(Node))
        return Builder.createObjCClassType(mangledName->str());
#endif
      LLVM_FALLTHROUGH;
    }
    case NodeKind::Enum:
    case NodeKind::Structure:
    case NodeKind::TypeAlias: // This can show up for imported Clang decls.
    case NodeKind::TypeSymbolicReference:
    {
      BuiltNominalTypeDecl typeDecl = BuiltNominalTypeDecl();
      BuiltType parent = BuiltType();
      if (!decodeMangledNominalType(Node, typeDecl, parent))
        return BuiltType();

      return Builder.createNominalType(typeDecl, parent);
    }
    case NodeKind::BoundGenericClass:
    {
#if SWIFT_OBJC_INTEROP
      if (Node->getNumChildren() >= 2) {
        auto ChildNode = Node->getChild(0);
        if (ChildNode->getKind() == NodeKind::Type &&
            ChildNode->getNumChildren() > 0)
          ChildNode = ChildNode->getChild(0);

        if (auto mangledName = getObjCClassOrProtocolName(ChildNode))
          return Builder.createObjCClassType(mangledName->str());
      }
#endif
      LLVM_FALLTHROUGH;
    }
    case NodeKind::BoundGenericEnum:
    case NodeKind::BoundGenericStructure:
    case NodeKind::BoundGenericOtherNominalType: {
      if (Node->getNumChildren() < 2)
        return BuiltType();

      BuiltNominalTypeDecl typeDecl = BuiltNominalTypeDecl();
      BuiltType parent = BuiltType();
      if (!decodeMangledNominalType(Node->getChild(0), typeDecl, parent))
        return BuiltType();

      std::vector<BuiltType> args;

      const auto &genericArgs = Node->getChild(1);
      assert(genericArgs->getKind() == NodeKind::TypeList);

      for (auto genericArg : *genericArgs) {
        auto paramType = decodeMangledType(genericArg);
        if (!paramType)
          return BuiltType();
{'fraction_non_alphanumeric': 0.13615710435117442, 'fraction_numerical': 0.004004620716211013, 'mean_word_length': 3.3099900431463656, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 70, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7043793', 'n_tokens_mistral': 3804, 'n_tokens_neox': 3649, 'n_words': 1003}