static std::string
getMaterializeForSetCallbackName(ProtocolConformance *conformance,
                                 FuncDecl *requirement) {

  DeclContext *dc = requirement;
  ClosureExpr closure(/*patterns*/ nullptr,
                      /*throws*/ SourceLoc(),
                      /*arrow*/ SourceLoc(),
                      /*in*/ SourceLoc(),
                      /*result*/ TypeLoc(),
                      /*discriminator*/ 0,
                      /*context*/ requirement);
  closure.setType(TupleType::getEmpty(dc->getASTContext()));
  closure.getCaptureInfo().setGenericParamCaptures(true);

  Mangle::ASTMangler Mangler;
  std::string New;
  if (conformance) {
    // Concrete witness thunk for a conformance:
    //
    // Mangle this as if it were a conformance thunk for a closure
    // within the requirement.
    return Mangler.mangleClosureWitnessThunk(conformance, &closure);
  }
  // Default witness thunk or concrete implementation:
  //
  // Mangle this as if it were a closure within the requirement.
  return Mangler.mangleClosureEntity(&closure,
                                 Mangle::ASTMangler::SymbolKind::Default);
}
Example #2
0
SubclassScope SILDeclRef::getSubclassScope() const {
  if (!hasDecl())
    return SubclassScope::NotApplicable;

  // If this declaration is a function which goes into a vtable, then it's
  // symbol must be as visible as its class. Derived classes even have to put
  // all less visible methods of the base class into their vtables.

  auto *FD = dyn_cast<AbstractFunctionDecl>(getDecl());
  if (!FD)
    return SubclassScope::NotApplicable;

  DeclContext *context = FD->getDeclContext();

  // Methods from extensions don't go into vtables (yet).
  if (context->isExtensionContext())
    return SubclassScope::NotApplicable;

  // Various forms of thunks don't either.
  if (isThunk() || isForeign)
    return SubclassScope::NotApplicable;

  // Default arg generators only need to be visible in Swift 3.
  if (isDefaultArgGenerator() && !context->getASTContext().isSwiftVersion3())
    return SubclassScope::NotApplicable;

  auto *classType = context->getSelfClassDecl();
  if (!classType || classType->isFinal())
    return SubclassScope::NotApplicable;

  if (FD->isFinal())
    return SubclassScope::NotApplicable;

  assert(FD->getEffectiveAccess() <= classType->getEffectiveAccess() &&
         "class must be as visible as its members");

  switch (classType->getEffectiveAccess()) {
  case AccessLevel::Private:
  case AccessLevel::FilePrivate:
    return SubclassScope::NotApplicable;
  case AccessLevel::Internal:
  case AccessLevel::Public:
    return SubclassScope::Internal;
  case AccessLevel::Open:
    return SubclassScope::External;
  }

  llvm_unreachable("Unhandled access level in switch.");
}
bool ConformanceLookupTable::addProtocol(NominalTypeDecl *nominal,
                                         ProtocolDecl *protocol, SourceLoc loc,
                                         ConformanceSource source) {
  DeclContext *dc = source.getDeclContext();
  ASTContext &ctx = dc->getASTContext();

  // Determine the kind of conformance.
  ConformanceEntryKind kind = source.getKind();

  // If this entry is synthesized or implied, scan to determine
  // whether there are any explicit better conformances that make this
  // conformance trivially superseded (and, therefore, not worth
  // recording).
  auto &conformanceEntries = Conformances[protocol];
  if (kind == ConformanceEntryKind::Implied ||
      kind == ConformanceEntryKind::Synthesized) {
    for (const auto *existingEntry : conformanceEntries) {
      switch (existingEntry->getKind()) {
      case ConformanceEntryKind::Explicit:
      case ConformanceEntryKind::Inherited:
        return false;

      case ConformanceEntryKind::Implied:
        // An implied conformance is better than a synthesized one.
        // Ignore implied circular protocol inheritance
        if (kind == ConformanceEntryKind::Synthesized ||
            existingEntry->getProtocol() == protocol)
          return false;
        break;

      case ConformanceEntryKind::Synthesized:
        break;
      }
    }
  }

  /// Build the conformance entry (if it hasn't been built before).
  ConformanceEntry *entry = new (ctx) ConformanceEntry(loc, protocol, source);
  conformanceEntries.push_back(entry);

  // Record this as a conformance within the given declaration
  // context.
  AllConformances[dc].push_back(entry);

  return true;
}