Example #1
0
  void layout() override {
    PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD);
    auto type = NTD->getDeclaredType()->getCanonicalType();
    addTypeRef(NTD->getModuleContext(), type);

    if (NTD->hasClangNode() &&
        !isa<ClassDecl>(NTD) &&
        !isa<ProtocolDecl>(NTD))
      return;

    switch (NTD->getKind()) {
      case DeclKind::Class:
      case DeclKind::Struct:
        layoutRecord();
        break;

      case DeclKind::Enum:
        layoutEnum();
        break;

      case DeclKind::Protocol:
        layoutProtocol();
        break;

      default:
        llvm_unreachable("Not a nominal type");
        break;
    }
  }
Example #2
0
bool IRGenerator::canEmitWitnessTableLazily(SILWitnessTable *wt) {
  if (Opts.UseJIT)
    return false;

  // Regardless of the access level, if the witness table is shared it means
  // we can safely not emit it. Every other module which needs it will generate
  // its own shared copy of it.
  if (wt->getLinkage() == SILLinkage::Shared)
    return true;

  NominalTypeDecl *ConformingTy =
    wt->getConformingType()->getNominalOrBoundGenericNominal();

  switch (ConformingTy->getEffectiveAccess()) {
    case AccessLevel::Private:
    case AccessLevel::FilePrivate:
      return true;

    case AccessLevel::Internal:
      return PrimaryIGM->getSILModule().isWholeModule();

    default:
      return false;
  }
  llvm_unreachable("switch does not handle all cases");
}
Example #3
0
SmallVector<ProtocolDecl *, 2>
DeclContext::getLocalProtocols(
  ConformanceLookupKind lookupKind,
  SmallVectorImpl<ConformanceDiagnostic> *diagnostics,
  bool sorted) const
{
  SmallVector<ProtocolDecl *, 2> result;

  // Dig out the nominal type.
  NominalTypeDecl *nominal = getAsNominalTypeOrNominalTypeExtensionContext();
  if (!nominal)
    return result;

  // Update to record all potential conformances.
  nominal->prepareConformanceTable();
  nominal->ConformanceTable->lookupConformances(
    nominal,
    const_cast<DeclContext *>(this),
    getASTContext().getLazyResolver(),
    lookupKind,
    &result,
    nullptr,
    diagnostics);

  // Sort if required.
  if (sorted) {
    llvm::array_pod_sort(result.begin(), result.end(),
                         &ProtocolType::compareProtocols);
  }

  return result;
}
Example #4
0
static Type findBaseTypeForReplacingArchetype(const ValueDecl *VD, const Type Ty) {
  if (Ty.isNull())
    return Type();

  // Find the nominal type decl related to VD.
  auto TC = VD->getDeclContext()->getInnermostTypeContext();
  NominalTypeDecl *NTD = dyn_cast_or_null<NominalTypeDecl>(TC);
  if (!NTD) {
    ExtensionDecl *ED = dyn_cast_or_null<ExtensionDecl>(TC);
    if (ED) {
      if (auto T = ED->getExtendedType())
        NTD = T->getAnyNominal();
    }
  }
  if (!NTD)
    return Type();
  Type Result;

  // Walk the type tree to find the a sub-type who's convertible to the
  // found nominal.
  Ty.visit([&](Type T) {
    if (!Result && (T->getAnyNominal() == NTD ||
                    isConvertibleTo(T, NTD->getDeclaredType(),
                                    VD->getDeclContext()))) {
      Result = T;
    }
  });
  return Result;
}
Example #5
0
  void layoutRecord() {
    auto kind = FieldDescriptorKind::Struct;

    if (auto CD = dyn_cast<ClassDecl>(NTD)) {
      auto type = CD->getDeclaredType()->getCanonicalType();
      auto RC = getReferenceCountingForType(IGM, type);
      if (RC == ReferenceCounting::ObjC)
        kind = FieldDescriptorKind::ObjCClass;
      else
        kind = FieldDescriptorKind::Class;
    }

    B.addInt16(uint16_t(kind));
    B.addInt16(fieldRecordSize);

    // Imported classes don't need field descriptors
    if (NTD->hasClangNode() && isa<ClassDecl>(NTD)) {
      B.addInt32(0);
      return;
    }

    assert(!NTD->hasClangNode() || isa<StructDecl>(NTD));

    auto properties = NTD->getStoredProperties();
    B.addInt32(std::distance(properties.begin(), properties.end()));
    for (auto property : properties)
      addFieldDecl(property,
                   property->getInterfaceType()
                       ->getCanonicalType());
  }
