예제 #1
0
파일: SILDeclRef.cpp 프로젝트: xwu/swift
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, because derived classes have to put
  // all less visible methods of the base class into their vtables.

  if (auto *CD = dyn_cast<ConstructorDecl>(getDecl()))
    if (!CD->isRequired())
      return SubclassScope::NotApplicable;

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

  DeclContext *context = FD->getDeclContext();

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

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

  // Default arg generators are not visible.
  if (isDefaultArgGenerator())
    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");

  // FIXME: This is too narrow. Any class with resilient metadata should
  // probably have this, at least for method overrides that don't add new
  // vtable entries.
  if (classType->isResilient())
    return SubclassScope::Resilient;

  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.");
}
예제 #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.");
}
예제 #3
0
SubclassScope SILDeclRef::getSubclassScope() const {
  if (!hasDecl())
    return SubclassScope::NotApplicable;

  auto *decl = getDecl();

  if (!isa<AbstractFunctionDecl>(decl))
    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, because derived classes have to put
  // all less visible methods of the base class into their vtables.

  if (auto *CD = dyn_cast<ConstructorDecl>(decl)) {
    // Initializing entry points do not appear in the vtable.
    if (kind == SILDeclRef::Kind::Initializer)
      return SubclassScope::NotApplicable;
    // Non-required convenience inits do not apper in the vtable.
    if (!CD->isRequired() && !CD->isDesignatedInit())
      return SubclassScope::NotApplicable;
  } else if (isa<DestructorDecl>(decl)) {
    // Detructors do not appear in the vtable.
    return SubclassScope::NotApplicable;
  } else {
    assert(isa<FuncDecl>(decl));
  }

  DeclContext *context = decl->getDeclContext();

  // Methods from extensions don't go in the vtable.
  if (isa<ExtensionDecl>(context))
    return SubclassScope::NotApplicable;

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

  // Default arg generators don't go in the vtable.
  if (isDefaultArgGenerator())
    return SubclassScope::NotApplicable;

  // Only non-final methods in non-final classes go in the vtable.
  auto *classType = context->getSelfClassDecl();
  if (!classType || classType->isFinal())
    return SubclassScope::NotApplicable;

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

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

  // FIXME: This is too narrow. Any class with resilient metadata should
  // probably have this, at least for method overrides that don't add new
  // vtable entries.
  if (classType->isResilient()) {
    if (isa<ConstructorDecl>(decl))
      return SubclassScope::NotApplicable;
    return SubclassScope::Resilient;
  }

  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.");
}