Ejemplo n.º 1
0
/// For a mangled node that refers to an Objective-C class or protocol,
/// return the class or protocol name.
static 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();
}
Ejemplo n.º 2
0
bool
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
                                         Demangle::NodePointer node) {
  while (context) {
    if (node->getKind() == Demangle::Node::Kind::Type)
      node = node->getChild(0);
    
    // We can directly match symbolic references to the current context.
    if (node && node->getKind() == Demangle::Node::Kind::SymbolicReference) {
      if (equalContexts(context, reinterpret_cast<const ContextDescriptor *>(
                                     node->getIndex()))) {
        return true;
      }
    }

    switch (context->getKind()) {
    case ContextDescriptorKind::Module: {
      auto module = cast<ModuleContextDescriptor>(context);
      // Match to a mangled module name.
      if (node->getKind() != Demangle::Node::Kind::Module)
        return false;
      if (!node->getText().equals(module->Name.get()))
        return false;
      
      node = nullptr;
      break;
    }
    
    case ContextDescriptorKind::Extension: {
      auto extension = cast<ExtensionContextDescriptor>(context);
      
      // Check whether the extension context matches the mangled context.
      if (node->getKind() != Demangle::Node::Kind::Extension)
        return false;
      if (node->getNumChildren() < 2)
        return false;
      
      // Check that the context being extended matches as well.
      auto extendedContextNode = node->getChild(1);
      auto extendedContextMangledName = extension->getMangledExtendedContext();
      auto demangler = getDemanglerForRuntimeTypeResolution();
      auto extendedContextDemangled =
         demangler.demangleType(extendedContextMangledName);
      if (!extendedContextDemangled)
        return false;
      if (extendedContextDemangled->getKind() == Node::Kind::Type) {
        if (extendedContextDemangled->getNumChildren() < 1)
          return false;
        extendedContextDemangled = extendedContextDemangled->getChild(0);
      }
      extendedContextDemangled =
        stripGenericArgsFromContextNode(extendedContextDemangled, demangler);
      
      auto extendedDescriptorFromNode =
        _findNominalTypeDescriptor(extendedContextNode, demangler);
      auto extendedDescriptorFromDemangled =
        _findNominalTypeDescriptor(extendedContextDemangled, demangler);
      
      if (!extendedDescriptorFromNode || !extendedDescriptorFromDemangled ||
          !equalContexts(extendedDescriptorFromNode,
                         extendedDescriptorFromDemangled))
        return false;
      
      // Check whether the generic signature of the extension matches the
      // mangled constraints, if any.

      if (node->getNumChildren() >= 3) {
        // NB: If we ever support extensions with independent generic arguments
        // like `extension <T> Array where Element == Optional<T>`, we'd need
        // to look at the mangled context name to match up generic arguments.
        // That would probably need a new extension mangling form, though.
        
        // TODO
      }
      
      // The parent context of the extension should match in the mangling and
      // context descriptor.
      node = node->getChild(0);
      break;
    }
    
    default:
      if (auto type = llvm::dyn_cast<TypeContextDescriptor>(context)) {
        switch (node->getKind()) {
        // If the mangled name doesn't indicate a type kind, accept anything.
        // Otherwise, try to match them up.
        case Demangle::Node::Kind::OtherNominalType:
          break;
        case Demangle::Node::Kind::Structure:
          if (type->getKind() != ContextDescriptorKind::Struct
              && !type->getTypeContextDescriptorFlags().isCTag())
            return false;
          break;
        case Demangle::Node::Kind::Class:
          if (type->getKind() != ContextDescriptorKind::Class)
            return false;
          break;
        case Demangle::Node::Kind::Enum:
          if (type->getKind() != ContextDescriptorKind::Enum)
            return false;
          break;
        case Demangle::Node::Kind::TypeAlias:
          if (!type->getTypeContextDescriptorFlags().isCTypedef())
            return false;
          break;

        default:
          return false;
        }

        auto nameNode = node->getChild(1);
        
        // Declarations synthesized by the Clang importer get a small tag
        // string in addition to their name.
        if (nameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName){
          if (nameNode->getText() != type->getSynthesizedDeclRelatedEntityTag())
            return false;
          
          nameNode = nameNode->getChild(0);
        } else if (type->isSynthesizedRelatedEntity()) {
          return false;
        }
        
        // We should only match public or internal declarations with stable
        // names. The runtime metadata for private declarations would be
        // anonymized.
        if (nameNode->getKind() == Demangle::Node::Kind::Identifier) {
          if (nameNode->getText() != type->Name.get())
            return false;
          
          node = node->getChild(0);
          break;
        }
        
        return false;

      }
      
      // We don't know about this kind of context, or it doesn't have a stable
      // name we can match to.
      return false;
    }
    
    context = context->Parent;
  }
  
  // We should have reached the top of the node tree at the same time we reached
  // the top of the context tree.
  if (node)
    return false;
  
  return true;
}
Ejemplo n.º 3
0
bool
swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
                                         Demangle::NodePointer node) {
  while (context) {
    if (node->getKind() == Demangle::Node::Kind::Type)
      node = node->getChild(0);
    
    // We can directly match symbolic references to the current context.
    if (node && node->getKind() == Demangle::Node::Kind::SymbolicReference) {
      if (equalContexts(context, reinterpret_cast<const ContextDescriptor *>(
                                     node->getIndex()))) {
        return true;
      }
    }

    switch (context->getKind()) {
    case ContextDescriptorKind::Module: {
      auto module = cast<ModuleContextDescriptor>(context);
      // Match to a mangled module name.
      if (node->getKind() != Demangle::Node::Kind::Module)
        return false;
      if (!node->getText().equals(module->Name.get()))
        return false;
      
      node = nullptr;
      break;
    }
    
    case ContextDescriptorKind::Extension: {
      auto extension = cast<ExtensionContextDescriptor>(context);
      
      // Check whether the extension context matches the mangled context.
      if (node->getKind() != Demangle::Node::Kind::Extension)
        return false;
      if (node->getNumChildren() < 2)
        return false;
      
      // Check that the context being extended matches as well.
      auto extendedContextNode = node->getChild(1);
      auto extendedContextMangledName = extension->getMangledExtendedContext();
      auto demangler = getDemanglerForRuntimeTypeResolution();
      auto extendedContextDemangled =
         demangler.demangleType(extendedContextMangledName);
      if (!extendedContextDemangled)
        return false;
      if (extendedContextDemangled->getKind() == Node::Kind::Type) {
        if (extendedContextDemangled->getNumChildren() < 1)
          return false;
        extendedContextDemangled = extendedContextDemangled->getChild(0);
      }
      extendedContextDemangled =
        stripGenericArgsFromContextNode(extendedContextDemangled, demangler);
      
      auto extendedDescriptorFromNode =
        _findNominalTypeDescriptor(extendedContextNode, demangler);
      auto extendedDescriptorFromDemangled =
        _findNominalTypeDescriptor(extendedContextDemangled, demangler);

      // Determine whether the contexts match.
      bool contextsMatch =
        extendedDescriptorFromNode && extendedDescriptorFromDemangled &&
        equalContexts(extendedDescriptorFromNode,
                      extendedDescriptorFromDemangled);
      
#if SWIFT_OBJC_INTEROP
      if (!contextsMatch &&
          (!extendedDescriptorFromNode || !extendedDescriptorFromDemangled) &&
          sameObjCTypeManglings(extendedContextNode,
                                extendedContextDemangled)) {
        contextsMatch = true;
      }
#endif

      if (!contextsMatch)
        return false;
      
      // Check whether the generic signature of the extension matches the
      // mangled constraints, if any.

      if (node->getNumChildren() >= 3) {
        // NB: If we ever support extensions with independent generic arguments
        // like `extension <T> Array where Element == Optional<T>`, we'd need
        // to look at the mangled context name to match up generic arguments.
        // That would probably need a new extension mangling form, though.
        
        // TODO
      }
      
      // The parent context of the extension should match in the mangling and
      // context descriptor.
      node = node->getChild(0);
      break;
    }

    case ContextDescriptorKind::Protocol:
      // Match a protocol context.
      if (node->getKind() == Demangle::Node::Kind::Protocol) {
        auto proto = llvm::cast<ProtocolDescriptor>(context);
        auto nameNode = node->getChild(1);
        if (nameNode->getText() == proto->Name.get()) {
          node = node->getChild(0);
          break;
        }
      }
      return false;

    default:
      if (auto type = llvm::dyn_cast<TypeContextDescriptor>(context)) {
        Optional<ParsedTypeIdentity> _identity;
        auto getIdentity = [&]() -> const ParsedTypeIdentity & {
          if (_identity) return *_identity;
          _identity = ParsedTypeIdentity::parse(type);
          return *_identity;
        };

        switch (node->getKind()) {
        // If the mangled name doesn't indicate a type kind, accept anything.
        // Otherwise, try to match them up.
        case Demangle::Node::Kind::OtherNominalType:
          break;
        case Demangle::Node::Kind::Structure:
          // We allow non-structs to match Kind::Structure if they are
          // imported C tag types.  This is necessary because we artificially
          // make imported C tag types Kind::Structure.
          if (type->getKind() != ContextDescriptorKind::Struct &&
              !_isCImportedTagType(type, getIdentity()))
            return false;
          break;
        case Demangle::Node::Kind::Class:
          if (type->getKind() != ContextDescriptorKind::Class)
            return false;
          break;
        case Demangle::Node::Kind::Enum:
          if (type->getKind() != ContextDescriptorKind::Enum)
            return false;
          break;
        case Demangle::Node::Kind::TypeAlias:
          if (!getIdentity().isCTypedef())
            return false;
          break;

        default:
          return false;
        }

        auto nameNode = node->getChild(1);
        
        // Declarations synthesized by the Clang importer get a small tag
        // string in addition to their name.
        if (nameNode->getKind() == Demangle::Node::Kind::RelatedEntityDeclName){          
          if (!getIdentity().isRelatedEntity(nameNode->getText()))
            return false;
          
          nameNode = nameNode->getChild(0);
        } else if (getIdentity().isAnyRelatedEntity()) {
          return false;
        }
        
        // We should only match public or internal declarations with stable
        // names. The runtime metadata for private declarations would be
        // anonymized.
        if (nameNode->getKind() == Demangle::Node::Kind::Identifier) {
          if (nameNode->getText() != getIdentity().getABIName())
            return false;
          
          node = node->getChild(0);
          break;
        }
        
        return false;

      }

      // We don't know about this kind of context, or it doesn't have a stable
      // name we can match to.
      return false;
    }
    
    context = context->Parent;
  }
  
  // We should have reached the top of the node tree at the same time we reached
  // the top of the context tree.
  if (node)
    return false;
  
  return true;
}