Example #6
0
static void lookupDeclsFromProtocolsBeingConformedTo(
    Type BaseTy, VisibleDeclConsumer &Consumer, LookupState LS,
    const DeclContext *FromContext, DeclVisibilityKind Reason,
    LazyResolver *TypeResolver, VisitedSet &Visited) {
  NominalTypeDecl *CurrNominal = BaseTy->getAnyNominal();
  if (!CurrNominal)
    return;

  for (auto Conformance : CurrNominal->getAllConformances()) {
    auto Proto = Conformance->getProtocol();
    if (!Proto->isAccessibleFrom(FromContext))
      continue;

    DeclVisibilityKind ReasonForThisProtocol;
    if (Reason == DeclVisibilityKind::MemberOfCurrentNominal)
      ReasonForThisProtocol =
          DeclVisibilityKind::MemberOfProtocolImplementedByCurrentNominal;
    else
      ReasonForThisProtocol = getReasonForSuper(Reason);

    auto NormalConformance = Conformance->getRootNormalConformance();
    for (auto Member : Proto->getMembers()) {
      if (auto *ATD = dyn_cast<AssociatedTypeDecl>(Member)) {
        // Skip type decls if they aren't visible, or any type that has a
        // witness. This cuts down on duplicates.
        if (areTypeDeclsVisibleInLookupMode(LS) &&
            !NormalConformance->hasTypeWitness(ATD)) {
          Consumer.foundDecl(ATD, ReasonForThisProtocol);
        }
        continue;
      }
      if (auto *VD = dyn_cast<ValueDecl>(Member)) {
        if (TypeResolver) {
          TypeResolver->resolveDeclSignature(VD);
          if (!NormalConformance->hasWitness(VD) &&
              (Conformance->getDeclContext()->getParentSourceFile() !=
              FromContext->getParentSourceFile()))
            TypeResolver->resolveWitness(NormalConformance, VD);
        }
        // Skip value requirements that have corresponding witnesses. This cuts
        // down on duplicates.
        if (!NormalConformance->hasWitness(VD) ||
            !NormalConformance->getWitness(VD, nullptr) ||
            NormalConformance->getWitness(VD, nullptr).getDecl()->getFullName()
              != VD->getFullName()) {
          Consumer.foundDecl(VD, ReasonForThisProtocol);
        }
      }
    }

    // Add members from any extensions.
    SmallVector<ValueDecl *, 2> FoundDecls;
    doGlobalExtensionLookup(BaseTy, Proto->getDeclaredType(), FoundDecls,
                            FromContext, LS, ReasonForThisProtocol,
                            TypeResolver);
    for (auto *VD : FoundDecls)
      Consumer.foundDecl(VD, ReasonForThisProtocol);
  }
}
Example #7
0
  void layout() {
    using swift::reflection::FieldDescriptorKind;

    PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD);
    auto type = NTD->getDeclaredType()->getCanonicalType();
    addTypeRef(NTD->getModuleContext(), type);

    switch (NTD->getKind()) {
      case DeclKind::Class:
      case DeclKind::Struct: {
        auto properties = NTD->getStoredProperties();
        addConstantInt16(uint16_t(isa<StructDecl>(NTD)
                                  ? FieldDescriptorKind::Struct
                                  : FieldDescriptorKind::Class));
        addConstantInt16(fieldRecordSize);
        addConstantInt32(std::distance(properties.begin(), properties.end()));
        for (auto property : properties)
          addFieldDecl(property,
                       property->getInterfaceType()
                       ->getCanonicalType());
        break;
      }
      case DeclKind::Enum: {
        auto enumDecl = cast<EnumDecl>(NTD);
        auto cases = enumDecl->getAllElements();
        addConstantInt16(uint16_t(FieldDescriptorKind::Enum));
        addConstantInt16(fieldRecordSize);
        addConstantInt32(std::distance(cases.begin(), cases.end()));
        for (auto enumCase : cases) {
          if (enumCase->hasArgumentType()) {
            addFieldDecl(enumCase,
                         enumCase->getArgumentInterfaceType()
                         ->getCanonicalType());
          } else {
            addFieldDecl(enumCase, CanType());
          }
        }
        break;
      }
      case DeclKind::Protocol: {
        auto protocolDecl = cast<ProtocolDecl>(NTD);
        FieldDescriptorKind Kind;
        if (protocolDecl->isObjC())
          Kind = FieldDescriptorKind::ObjCProtocol;
        else if (protocolDecl->requiresClass())
          Kind = FieldDescriptorKind::ClassProtocol;
        else
          Kind = FieldDescriptorKind::Protocol;
        addConstantInt16(uint16_t(Kind));
        addConstantInt16(fieldRecordSize);
        addConstantInt32(0);
        break;
      }
      default:
        llvm_unreachable("Not a nominal type");
        break;
    }
  }
/// Recursively traverse the conformance lists to determine sole conforming
/// class, struct or enum type.
NominalTypeDecl *
ProtocolConformanceAnalysis::findSoleConformingType(ProtocolDecl *Protocol) {

  /// First check in the SoleConformingTypeCache.
  auto SoleConformingTypeIt = SoleConformingTypeCache.find(Protocol);
  if (SoleConformingTypeIt != SoleConformingTypeCache.end())
    return SoleConformingTypeIt->second;

  SmallVector<ProtocolDecl *, 8> PDWorkList;
  SmallPtrSet<ProtocolDecl *, 8> VisitedPDs;
  NominalTypeDecl *SoleConformingNTD = nullptr;
  PDWorkList.push_back(Protocol);
  while (!PDWorkList.empty()) {
    auto *PD = PDWorkList.pop_back_val();
    // Protocols must have internal or lower access.
    if (PD->getEffectiveAccess() > AccessLevel::Internal) {
      return nullptr;
    }
    VisitedPDs.insert(PD);
    auto NTDList = getConformances(PD);
    for (auto *ConformingNTD : NTDList) {
      // Recurse on protocol types.
      if (auto *Proto = dyn_cast<ProtocolDecl>(ConformingNTD)) {
        // Ignore visited protocol decls.
        if (!VisitedPDs.count(Proto))
          PDWorkList.push_back(Proto);
      } else { // Classes, Structs and Enums are added here.
        // Bail if more than one conforming types were found.
        if (SoleConformingNTD && ConformingNTD != SoleConformingNTD) {
          return nullptr;
        } else {
          SoleConformingNTD = ConformingNTD;
        }
      }
    }
  }

  // Bail if we did not find a sole conforming type.
  if (!SoleConformingNTD)
    return nullptr;

  // Generic declarations are ignored.
  if (SoleConformingNTD->isGenericContext()) {
    return nullptr;
  }

  // Populate SoleConformingTypeCache.
  SoleConformingTypeCache.insert(std::pair<ProtocolDecl *, NominalTypeDecl *>(
      Protocol, SoleConformingNTD));

  // Return SoleConformingNTD.
  return SoleConformingNTD;
}
Example #9
0
static unsigned getIndexForValueDecl(ValueDecl *Decl) {
    NominalTypeDecl *D = cast<NominalTypeDecl>(Decl->getDeclContext());

    unsigned i = 0;
    for (auto *V : D->getStoredProperties()) {
        if (V == Decl)
            return i;
        ++i;
    }

    llvm_unreachable("Failed to find Decl in its decl context?!");
}
Example #10
0
static bool shouldPrintAsFavorable(const Decl *D, PrintOptions &Options) {
  if (!Options.TransformContext ||
      !D->getDeclContext()->isExtensionContext() ||
      !Options.TransformContext->isPrintingSynthesizedExtension())
    return true;
  NominalTypeDecl *Target = Options.TransformContext->getNominal();
  Type BaseTy = Target->getDeclaredTypeInContext();
  const auto *FD = dyn_cast<FuncDecl>(D);
  if (!FD)
    return true;
  ResolvedMemberResult Result =
  resolveValueMember(*Target->getDeclContext(), BaseTy,
                     FD->getEffectiveFullName());
  return !(Result.hasBestOverload() && Result.getBestOverload() != D);
}
Example #11
0
 Implementation(NominalTypeDecl *Target,
                bool IncludeUnconditional,
                PrintOptions Options):
 Target(Target),
 BaseType(Target->getDeclaredInterfaceType()),
 DC(Target),
 IncludeUnconditional(IncludeUnconditional),
 Options(Options), AllGroups(MergeGroupVector()),
 InfoMap(collectSynthesizedExtensionInfo(AllGroups)) {}
Example #12
0
bool IRGenerator::canEmitWitnessTableLazily(SILWitnessTable *wt) {
  if (Opts.UseJIT)
    return false;

  NominalTypeDecl *ConformingTy =
    wt->getConformance()->getType()->getNominalOrBoundGenericNominal();

  switch (ConformingTy->getEffectiveAccess()) {
    case AccessLevel::Private:
    case AccessLevel::FilePrivate:
      return true;

    case AccessLevel::Internal:
      return PrimaryIGM->getSILModule().isWholeModule();

    default:
      return false;
  }
  llvm_unreachable("switch does not handle all cases");
}
Example #13
0
/// \brief Enumerate immediate members of the type \c LookupType and its
/// extensions, as seen from the context \c CurrDC.
///
/// Don't do lookup into superclasses or implemented protocols.  Uses
/// \p BaseType as the underlying type when checking any constraints on the
/// extensions.
static void lookupTypeMembers(Type BaseType, Type LookupType,
                              VisibleDeclConsumer &Consumer,
                              const DeclContext *CurrDC, LookupState LS,
                              DeclVisibilityKind Reason,
                              LazyResolver *TypeResolver) {
  NominalTypeDecl *D = LookupType->getAnyNominal();
  assert(D && "should have a nominal type");

  bool LookupFromChildDeclContext = false;
  const DeclContext *TempDC = CurrDC;
  while (!TempDC->isModuleContext()) {
    if (TempDC == D) {
      LookupFromChildDeclContext = true;
      break;
    }
    TempDC = TempDC->getParent();
  }

  SmallVector<ValueDecl*, 2> FoundDecls;

  if (LookupFromChildDeclContext) {
    // Current decl context is contained inside 'D', so generic parameters
    // are visible.
    if (D->getGenericParams())
      for (auto Param : *D->getGenericParams())
        if (isDeclVisibleInLookupMode(Param, LS, CurrDC, TypeResolver))
          FoundDecls.push_back(Param);
  }

  for (Decl *Member : D->getMembers()) {
    if (auto *VD = dyn_cast<ValueDecl>(Member))
      if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
        FoundDecls.push_back(VD);
  }
  doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason,
                          TypeResolver);

  // Report the declarations we found to the consumer.
  for (auto *VD : FoundDecls)
    Consumer.foundDecl(VD, Reason);
}
void findExtensionsFromConformingProtocols(Decl *D,
                                           llvm::SmallPtrSetImpl<ExtensionDecl*> &Results) {
  NominalTypeDecl* NTD = dyn_cast<NominalTypeDecl>(D);
  if (!NTD || NTD->getKind() == DeclKind::Protocol)
    return;
  std::vector<NominalTypeDecl*> Unhandled;
  auto addTypeLocNominal = [&](TypeLoc TL){
    if (TL.getType()) {
      if (auto D = TL.getType()->getAnyNominal()) {
        Unhandled.push_back(D);
      }
    }
  };
  for (auto TL : NTD->getInherited()) {
    addTypeLocNominal(TL);
  }
  while(!Unhandled.empty()) {
    NominalTypeDecl* Back = Unhandled.back();
    Unhandled.pop_back();
    for (ExtensionDecl *E : Back->getExtensions()) {
      if(E->isConstrainedExtension())
        Results.insert(E);
      for (auto TL : Back->getInherited()) {
        addTypeLocNominal(TL);
      }
    }
  }
}
Example #15
0
static Type findBaseTypeForReplacingArchetype(const ValueDecl *VD, const Type Ty) {
  if (Ty.isNull())
    return Type();

  // Find the nominal type decl related to VD.
  NominalTypeDecl *NTD = VD->getDeclContext()->
    getAsNominalTypeOrNominalTypeExtensionContext();
  if (!NTD)
    return Type();
  Type Result;

  // Walk the type tree to find the a sub-type who's convertible to the
  // found nominal.
  Ty.visit([&](Type T) {
    if (!Result && (T->getAnyNominal() == NTD ||
                    isConvertibleTo(T, NTD->getDeclaredType(),
                                    VD->getDeclContext()))) {
      Result = T;
    }
  });
  return Result;
}
Example #16
0
/// Enumerate immediate members of the type \c LookupType and its
/// extensions, as seen from the context \c CurrDC.
///
/// Don't do lookup into superclasses or implemented protocols.  Uses
/// \p BaseType as the underlying type when checking any constraints on the
/// extensions.
static void lookupTypeMembers(Type BaseType, Type LookupType,
                              VisibleDeclConsumer &Consumer,
                              const DeclContext *CurrDC, LookupState LS,
                              DeclVisibilityKind Reason,
                              LazyResolver *TypeResolver) {
  NominalTypeDecl *D = LookupType->getAnyNominal();
  assert(D && "should have a nominal type");

  SmallVector<ValueDecl*, 2> FoundDecls;

  for (Decl *Member : D->getMembers()) {
    if (auto *VD = dyn_cast<ValueDecl>(Member))
      if (isDeclVisibleInLookupMode(VD, LS, CurrDC, TypeResolver))
        FoundDecls.push_back(VD);
  }
  doGlobalExtensionLookup(BaseType, LookupType, FoundDecls, CurrDC, LS, Reason,
                          TypeResolver);

  // Report the declarations we found to the consumer.
  for (auto *VD : FoundDecls)
    Consumer.foundDecl(VD, Reason);
}
SmallVector<ProtocolConformance *, 2>
DeclContext::getLocalConformances(
  ConformanceLookupKind lookupKind,
  SmallVectorImpl<ConformanceDiagnostic> *diagnostics,
  bool sorted) const
{
  SmallVector<ProtocolConformance *, 2> result;

  // Dig out the nominal type.
  NominalTypeDecl *nominal = isNominalTypeOrNominalTypeExtensionContext();
  if (!nominal)
    return result;

  // Protocols don't have conformances.
  if (isa<ProtocolDecl>(nominal))
    return { };

  // Update to record all potential conformances.
  nominal->prepareConformanceTable();
  nominal->ConformanceTable->lookupConformances(
    nominal,
    const_cast<DeclContext *>(this),
    nominal->getASTContext().getLazyResolver(),
    lookupKind,
    nullptr,
    &result,
    diagnostics);

  // If requested, sort the results.
  if (sorted) {
    llvm::array_pod_sort(result.begin(), result.end(),
                         &ConformanceLookupTable::compareProtocolConformances);
  }

  return result;
}
Example #18
0
  void layout() override {
    if (NTD->hasClangNode() &&
        !isa<ClassDecl>(NTD) &&
        !isa<StructDecl>(NTD) &&
        !isa<ProtocolDecl>(NTD))
      return;

    PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD);
    addNominalRef(NTD);

    auto *CD = dyn_cast<ClassDecl>(NTD);
    if (CD && CD->getSuperclass()) {
      addTypeRef(CD->getSuperclass()->getCanonicalType());
    } else {
      B.addInt32(0);
    }

    switch (NTD->getKind()) {
    case DeclKind::Class:
    case DeclKind::Struct:
      layoutRecord();
      break;

    case DeclKind::Enum:
      layoutEnum();
      break;

    case DeclKind::Protocol:
      layoutProtocol();
      break;

    default:
      llvm_unreachable("Not a nominal type");
      break;
    }
  }
Example #19
0
 std::unique_ptr<ExtensionInfoMap>
 collectSynthesizedExtensionInfoForProtocol(MergeGroupVector &AllGroups) {
   std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap());
   ExtensionMergeInfoMap MergeInfoMap;
   for (auto *E : Target->getExtensions()) {
     if (!Options.shouldPrint(E))
       continue;
     auto Pair = isApplicable(E, /*Synthesized*/false);
     if (Pair.first) {
       InfoMap->insert({E, Pair.first});
       MergeInfoMap.insert({E, Pair.second});
     }
   }
   populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups,
                      /*AllowMergeWithDefBody*/false);
   std::sort(AllGroups.begin(), AllGroups.end());
   for (auto &Group : AllGroups) {
     Group.sortMembers();
   }
   return InfoMap;
 }
Example #20
0
//===----------------------------------------------------------------------===//
// Qualified name lookup handling
//===----------------------------------------------------------------------===//
bool IterativeTypeChecker::isQualifiedLookupInDeclContextSatisfied(
       TypeCheckRequest::DeclContextLookupPayloadType payload) {
  auto dc = payload.DC;

  NominalTypeDecl *nominal = nullptr;
  switch (dc->getContextKind()) {
  case DeclContextKind::AbstractClosureExpr:
  case DeclContextKind::AbstractFunctionDecl:
  case DeclContextKind::Initializer:
  case DeclContextKind::TopLevelCodeDecl:
  case DeclContextKind::SerializedLocal:
  case DeclContextKind::SubscriptDecl:
    llvm_unreachable("not a DeclContext that supports name lookup");

  case DeclContextKind::Module:
  case DeclContextKind::FileUnit:
    // Modules and file units can always handle name lookup.
    return true;

  case DeclContextKind::GenericTypeDecl:
    // Get the nominal type.
    nominal = dyn_cast<NominalTypeDecl>(cast<GenericTypeDecl>(dc));
    if (!nominal) return true;
    break;

  case DeclContextKind::ExtensionDecl: {
    auto ext = cast<ExtensionDecl>(dc);
    // FIXME: bind the extension. We currently assume this is done.
    nominal = ext->getAsNominalTypeOrNominalTypeExtensionContext();
    if (!nominal) return true;
    break;
  }
  }

  assert(nominal && "Only nominal types are handled here");
  // FIXME: Cache a bit indicating when qualified lookup is possible.

  // If we needed them for this query, did we already add implicit
  // initializers?
  auto name = payload.Name;
  if ((!name || name.matchesRef(getASTContext().Id_init)) &&
      !nominal->addedImplicitInitializers())
    return false;

  // For classes, check the superclass.
  if (auto classDecl = dyn_cast<ClassDecl>(nominal)) {
    if (!isSatisfied(requestTypeCheckSuperclass(classDecl)))
      return false;

    if (auto superclass = classDecl->getSuperclass()) {
      if (auto superclassDecl = superclass->getAnyNominal()) {
        if (!isSatisfied(requestQualifiedLookupInDeclContext({ superclassDecl,
                                                               payload.Name,
                                                               payload.Loc })))
          return false;
      }
    }
  }

  return true;
}
Example #21
0
  std::unique_ptr<ExtensionInfoMap>
  collectSynthesizedExtensionInfo(MergeGroupVector &AllGroups) {
    if (isa<ProtocolDecl>(Target)) {
      return collectSynthesizedExtensionInfoForProtocol(AllGroups);
    }
    std::unique_ptr<ExtensionInfoMap> InfoMap(new ExtensionInfoMap());
    ExtensionMergeInfoMap MergeInfoMap;
    std::vector<NominalTypeDecl*> Unhandled;

    auto handleExtension = [&](ExtensionDecl *E, bool Synthesized,
                               ExtensionDecl *EnablingE,
                               NormalProtocolConformance *Conf) {
      if (Options.shouldPrint(E)) {
        auto Pair = isApplicable(E, Synthesized, EnablingE, Conf);
        if (Pair.first) {
          InfoMap->insert({E, Pair.first});
          MergeInfoMap.insert({E, Pair.second});
        }
      }
    };

    for (auto *Conf : Target->getLocalConformances()) {
      Unhandled.push_back(Conf->getProtocol());
    }
    if (auto *CD = dyn_cast<ClassDecl>(Target)) {
      if (auto Super = CD->getSuperclassDecl())
        Unhandled.push_back(Super);
    }
    while (!Unhandled.empty()) {
      NominalTypeDecl* Back = Unhandled.back();
      Unhandled.pop_back();
      for (ExtensionDecl *E : Back->getExtensions()) {
        handleExtension(E, true, nullptr, nullptr);
      }
      for (auto *Conf : Back->getLocalConformances()) {
        Unhandled.push_back(Conf->getProtocol());
      }
      if (auto *CD = dyn_cast<ClassDecl>(Back)) {
        if (auto Super = CD->getSuperclass())
          Unhandled.push_back(Super->getAnyNominal());
      }
    }

    // Merge with actual extensions.
    for (auto *EnablingE : Target->getExtensions()) {
      handleExtension(EnablingE, false, nullptr, nullptr);
      for (auto *Conf : EnablingE->getLocalConformances()) {
        for (auto E : Conf->getProtocol()->getExtensions())
          handleExtension(E, true, EnablingE, Conf->getRootNormalConformance());
      }
    }

    populateMergeGroup(*InfoMap, MergeInfoMap, AllGroups,
                       /*AllowMergeWithDefBody*/true);

    std::sort(AllGroups.begin(), AllGroups.end());
    for (auto &Group : AllGroups) {
      Group.removeUnfavored(Target);
      Group.sortMembers();
    }
    AllGroups.erase(std::remove_if(AllGroups.begin(), AllGroups.end(),
      [](ExtensionMergeGroup &Group) { return Group.Members.empty(); }),
                    AllGroups.end());

    return InfoMap;
  }
Example #22
0
  void layout() {
    using swift::reflection::FieldDescriptorKind;

    PrettyStackTraceDecl DebugStack("emitting field type metadata", NTD);
    auto type = NTD->getDeclaredType()->getCanonicalType();
    addTypeRef(NTD->getModuleContext(), type);

    if (NTD->hasClangNode() &&
        !isa<ClassDecl>(NTD) &&
        !isa<ProtocolDecl>(NTD))
      return;

    switch (NTD->getKind()) {
      case DeclKind::Class:
      case DeclKind::Struct: {
        auto kind = FieldDescriptorKind::Struct;

        if (auto CD = dyn_cast<ClassDecl>(NTD)) {
          auto RC = getReferenceCountingForClass(IGM, const_cast<ClassDecl *>(CD));
          if (RC == ReferenceCounting::ObjC)
            kind = FieldDescriptorKind::ObjCClass;
          else
            kind = FieldDescriptorKind::Class;
        }

        addConstantInt16(uint16_t(kind));
        addConstantInt16(fieldRecordSize);

        // Imported classes don't need field descriptors
        if (NTD->hasClangNode()) {
          assert(isa<ClassDecl>(NTD));
          addConstantInt32(0);
          break;
        }

        auto properties = NTD->getStoredProperties();
        addConstantInt32(std::distance(properties.begin(), properties.end()));
        for (auto property : properties)
          addFieldDecl(property,
                       property->getInterfaceType()
                       ->getCanonicalType());
        break;
      }
      case DeclKind::Enum: {
        auto enumDecl = cast<EnumDecl>(NTD);
        auto cases = enumDecl->getAllElements();
        addConstantInt16(uint16_t(FieldDescriptorKind::Enum));
        addConstantInt16(fieldRecordSize);
        addConstantInt32(std::distance(cases.begin(), cases.end()));
        for (auto enumCase : cases) {
          if (enumCase->hasArgumentType()) {
            addFieldDecl(enumCase,
                         enumCase->getArgumentInterfaceType()
                         ->getCanonicalType());
          } else {
            addFieldDecl(enumCase, CanType());
          }
        }
        break;
      }
      case DeclKind::Protocol: {
        auto protocolDecl = cast<ProtocolDecl>(NTD);
        FieldDescriptorKind Kind;
        if (protocolDecl->isObjC())
          Kind = FieldDescriptorKind::ObjCProtocol;
        else if (protocolDecl->requiresClass())
          Kind = FieldDescriptorKind::ClassProtocol;
        else
          Kind = FieldDescriptorKind::Protocol;
        addConstantInt16(uint16_t(Kind));
        addConstantInt16(fieldRecordSize);
        addConstantInt32(0);
        break;
      }
      default:
        llvm_unreachable("Not a nominal type");
        break;
    }
  }
Example #23
0
static void bindExtensionDecl(ExtensionDecl *ED, TypeChecker &TC) {
  if (ED->getExtendedType())
    return;

  // If we didn't parse a type, fill in an error type and bail out.
  if (!ED->getExtendedTypeLoc().getTypeRepr()) {
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }

  auto dc = ED->getDeclContext();

  // Validate the representation.
  // FIXME: Perform some kind of "shallow" validation here?
  TypeResolutionOptions options;
  options |= TR_AllowUnboundGenerics;
  options |= TR_ExtensionBinding;
  if (TC.validateType(ED->getExtendedTypeLoc(), dc, options)) {
    ED->setInvalid();
    return;
  }

  // Dig out the extended type.
  auto extendedType = ED->getExtendedType();

  // Hack to allow extending a generic typealias.
  if (auto *unboundGeneric = extendedType->getAs<UnboundGenericType>()) {
    if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(unboundGeneric->getDecl())) {
      auto extendedNominal = aliasDecl->getDeclaredInterfaceType()->getAnyNominal();
      if (extendedNominal) {
        extendedType = extendedNominal->getDeclaredType();
        ED->getExtendedTypeLoc().setType(extendedType);
      }
    }
  }

  // Handle easy cases.

  // Cannot extend a metatype.
  if (extendedType->is<AnyMetatypeType>()) {
    TC.diagnose(ED->getLoc(), diag::extension_metatype, extendedType)
      .highlight(ED->getExtendedTypeLoc().getSourceRange());
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }

  // Cannot extend a bound generic type.
  if (extendedType->isSpecialized()) {
    TC.diagnose(ED->getLoc(), diag::extension_specialization,
                extendedType->getAnyNominal()->getName())
      .highlight(ED->getExtendedTypeLoc().getSourceRange());
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }

  // Dig out the nominal type being extended.
  NominalTypeDecl *extendedNominal = extendedType->getAnyNominal();
  if (!extendedNominal) {
    TC.diagnose(ED->getLoc(), diag::non_nominal_extension, extendedType)
      .highlight(ED->getExtendedTypeLoc().getSourceRange());
    ED->setInvalid();
    ED->getExtendedTypeLoc().setInvalidType(TC.Context);
    return;
  }
  assert(extendedNominal && "Should have the nominal type being extended");

  // If the extended type is generic or is a protocol. Clone or create
  // the generic parameters.
  if (extendedNominal->isGenericContext()) {
    if (auto proto = dyn_cast<ProtocolDecl>(extendedNominal)) {
      // For a protocol extension, build the generic parameter list.
      ED->setGenericParams(proto->createGenericParams(ED));
    } else {
      // Clone the existing generic parameter list.
      ED->setGenericParams(
        cloneGenericParams(TC.Context, ED,
                           extendedNominal->getGenericParamsOfContext()));
    }
  }

  // If we have a trailing where clause, deal with it now.
  // For now, trailing where clauses are only permitted on protocol extensions.
  if (auto trailingWhereClause = ED->getTrailingWhereClause()) {
    if (!extendedNominal->isGenericContext()) {
      // Only generic and protocol types are permitted to have
      // trailing where clauses.
      TC.diagnose(ED, diag::extension_nongeneric_trailing_where, extendedType)
        .highlight(trailingWhereClause->getSourceRange());
      ED->setTrailingWhereClause(nullptr);
    } else {
      // Merge the trailing where clause into the generic parameter list.
      // FIXME: Long-term, we'd like clients to deal with the trailing where
      // clause explicitly, but for now it's far more direct to represent
      // the trailing where clause as part of the requirements.
      ED->getGenericParams()->addTrailingWhereClause(
        TC.Context,
        trailingWhereClause->getWhereLoc(),
        trailingWhereClause->getRequirements());
    }
  }

  extendedNominal->addExtension(ED);
}
ProtocolConformance *ConformanceLookupTable::getConformance(
                       NominalTypeDecl *nominal,
                       LazyResolver *resolver,
                       ConformanceEntry *entry) {
  // If we already have a conformance, we're done.
  if (auto conformance = entry->getConformance())
    return conformance;

  ProtocolDecl *protocol = entry->getProtocol();

  // Determine where the explicit conformance actually lives.
  // FIXME: This is a hack to ensure that inherited conformances are
  // always "single step", which is bad for resilience but is assumed
  // elsewhere in the compiler.
  DeclContext *conformingDC = getConformingContext(nominal, resolver, entry);
  if (!conformingDC)
    return nullptr;

  NominalTypeDecl *conformingNominal
    = conformingDC->isNominalTypeOrNominalTypeExtensionContext();

  // Form the conformance.
  Type type = entry->getDeclContext()->getDeclaredTypeInContext();
  ProtocolConformance *conformance;
    ASTContext &ctx = nominal->getASTContext();
  if (entry->getKind() == ConformanceEntryKind::Inherited) {
    // For an inherited conformance, the conforming nominal type will
    // be different from the nominal type.
    assert(conformingNominal != nominal && "Broken inherited conformance");

    // Find the superclass type that matches where the conformance was
    // declared.
    Type superclassTy = type->getSuperclass(resolver);
    while (superclassTy->getAnyNominal() != conformingNominal)
      superclassTy = superclassTy->getSuperclass(resolver);

    // Look up the inherited conformance.
    Module *module = entry->getDeclContext()->getParentModule();
    auto inheritedConformance = module->lookupConformance(superclassTy,
                                                          protocol,
                                                          resolver)
                                  .getPointer();

    // Form the inherited conformance.
    conformance = ctx.getInheritedConformance(type, inheritedConformance);
  } else {
    // Create or find the normal conformance.
    Type conformingType = conformingDC->getDeclaredTypeInContext();
    SourceLoc conformanceLoc
      = conformingNominal == conformingDC
          ? conformingNominal->getLoc()
          : cast<ExtensionDecl>(conformingDC)->getLoc();

    conformance = ctx.getConformance(conformingType, protocol, conformanceLoc,
                                     conformingDC,
                                     ProtocolConformanceState::Incomplete);
  }

  // Record the conformance.
  entry->Conformance = conformance;
  return conformance;
}
Example #25
0
 llvm::GlobalVariable *emit() {
   auto entity = LinkEntity::forReflectionFieldDescriptor(
       NTD->getDeclaredType()->getCanonicalType());
   auto section = IGM.getFieldTypeMetadataSectionName();
   return ReflectionMetadataBuilder::emit(entity, section);
 }