text: //===--- ImportDecl.cpp - Import Clang Declarations -----------------------===//
  //
  // 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 implements support for importing Clang declarations into Swift.
  //
  //===----------------------------------------------------------------------===//
  
  #include "CFTypeInfo.h"
  #include "ImporterImpl.h"
  #include "swift/Strings.h"
  #include "swift/AST/ASTContext.h"
  #include "swift/AST/GenericSignatureBuilder.h"
  #include "swift/AST/Attr.h"
  #include "swift/AST/Builtins.h"
  #include "swift/AST/Decl.h"
  #include "swift/AST/DiagnosticsClangImporter.h"
  #include "swift/AST/ExistentialLayout.h"
  #include "swift/AST/Expr.h"
  #include "swift/AST/GenericEnvironment.h"
  #include "swift/AST/GenericSignature.h"
  #include "swift/AST/Module.h"
  #include "swift/AST/NameLookup.h"
  #include "swift/AST/ParameterList.h"
  #include "swift/AST/Pattern.h"
  #include "swift/AST/PrettyStackTrace.h"
  #include "swift/AST/ProtocolConformance.h"
  #include "swift/AST/Stmt.h"
  #include "swift/AST/Types.h"
  #include "swift/Basic/Defer.h"
  #include "swift/Basic/PrettyStackTrace.h"
  #include "swift/ClangImporter/ClangModule.h"
  #include "swift/Parse/Lexer.h"
  #include "swift/Config.h"
  #include "clang/AST/ASTContext.h"
  #include "clang/AST/Attr.h"
  #include "clang/Basic/CharInfo.h"
  #include "swift/Basic/Statistic.h"
  #include "clang/Lex/Preprocessor.h"
  #include "clang/Sema/Lookup.h"
  
  #include "llvm/ADT/SmallString.h"
  #include "llvm/ADT/Statistic.h"
  #include "llvm/ADT/StringExtras.h"
  #include "llvm/ADT/StringSwitch.h"
  #include "llvm/Support/Path.h"
  
  #include <algorithm>
  
  #define DEBUG_TYPE "Clang module importer"
  
  STATISTIC(NumTotalImportedEntities, "# of imported clang entities");
  STATISTIC(NumFactoryMethodsAsInitializers,
            "# of factory methods mapped to initializers");
  
  using namespace swift;
  using namespace importer;
  
  namespace swift {
  namespace inferred_attributes {
    enum {
      requires_stored_property_inits = 0x01
    };
  } // end namespace inferred_attributes
  } // end namespace swift
  
  namespace {
  enum class MakeStructRawValuedFlags {
    /// whether to also create an unlabeled init
    MakeUnlabeledValueInit = 0x01,
  
    /// whether the raw value should be a let
    IsLet = 0x02,
  
    /// whether to mark the rawValue as implicit
    IsImplicit = 0x04,
  };
  using MakeStructRawValuedOptions = OptionSet<MakeStructRawValuedFlags>;
  } // end anonymous namespace
  
  static MakeStructRawValuedOptions
  getDefaultMakeStructRawValuedOptions() {
    MakeStructRawValuedOptions opts;
    opts -= MakeStructRawValuedFlags::MakeUnlabeledValueInit; // default off
    opts |= MakeStructRawValuedFlags::IsLet;                  // default on
    opts |= MakeStructRawValuedFlags::IsImplicit;             // default on
    return opts;
  }
  
  static bool isInSystemModule(DeclContext *D) {
    return cast<ClangModuleUnit>(D->getModuleScopeContext())->isSystemModule();
  }
  
  static AccessLevel getOverridableAccessLevel(DeclContext *dc) {
    return (dc->getAsProtocolOrProtocolExtensionContext()
              ? AccessLevel::Public : AccessLevel::Open);
  }
  
  /// Create a typedpattern(namedpattern(decl))
  static Pattern *createTypedNamedPattern(VarDecl *decl) {
    ASTContext &Ctx = decl->getASTContext();
    Type ty = decl->getType();
  
    Pattern *P = new (Ctx) NamedPattern(decl);
    P->setType(ty);
    P->setImplicit();
    P = new (Ctx) TypedPattern(P, TypeLoc::withoutLoc(ty));
    P->setType(ty);
    P->setImplicit();
    return P;
  }
  
  /// Create a var member for this struct, along with its pattern binding, and add
  /// it as a member
  static std::pair<VarDecl *, PatternBindingDecl *>
  createVarWithPattern(ASTContext &ctx, DeclContext *dc, Identifier name, Type ty,
                       VarDecl::Specifier specifier, bool isImplicit,
                       AccessLevel access,
                       AccessLevel setterAccess) {
    // Create a variable to store the underlying value.
    auto var = new (ctx) VarDecl(
        /*IsStatic*/false,
        specifier,
        /*IsCaptureList*/false,
        SourceLoc(), name, dc->mapTypeIntoContext(ty), dc);
    if (isImplicit)
      var->setImplicit();
    var->setInterfaceType(ty);
    var->setValidationStarted();
    var->setAccess(access);
    var->setSetterAccess(setterAccess);
  
    // Create a pattern binding to describe the variable.
    Pattern *varPattern = createTypedNamedPattern(var);
    auto patternBinding =
        PatternBindingDecl::create(ctx, SourceLoc(), StaticSpellingKind::None,
                                   SourceLoc(), varPattern, nullptr, dc);
  
    return {var, patternBinding};
  }
  
  #ifndef NDEBUG
  static bool verifyNameMapping(MappedTypeNameKind NameMapping,
                                StringRef left, StringRef right) {
    return NameMapping == MappedTypeNameKind::DoNothing || left != right;
  }
  #endif
  
  /// \brief Map a well-known C type to a swift type from the standard library.
  ///
  /// \param IsError set to true when we know the corresponding swift type name,
  /// but we could not find it.  (For example, the type was not defined in the
  /// standard library or the required standard library module was not imported.)
  /// This should be a hard error, we don't want to map the type only sometimes.
  ///
  /// \returns A pair of a swift type and its name that corresponds to a given
  /// C type.
  static std::pair<Type, StringRef>
  getSwiftStdlibType(const clang::TypedefNameDecl *D,
                     Identifier Name,
                     ClangImporter::Implementation &Impl,
                     bool *IsError, MappedTypeNameKind &NameMapping) {
    *IsError = false;
  
    MappedCTypeKind CTypeKind;
    unsigned Bitwidth;
    StringRef SwiftModuleName;
    bool IsSwiftModule; // True if SwiftModuleName == STDLIB_NAME.
    StringRef SwiftTypeName;
    bool CanBeMissing;
  
    do {
  #define MAP_TYPE(C_TYPE_NAME, C_TYPE_KIND, C_TYPE_BITWIDTH,        \
                   SWIFT_MODULE_NAME, SWIFT_TYPE_NAME,               \
                   CAN_BE_MISSING, C_NAME_MAPPING)                   \
      if (Name.str() == C_TYPE_NAME) {                               \
        CTypeKind = MappedCTypeKind::C_TYPE_KIND;                    \
        Bitwidth = C_TYPE_BITWIDTH;                                  \
        if (StringRef(SWIFT_MODULE_NAME) == StringRef(STDLIB_NAME))  \
          IsSwiftModule = true;                                      \
        else {                                                       \
          IsSwiftModule = false;                                     \
          SwiftModuleName = SWIFT_MODULE_NAME;                       \
        }                                                            \
        SwiftTypeName = SWIFT_TYPE_NAME;                             \
        CanBeMissing = CAN_BE_MISSING;                               \
        NameMapping = MappedTypeNameKind::C_NAME_MAPPING;            \
        assert(verifyNameMapping(MappedTypeNameKind::C_NAME_MAPPING, \
                                 C_TYPE_NAME, SWIFT_TYPE_NAME) &&    \
               "MappedTypes.def: Identical names must use DoNothing"); \
        break;                                                       \
      }
  #include "MappedTypes.def"
  
      // We did not find this type, thus it is not mapped.
      return std::make_pair(Type(), "");
    } while (0);
  
    clang::ASTContext &ClangCtx = Impl.getClangASTContext();
  
    auto ClangType = D->getUnderlyingType();
  
    // If the C type does not have the expected size, don't import it as a stdlib
    // type.
    unsigned ClangTypeSize = ClangCtx.getTypeSize(ClangType);
    if (Bitwidth != 0 && Bitwidth != ClangTypeSize)
      return std::make_pair(Type(), "");
  
    // Check other expected properties of the C type.
    switch(CTypeKind) {
    case MappedCTypeKind::UnsignedInt:
      if (!ClangType->isUnsignedIntegerType())
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::SignedInt:
      if (!ClangType->isSignedIntegerType())
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::UnsignedWord:
      if (ClangTypeSize != 64 && ClangTypeSize != 32)
        return std::make_pair(Type(), "");
      if (!ClangType->isUnsignedIntegerType())
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::SignedWord:
      if (ClangTypeSize != 64 && ClangTypeSize != 32)
        return std::make_pair(Type(), "");
      if (!ClangType->isSignedIntegerType())
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::FloatIEEEsingle:
    case MappedCTypeKind::FloatIEEEdouble:
    case MappedCTypeKind::FloatX87DoubleExtended: {
      if (!ClangType->isFloatingType())
        return std::make_pair(Type(), "");
  
      const llvm::fltSemantics &Sem = ClangCtx.getFloatTypeSemantics(ClangType);
      switch(CTypeKind) {
      case MappedCTypeKind::FloatIEEEsingle:
        assert(Bitwidth == 32 && "FloatIEEEsingle should be 32 bits wide");
        if (&Sem != &APFloat::IEEEsingle())
          return std::make_pair(Type(), "");
        break;
  
      case MappedCTypeKind::FloatIEEEdouble:
        assert(Bitwidth == 64 && "FloatIEEEdouble should be 64 bits wide");
        if (&Sem != &APFloat::IEEEdouble())
          return std::make_pair(Type(), "");
        break;
  
      case MappedCTypeKind::FloatX87DoubleExtended:
        assert(Bitwidth == 80 && "FloatX87DoubleExtended should be 80 bits wide");
        if (&Sem != &APFloat::x87DoubleExtended())
          return std::make_pair(Type(), "");
        break;
  
      default:
        llvm_unreachable("should see only floating point types here");
      }
      }
      break;
  
    case MappedCTypeKind::VaList:
      if (ClangTypeSize != ClangCtx.getTypeSize(ClangCtx.VoidPtrTy))
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::ObjCBool:
      if (!ClangCtx.hasSameType(ClangType, ClangCtx.ObjCBuiltinBoolTy) &&
          !(ClangCtx.getBOOLDecl() &&
            ClangCtx.hasSameType(ClangType, ClangCtx.getBOOLType())))
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::ObjCSel:
      if (!ClangCtx.hasSameType(ClangType, ClangCtx.getObjCSelType()) &&
          !ClangCtx.hasSameType(ClangType,
                                ClangCtx.getObjCSelRedefinitionType()))
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::ObjCId:
      if (!ClangCtx.hasSameType(ClangType, ClangCtx.getObjCIdType()) &&
          !ClangCtx.hasSameType(ClangType,
                                ClangCtx.getObjCIdRedefinitionType()))
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::ObjCClass:
      if (!ClangCtx.hasSameType(ClangType, ClangCtx.getObjCClassType()) &&
          !ClangCtx.hasSameType(ClangType,
                                ClangCtx.getObjCClassRedefinitionType()))
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::CGFloat:
      if (!ClangType->isFloatingType())
        return std::make_pair(Type(), "");
      break;
  
    case MappedCTypeKind::Block:
      if (!ClangType->isBlockPointerType())
        return std::make_pair(Type(), "");
      break;
    }
  
    ModuleDecl *M;
    if (IsSwiftModule)
      M = Impl.getStdlibModule();
    else
      M = Impl.getNamedModule(SwiftModuleName);
    if (!M) {
      // User did not import the library module that contains the type we want to
      // substitute.
      *IsError = true;
      return std::make_pair(Type(), "");
    }
  
    Type SwiftType = Impl.getNamedSwiftType(M, SwiftTypeName);
    if (!SwiftType && !CanBeMissing) {
      // The required type is not defined in the standard library.
      *IsError = true;
      return std::make_pair(Type(), "");
    }
    return std::make_pair(SwiftType, SwiftTypeName);
  }
  
  static bool isNSDictionaryMethod(const clang::ObjCMethodDecl *MD,
                                   clang::Selector cmd) {
    if (MD->getSelector() != cmd)
      return false;
    if (isa<clang::ObjCProtocolDecl>(MD->getDeclContext()))
      return false;
    if (MD->getClassInterface()->getName() != "NSDictionary")
      return false;
    return true;
  }
  
  void ClangImporter::Implementation::forEachDistinctName(
      const clang::NamedDecl *decl,
      llvm::function_ref<bool(ImportedName, ImportNameVersion)> action) {
    using ImportNameKey = std::pair<DeclName, EffectiveClangContext>;
    SmallVector<ImportNameKey, 8> seenNames;
  
    ImportedName newName = importFullName(decl, CurrentVersion);
    ImportNameKey key(newName, newName.getEffectiveContext());
    if (action(newName, CurrentVersion))
      seenNames.push_back(key);
  
    CurrentVersion.forEachOtherImportNameVersion(
        [&](ImportNameVersion nameVersion) {
      // Check to see if the name is different.
      ImportedName newName = importFullName(decl, nameVersion);
      ImportNameKey key(newName, newName.getEffectiveContext());
      bool seen = llvm::any_of(seenNames,
                               [&key](const ImportNameKey &existing) -> bool {
        if (key.first != existing.first)
          return false;
        return key.second.equalsWithoutResolving(existing.second);
      });
      if (seen)
        return;
      if (action(newName, nameVersion))
        seenNames.push_back(key);
    });
  }
  
  // Build the init(rawValue:) initializer for an imported NS_ENUM.
  //   enum NSSomeEnum: RawType {
  //     init?(rawValue: RawType) {
  //       self = Builtin.reinterpretCast(rawValue)
  //     }
  //   }
  // Unlike a standard init(rawValue:) enum initializer, this does a reinterpret
  // cast in order to preserve unknown or future cases from C.
  static ConstructorDecl *
  makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
                              EnumDecl *enumDecl) {
    ASTContext &C = Impl.SwiftContext;
    auto rawTy = enumDecl->getRawType();
    auto enumTy = enumDecl->getDeclaredInterfaceType();
    auto metaTy = MetatypeType::get(enumTy);
    
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), enumDecl,
                                          /*static*/false, /*inout*/true);
  
    auto param = new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(),
                                   SourceLoc(), C.Id_rawValue,
                                   SourceLoc(), C.Id_rawValue,
                                   rawTy,
                                   enumDecl);
    param->setInterfaceType(enumDecl->getRawType());
    param->setValidationStarted();
  
    auto paramPL = ParameterList::createWithoutLoc(param);
    
    DeclName name(C, C.Id_init, paramPL);
    auto *ctorDecl =
      new (C) ConstructorDecl(name, enumDecl->getLoc(),
                              OTK_Optional, /*FailabilityLoc=*/SourceLoc(),
                              /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                              selfDecl, paramPL,
                              /*GenericParams=*/nullptr, enumDecl);
    ctorDecl->setImplicit();
    ctorDecl->setAccess(AccessLevel::Public);
  
    auto optEnumTy = OptionalType::get(enumTy);
  
    auto fnTy = FunctionType::get(paramPL->getType(C), optEnumTy);
    auto allocFnTy = FunctionType::get(metaTy, fnTy);
    auto initFnTy = FunctionType::get(enumTy, fnTy);
    ctorDecl->setInterfaceType(allocFnTy);
    ctorDecl->setInitializerInterfaceType(initFnTy);
    ctorDecl->setValidationStarted();
  
    // Don't bother synthesizing the body if we've already finished type-checking.
    if (Impl.hasFinishedTypeChecking())
      return ctorDecl;
    
    auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(), /*implicit*/true);
    selfRef->setType(LValueType::get(selfDecl->getType()->getInOutObjectType()));
    selfRef->propagateLValueAccessKind(AccessKind::Write);
  
    auto paramRef = new (C) DeclRefExpr(param, DeclNameLoc(),
                                        /*implicit*/ true);
    paramRef->setType(param->getType());
  
    auto reinterpretCast
      = getBuiltinValueDecl(C, C.getIdentifier("reinterpretCast"));
    ConcreteDeclRef concreteDeclRef(C, reinterpretCast,
                                    { Substitution(rawTy, {}),
                                      Substitution(enumTy, {}) });
    auto reinterpretCastRef
      = new (C) DeclRefExpr(concreteDeclRef, DeclNameLoc(), /*implicit*/ true);
    reinterpretCastRef->setType(FunctionType::get({rawTy}, enumTy));
  
    auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
                                                  { paramRef }, { Identifier() });
    reinterpreted->setType(enumTy);
  
    auto assign = new (C) AssignExpr(selfRef, SourceLoc(), reinterpreted,
                                     /*implicit*/ true);
    assign->setType(TupleType::getEmpty(C));
  
    auto result = TupleExpr::createEmpty(C, SourceLoc(), SourceLoc(),
                                         /*Implicit=*/true);
    auto ret = new (C) ReturnStmt(SourceLoc(), result, /*Implicit=*/true);
  
    auto body = BraceStmt::create(C, SourceLoc(), {assign, ret}, SourceLoc(),
                                  /*implicit*/ true);
    
    ctorDecl->setBody(body);
    ctorDecl->setBodyTypeCheckedIfPresent();
    
    C.addExternalDecl(ctorDecl);
    
    return ctorDecl;
  }
  
  // Build the rawValue getter for an imported NS_ENUM.
  //   enum NSSomeEnum: RawType {
  //     var rawValue: RawType {
  //       return Builtin.reinterpretCast(self)
  //     }
  //   }
  // Unlike a standard init(rawValue:) enum initializer, this does a reinterpret
  // cast in order to preserve unknown or future cases from C.
  static FuncDecl *makeEnumRawValueGetter(ClangImporter::Implementation &Impl,
                                          EnumDecl *enumDecl,
                                          VarDecl *rawValueDecl) {
    ASTContext &C = Impl.SwiftContext;
  
    auto rawTy = enumDecl->getRawType();
    auto enumTy = enumDecl->getDeclaredType();
  
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), enumDecl);
    
    ParameterList *params[] = {
      ParameterList::createWithoutLoc(selfDecl),
      ParameterList::createEmpty(C)
    };
  
    auto getterDecl =
      FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
                       /*FuncLoc=*/SourceLoc(), DeclName(), /*NameLoc=*/SourceLoc(),
                       /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                       /*AccessorKeywordLoc=*/SourceLoc(),
                       /*GenericParams=*/nullptr, params,
                       TypeLoc::withoutLoc(rawTy), enumDecl);
    getterDecl->setImplicit();
  
    auto type = ParameterList::getFullInterfaceType(rawTy, params, C);
  
    getterDecl->setInterfaceType(type);
    getterDecl->setValidationStarted();
  
    getterDecl->setAccess(AccessLevel::Public);
  
    rawValueDecl->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
                               SourceLoc());
  
    // Don't bother synthesizing the body if we've already finished type-checking.
    if (Impl.hasFinishedTypeChecking())
      return getterDecl;
    
    auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(), /*implicit*/true);
    selfRef->setType(selfDecl->getType());
  
    auto reinterpretCast
      = getBuiltinValueDecl(C, C.getIdentifier("reinterpretCast"));
    ConcreteDeclRef concreteDeclRef(C, reinterpretCast,
                                    { Substitution(enumTy, {}),
                                      Substitution(rawTy, {}) });
    auto reinterpretCastRef
      = new (C) DeclRefExpr(concreteDeclRef, DeclNameLoc(), /*implicit*/ true);
    reinterpretCastRef->setType(FunctionType::get({enumTy}, rawTy));
  
    auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
                                                  { selfRef }, { Identifier() });
    reinterpreted->setType(rawTy);
  
    auto ret = new (C) ReturnStmt(SourceLoc(), reinterpreted);
    auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
                                  /*implicit*/ true);
    
    getterDecl->setBody(body);
    getterDecl->setBodyTypeCheckedIfPresent();
    C.addExternalDecl(getterDecl);
    return getterDecl;
  }
  
  // Build the rawValue getter for a struct type.
  //
  //   struct SomeType: RawRepresentable {
  //     private var _rawValue: ObjCType
  //     var rawValue: SwiftType {
  //       return _rawValue as SwiftType
  //     }
  //   }
  static FuncDecl *makeStructRawValueGetter(
                     ClangImporter::Implementation &Impl,
                     StructDecl *structDecl,
                     VarDecl *computedVar,
                     VarDecl *storedVar) {
    assert(storedVar->hasStorage());
  
    ASTContext &C = Impl.SwiftContext;
    
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), structDecl);
    
    ParameterList *params[] = {
      ParameterList::createWithoutLoc(selfDecl),
      ParameterList::createEmpty(C)
    };
  
    auto computedType = computedVar->getInterfaceType();
    auto storedType = storedVar->getInterfaceType();
  
    auto getterDecl =
      FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
                       /*FuncLoc=*/SourceLoc(), DeclName(), /*NameLoc=*/SourceLoc(),
                       /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                       /*AccessorKeywordLoc=*/SourceLoc(),
                       /*GenericParams=*/nullptr,
                       params,
                       TypeLoc::withoutLoc(computedType), structDecl);
    getterDecl->setImplicit();
  
    auto type = ParameterList::getFullInterfaceType(computedType, params, C);
  
    getterDecl->setInterfaceType(type);
    getterDecl->setValidationStarted();
  
    getterDecl->setAccess(AccessLevel::Public);
  
    // Don't bother synthesizing the body if we've already finished type-checking.
    if (Impl.hasFinishedTypeChecking())
      return getterDecl;
  
    auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(), /*implicit*/true);
    selfRef->setType(selfDecl->getType());
  
    auto storedRef = new (C) MemberRefExpr(selfRef, SourceLoc(), storedVar,
                                           DeclNameLoc(), /*Implicit=*/true,
                                           AccessSemantics::DirectToStorage);
    storedRef->setType(storedType);
  
    Expr *result = storedRef;
  
    if (!computedType->isEqual(storedType)) {
      auto bridge = new (C) BridgeFromObjCExpr(storedRef, computedType);
      bridge->setType(computedType);
  
      auto coerce = new (C) CoerceExpr(bridge, {}, {nullptr, computedType});
      coerce->setType(computedType);
  
      result = coerce;
    }
  
    auto ret = new (C) ReturnStmt(SourceLoc(), result);
    auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
                                  /*implicit*/ true);
    
    getterDecl->setBody(body);
    getterDecl->setBodyTypeCheckedIfPresent();
  
    C.addExternalDecl(getterDecl);
    return getterDecl;
  }
  
  static FuncDecl *makeFieldGetterDecl(ClangImporter::Implementation &Impl,
                                       StructDecl *importedDecl,
                                       VarDecl *importedFieldDecl,
                                       ClangNode clangNode = ClangNode()) {
    auto &C = Impl.SwiftContext;
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), importedDecl);
  
    ParameterList *params[] = {
      ParameterList::createWithoutLoc(selfDecl),
      ParameterList::createEmpty(C)
    };
    
    auto getterType = importedFieldDecl->getType();
    auto getterDecl =
      FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
                       /*FuncLoc=*/importedFieldDecl->getLoc(),
                       DeclName(), /*NameLoc=*/SourceLoc(),
                       /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                       /*AccessorKeywordLoc=*/SourceLoc(),
                       /*GenericParams=*/nullptr, params,
                       TypeLoc::withoutLoc(getterType), importedDecl, clangNode);
    getterDecl->setAccess(AccessLevel::Public);
  
    auto type = ParameterList::getFullInterfaceType(getterType, params, C);
    getterDecl->setInterfaceType(type);
    getterDecl->setValidationStarted();
  
    return getterDecl;
  }
  
  static FuncDecl *makeFieldSetterDecl(ClangImporter::Implementation &Impl,
                                       StructDecl *importedDecl,
                                       VarDecl *importedFieldDecl,
                                       ClangNode clangNode = ClangNode()) {
    auto &C = Impl.SwiftContext;
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), importedDecl,
                                          /*isStatic*/false, /*isInOut*/true);
    auto newValueDecl = new (C) ParamDecl(VarDecl::Specifier::Owned,
                                          SourceLoc(), SourceLoc(),
                                          Identifier(), SourceLoc(), C.Id_value,
                                          importedFieldDecl->getType(),
                                          importedDecl);
    newValueDecl->setInterfaceType(importedFieldDecl->getInterfaceType());
  
    ParameterList *params[] = {
      ParameterList::createWithoutLoc(selfDecl),
      ParameterList::createWithoutLoc(newValueDecl),
    };
  
    auto voidTy = TupleType::getEmpty(C);
  
    auto setterDecl =
      FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
                       /*FuncLoc=*/SourceLoc(), DeclName(), /*NameLoc=*/SourceLoc(),
                       /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                       /*AccessorKeywordLoc=*/SourceLoc(),
                       /*GenericParams=*/nullptr, params,
                       TypeLoc::withoutLoc(voidTy), importedDecl, clangNode);
  
    auto type = ParameterList::getFullInterfaceType(voidTy, params, C);
    setterDecl->setInterfaceType(type);
    setterDecl->setValidationStarted();
  
    setterDecl->setAccess(AccessLevel::Public);
    setterDecl->setSelfAccessKind(SelfAccessKind::Mutating);
  
    return setterDecl;
  }
  
  /// Build the indirect field getter and setter.
  ///
  /// \code
  /// struct SomeImportedIndirectField {
  ///   struct __Unnamed_struct___Anonymous_field_1 {
  ///     var myField : Int
  ///   }
  ///   var __Anonymous_field_1 : __Unnamed_struct___Anonymous_field_1
  ///   var myField : Int {
  ///     get {
  ///       __Anonymous_field_1.myField
  ///     }
  ///     set(newValue) {
  ///       __Anonymous_field_1.myField = newValue
  ///     }
  ///   }
  /// }
  /// \endcode
  ///
  /// \returns a pair of getter and setter function decls.
  static std::pair<FuncDecl *, FuncDecl *>
  makeIndirectFieldAccessors(ClangImporter::Implementation &Impl,
                             const clang::IndirectFieldDecl *indirectField,
                             ArrayRef<VarDecl *> members,
                             StructDecl *importedStructDecl,
                             VarDecl *importedFieldDecl) {
    auto &C = Impl.SwiftContext;
  
    auto getterDecl = makeFieldGetterDecl(Impl,
                                          importedStructDecl,
                                          importedFieldDecl);
  
    auto setterDecl = makeFieldSetterDecl(Impl,
                                          importedStructDecl,
                                          importedFieldDecl);
  
    importedFieldDecl->makeComputed(SourceLoc(), getterDecl, setterDecl, nullptr,
                                    SourceLoc());
  
    auto containingField = indirectField->chain().front();
    VarDecl *anonymousFieldDecl = nullptr;
  
    // Reverse scan of the members because indirect field are generated just
    // after the corresponding anonymous type, so a reverse scan allows
    // switching from O(n) to O(1) here.
    for (auto decl : reverse(members)) {
      if (decl->getClangDecl() == containingField) {
        anonymousFieldDecl = cast<VarDecl>(decl);
        break;
      }
    }
    assert (anonymousFieldDecl && "anonymous field not generated");
  
    auto anonymousFieldType = anonymousFieldDecl->getInterfaceType();
    auto anonymousFieldTypeDecl = anonymousFieldType->getStructOrBoundGenericStruct();
  
    VarDecl *anonymousInnerFieldDecl = nullptr;
    for (auto decl : anonymousFieldTypeDecl->lookupDirect(importedFieldDecl->getName())) {
      if (isa<VarDecl>(decl)) {
        anonymousInnerFieldDecl = cast<VarDecl>(decl);
        break;
      }
    }
    assert (anonymousInnerFieldDecl && "cannot find field in anonymous generated structure");
  
    // Don't bother synthesizing the body if we've already finished type-checking.
    if (Impl.hasFinishedTypeChecking())
      return { getterDecl, setterDecl };
  
    // Synthesize the getter body
    {
      auto selfDecl = getterDecl->getImplicitSelfDecl();
      Expr *expr = new (C) DeclRefExpr(selfDecl, DeclNameLoc(),
                                       /*implicit*/true);
      expr = new (C) MemberRefExpr(expr, SourceLoc(), anonymousFieldDecl,
                                   DeclNameLoc(), /*implicit*/true);
  
      expr = new (C) MemberRefExpr(expr, SourceLoc(), anonymousInnerFieldDecl,
                                   DeclNameLoc(), /*implicit*/true);
  
      auto ret = new (C) ReturnStmt(SourceLoc(), expr);
      auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
                                    /*implicit*/ true);
      getterDecl->setBody(body);
      getterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
      C.addExternalDecl(getterDecl);
    }
  
    // Synthesize the setter body
    {
      auto selfDecl = setterDecl->getImplicitSelfDecl();
      Expr *lhs = new (C) DeclRefExpr(selfDecl, DeclNameLoc(),
                                       /*implicit*/true);
      lhs = new (C) MemberRefExpr(lhs, SourceLoc(), anonymousFieldDecl,
                                   DeclNameLoc(), /*implicit*/true);
  
      lhs = new (C) MemberRefExpr(lhs, SourceLoc(), anonymousInnerFieldDecl,
                                  DeclNameLoc(), /*implicit*/true);
  
      auto newValueDecl = setterDecl->getParameterList(1)->get(0);
  
      auto rhs = new (C) DeclRefExpr(newValueDecl, DeclNameLoc(),
                                     /*implicit*/ true);
  
      auto assign = new (C) AssignExpr(lhs, SourceLoc(), rhs, /*implicit*/true);
  
      auto body = BraceStmt::create(C, SourceLoc(), { assign }, SourceLoc(),
                                    /*implicit*/ true);
      setterDecl->setBody(body);
      setterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
      C.addExternalDecl(setterDecl);
    }
  
    return { getterDecl, setterDecl };
  }
  
  /// Build the union field getter and setter.
  ///
  /// \code
  /// struct SomeImportedUnion {
  ///   var myField: Int {
  ///     get {
  ///       return Builtin.reinterpretCast(self)
  ///     }
  ///     set(newValue) {
  ///       Builtin.initialize(Builtin.addressof(self), newValue))
  ///     }
  ///   }
  /// }
  /// \endcode
  ///
  /// \returns a pair of the getter and setter function decls.
  static std::pair<FuncDecl *, FuncDecl *>
  makeUnionFieldAccessors(ClangImporter::Implementation &Impl,
                          StructDecl *importedUnionDecl,
                          VarDecl *importedFieldDecl) {
    auto &C = Impl.SwiftContext;
  
    auto getterDecl = makeFieldGetterDecl(Impl,
                                          importedUnionDecl,
                                          importedFieldDecl);
  
    auto setterDecl = makeFieldSetterDecl(Impl,
                                          importedUnionDecl,
                                          importedFieldDecl);
  
    importedFieldDecl->makeComputed(SourceLoc(), getterDecl, setterDecl, nullptr,
                                    SourceLoc());
  
    // Don't bother synthesizing the body if we've already finished type-checking.
    if (Impl.hasFinishedTypeChecking())
      return { getterDecl, setterDecl };
  
    // Synthesize the getter body
    {
      auto selfDecl = getterDecl->getImplicitSelfDecl();
  
      auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(),
                                         /*implicit*/ true);
      auto reinterpretCast = cast<FuncDecl>(getBuiltinValueDecl(
          C, C.getIdentifier("reinterpretCast")));
      auto reinterpretCastRef
        = new (C) DeclRefExpr(reinterpretCast, DeclNameLoc(), /*implicit*/ true);
      auto reinterpreted = CallExpr::createImplicit(C, reinterpretCastRef,
                                                    { selfRef },
                                                    { Identifier() });
      auto ret = new (C) ReturnStmt(SourceLoc(), reinterpreted);
      auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
                                    /*implicit*/ true);
      getterDecl->setBody(body);
      getterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
      C.addExternalDecl(getterDecl);
    }
  
    // Synthesize the setter body
    {
      auto inoutSelfDecl = setterDecl->getImplicitSelfDecl();
  
      auto inoutSelfRef = new (C) DeclRefExpr(inoutSelfDecl, DeclNameLoc(),
                                              /*implicit*/ true);
      auto inoutSelf = new (C) InOutExpr(SourceLoc(), inoutSelfRef,
        importedUnionDecl->getDeclaredType(), /*implicit*/ true);
  
      auto newValueDecl = setterDecl->getParameterList(1)->get(0);
  
      auto newValueRef = new (C) DeclRefExpr(newValueDecl, DeclNameLoc(),
                                             /*implicit*/ true);
      auto addressofFn = cast<FuncDecl>(getBuiltinValueDecl(
        C, C.getIdentifier("addressof")));
      auto addressofFnRef
        = new (C) DeclRefExpr(addressofFn, DeclNameLoc(), /*implicit*/ true);
      auto selfPointer = CallExpr::createImplicit(C, addressofFnRef,
                                                  { inoutSelf },
                                                  { Identifier() });
      auto initializeFn = cast<FuncDecl>(getBuiltinValueDecl(
        C, C.getIdentifier("initialize")));
      auto initializeFnRef
        = new (C) DeclRefExpr(initializeFn, DeclNameLoc(), /*implicit*/ true);
      auto initialize = CallExpr::createImplicit(C, initializeFnRef,
                                                 { newValueRef, selfPointer },
                                                 { Identifier(), Identifier() });
      auto body = BraceStmt::create(C, SourceLoc(), { initialize }, SourceLoc(),
                                    /*implicit*/ true);
      setterDecl->setBody(body);
      setterDecl->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
      C.addExternalDecl(setterDecl);
    }
  
    return { getterDecl, setterDecl };
  }
  
  static clang::DeclarationName
  getAccessorDeclarationName(clang::ASTContext &Ctx,
                             StructDecl *structDecl,
                             VarDecl *fieldDecl,
                             const char *suffix) {
    std::string id;
    llvm::raw_string_ostream IdStream(id);
    IdStream << "$" << structDecl->getName()
             << "$" << fieldDecl->getName()
             << "$" << suffix;
  
    return clang::DeclarationName(&Ctx.Idents.get(IdStream.str()));
  }
  
  /// Build the bitfield getter and setter using Clang.
  ///
  /// \code
  /// static inline int get(RecordType self) {
  ///   return self.field;
  /// }
  /// static inline void set(int newValue, RecordType *self) {
  ///   self->field = newValue;
  /// }
  /// \endcode
  ///
  /// \returns a pair of the getter and setter function decls.
  static std::pair<FuncDecl *, FuncDecl *>
  makeBitFieldAccessors(ClangImporter::Implementation &Impl,
                        clang::RecordDecl *structDecl,
                        StructDecl *importedStructDecl,
                        clang::FieldDecl *fieldDecl,
                        VarDecl *importedFieldDecl) {
    clang::ASTContext &Ctx = Impl.getClangASTContext();
  
    // Getter: static inline FieldType get(RecordType self);
    auto recordType = Ctx.getRecordType(structDecl);
    auto recordPointerType = Ctx.getPointerType(recordType);
    auto fieldType = fieldDecl->getType();
    auto fieldNameInfo = clang::DeclarationNameInfo(fieldDecl->getDeclName(),
                                                    clang::SourceLocation());
  
    auto cGetterName = getAccessorDeclarationName(Ctx, importedStructDecl,
                                                  importedFieldDecl, "getter");
    auto cGetterType = Ctx.getFunctionType(fieldDecl->getType(),
                                           recordType,
                                           clang::FunctionProtoType::ExtProtoInfo());
    auto cGetterTypeInfo = Ctx.getTrivialTypeSourceInfo(cGetterType);
    auto cGetterDecl = clang::FunctionDecl::Create(Ctx,
                                                   structDecl->getDeclContext(),
                                                   clang::SourceLocation(),
                                                   clang::SourceLocation(),
                                                   cGetterName,
                                                   cGetterType,
                                                   cGetterTypeInfo,
                                                   clang::SC_Static);
    cGetterDecl->setImplicitlyInline();
    assert(!cGetterDecl->isExternallyVisible());
  
    auto getterDecl = makeFieldGetterDecl(Impl,
                                          importedStructDecl,
                                          importedFieldDecl,
                                          cGetterDecl);
  
    // Setter: static inline void set(FieldType newValue, RecordType *self);
    SmallVector<clang::QualType, 8> cSetterParamTypes;
    cSetterParamTypes.push_back(fieldType);
    cSetterParamTypes.push_back(recordPointerType);
  
    auto cSetterName = getAccessorDeclarationName(Ctx, importedStructDecl,
                                                  importedFieldDecl, "setter");
    auto cSetterType = Ctx.getFunctionType(Ctx.VoidTy,
                                           cSetterParamTypes,
                                           clang::FunctionProtoType::ExtProtoInfo());
    auto cSetterTypeInfo = Ctx.getTrivialTypeSourceInfo(cSetterType);
    
    auto cSetterDecl = clang::FunctionDecl::Create(Ctx,
                                                   structDecl->getDeclContext(),
                                                   clang::SourceLocation(),
                                                   clang::SourceLocation(),
                                                   cSetterName,
                                                   cSetterType,
                                                   cSetterTypeInfo,
                                                   clang::SC_Static);
    cSetterDecl->setImplicitlyInline();
    assert(!cSetterDecl->isExternallyVisible());
  
    auto setterDecl = makeFieldSetterDecl(Impl,
                                          importedStructDecl,
                                          importedFieldDecl,
                                          cSetterDecl);
  
    importedFieldDecl->makeComputed(SourceLoc(),
                                    getterDecl,
                                    setterDecl,
                                    nullptr,
                                    SourceLoc());
  
    // Don't bother synthesizing the body if we've already finished type-checking.
    if (Impl.hasFinishedTypeChecking())
      return { getterDecl, setterDecl };
    
    // Synthesize the getter body
    {
      auto cGetterSelfId = nullptr;
      auto recordTypeInfo = Ctx.getTrivialTypeSourceInfo(recordType);
      auto cGetterSelf = clang::ParmVarDecl::Create(Ctx, cGetterDecl,
                                                    clang::SourceLocation(),
                                                    clang::SourceLocation(),
                                                    cGetterSelfId,
                                                    recordType,
                                                    recordTypeInfo,
                                                    clang::SC_None,
                                                    nullptr);
      cGetterDecl->setParams(cGetterSelf);
      
      auto cGetterSelfExpr = new (Ctx) clang::DeclRefExpr(cGetterSelf, false,
                                                          recordType,
                                                          clang::VK_RValue,
                                                          clang::SourceLocation());
      auto cGetterExpr = new (Ctx) clang::MemberExpr(cGetterSelfExpr,
                                                     /*isarrow=*/ false,
                                                     clang::SourceLocation(),
                                                     fieldDecl,
                                                     fieldNameInfo,
                                                     fieldType,
                                                     clang::VK_RValue,
                                                     clang::OK_BitField);
      
      auto cGetterBody = new (Ctx) clang::ReturnStmt(clang::SourceLocation(),
                                                     cGetterExpr,
                                                     nullptr);
      cGetterDecl->setBody(cGetterBody);
  
      Impl.registerExternalDecl(getterDecl);
    }
  
    // Synthesize the setter body
    {
      SmallVector<clang::ParmVarDecl *, 2> cSetterParams;
      auto fieldTypeInfo = Ctx.getTrivialTypeSourceInfo(fieldType);
      auto cSetterValue = clang::ParmVarDecl::Create(Ctx, cSetterDecl,
                                                     clang::SourceLocation(),
                                                     clang::SourceLocation(),
                                                     /* nameID? */ nullptr,
                                                     fieldType,
                                                     fieldTypeInfo,
                                                     clang::SC_None,
                                                     nullptr);
      cSetterParams.push_back(cSetterValue);
      auto recordPointerTypeInfo = Ctx.getTrivialTypeSourceInfo(recordPointerType);
      auto cSetterSelf = clang::ParmVarDecl::Create(Ctx, cSetterDecl,
                                                    clang::SourceLocation(),
                                                    clang::SourceLocation(),
                                                    /* nameID? */ nullptr,
                                                    recordPointerType,
                                                    recordPointerTypeInfo,
                                                    clang::SC_None,
                                                    nullptr);
      cSetterParams.push_back(cSetterSelf);
      cSetterDecl->setParams(cSetterParams);
      
      auto cSetterSelfExpr = new (Ctx) clang::DeclRefExpr(cSetterSelf, false,
                                                          recordPointerType,
                                                          clang::VK_RValue,
                                                          clang::SourceLocation());
      
      auto cSetterMemberExpr = new (Ctx) clang::MemberExpr(cSetterSelfExpr,
                                                           /*isarrow=*/ true,
                                                           clang::SourceLocation(),
                                                           fieldDecl,
                                                           fieldNameInfo,
                                                           fieldType,
                                                           clang::VK_LValue,
                                                           clang::OK_BitField);
      
      auto cSetterValueExpr = new (Ctx) clang::DeclRefExpr(cSetterValue, false,
                                                           fieldType,
                                                           clang::VK_RValue,
                                                           clang::SourceLocation());
      
      auto cSetterExpr = new (Ctx) clang::BinaryOperator(cSetterMemberExpr,
                                                         cSetterValueExpr,
                                                         clang::BO_Assign,
                                                         fieldType,
                                                         clang::VK_RValue,
                                                         clang::OK_Ordinary,
                                                         clang::SourceLocation(),
                                                         clang::FPOptions());
      
      cSetterDecl->setBody(cSetterExpr);
  
      Impl.registerExternalDecl(setterDecl);
    }
  
    return { getterDecl, setterDecl };
  }
  
  /// Create a default constructor that initializes a struct to zero.
  static ConstructorDecl *
  createDefaultConstructor(ClangImporter::Implementation &Impl,
                           StructDecl *structDecl) {
    auto &context = Impl.SwiftContext;
  
    // Create the 'self' declaration.
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), structDecl,
                                          /*static*/ false, /*inout*/ true);
  
    // self & param.
    auto emptyPL = ParameterList::createEmpty(context);
  
    // Create the constructor.
    DeclName name(context, context.Id_init, emptyPL);
    auto constructor = new (context) ConstructorDecl(
        name, structDecl->getLoc(), OTK_None, /*FailabilityLoc=*/SourceLoc(),
        /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), selfDecl, emptyPL,
        /*GenericParams=*/nullptr, structDecl);
  
    // Set the constructor's type.
    auto selfType = structDecl->getDeclaredInterfaceType();
    auto selfMetatype = MetatypeType::get(selfType);
    auto emptyTy = TupleType::getEmpty(context);
    auto fnTy = FunctionType::get(emptyTy, selfType);
    auto allocFnTy = FunctionType::get(selfMetatype, fnTy);
    auto initFnTy = FunctionType::get(selfType, fnTy);
    constructor->setInterfaceType(allocFnTy);
    constructor->setInitializerInterfaceType(initFnTy);
    constructor->setValidationStarted();
  
    constructor->setAccess(AccessLevel::Public);
  
    // Mark the constructor transparent so that we inline it away completely.
    constructor->getAttrs().add(new (context) TransparentAttr(/*implicit*/ true));
  
    if (Impl.hasFinishedTypeChecking())
      return constructor;
  
    // Use a builtin to produce a zero initializer, and assign it to self.
  
    // Construct the left-hand reference to self.
    Expr *lhs = new (context) DeclRefExpr(selfDecl,
                                          DeclNameLoc(), /*Implicit=*/true);
    lhs->setType(LValueType::get(selfType));
    lhs->propagateLValueAccessKind(AccessKind::Write);
  
    auto emptyTuple = TupleType::getEmpty(context);
  
    // Construct the right-hand call to Builtin.zeroInitializer.
    Identifier zeroInitID = context.getIdentifier("zeroInitializer");
    auto zeroInitializerFunc = getBuiltinValueDecl(context, zeroInitID);
    ConcreteDeclRef concreteDeclRef(context, zeroInitializerFunc,
                                    { Substitution(selfType, {}) });
    auto zeroInitializerRef =
      new (context) DeclRefExpr(concreteDeclRef, DeclNameLoc(),
                                /*implicit*/ true);
    zeroInitializerRef->setType(FunctionType::get(emptyTuple, selfType));
  
    auto call = CallExpr::createImplicit(context, zeroInitializerRef, {}, {});
    call->setType(selfType);
  
    auto assign = new (context) AssignExpr(lhs, SourceLoc(), call,
                                           /*implicit*/ true);
    assign->setType(emptyTuple);
  
    auto result = TupleExpr::createEmpty(context, SourceLoc(), SourceLoc(),
                                         /*Implicit=*/true);
    result->setType(emptyTuple);
  
    auto ret = new (context) ReturnStmt(SourceLoc(), result, /*Implicit=*/true);
  
    // Create the function body.
    auto body = BraceStmt::create(context, SourceLoc(), {assign, ret},
                                  SourceLoc());
    constructor->setBody(body);
    constructor->setBodyTypeCheckedIfPresent();
  
    // Add this as an external definition.
    Impl.registerExternalDecl(constructor);
  
    // We're done.
    return constructor;
  }
  
  /// \brief Create a constructor that initializes a struct from its members.
  static ConstructorDecl *
  createValueConstructor(ClangImporter::Implementation &Impl,
                         StructDecl *structDecl, ArrayRef<VarDecl *> members,
                         bool wantCtorParamNames, bool wantBody) {
    auto &context = Impl.SwiftContext;
  
    // Create the 'self' declaration.
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), structDecl,
                                          /*static*/ false, /*inout*/ true);
  
    // Construct the set of parameters from the list of members.
    SmallVector<ParamDecl *, 8> valueParameters;
    for (auto var : members) {
      bool generateParamName = wantCtorParamNames;
  
      if (var->hasClangNode()) {
        // TODO create value constructor with indirect fields instead of the
        // generated __Anonymous_field.
        if (isa<clang::IndirectFieldDecl>(var->getClangDecl()))
          continue;
  
        if (auto clangField = dyn_cast<clang::FieldDecl>(var->getClangDecl()))
          if (clangField->isAnonymousStructOrUnion())
            generateParamName = false;
      }
  
      Identifier argName = generateParamName ? var->getName() : Identifier();
      auto param = new (context)
          ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(), argName,
                    SourceLoc(), var->getName(), var->getType(), structDecl);
      param->setInterfaceType(var->getInterfaceType());
      param->setValidationStarted();
      valueParameters.push_back(param);
    }
  
    // self & param.
    ParameterList *paramLists[] = {
        ParameterList::createWithoutLoc(selfDecl),
        ParameterList::create(context, valueParameters)};
  
    // Create the constructor
    DeclName name(context, context.Id_init, paramLists[1]);
    auto constructor = new (context) ConstructorDecl(
        name, structDecl->getLoc(), OTK_None, /*FailabilityLoc=*/SourceLoc(),
        /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), selfDecl, paramLists[1],
        /*GenericParams=*/nullptr, structDecl);
  
    // Set the constructor's type.
    auto paramTy = paramLists[1]->getType(context);
    auto selfType = structDecl->getDeclaredTypeInContext();
    auto selfMetatype = MetatypeType::get(selfType);
    auto fnTy = FunctionType::get(paramTy, selfType);
    auto allocFnTy = FunctionType::get(selfMetatype, fnTy);
    auto initFnTy = FunctionType::get(selfType, fnTy);
    constructor->setInterfaceType(allocFnTy);
    constructor->setInitializerInterfaceType(initFnTy);
    constructor->setValidationStarted();
  
    constructor->setAccess(AccessLevel::Public);
  
    // Make the constructor transparent so we inline it away completely.
    constructor->getAttrs().add(new (context) TransparentAttr(/*implicit*/ true));
  
    if (wantBody) {
      // Assign all of the member variables appropriately.
      SmallVector<ASTNode, 4> stmts;
  
      // To keep DI happy, initialize stored properties before computed.
      for (unsigned pass = 0; pass < 2; pass++) {
        unsigned paramPos = 0;
  
        for (unsigned i = 0, e = members.size(); i < e; i++) {
          auto var = members[i];
  
          if (var->hasClangNode() && isa<clang::IndirectFieldDecl>(var->getClangDecl()))
            continue;
  
          if (var->hasStorage() == (pass != 0)) {
            paramPos++;
            continue;
          }
  
          // Construct left-hand side.
          Expr *lhs = new (context) DeclRefExpr(selfDecl, DeclNameLoc(),
                                                /*Implicit=*/true);
          lhs->setType(LValueType::get(selfDecl->getType()->getInOutObjectType()));
  
          auto semantics = (var->hasStorage()
                            ? AccessSemantics::DirectToStorage
                            : AccessSemantics::Ordinary);
  
          lhs = new (context) MemberRefExpr(lhs, SourceLoc(), var, DeclNameLoc(),
                                            /*Implicit=*/true,
                                            semantics);
          lhs->setType(LValueType::get(var->getType()));
          lhs->propagateLValueAccessKind(AccessKind::Write);
  
          // Construct right-hand side.
          auto rhs = new (context) DeclRefExpr(valueParameters[paramPos],
                                               DeclNameLoc(),
                                               /*Implicit=*/true);
          rhs->setType(valueParameters[paramPos]->getType());
  
          // Add assignment.
          auto assign = new (context) AssignExpr(lhs, SourceLoc(), rhs,
                                                 /*Implicit=*/true);
          assign->setType(TupleType::getEmpty(context));
  
          stmts.push_back(assign);
          paramPos++;
        }
      }
  
      auto result = TupleExpr::createEmpty(context, SourceLoc(), SourceLoc(),
                                           /*Implicit=*/true);
      result->setType(TupleType::getEmpty(context));
  
      auto ret = new (context) ReturnStmt(SourceLoc(), result, /*Implicit=*/true);
      stmts.push_back(ret);
  
      // Create the function body.
      auto body = BraceStmt::create(context, SourceLoc(), stmts, SourceLoc());
      constructor->setBody(body);
      constructor->setBodyTypeCheckedIfPresent();
    }
  
    // Add this as an external definition.
    Impl.registerExternalDecl(constructor);
  
    // We're done.
    return constructor;
  }
  
  static void addSynthesizedProtocolAttrs(
      ClangImporter::Implementation &Impl,
      NominalTypeDecl *nominal,
      ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs) {
    for (auto kind : synthesizedProtocolAttrs) {
      nominal->getAttrs().add(new (Impl.SwiftContext)
                                   SynthesizedProtocolAttr(kind, &Impl));
    }
  }
  
  /// Add a synthesized typealias to the given nominal type.
  static void addSynthesizedTypealias(NominalTypeDecl *nominal, Identifier name,
                                      Type underlyingType) {
    auto &ctx = nominal->getASTContext();
  
    auto typealias = new (ctx) TypeAliasDecl(SourceLoc(), SourceLoc(),
                                             name, SourceLoc(),
                                             nullptr, nominal);
    typealias->setUnderlyingType(underlyingType);
    typealias->setEarlyAttrValidation(true);
    typealias->setAccess(AccessLevel::Public);
    typealias->setValidationStarted();
    typealias->setImplicit();
  
    nominal->addMember(typealias);
  }
  
  /// Make a struct declaration into a raw-value-backed struct
  ///
  /// \param structDecl the struct to make a raw value for
  /// \param underlyingType the type of the raw value
  /// \param synthesizedProtocolAttrs synthesized protocol attributes to add
  /// \param setterAccess the access level of the raw value's setter
  ///
  /// This will perform most of the work involved in making a new Swift struct
  /// be backed by a raw value. This will populated derived protocols and
  /// synthesized protocols, add the new variable and pattern bindings, and
  /// create the inits parameterized over a raw value
  ///
  static void makeStructRawValued(
      ClangImporter::Implementation &Impl, StructDecl *structDecl,
      Type underlyingType, ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
      MakeStructRawValuedOptions options = getDefaultMakeStructRawValuedOptions(),
      AccessLevel setterAccess = AccessLevel::Private) {
    auto &ctx = Impl.SwiftContext;
  
    addSynthesizedProtocolAttrs(Impl, structDecl, synthesizedProtocolAttrs);
  
    // Create a variable to store the underlying value.
    VarDecl *var;
    PatternBindingDecl *patternBinding;
    auto specifier = options.contains(MakeStructRawValuedFlags::IsLet)
                   ? VarDecl::Specifier::Let
                   : VarDecl::Specifier::Var;
    std::tie(var, patternBinding) = createVarWithPattern(
        ctx, structDecl, ctx.Id_rawValue, underlyingType,
        specifier,
        options.contains(MakeStructRawValuedFlags::IsImplicit),
        AccessLevel::Public,
        setterAccess);
  
    // Create the getter for the computed value variable.
    auto varGetter = makeStructRawValueGetter(
        Impl, structDecl, var, var);
  
    var->addTrivialAccessors(varGetter, nullptr, nullptr);
    assert(var->hasStorage());
  
    structDecl->setHasDelayedMembers();
  
    // Create constructors to initialize that value from a value of the
    // underlying type.
    if (options.contains(MakeStructRawValuedFlags::MakeUnlabeledValueInit))
      structDecl->addMember(
          createValueConstructor(Impl, structDecl, var,
                                 /*wantCtorParamNames=*/false,
                                 /*wantBody=*/!Impl.hasFinishedTypeChecking()));
    structDecl->addMember(
        createValueConstructor(Impl, structDecl, var,
                               /*wantCtorParamNames=*/true,
                               /*wantBody=*/!Impl.hasFinishedTypeChecking()));
    structDecl->addMember(patternBinding);
    structDecl->addMember(var);
    structDecl->addMember(varGetter);
  
    addSynthesizedTypealias(structDecl, ctx.Id_RawValue, underlyingType);
  }
  
  /// Create a rawValue-ed constructor that bridges to its underlying storage.
  static ConstructorDecl *createRawValueBridgingConstructor(
      ClangImporter::Implementation &Impl, StructDecl *structDecl,
      VarDecl *computedRawValue, VarDecl *storedRawValue, bool wantLabel,
      bool wantBody) {
    auto &ctx = Impl.SwiftContext;
    auto init = createValueConstructor(Impl, structDecl, computedRawValue,
                                       /*wantCtorParamNames=*/wantLabel,
                                       /*wantBody=*/false);
    // Insert our custom init body
    if (wantBody) {
      auto selfDecl = init->getParameterList(0)->get(0);
  
      auto storedType = storedRawValue->getInterfaceType();
  
      // Construct left-hand side.
      Expr *lhs = new (ctx) DeclRefExpr(selfDecl, DeclNameLoc(),
                                        /*Implicit=*/true);
      lhs->setType(LValueType::get(selfDecl->getType()->getInOutObjectType()));
  
      lhs = new (ctx) MemberRefExpr(lhs, SourceLoc(), storedRawValue,
                                    DeclNameLoc(), /*Implicit=*/true,
                                    AccessSemantics::DirectToStorage);
      lhs->setType(LValueType::get(storedType));
      lhs->propagateLValueAccessKind(AccessKind::Write);
  
      // Construct right-hand side.
      // FIXME: get the parameter from the init, and plug it in here.
      auto *paramDecl = init->getParameterList(1)->get(0);
      auto *paramRef = new (ctx) DeclRefExpr(
          paramDecl, DeclNameLoc(), /*Implicit=*/true);
      paramRef->setType(paramDecl->getType());
  
      Expr *rhs = paramRef;
      if (!storedRawValue->getInterfaceType()->isEqual(paramDecl->getType())) {
        auto bridge = new (ctx) BridgeToObjCExpr(paramRef, storedType);
        bridge->setType(storedType);
  
        auto coerce = new (ctx) CoerceExpr(bridge, SourceLoc(),
                                           {nullptr, storedType});
        coerce->setType(storedType);
  
        rhs = coerce;
      }
  
      // Add assignment.
      auto assign = new (ctx) AssignExpr(lhs, SourceLoc(), rhs,
                                         /*Implicit=*/true);
      assign->setType(TupleType::getEmpty(ctx));
  
      auto result = TupleExpr::createEmpty(ctx, SourceLoc(), SourceLoc(),
                                           /*Implicit=*/true);
      auto ret = new (ctx) ReturnStmt(SourceLoc(), result, /*Implicit=*/true);
  
      auto body = BraceStmt::create(ctx, SourceLoc(), {assign, ret}, SourceLoc());
      init->setBody(body);
      init->setBodyTypeCheckedIfPresent();
    }
  
    return init;
  }
  
  /// Make a struct declaration into a raw-value-backed struct, with
  /// bridged computed rawValue property which differs from stored backing
  ///
  /// \param structDecl the struct to make a raw value for
  /// \param storedUnderlyingType the type of the stored raw value
  /// \param bridgedType the type of the 'rawValue' computed property bridge
  /// \param synthesizedProtocolAttrs synthesized protocol attributes to add
  ///
  /// This will perform most of the work involved in making a new Swift struct
  /// be backed by a stored raw value and computed raw value of bridged type.
  /// This will populated derived protocols and synthesized protocols, add the
  /// new variable and pattern bindings, and create the inits parameterized
  /// over a bridged type that will cast to the stored type, as appropriate.
  ///
  static void makeStructRawValuedWithBridge(
      ClangImporter::Implementation &Impl, StructDecl *structDecl,
      Type storedUnderlyingType, Type bridgedType,
      ArrayRef<KnownProtocolKind> synthesizedProtocolAttrs,
      bool makeUnlabeledValueInit = false) {
    auto &ctx = Impl.SwiftContext;
  
    addSynthesizedProtocolAttrs(Impl, structDecl, synthesizedProtocolAttrs);
  
    auto storedVarName = ctx.getIdentifier("_rawValue");
    auto computedVarName = ctx.Id_rawValue;
  
    // Create a variable to store the underlying value.
    VarDecl *storedVar;
    PatternBindingDecl *storedPatternBinding;
    std::tie(storedVar, storedPatternBinding) = createVarWithPattern(
        ctx, structDecl, storedVarName, storedUnderlyingType,
        VarDecl::Specifier::Var, /*isImplicit=*/true,
        AccessLevel::Private,
        AccessLevel::Private);
  
    // Create a computed value variable.
    auto computedVar = new (ctx) VarDecl(
        /*IsStatic*/false, VarDecl::Specifier::Var, /*IsCaptureList*/false,
        SourceLoc(), computedVarName, bridgedType, structDecl);
    computedVar->setInterfaceType(bridgedType);
    computedVar->setImplicit();
    computedVar->setAccess(AccessLevel::Public);
    computedVar->setSetterAccess(AccessLevel::Private);
    computedVar->setValidationStarted();
  
    // Create the getter for the computed value variable.
    auto computedVarGetter = makeStructRawValueGetter(
        Impl, structDecl, computedVar, storedVar);
    computedVar->makeComputed(SourceLoc(), computedVarGetter, nullptr, nullptr,
                              SourceLoc());
  
    // Create a pattern binding to describe the variable.
    Pattern *computedVarPattern = createTypedNamedPattern(computedVar);
    auto computedPatternBinding = PatternBindingDecl::create(
        ctx, SourceLoc(), StaticSpellingKind::None, SourceLoc(),
        computedVarPattern, nullptr, structDecl);
  
    // Don't bother synthesizing the body if we've already finished
    // type-checking.
    bool wantBody = !Impl.hasFinishedTypeChecking();
  
    auto init = createRawValueBridgingConstructor(Impl, structDecl, computedVar,
                                                  storedVar,
                                                  /*wantLabel*/ true, wantBody);
  
    ConstructorDecl *unlabeledCtor = nullptr;
    if (makeUnlabeledValueInit)
      unlabeledCtor = createRawValueBridgingConstructor(
          Impl, structDecl, computedVar, storedVar,
          /*wantLabel*/ false, wantBody);
  
    structDecl->setHasDelayedMembers();
    if (unlabeledCtor)
      structDecl->addMember(unlabeledCtor);
    structDecl->addMember(init);
    structDecl->addMember(storedPatternBinding);
    structDecl->addMember(storedVar);
    structDecl->addMember(computedPatternBinding);
    structDecl->addMember(computedVar);
    structDecl->addMember(computedVarGetter);
  
    addSynthesizedTypealias(structDecl, ctx.Id_RawValue, bridgedType);
  }
  
  static Type getGenericMethodType(DeclContext *dc, AnyFunctionType *fnType) {
    assert(!fnType->hasArchetype());
  
    auto *sig = dc->getGenericSignatureOfContext();
    if (!sig)
      return fnType;
  
    Type interfaceType = GenericFunctionType::get(
        sig, fnType->getParams(), fnType->getResult(), AnyFunctionType::ExtInfo());
  
    return interfaceType;
  }
  
  /// Build a declaration for an Objective-C subscript getter.
  static FuncDecl *buildSubscriptGetterDecl(ClangImporter::Implementation &Impl,
                                            const FuncDecl *getter,
                                            Type elementTy, DeclContext *dc,
                                            ParamDecl *index) {
    auto &C = Impl.SwiftContext;
    auto loc = getter->getLoc();
  
    // self & index.
    ParameterList *getterArgs[] = {ParameterList::createSelf(SourceLoc(), dc),
                                   ParameterList::create(C, index)};
  
    // Form the type of the getter.
    auto getterType =
        ParameterList::getFullInterfaceType(elementTy, getterArgs, C);
  
    auto interfaceType =
        getGenericMethodType(dc, getterType->castTo<AnyFunctionType>());
  
    // Create the getter thunk.
    FuncDecl *thunk = FuncDecl::create(
        C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
        /*FuncLoc=*/loc, /*Name=*/Identifier(), /*NameLoc=*/SourceLoc(),
        /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
        /*AccessorKeywordLoc=*/SourceLoc(),
        /*GenericParams=*/nullptr, getterArgs,
        TypeLoc::withoutLoc(elementTy), dc, getter->getClangNode());
    thunk->setInterfaceType(interfaceType);
    thunk->setValidationStarted();
    thunk->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
  
    thunk->setAccess(getOverridableAccessLevel(dc));
  
    auto objcAttr = getter->getAttrs().getAttribute<ObjCAttr>();
    assert(objcAttr);
    thunk->getAttrs().add(objcAttr->clone(C));
    // FIXME: Should we record thunks?
  
    return thunk;
  }
  
  /// Build a declaration for an Objective-C subscript setter.
  static FuncDecl *buildSubscriptSetterDecl(ClangImporter::Implementation &Impl,
                                            const FuncDecl *setter,
                                            Type elementInterfaceTy,
                                            DeclContext *dc, ParamDecl *index) {
    auto &C = Impl.SwiftContext;
    auto loc = setter->getLoc();
  
    // Objective-C subscript setters are imported with a function type
    // such as:
    //
    //   (self) -> (value, index) -> ()
    //
    // Build a setter thunk with the latter signature that maps to the
    // former.
    auto valueIndex = setter->getParameterList(1);
  
    // 'self'
    auto selfDecl = ParamDecl::createSelf(SourceLoc(), dc);
    auto elementTy = dc->mapTypeIntoContext(elementInterfaceTy);
  
    auto paramVarDecl =
        new (C) ParamDecl(VarDecl::Specifier::Owned, SourceLoc(), SourceLoc(),
                          Identifier(), loc, valueIndex->get(0)->getName(),
                          elementTy, dc);
    paramVarDecl->setInterfaceType(elementInterfaceTy);
    paramVarDecl->setValidationStarted();
  
    auto valueIndicesPL = ParameterList::create(C, {paramVarDecl, index});
  
    // Form the argument lists.
    ParameterList *setterArgs[] = {ParameterList::createWithoutLoc(selfDecl),
                                   valueIndicesPL};
  
    // Form the type of the setter.
    Type setterType = ParameterList::getFullInterfaceType(TupleType::getEmpty(C),
                                                          setterArgs, C);
  
    auto interfaceType =
        getGenericMethodType(dc, setterType->castTo<AnyFunctionType>());
  
    // Create the setter thunk.
    FuncDecl *thunk = FuncDecl::create(
        C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
        /*FuncLoc=*/setter->getLoc(),
        /*Name=*/Identifier(), /*NameLoc=*/SourceLoc(),
        /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
        /*AccessorKeywordLoc=*/SourceLoc(),
        /*GenericParams=*/nullptr, setterArgs,
        TypeLoc::withoutLoc(TupleType::getEmpty(C)), dc, setter->getClangNode());
    thunk->setInterfaceType(interfaceType);
    thunk->setValidationStarted();
    thunk->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
  
    thunk->setAccess(getOverridableAccessLevel(dc));
  
    auto objcAttr = setter->getAttrs().getAttribute<ObjCAttr>();
    assert(objcAttr);
    thunk->getAttrs().add(objcAttr->clone(C));
  
    return thunk;
  }
  
  /// Retrieve the element interface type and key param decl of a subscript
  /// setter.
  static std::pair<Type, ParamDecl *> decomposeSubscriptSetter(FuncDecl *setter) {
    auto *PL = setter->getParameterList(1);
    if (PL->size() != 2)
      return {nullptr, nullptr};
  
    // Setter type is (self) -> (elem_type, key_type) -> ()
    Type elementType = setter->getInterfaceType()
                           ->castTo<AnyFunctionType>()
                           ->getResult()
                           ->castTo<AnyFunctionType>()
                           ->getParams().front().getType();
    ParamDecl *keyDecl = PL->get(1);
  
    return {elementType, keyDecl};
  }
  
  /// Rectify the (possibly different) types determined by the
  /// getter and setter for a subscript.
  ///
  /// \param canUpdateType whether the type of subscript can be
  /// changed from the getter type to something compatible with both
  /// the getter and the setter.
  ///
  /// \returns the type to be used for the subscript, or a null type
  /// if the types cannot be rectified.
  static Type rectifySubscriptTypes(Type getterType, Type setterType,
                                    bool canUpdateType) {
    // If the caller couldn't provide a setter type, there is
    // nothing to rectify.
    if (!setterType)
      return nullptr;
  
    // Trivial case: same type in both cases.
    if (getterType->isEqual(setterType))
      return getterType;
  
    // The getter/setter types are different. If we cannot update
    // the type, we have to fail.
    if (!canUpdateType)
      return nullptr;
  
    // Unwrap one level of optionality from each.
    if (Type getterObjectType = getterType->getAnyOptionalObjectType())
      getterType = getterObjectType;
    if (Type setterObjectType = setterType->getAnyOptionalObjectType())
      setterType = setterObjectType;
  
    // If they are still different, fail.
    // FIXME: We could produce the greatest common supertype of the
    // two types.
    if (!getterType->isEqual(setterType))
      return nullptr;
  
    // Create an implicitly-unwrapped optional of the object type,
    // which subsumes both behaviors.
    return ImplicitlyUnwrappedOptionalType::get(setterType);
  }
  
  /// Add an AvailableAttr to the declaration for the given
  /// version range.
  static void applyAvailableAttribute(Decl *decl, AvailabilityContext &info,
                                      ASTContext &C) {
    // If the range is "all", this is the same as not having an available
    // attribute.
    if (info.isAlwaysAvailable())
      return;
  
    clang::VersionTuple noVersion;
    auto AvAttr = new (C) AvailableAttr(SourceLoc(), SourceRange(),
                                        targetPlatform(C.LangOpts),
                                        /*Message=*/StringRef(),
                                        /*Rename=*/StringRef(),
                                        info.getOSVersion().getLowerEndpoint(),
                                        /*IntroducedRange*/SourceRange(),
                                        /*Deprecated=*/noVersion,
                                        /*DeprecatedRange*/SourceRange(),
                                        /*Obsoleted=*/noVersion,
                                        /*ObsoletedRange*/SourceRange(),
                                        PlatformAgnosticAvailabilityKind::None,
                                        /*Implicit=*/false);
  
    decl->getAttrs().add(AvAttr);
  }
  
  /// Synthesize availability attributes for protocol requirements
  /// based on availability of the types mentioned in the requirements.
  static void inferProtocolMemberAvailability(ClangImporter::Implementation &impl,
                                              DeclContext *dc, Decl *member) {
    // Don't synthesize attributes if there is already an
    // availability annotation.
    if (member->getAttrs().hasAttribute<AvailableAttr>())
      return;
  
    auto *valueDecl = dyn_cast<ValueDecl>(member);
    if (!valueDecl)
      return;
  
    AvailabilityContext requiredRange =
        AvailabilityInference::inferForType(valueDecl->getInterfaceType());
  
    ASTContext &C = impl.SwiftContext;
  
    const Decl *innermostDecl = dc->getInnermostDeclarationDeclContext();
    AvailabilityContext containingDeclRange =
        AvailabilityInference::availableRange(innermostDecl, C);
  
    requiredRange.intersectWith(containingDeclRange);
  
    applyAvailableAttribute(valueDecl, requiredRange, C);
  }
  
  /// Add a domain error member, as required by conformance to
  /// _BridgedStoredNSError.
  /// \returns true on success, false on failure
  static bool addErrorDomain(NominalTypeDecl *swiftDecl,
                             clang::NamedDecl *errorDomainDecl,
                             ClangImporter::Implementation &importer) {
    auto &C = importer.SwiftContext;
    auto swiftValueDecl = dyn_cast_or_null<ValueDecl>(
        importer.importDecl(errorDomainDecl, importer.CurrentVersion));
    auto stringTy = C.getStringDecl()->getDeclaredType();
    assert(stringTy && "no string type available");
    if (!swiftValueDecl || !swiftValueDecl->getInterfaceType()->isEqual(stringTy)) {
      // Couldn't actually import it as an error enum, fall back to enum
      return false;
    }
  
    bool isStatic = true;
    bool isImplicit = true;
  
    DeclRefExpr *domainDeclRef = new (C)
        DeclRefExpr(ConcreteDeclRef(swiftValueDecl), {}, isImplicit);
    ParameterList *params[] = {
        ParameterList::createWithoutLoc(
            ParamDecl::createSelf(SourceLoc(), swiftDecl, isStatic)),
        ParameterList::createEmpty(C)};
    auto toStringTy = ParameterList::getFullInterfaceType(stringTy, params, C);
  
    FuncDecl *getterDecl =
      FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
                       /*FuncLoc=*/SourceLoc(), DeclName(), /*NameLoc=*/SourceLoc(),
                       /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                       /*AccessorKeywordLoc=*/SourceLoc(),
                       /*GenericParams=*/nullptr, params,
                       TypeLoc::withoutLoc(stringTy), swiftDecl);
    getterDecl->setInterfaceType(toStringTy);
    getterDecl->setValidationStarted();
  
    // Make the property decl
    auto errorDomainPropertyDecl = new (C) VarDecl(
        /*IsStatic*/isStatic, VarDecl::Specifier::Var, /*IsCaptureList*/false,
        SourceLoc(), C.Id_nsErrorDomain, stringTy, swiftDecl);
    errorDomainPropertyDecl->setInterfaceType(stringTy);
    errorDomainPropertyDecl->setValidationStarted();
    errorDomainPropertyDecl->setAccess(AccessLevel::Public);
  
    swiftDecl->addMember(errorDomainPropertyDecl);
    swiftDecl->addMember(getterDecl);
    errorDomainPropertyDecl->makeComputed(SourceLoc(), getterDecl,
                                          /*Set=*/nullptr,
                                          /*MaterializeForSet=*/nullptr,
                                          SourceLoc());
  
    getterDecl->setImplicit();
    getterDecl->setStatic(isStatic);
    getterDecl->setAccess(AccessLevel::Public);
  
    auto ret = new (C) ReturnStmt(SourceLoc(), domainDeclRef);
    getterDecl->setBody(
        BraceStmt::create(C, SourceLoc(), {ret}, SourceLoc(), isImplicit));
    importer.registerExternalDecl(getterDecl);
    return true;
  }
  
  /// As addErrorDomain above, but performs a lookup
  static bool addErrorDomain(NominalTypeDecl *swiftDecl,
                             StringRef errorDomainName,
                             ClangImporter::Implementation &importer) {
    auto &clangSema = importer.getClangSema();
    clang::IdentifierInfo *errorDomainDeclName =
      &clangSema.getASTContext().Idents.get(errorDomainName);
    clang::LookupResult lookupResult(
        clangSema, clang::DeclarationName(errorDomainDeclName),
        clang::SourceLocation(), clang::Sema::LookupNameKind::LookupOrdinaryName);
  
    if (!clangSema.LookupName(lookupResult, clangSema.TUScope)) {
      // Couldn't actually import it as an error enum, fall back to enum
      return false;
    }
  
    auto clangNamedDecl = lookupResult.getAsSingle<clang::NamedDecl>();
    if (!clangNamedDecl) {
      // Couldn't actually import it as an error enum, fall back to enum
      return false;
    }
  
    return addErrorDomain(swiftDecl, clangNamedDecl, importer);
  }
  
  /// Retrieve the property type as determined by the given accessor.
  static clang::QualType
  getAccessorPropertyType(const clang::FunctionDecl *accessor, bool isSetter,
                          Optional<unsigned> selfIndex) {
    // Simple case: the property type of the getter is in the return
    // type.
    if (!isSetter) return accessor->getReturnType();
  
    // For the setter, first check that we have the right number of
    // parameters.
    unsigned numExpectedParams = selfIndex ? 2 : 1;
    if (accessor->getNumParams() != numExpectedParams)
      return clang::QualType();
  
    // Dig out the parameter for the value.
    unsigned valueIdx = selfIndex ? (1 - *selfIndex) : 0;
    auto param = accessor->getParamDecl(valueIdx);
    return param->getType();
  }
  
  /// Whether we should suppress importing the Objective-C generic type params
  /// of this class as Swift generic type params.
  static bool
  shouldSuppressGenericParamsImport(const LangOptions &langOpts,
                                    const clang::ObjCInterfaceDecl *decl) {
    if (decl->hasAttr<clang::SwiftImportAsNonGenericAttr>())
      return true;
  
    // FIXME: This check is only necessary to keep things working even without
    // the SwiftImportAsNonGeneric API note. Once we can guarantee that that
    // attribute is present in all contexts, we can remove this check.
    auto isFromFoundationModule = [](const clang::Decl *decl) -> bool {
      clang::Module *module = getClangSubmoduleForDecl(decl).getValue();
      if (!module)
        return false;
      return module->getTopLevelModuleName() == "Foundation";
    };
  
    if (langOpts.isSwiftVersion3() || isFromFoundationModule(decl)) {
      // In Swift 3 we used a hardcoded list of declarations, and made all of
      // their subclasses drop their generic parameters when imported.
      while (decl) {
        StringRef name = decl->getName();
        if (name == "NSArray" || name == "NSDictionary" || name == "NSSet" ||
            name == "NSOrderedSet" || name == "NSEnumerator" ||
            name == "NSMeasurement") {
          return true;
        }
        decl = decl->getSuperClass();
      }
    }
  
    return false;
  }
  
  /// Determine if the given Objective-C instance method should also
  /// be imported as a class method.
  ///
  /// Objective-C root class instance methods are also reflected as
  /// class methods.
  static bool shouldAlsoImportAsClassMethod(FuncDecl *method) {
    // Only instance methods.
    if (!method->isInstanceMember())
      return false;
  
    // Must be a method within a class or extension thereof.
    auto classDecl =
        method->getDeclContext()->getAsClassOrClassExtensionContext();
    if (!classDecl)
      return false;
  
    // The class must not have a superclass.
    if (classDecl->getSuperclass())
      return false;
  
    // There must not already be a class method with the same
    // selector.
    auto objcClass =
        cast_or_null<clang::ObjCInterfaceDecl>(classDecl->getClangDecl());
    if (!objcClass)
      return false;
  
    auto objcMethod = cast_or_null<clang::ObjCMethodDecl>(method->getClangDecl());
    if (!objcMethod)
      return false;
    return !objcClass->getClassMethod(objcMethod->getSelector(),
                                      /*AllowHidden=*/true);
  }
  
  static bool
  classImplementsProtocol(const clang::ObjCInterfaceDecl *constInterface,
                          const clang::ObjCProtocolDecl *constProto,
                          bool checkCategories) {
    auto interface = const_cast<clang::ObjCInterfaceDecl *>(constInterface);
    auto proto = const_cast<clang::ObjCProtocolDecl *>(constProto);
    return interface->ClassImplementsProtocol(proto, checkCategories);
  }
  
  static void
  applyPropertyOwnership(VarDecl *prop,
                         clang::ObjCPropertyDecl::PropertyAttributeKind attrs) {
    Type ty = prop->getInterfaceType();
    if (auto innerTy = ty->getAnyOptionalObjectType())
      ty = innerTy;
    if (!ty->is<GenericTypeParamType>() && !ty->isAnyClassReferenceType())
      return;
  
    ASTContext &ctx = prop->getASTContext();
    if (attrs & clang::ObjCPropertyDecl::OBJC_PR_copy) {
      prop->getAttrs().add(new (ctx) NSCopyingAttr(false));
      return;
    }
    if (attrs & clang::ObjCPropertyDecl::OBJC_PR_weak) {
      prop->getAttrs().add(new (ctx) OwnershipAttr(Ownership::Weak));
      prop->setType(WeakStorageType::get(prop->getType(), ctx));
      prop->setInterfaceType(WeakStorageType::get(
          prop->getInterfaceType(), ctx));
      return;
    }
    if ((attrs & clang::ObjCPropertyDecl::OBJC_PR_assign) ||
        (attrs & clang::ObjCPropertyDecl::OBJC_PR_unsafe_unretained)) {
      prop->getAttrs().add(new (ctx) OwnershipAttr(Ownership::Unmanaged));
      prop->setType(UnmanagedStorageType::get(prop->getType(), ctx));
      prop->setInterfaceType(UnmanagedStorageType::get(
          prop->getInterfaceType(), ctx));
      return;
    }
  }
  
  /// Does this name refer to a method that might shadow Swift.print?
  ///
  /// As a heuristic, methods that have a base name of 'print' but more than
  /// one argument are left alone. These can still shadow Swift.print but are
  /// less likely to be confused for it, at least.
  static bool isPrintLikeMethod(DeclName name, const DeclContext *dc) {
    if (!name || name.isSpecial() || name.isSimpleName())
      return false;
    if (name.getBaseIdentifier().str() != "print")
      return false;
    if (!dc->isTypeContext())
      return false;
    if (name.getArgumentNames().size() > 1)
      return false;
    return true;
  }
  
  using MirroredMethodEntry =
    std::pair<const clang::ObjCMethodDecl*, ProtocolDecl*>;
  
  namespace {
    /// Customized llvm::DenseMapInfo for storing borrowed APSInts.
    struct APSIntRefDenseMapInfo {
      static inline const llvm::APSInt *getEmptyKey() {
        return llvm::DenseMapInfo<const llvm::APSInt *>::getEmptyKey();
      }
      static inline const llvm::APSInt *getTombstoneKey() {
        return llvm::DenseMapInfo<const llvm::APSInt *>::getTombstoneKey();
      }
      static unsigned getHashValue(const llvm::APSInt *ptrVal) {
        assert(ptrVal != getEmptyKey() && ptrVal != getTombstoneKey());
        return llvm::hash_value(*ptrVal);
      }
      static bool isEqual(const llvm::APSInt *lhs, const llvm::APSInt *rhs) {
        if (lhs == rhs) return true;
        if (lhs == getEmptyKey() || rhs == getEmptyKey()) return false;
        if (lhs == getTombstoneKey() || rhs == getTombstoneKey()) return false;
        return *lhs == *rhs;
      }
    };
  
    /// \brief Convert Clang declarations into the corresponding Swift
    /// declarations.
    class SwiftDeclConverter
      : public clang::ConstDeclVisitor<SwiftDeclConverter, Decl *>
    {
      ClangImporter::Implementation &Impl;
      bool forwardDeclaration = false;
      ImportNameVersion version;
  
      /// The version that we're being asked to import for. May not be the version
      /// the user requested, as we may be forming an alternate for diagnostic
      /// purposes.
      ImportNameVersion getVersion() const { return version; }
  
      /// The actual language version the user requested we compile for.
      ImportNameVersion getActiveSwiftVersion() const {
        return Impl.CurrentVersion;
      }
  
      /// Whether the names we're importing are from the language version the user
      /// requested, or if these are decls from another version
      bool isActiveSwiftVersion() const {
        return getVersion() == getActiveSwiftVersion();
      }
  
      /// Import the name of the given entity.
      ///
      /// This version of importFullName introduces any context-specific
      /// name importing options (e.g., if we're importing the Swift 2 version).
      ///
      /// Note: Use this rather than calling Impl.importFullName directly!
      ImportedName importFullName(const clang::NamedDecl *D,
                                  Optional<ImportedName> &correctSwiftName) {
        ImportNameVersion canonicalVersion = getActiveSwiftVersion();
        if (isa<clang::TypeDecl>(D) || isa<clang::ObjCContainerDecl>(D)) {
          canonicalVersion = ImportNameVersion::forTypes();
        }
        correctSwiftName = None;
  
        // First, import based on the Swift name of the canonical declaration:
        // the latest version for types and the current version for non-type
        // values. If that fails, we won't do anything.
        auto canonicalName = Impl.importFullName(D, canonicalVersion);
        if (!canonicalName)
          return ImportedName();
  
        if (getVersion() == canonicalVersion) {
          // Make sure we don't try to import the same type twice as canonical.
          if (canonicalVersion != getActiveSwiftVersion()) {
            auto activeName = Impl.importFullName(D, getActiveSwiftVersion());
            if (activeName &&
                activeName.getDeclName() == canonicalName.getDeclName()) {
              return ImportedName();
            }
          }
  
          return canonicalName;
        }
  
        // Special handling when we import using the older Swift name.
        //
        // Import using the alternate Swift name. If that fails, or if it's
        // identical to the active Swift name, we won't introduce an alternate
        // Swift name stub declaration.
        auto alternateName = Impl.importFullName(D, getVersion());
        if (!alternateName)
          return ImportedName();
  
        if (alternateName.getDeclName() == canonicalName.getDeclName()) {
          if (getVersion() == getActiveSwiftVersion()) {
            assert(canonicalVersion != getActiveSwiftVersion());
            return alternateName;
          }
          return ImportedName();
        }
  
        // Always use the active version as the preferred name, even if the
        // canonical name is a different version.
        correctSwiftName = Impl.importFullName(D, getActiveSwiftVersion());
        assert(correctSwiftName);
  
        return alternateName;
      }
  
      /// \brief Create a declaration name for anonymous enums, unions and
      /// structs.
      ///
      /// Since Swift does not natively support these features, we fake them by
      /// importing them as declarations with generated names. The generated name
      /// is derived from the name of the field in the outer type. Since the
      /// anonymous type is imported as a nested type of the outer type, this
      /// generated name will most likely be unique.
      ImportedName getClangDeclName(const clang::TagDecl *decl,
                                    Optional<ImportedName> &correctSwiftName) {
        // If we have a name for this declaration, use it.
        if (auto name = importFullName(decl, correctSwiftName))
          return name;
  
        // If that didn't succeed, check whether this is an anonymous tag declaration
        // with a corresponding typedef-name declaration.
        if (decl->getDeclName().isEmpty()) {
          if (auto *typedefForAnon = decl->getTypedefNameForAnonDecl())
            return importFullName(typedefForAnon, correctSwiftName);
        }
  
        if (!decl->isRecord())
          return ImportedName();
  
        // If the type has no name and no structure name, but is not anonymous,
        // generate a name for it. Specifically this is for cases like:
        //   struct a {
        //     struct {} z;
        //   }
        // Where the member z is an unnamed struct, but does have a member-name
        // and is accessible as a member of struct a.
        correctSwiftName = None;
        if (auto recordDecl = dyn_cast<clang::RecordDecl>(
                                decl->getLexicalDeclContext())) {
          for (auto field : recordDecl->fields()) {
            if (field->getType()->getAsTagDecl() == decl) {
              // Create a name for the declaration from the field name.
              std::string Id;
              llvm::raw_string_ostream IdStream(Id);
  
              const char *kind;
              if (decl->isStruct())
                kind = "struct";
              else if (decl->isUnion())
                kind = "union";
              else
                llvm_unreachable("unknown decl kind");
  
              IdStream << "__Unnamed_" << kind << "_";
              if (field->isAnonymousStructOrUnion()) {
                IdStream << "__Anonymous_field" << field->getFieldIndex();
              } else {
                IdStream << field->getName();
              }
              ImportedName Result;
              Result.setDeclName(Impl.SwiftContext.getIdentifier(IdStream.str()));
              Result.setEffectiveContext(decl->getDeclContext());
              return Result;
            }
          }
        }
        
        return ImportedName();
      }
  
      bool isFactoryInit(ImportedName &name) {
        return name &&
               name.getDeclName().getBaseName() == Impl.SwiftContext.Id_init &&
               (name.getInitKind() == CtorInitializerKind::Factory ||
                name.getInitKind() == CtorInitializerKind::ConvenienceFactory);
      }
  
    public:
      explicit SwiftDeclConverter(ClangImporter::Implementation &impl,
                                  ImportNameVersion vers)
        : Impl(impl), version(vers) { }
  
      bool hadForwardDeclaration() const {
        return forwardDeclaration;
      }
  
      Decl *VisitDecl(const clang::Decl *decl) {
        return nullptr;
      }
  
      Decl *VisitTranslationUnitDecl(const clang::TranslationUnitDecl *decl) {
        // Note: translation units are handled specially by importDeclContext.
        return nullptr;
      }
  
      Decl *VisitNamespaceDecl(const clang::NamespaceDecl *decl) {
        // FIXME: Implement once Swift has namespaces.
        return nullptr;
      }
  
      Decl *VisitUsingDirectiveDecl(const clang::UsingDirectiveDecl *decl) {
        // Never imported.
        return nullptr;
      }
  
      Decl *VisitNamespaceAliasDecl(const clang::NamespaceAliasDecl *decl) {
        // FIXME: Implement once Swift has namespaces.
        return nullptr;
      }
  
      Decl *VisitLabelDecl(const clang::LabelDecl *decl) {
        // Labels are function-local, and therefore never imported.
        return nullptr;
      }
  
      ClassDecl *importCFClassType(const clang::TypedefNameDecl *decl,
                                   Identifier className, CFPointeeInfo info,
                                   EffectiveClangContext effectiveContext);
  
      /// Mark the given declaration as an older Swift version variant of the
      /// current name.
      void markAsVariant(Decl *decl, ImportedName correctSwiftName) {
        // Types always import using the latest version. Make sure all names up
        // to that version are considered available.
        if (isa<TypeDecl>(decl)) {
          cast<TypeAliasDecl>(decl)->markAsCompatibilityAlias();
  
          if (getVersion() >= getActiveSwiftVersion())
            return;
        }
  
        // TODO: some versions should be deprecated instead of unavailable
  
        ASTContext &ctx = decl->getASTContext();
        llvm::SmallString<64> renamed;
        {
          // Render a swift_name string.
          llvm::raw_svector_ostream os(renamed);
  
          // If we're importing a global as a member, we need to provide the
          // effective context.
          Impl.printSwiftName(
              correctSwiftName, getActiveSwiftVersion(),
              /*fullyQualified=*/correctSwiftName.importAsMember(), os);
        }
  
        DeclAttribute *attr;
        if (isActiveSwiftVersion() || getVersion() == ImportNameVersion::raw()) {
          // "Raw" is the Objective-C name, which was never available in Swift.
          // Variants within the active version are usually declarations that
          // have been superseded, like the accessors of a property.
          attr = AvailableAttr::createPlatformAgnostic(
              ctx, /*Message*/StringRef(), ctx.AllocateCopy(renamed.str()),
              PlatformAgnosticAvailabilityKind::UnavailableInSwift);
        } else {
          unsigned majorVersion = getVersion().majorVersionNumber();
          if (getVersion() < getActiveSwiftVersion()) {
            // A Swift 2 name, for example, was obsoleted in Swift 3.
            attr = AvailableAttr::createPlatformAgnostic(
                ctx, /*Message*/StringRef(), ctx.AllocateCopy(renamed.str()),
                PlatformAgnosticAvailabilityKind::SwiftVersionSpecific,
                clang::VersionTuple(majorVersion + 1));
          } else {
            // Future names are introduced in their future version.
            assert(getVersion() > getActiveSwiftVersion());
            attr = new (ctx) AvailableAttr(
                SourceLoc(), SourceRange(), PlatformKind::none,
                /*Message*/StringRef(), ctx.AllocateCopy(renamed.str()),
                /*Introduced*/clang::VersionTuple(majorVersion), SourceRange(),
                /*Deprecated*/clang::VersionTuple(), SourceRange(),
                /*Obsoleted*/clang::VersionTuple(), SourceRange(),
                PlatformAgnosticAvailabilityKind::SwiftVersionSpecific,
                /*Implicit*/false);
          }
        }
  
        decl->getAttrs().add(attr);
        decl->setImplicit();
      }
  
      /// Create a typealias for the name of a Clang type declaration in an
      /// alternate version of Swift.
      Decl *importCompatibilityTypeAlias(const clang::NamedDecl *decl,
                                         ImportedName compatibilityName,
                                         ImportedName correctSwiftName);
  
      /// Create a swift_newtype struct corresponding to a typedef. Returns
      /// nullptr if unable.
      Decl *importSwiftNewtype(const clang::TypedefNameDecl *decl,
                               clang::SwiftNewtypeAttr *newtypeAttr,
                               DeclContext *dc, Identifier name);
  
      Decl *VisitTypedefNameDecl(const clang::TypedefNameDecl *Decl) {
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(Decl, correctSwiftName);
        auto Name = importedName.getDeclName().getBaseIdentifier();
        if (Name.empty())
          return nullptr;
  
        // If we've been asked to produce a compatibility stub, handle it via a
        // typealias.
        if (correctSwiftName)
          return importCompatibilityTypeAlias(Decl, importedName,
                                              *correctSwiftName);
  
        Type SwiftType;
        if (Decl->getDeclContext()->getRedeclContext()->isTranslationUnit()) {
          bool IsError;
          StringRef StdlibTypeName;
          MappedTypeNameKind NameMapping;
          std::tie(SwiftType, StdlibTypeName) =
              getSwiftStdlibType(Decl, Name, Impl, &IsError, NameMapping);
  
          if (IsError)
            return nullptr;
  
          // Import 'typedef struct __Blah *BlahRef;' and
          // 'typedef const void *FooRef;' as CF types if they have the
          // right attributes or match our list of known types.
          if (!SwiftType) {
            auto DC = Impl.importDeclContextOf(
                Decl, importedName.getEffectiveContext());
            if (!DC)
              return nullptr;
  
            if (auto pointee = CFPointeeInfo::classifyTypedef(Decl)) {
              // If the pointee is a record, consider creating a class type.
              if (pointee.isRecord()) {
                auto swiftClass = importCFClassType(
                    Decl, Name, pointee, importedName.getEffectiveContext());
                if (!swiftClass) return nullptr;
  
                Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] =
                  MappedTypeNameKind::DefineAndUse;
                return swiftClass;
              }
  
              // If the pointee is another CF typedef, create an extra typealias
              // for the name without "Ref", but not a separate type.
              if (pointee.isTypedef()) {
                auto underlying = cast_or_null<TypeDecl>(Impl.importDecl(
                    pointee.getTypedef(), getActiveSwiftVersion()));
                if (!underlying)
                  return nullptr;
  
                // Check for a newtype
                if (auto newtypeAttr =
                        getSwiftNewtypeAttr(Decl, getVersion()))
                  if (auto newtype =
                          importSwiftNewtype(Decl, newtypeAttr, DC, Name))
                    return newtype;
  
                // Create a typealias for this CF typedef.
                TypeAliasDecl *typealias = nullptr;
                typealias = Impl.createDeclWithClangNode<TypeAliasDecl>(
                              Decl, AccessLevel::Public,
                              Impl.importSourceLoc(Decl->getLocStart()),
                              SourceLoc(), Name,
                              Impl.importSourceLoc(Decl->getLocation()),
                              /*genericparams*/nullptr, DC);
                typealias->setUnderlyingType(
                    underlying->getDeclaredInterfaceType());
  
                Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] =
                  MappedTypeNameKind::DefineAndUse;
                return typealias;
              }
  
              // If the pointee is 'void', 'CFTypeRef', bring it
              // in specifically as AnyObject.
              if (pointee.isVoid()) {
                // Create a typealias for this CF typedef.
                TypeAliasDecl *typealias = nullptr;
                typealias = Impl.createDeclWithClangNode<TypeAliasDecl>(
                              Decl, AccessLevel::Public,
                              Impl.importSourceLoc(Decl->getLocStart()),
                              SourceLoc(), Name,
                              Impl.importSourceLoc(Decl->getLocation()),
                              /*genericparams*/nullptr, DC);
                typealias->setUnderlyingType(
                  Impl.SwiftContext.getAnyObjectType());
  
                Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] =
                  MappedTypeNameKind::DefineAndUse;
                return typealias;
              }
            }
          }
  
          if (SwiftType) {
            // Note that this typedef-name is special.
            Impl.SpecialTypedefNames[Decl->getCanonicalDecl()] = NameMapping;
  
            if (NameMapping == MappedTypeNameKind::DoNothing) {
              // Record the remapping using the name of the Clang declaration.
              // This will be useful for type checker diagnostics when
              // a user tries to use the Objective-C/C type instead of the
              // Swift type.
              Impl.SwiftContext.RemappedTypes[Decl->getNameAsString()]
                = SwiftType;
  
              // Don't create an extra typealias in the imported module because
              // doing so will cause confusion (or even lookup ambiguity) between
              // the name in the imported module and the same name in the
              // standard library.
              if (auto *NAT = dyn_cast<NameAliasType>(SwiftType.getPointer()))
                return NAT->getDecl();
  
              auto *NTD = SwiftType->getAnyNominal();
              assert(NTD);
              return NTD;
            }
          }
        }
  
        auto DC =
            Impl.importDeclContextOf(Decl, importedName.getEffectiveContext());
        if (!DC)
          return nullptr;
  
        // Check for swift_newtype
        if (!SwiftType)
          if (auto newtypeAttr = getSwiftNewtypeAttr(Decl, getVersion()))
            if (auto newtype = importSwiftNewtype(Decl, newtypeAttr, DC, Name))
              return newtype;
  
        if (!SwiftType) {
          // Import typedefs of blocks as their fully-bridged equivalent Swift
          // type. That matches how we want to use them in most cases. All other
          // types should be imported in a non-bridged way.
          clang::QualType ClangType = Decl->getUnderlyingType();
          SwiftType = Impl.importType(ClangType,
                                      ImportTypeKind::Typedef,
                                      isInSystemModule(DC),
                                      getTypedefBridgeability(ClangType),
                                      OTK_Optional);
        }
  
        if (!SwiftType)
          return nullptr;
  
        auto Loc = Impl.importSourceLoc(Decl->getLocation());
        auto Result = Impl.createDeclWithClangNode<TypeAliasDecl>(Decl,
                                        AccessLevel::Public,
                                        Impl.importSourceLoc(Decl->getLocStart()),
                                        SourceLoc(), Name,
                                        Loc,
                                        /*genericparams*/nullptr, DC);
        Result->setUnderlyingType(SwiftType);
  
        // Make Objective-C's 'id' unavailable.
        if (Impl.SwiftContext.LangOpts.EnableObjCInterop && isObjCId(Decl)) {
          auto attr = AvailableAttr::createPlatformAgnostic(
                        Impl.SwiftContext,
                        "'id' is not available in Swift; use 'Any'", "",
                        PlatformAgnosticAvailabilityKind::UnavailableInSwift);
          Result->getAttrs().add(attr);
        }
  
        return Result;
      }
  
      Decl *
      VisitUnresolvedUsingTypenameDecl(const
                                       clang::UnresolvedUsingTypenameDecl *decl) {
        // Note: only occurs in templates.
        return nullptr;
      }
  
      /// Import an NS_ENUM constant as a case of a Swift enum.
      Decl *importEnumCase(const clang::EnumConstantDecl *decl,
                           const clang::EnumDecl *clangEnum,
                           EnumDecl *theEnum,
                           Decl *swift3Decl = nullptr);
  
      /// Import an NS_OPTIONS constant as a static property of a Swift struct.
      ///
      /// This is also used to import enum case aliases.
      Decl *importOptionConstant(const clang::EnumConstantDecl *decl,
                                 const clang::EnumDecl *clangEnum,
                                 NominalTypeDecl *theStruct);
  
      /// Import \p alias as an alias for the imported constant \p original.
      ///
      /// This builds the getter in a way that's compatible with switch
      /// statements. Changing the body here may require changing
      /// TypeCheckPattern.cpp as well.
      Decl *importEnumCaseAlias(Identifier name,
                                const clang::EnumConstantDecl *alias,
                                ValueDecl *original,
                                const clang::EnumDecl *clangEnum,
                                NominalTypeDecl *importedEnum,
                                DeclContext *importIntoDC = nullptr);
  
      NominalTypeDecl *importAsOptionSetType(DeclContext *dc,
                                             Identifier name,
                                             const clang::EnumDecl *decl);
  
      Decl *VisitEnumDecl(const clang::EnumDecl *decl) {
        decl = decl->getDefinition();
        if (!decl) {
          forwardDeclaration = true;
          return nullptr;
        }
  
        Optional<ImportedName> correctSwiftName;
        auto importedName = getClangDeclName(decl, correctSwiftName);
        if (!importedName)
          return nullptr;
  
        // If we've been asked to produce a compatibility stub, handle it via a
        // typealias.
        if (correctSwiftName)
          return importCompatibilityTypeAlias(decl, importedName,
                                              *correctSwiftName);
  
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
        
        auto name = importedName.getDeclName().getBaseIdentifier();
  
        // Create the enum declaration and record it.
        StructDecl *errorWrapper = nullptr;
        NominalTypeDecl *result;
        auto enumInfo = Impl.getEnumInfo(decl);
        auto enumKind = enumInfo.getKind();
        switch (enumKind) {
        case EnumKind::Constants: {
          // There is no declaration. Rather, the type is mapped to the
          // underlying type.
          return nullptr;
        }
  
        case EnumKind::Unknown: {
          // Compute the underlying type of the enumeration.
          auto underlyingType = Impl.importType(decl->getIntegerType(),
                                                ImportTypeKind::Enum,
                                                isInSystemModule(dc),
                                                Bridgeability::None);
          if (!underlyingType)
            return nullptr;
  
          auto Loc = Impl.importSourceLoc(decl->getLocation());
          auto structDecl = Impl.createDeclWithClangNode<StructDecl>(decl,
            AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
          structDecl->computeType();
          structDecl->setCheckedInheritanceClause();
  
          auto options = getDefaultMakeStructRawValuedOptions();
          options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
          options -= MakeStructRawValuedFlags::IsLet;
          options -= MakeStructRawValuedFlags::IsImplicit;
  
          makeStructRawValued(Impl, structDecl, underlyingType,
                              {KnownProtocolKind::RawRepresentable,
                               KnownProtocolKind::Equatable},
                              options, /*setterAccess=*/AccessLevel::Public);
  
          result = structDecl;
          break;
        }
  
        case EnumKind::Enum: {
          auto &C = Impl.SwiftContext;
          EnumDecl *nativeDecl;
          bool declaredNative = hasNativeSwiftDecl(decl, name, dc, nativeDecl);
          if (declaredNative && nativeDecl)
            return nativeDecl;
  
          // Compute the underlying type.
          auto underlyingType = Impl.importType(
              decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc),
              Bridgeability::None);
          if (!underlyingType)
            return nullptr;
  
          /// Basic information about the enum type we're building.
          Identifier enumName = name;
          DeclContext *enumDC = dc;
          SourceLoc loc = Impl.importSourceLoc(decl->getLocStart());
  
          // If this is an error enum, form the error wrapper type,
          // which is a struct containing an NSError instance.
          ProtocolDecl *bridgedNSError = nullptr;
          ClassDecl *nsErrorDecl = nullptr;
          ProtocolDecl *errorCodeProto = nullptr;
          if (enumInfo.isErrorEnum() && 
              (bridgedNSError =
                 C.getProtocol(KnownProtocolKind::BridgedStoredNSError)) &&
              (nsErrorDecl = C.getNSErrorDecl()) &&
              (errorCodeProto =
                 C.getProtocol(KnownProtocolKind::ErrorCodeProtocol))) {
            // Create the wrapper struct.
            errorWrapper = new (C) StructDecl(loc, name, loc, None, nullptr, dc);
            errorWrapper->computeType();
            errorWrapper->setValidationStarted();
            errorWrapper->setAccess(AccessLevel::Public);
  
            // Add inheritance clause.
            addSynthesizedProtocolAttrs(Impl, errorWrapper,
                                        {KnownProtocolKind::BridgedStoredNSError});
  
            // Create the _nsError member.
            //   public let _nsError: NSError
            auto nsErrorType = nsErrorDecl->getDeclaredInterfaceType();
            auto nsErrorProp = new (C) VarDecl(/*IsStatic*/false,
                                               VarDecl::Specifier::Let,
                                               /*IsCaptureList*/false,
                                               loc, C.Id_nsError, nsErrorType,
                                               errorWrapper);
            nsErrorProp->setImplicit();
            nsErrorProp->setAccess(AccessLevel::Public);
            nsErrorProp->setInterfaceType(nsErrorType);
            nsErrorProp->setValidationStarted();
  
            // Create a pattern binding to describe the variable.
            Pattern *nsErrorPattern = createTypedNamedPattern(nsErrorProp);
  
            auto nsErrorBinding = PatternBindingDecl::create(
                                    C, loc, StaticSpellingKind::None, loc,
                                    nsErrorPattern, nullptr, errorWrapper);
            errorWrapper->addMember(nsErrorProp);
            errorWrapper->addMember(nsErrorBinding);
  
            // Create the _nsError initializer.
            //   public init(_nsError error: NSError)
            VarDecl *members[1] = { nsErrorProp };
            auto nsErrorInit = createValueConstructor(Impl, errorWrapper, members,
                                                      /*wantCtorParamNames=*/true,
                                                      /*wantBody=*/true);
            errorWrapper->addMember(nsErrorInit);
  
            // Add the domain error member.
            //   public static var _nsErrorDomain: String { return error-domain }
            addErrorDomain(errorWrapper, enumInfo.getErrorDomain(), Impl);
  
            // Note: the Code will be added after it's created.
  
            // The enum itself will be nested within the error wrapper,
            // and be named Code.
            enumDC = errorWrapper;
            enumName = C.Id_Code;
          }
  
          // Create the enumeration.
          auto enumDecl = Impl.createDeclWithClangNode<EnumDecl>(
              decl, AccessLevel::Public, loc, enumName,
              Impl.importSourceLoc(decl->getLocation()), None, nullptr, enumDC);
          enumDecl->computeType();
  
          // Set up the C underlying type as its Swift raw type.
          enumDecl->setRawType(underlyingType);
  
          // Add the C name.
          addObjCAttribute(enumDecl,
                           Impl.importIdentifier(decl->getIdentifier()));
  
          // Add protocol declarations to the enum declaration.
          SmallVector<TypeLoc, 2> inheritedTypes;
          inheritedTypes.push_back(TypeLoc::withoutLoc(underlyingType));
          enumDecl->setInherited(C.AllocateCopy(inheritedTypes));
          enumDecl->setCheckedInheritanceClause();
  
          if (errorWrapper) {
            addSynthesizedProtocolAttrs(Impl, enumDecl,
                                        {KnownProtocolKind::ErrorCodeProtocol,
                                         KnownProtocolKind::RawRepresentable});
          } else {
            addSynthesizedProtocolAttrs(Impl, enumDecl,
                                        {KnownProtocolKind::RawRepresentable});
          }
  
          // Provide custom implementations of the init(rawValue:) and rawValue
          // conversions that just do a bitcast. We can't reliably filter a
          // C enum without additional knowledge that the type has no
          // undeclared values, and won't ever add cases.
          auto rawValueConstructor = makeEnumRawValueConstructor(Impl, enumDecl);
  
          auto varName = C.Id_rawValue;
          auto rawValue = new (C) VarDecl(/*IsStatic*/false,
                                          VarDecl::Specifier::Var,
                                          /*IsCaptureList*/false,
                                          SourceLoc(), varName, underlyingType,
                                          enumDecl);
          rawValue->setImplicit();
          rawValue->setAccess(AccessLevel::Public);
          rawValue->setSetterAccess(AccessLevel::Private);
          rawValue->setInterfaceType(underlyingType);
          rawValue->setValidationStarted();
  
          // Create a pattern binding to describe the variable.
          Pattern *varPattern = createTypedNamedPattern(rawValue);
  
          auto rawValueBinding = PatternBindingDecl::create(
              C, SourceLoc(), StaticSpellingKind::None, SourceLoc(),
              varPattern, nullptr, enumDecl);
  
          auto rawValueGetter = makeEnumRawValueGetter(Impl, enumDecl, rawValue);
  
          enumDecl->addMember(rawValueConstructor);
          enumDecl->addMember(rawValueGetter);
          enumDecl->addMember(rawValue);
          enumDecl->addMember(rawValueBinding);
  
          addSynthesizedTypealias(enumDecl, C.Id_RawValue, underlyingType);
  
          // If we have an error wrapper, finish it up now that its
          // nested enum has been constructed.
          if (errorWrapper) {
            // Add the ErrorType alias:
            //   public typealias ErrorType
            auto alias = Impl.createDeclWithClangNode<TypeAliasDecl>(
                           decl,
                           AccessLevel::Public, loc, SourceLoc(),
                           C.Id_ErrorType, loc,
                           /*genericparams=*/nullptr, enumDecl);
            alias->setUnderlyingType(errorWrapper->getDeclaredInterfaceType());
            enumDecl->addMember(alias);
  
            // Add the 'Code' enum to the error wrapper.
            errorWrapper->addMember(enumDecl);
            Impl.addAlternateDecl(enumDecl, errorWrapper);
          }
  
          // The enumerators go into this enumeration.
          result = enumDecl;
          break;
        }
  
        case EnumKind::Options: {
          result = importAsOptionSetType(dc, name, decl);
          if (!result)
            return nullptr;
  
          // HACK: Make sure PrintAsObjC always omits the 'enum' tag for
          // option set enums.
          Impl.DeclsWithSuperfluousTypedefs.insert(decl);
          break;
        }
        }
  
        const clang::EnumDecl *canonicalClangDecl = decl->getCanonicalDecl();
        Impl.ImportedDecls[{canonicalClangDecl, getVersion()}] = result;
  
        // Import each of the enumerators.
        
        bool addEnumeratorsAsMembers;
        switch (enumKind) {
        case EnumKind::Constants:
        case EnumKind::Unknown:
          addEnumeratorsAsMembers = false;
          break;
        case EnumKind::Options:
        case EnumKind::Enum:
          addEnumeratorsAsMembers = true;
          break;
        }
  
        llvm::SmallDenseMap<const llvm::APSInt *,
                            PointerUnion<const clang::EnumConstantDecl *,
                                         EnumElementDecl *>, 8,
                            APSIntRefDenseMapInfo> canonicalEnumConstants;
  
        if (enumKind == EnumKind::Enum) {
          for (auto constant : decl->enumerators()) {
            if (Impl.isUnavailableInSwift(constant))
              continue;
            canonicalEnumConstants.insert({&constant->getInitVal(), constant});
          }
        }
  
        auto contextIsEnum = [&](const ImportedName &name) -> bool {
          EffectiveClangContext importContext = name.getEffectiveContext();
          switch (importContext.getKind()) {
          case EffectiveClangContext::DeclContext:
            return importContext.getAsDeclContext() == canonicalClangDecl;
          case EffectiveClangContext::TypedefContext: {
            auto *typedefName = importContext.getTypedefName();
            clang::QualType underlyingTy = typedefName->getUnderlyingType();
            return underlyingTy->getAsTagDecl() == canonicalClangDecl;
          }
          case EffectiveClangContext::UnresolvedContext:
            // Assume this is a context other than the enum.
            return false;
          }
        };
  
        for (auto constant : decl->enumerators()) {
          Decl *enumeratorDecl = nullptr;
          TinyPtrVector<Decl *> variantDecls;
          switch (enumKind) {
          case EnumKind::Constants:
          case EnumKind::Unknown:
            Impl.forEachDistinctName(constant,
                                     [&](ImportedName newName,
                                         ImportNameVersion nameVersion) -> bool {
              Decl *imported = Impl.importDecl(constant, nameVersion);
              if (!imported)
                return false;
              if (nameVersion == getActiveSwiftVersion())
                enumeratorDecl = imported;
              else
                variantDecls.push_back(imported);
              return true;
            });
            break;
          case EnumKind::Options:
            Impl.forEachDistinctName(constant,
                                     [&](ImportedName newName,
                                         ImportNameVersion nameVersion) -> bool {
              if (!contextIsEnum(newName))
                return true;
              SwiftDeclConverter converter(Impl, nameVersion);
              Decl *imported =
                  converter.importOptionConstant(constant, decl, result);
              if (!imported)
                return false;
              if (nameVersion == getActiveSwiftVersion())
                enumeratorDecl = imported;
              else
                variantDecls.push_back(imported);
              return true;
            });
            break;
          case EnumKind::Enum: {
            auto canonicalCaseIter =
              canonicalEnumConstants.find(&constant->getInitVal());
  
            if (canonicalCaseIter == canonicalEnumConstants.end()) {
              // Unavailable declarations get no special treatment.
              enumeratorDecl =
                  SwiftDeclConverter(Impl, getActiveSwiftVersion())
                      .importEnumCase(constant, decl, cast<EnumDecl>(result));
            } else {
              const clang::EnumConstantDecl *unimported =
                  canonicalCaseIter->
                    second.dyn_cast<const clang::EnumConstantDecl *>();
  
              // Import the canonical enumerator for this case first.
              if (unimported) {
                enumeratorDecl = SwiftDeclConverter(Impl, getActiveSwiftVersion())
                    .importEnumCase(unimported, decl, cast<EnumDecl>(result));
                if (enumeratorDecl) {
                  canonicalCaseIter->getSecond() =
                      cast<EnumElementDecl>(enumeratorDecl);
                }
              } else {
                enumeratorDecl =
                    canonicalCaseIter->second.get<EnumElementDecl *>();
              }
  
              if (unimported != constant && enumeratorDecl) {
                ImportedName importedName =
                    Impl.importFullName(constant, getActiveSwiftVersion());
                Identifier name = importedName.getDeclName().getBaseIdentifier();
                if (name.empty()) {
                  // Clear the existing declaration so we don't try to process it
                  // twice later.
                  enumeratorDecl = nullptr;
                } else {
                  auto original = cast<ValueDecl>(enumeratorDecl);
                  enumeratorDecl = importEnumCaseAlias(name, constant, original,
                                                       decl, result);
                }
              }
            }
  
            Impl.forEachDistinctName(constant,
                                     [&](ImportedName newName,
                                         ImportNameVersion nameVersion) -> bool {
              if (nameVersion == getActiveSwiftVersion())
                return true;
              if (!contextIsEnum(newName))
                return true;
              SwiftDeclConverter converter(Impl, nameVersion);
              Decl *imported =
                  converter.importEnumCase(constant, decl, cast<EnumDecl>(result),
                                           enumeratorDecl);
              if (!imported)
                return false;
              variantDecls.push_back(imported);
              return true;
            });
            break;
          }
          }
          if (!enumeratorDecl)
            continue;
  
          if (addEnumeratorsAsMembers) {
            // Add a member enumerator to the given nominal type.
            auto addDecl = [&](NominalTypeDecl *nominal, Decl *decl) {
              if (!decl) return;
              nominal->addMember(decl);
              if (auto *var = dyn_cast<VarDecl>(decl))
                nominal->addMember(var->getGetter());
            };
  
            addDecl(result, enumeratorDecl);
            for (auto *variant : variantDecls)
              addDecl(result, variant);
            
            // If there is an error wrapper, add an alias within the
            // wrapper to the corresponding value within the enumerator
            // context.
            if (errorWrapper) {
              auto enumeratorValue = cast<ValueDecl>(enumeratorDecl);
              auto name = enumeratorValue->getBaseName().getIdentifier();
              auto alias = importEnumCaseAlias(name,
                                               constant,
                                               enumeratorValue,
                                               decl,
                                               result,
                                               errorWrapper);
              addDecl(errorWrapper, alias);
            }
          }
        }
  
        // Add the type decl to ExternalDefinitions so that we can type-check
        // raw values and SILGen can emit witness tables for derived conformances.
        // FIXME: There might be better ways to do this.
        Impl.registerExternalDecl(result);
        if (errorWrapper)
          Impl.registerExternalDecl(errorWrapper);
        return result;
      }
  
      Decl *VisitRecordDecl(const clang::RecordDecl *decl) {
        // Track whether this record contains fields we can't reference in Swift
        // as stored properties.
        bool hasUnreferenceableStorage = false;
        
        // Track whether this record contains fields that can't be zero-
        // initialized.
        bool hasZeroInitializableStorage = true;
  
        // Track whether all fields in this record can be referenced in Swift,
        // either as stored or computed properties, in which case the record type
        // gets a memberwise initializer.
        bool hasMemberwiseInitializer = true;
  
        if (decl->isUnion()) {
          hasUnreferenceableStorage = true;
  
          // We generate initializers specially for unions below.
          hasMemberwiseInitializer = false;
        }
  
        // FIXME: Skip Microsoft __interfaces.
        if (decl->isInterface())
          return nullptr;
  
        // FIXME: Figure out how to deal with incomplete types, since that
        // notion doesn't exist in Swift.
        decl = decl->getDefinition();
        if (!decl) {
          forwardDeclaration = true;
          return nullptr;
        }
  
        // Import the name.
        Optional<ImportedName> correctSwiftName;
        auto importedName = getClangDeclName(decl, correctSwiftName);
        if (!importedName)
          return nullptr;
  
        // If we've been asked to produce a compatibility stub, handle it via a
        // typealias.
        if (correctSwiftName)
          return importCompatibilityTypeAlias(decl, importedName,
                                              *correctSwiftName);
  
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
  
        // Create the struct declaration and record it.
        auto name = importedName.getDeclName().getBaseIdentifier();
        auto result = Impl.createDeclWithClangNode<StructDecl>(decl,
                                   AccessLevel::Public,
                                   Impl.importSourceLoc(decl->getLocStart()),
                                   name,
                                   Impl.importSourceLoc(decl->getLocation()),
                                   None, nullptr, dc);
        result->computeType();
        Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
  
        // FIXME: Figure out what to do with superclasses in C++. One possible
        // solution would be to turn them into members and add conversion
        // functions.
  
        // Import each of the members.
        SmallVector<VarDecl *, 4> members;
        SmallVector<ConstructorDecl *, 4> ctors;
  
        // FIXME: Import anonymous union fields and support field access when
        // it is nested in a struct.
  
        for (auto m : decl->decls()) {
          auto nd = dyn_cast<clang::NamedDecl>(m);
          if (!nd) {
            // We couldn't import the member, so we can't reference it in Swift.
            hasUnreferenceableStorage = true;
            hasMemberwiseInitializer = false;
            continue;
          }
  
          if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
            // Non-nullable pointers can't be zero-initialized.
            if (auto nullability = field->getType()
                  ->getNullability(Impl.getClangASTContext())) {
              if (*nullability == clang::NullabilityKind::NonNull)
                hasZeroInitializableStorage = false;
            }
            // TODO: If we had the notion of a closed enum with no private
            // cases or resilience concerns, then complete NS_ENUMs with
            // no case corresponding to zero would also not be zero-
            // initializable.
  
            // Unnamed bitfields are just for padding and should not
            // inhibit creation of a memberwise initializer.
            if (field->isUnnamedBitfield()) {
              hasUnreferenceableStorage = true;
              continue;
            }
          }
  
          auto member = Impl.importDecl(nd, getActiveSwiftVersion());
          if (!member) {
            if (!isa<clang::TypeDecl>(nd)) {
              // We don't know what this field is.
              // Assume it may be important in C.
              hasUnreferenceableStorage = true;
              hasMemberwiseInitializer = false;
            }
            continue;
          }
  
          if (isa<TypeDecl>(member)) {
            // A struct nested inside another struct will either be logically
            // a sibling of the outer struct, or contained inside of it, depending
            // on if it has a declaration name or not.
            //
            // struct foo { struct bar { ... } baz; } // sibling
            // struct foo { struct { ... } baz; } // child
            //
            // In the latter case, we add the imported type as a nested type
            // of the parent.
            //
            // TODO: C++ types have different rules.
            if (auto nominalDecl = dyn_cast<NominalTypeDecl>(member->getDeclContext())) {
              assert(nominalDecl == result && "interesting nesting of C types?");
              nominalDecl->addMember(member);
            }
            continue;
          }
  
          auto VD = cast<VarDecl>(member);
  
          if (isa<clang::IndirectFieldDecl>(nd) || decl->isUnion()) {
            // Don't import unavailable fields that have no associated storage.
            if (VD->getAttrs().isUnavailable(Impl.SwiftContext)) {
              continue;
            }
          }
  
          members.push_back(VD);
  
          // Bitfields are imported as computed properties with Clang-generated
          // accessors.
          if (auto field = dyn_cast<clang::FieldDecl>(nd)) {
            if (field->isBitField()) {
              // We can't represent this struct completely in SIL anymore,
              // but we're still able to define a memberwise initializer.
              hasUnreferenceableStorage = true;
  
              makeBitFieldAccessors(Impl,
                                    const_cast<clang::RecordDecl *>(decl),
                                    result,
                                    const_cast<clang::FieldDecl *>(field),
                                    VD);
            }
          }
  
          if (auto ind = dyn_cast<clang::IndirectFieldDecl>(nd)) {
            // Indirect fields are created as computed property accessible the
            // fields on the anonymous field from which they are injected.
            makeIndirectFieldAccessors(Impl, ind, members, result, VD);
          } else if (decl->isUnion()) {
            // Union fields should only be available indirectly via a computed
            // property. Since the union is made of all of the fields at once,
            // this is a trivial accessor that casts self to the correct
            // field type.
            makeUnionFieldAccessors(Impl, result, VD);
  
            // Create labeled initializers for unions that take one of the
            // fields, which only initializes the data for that field.
            auto valueCtor =
                createValueConstructor(Impl, result, VD,
                                       /*want param names*/true,
                                       /*wantBody=*/!Impl.hasFinishedTypeChecking());
            ctors.push_back(valueCtor);
          }
        }
  
        bool hasReferenceableFields = !members.empty();
  
        if (hasZeroInitializableStorage) {
          // Add constructors for the struct.
          ctors.push_back(createDefaultConstructor(Impl, result));
          if (hasReferenceableFields && hasMemberwiseInitializer) {
            // The default zero initializer suppresses the implicit value
            // constructor that would normally be formed, so we have to add that
            // explicitly as well.
            //
            // If we can completely represent the struct in SIL, leave the body
            // implicit, otherwise synthesize one to call property setters.
            bool wantBody = (hasUnreferenceableStorage &&
                             !Impl.hasFinishedTypeChecking());
            auto valueCtor = createValueConstructor(Impl, result, members,
                                                    /*want param names*/true,
                                                    /*want body*/wantBody);
            if (!hasUnreferenceableStorage)
              valueCtor->setIsMemberwiseInitializer();
  
            ctors.push_back(valueCtor);
          }
        }
  
        for (auto member : members) {
          result->addMember(member);
        }
        
        for (auto ctor : ctors) {
          result->addMember(ctor);
        }
  
        result->setHasUnreferenceableStorage(hasUnreferenceableStorage);
  
        // Add the struct decl to ExternalDefinitions so that IRGen can emit
        // metadata for it.
        // FIXME: There might be better ways to do this.
        Impl.registerExternalDecl(result);
  
        return result;
      }
  
      Decl *VisitClassTemplateSpecializationDecl(
                   const clang::ClassTemplateSpecializationDecl *decl) {
        // FIXME: We could import specializations, but perhaps only as unnamed
        // structural types.
        return nullptr;
      }
  
      Decl *VisitClassTemplatePartialSpecializationDecl(
                   const clang::ClassTemplatePartialSpecializationDecl *decl) {
        // Note: templates are not imported.
        return nullptr;
      }
  
      Decl *VisitTemplateTypeParmDecl(const clang::TemplateTypeParmDecl *decl) {
        // Note: templates are not imported.
        return nullptr;
      }
  
      Decl *VisitEnumConstantDecl(const clang::EnumConstantDecl *decl) {
        auto clangEnum = cast<clang::EnumDecl>(decl->getDeclContext());
  
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(decl, correctSwiftName);
        if (!importedName) return nullptr;
  
        auto name = importedName.getDeclName().getBaseIdentifier();
        if (name.empty())
          return nullptr;
  
        switch (Impl.getEnumKind(clangEnum)) {
        case EnumKind::Constants: {
          // The enumeration was simply mapped to an integral type. Create a
          // constant with that integral type.
  
          // The context where the constant will be introduced.
          auto dc =
              Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
          if (!dc)
            return nullptr;
  
          // Enumeration type.
          auto &clangContext = Impl.getClangASTContext();
          auto type = Impl.importType(clangContext.getTagDeclType(clangEnum),
                                      ImportTypeKind::Value,
                                      isInSystemModule(dc),
                                      Bridgeability::None);
          if (!type)
            return nullptr;
          // FIXME: Importing the type will recursively revisit this same
          // EnumConstantDecl. Short-circuit out if we already emitted the import
          // for this decl.
          if (auto Known = Impl.importDeclCached(decl, getVersion()))
            return Known;
  
          // Create the global constant.
          auto result = Impl.createConstant(name, dc, type,
                                            clang::APValue(decl->getInitVal()),
                                            ConstantConvertKind::Coerce,
                                            /*static*/dc->isTypeContext(), decl);
          Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
  
          // If this is a compatibility stub, mark it as such.
          if (correctSwiftName)
            markAsVariant(result, *correctSwiftName);
  
          return result;
        }
  
        case EnumKind::Unknown: {
          // The enumeration was mapped to a struct containing the integral
          // type. Create a constant with that struct type.
  
          // The context where the constant will be introduced.
          auto dc =
              Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
          if (!dc)
            return nullptr;
  
          // Import the enumeration type.
          auto enumType = Impl.importType(
                            Impl.getClangASTContext().getTagDeclType(clangEnum),
                            ImportTypeKind::Value,
                            isInSystemModule(dc),
                            Bridgeability::None);
          if (!enumType)
            return nullptr;
  
          // FIXME: Importing the type will can recursively revisit this same
          // EnumConstantDecl. Short-circuit out if we already emitted the import
          // for this decl.
          if (auto Known = Impl.importDeclCached(decl, getVersion()))
            return Known;
  
          // Create the global constant.
          auto result = Impl.createConstant(name, dc, enumType,
                                            clang::APValue(decl->getInitVal()),
                                            ConstantConvertKind::Construction,
                                            /*static*/ false, decl);
          Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
  
          // If this is a compatibility stub, mark it as such.
          if (correctSwiftName)
            markAsVariant(result, *correctSwiftName);
  
          return result;
        }
  
        case EnumKind::Enum:
        case EnumKind::Options: {
          // The enumeration was mapped to a high-level Swift type, and its
          // elements were created as children of that enum. They aren't available
          // independently.
  
          // FIXME: This is gross. We shouldn't have to import
          // everything to get at the individual constants.
          return nullptr;
        }
        }
        
        llvm_unreachable("Invalid EnumKind.");
      }
  
  
      Decl *
      VisitUnresolvedUsingValueDecl(const clang::UnresolvedUsingValueDecl *decl) {
        // Note: templates are not imported.
        return nullptr;
      }
  
      Decl *VisitIndirectFieldDecl(const clang::IndirectFieldDecl *decl) {
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(decl, correctSwiftName);
        if (!importedName) return nullptr;
  
        auto name = importedName.getDeclName().getBaseIdentifier();
  
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
  
        auto type = Impl.importType(decl->getType(),
                                    ImportTypeKind::Variable,
                                    isInSystemModule(dc),
                                    Bridgeability::None);
        if (!type)
          return nullptr;
  
        // Map this indirect field to a Swift variable.
        auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
                         AccessLevel::Public,
                         /*IsStatic*/false,
                         VarDecl::Specifier::Var,
                         /*IsCaptureList*/false,
                         Impl.importSourceLoc(decl->getLocStart()),
                         name, dc->mapTypeIntoContext(type), dc);
        result->setInterfaceType(type);
  
        // If this is a compatibility stub, mark is as such.
        if (correctSwiftName)
          markAsVariant(result, *correctSwiftName);
  
        return result;
      }
  
      ParameterList *getNonSelfParamList(
          DeclContext *dc, const clang::FunctionDecl *decl,
          Optional<unsigned> selfIdx, ArrayRef<Identifier> argNames,
          bool allowNSUIntegerAsInt, bool isAccessor) {
        if (bool(selfIdx)) {
          assert(((decl->getNumParams() == argNames.size() + 1) || isAccessor) &&
                 (*selfIdx < decl->getNumParams()) && "where's self?");
        } else {
          assert(decl->getNumParams() == argNames.size() || isAccessor);
        }
  
        SmallVector<const clang::ParmVarDecl *, 4> nonSelfParams;
        for (unsigned i = 0; i < decl->getNumParams(); ++i) {
          if (selfIdx && i == *selfIdx)
            continue;
          nonSelfParams.push_back(decl->getParamDecl(i));
        }
        return Impl.importFunctionParameterList(dc, decl, nonSelfParams,
                                                decl->isVariadic(),
                                                allowNSUIntegerAsInt, argNames);
      }
  
      Decl *importGlobalAsInitializer(const clang::FunctionDecl *decl,
                                      DeclName name, DeclContext *dc,
                                      CtorInitializerKind initKind,
                                      Optional<ImportedName> correctSwiftName);
  
      Decl *importGlobalAsMethod(const clang::FunctionDecl *decl, DeclName name,
                                 DeclContext *dc, Optional<unsigned> selfIdx,
                                 Optional<ImportedName> correctSwiftName);
  
      /// Create an implicit property given the imported name of one of
      /// the accessors.
      VarDecl *getImplicitProperty(ImportedName importedName,
                                   const clang::FunctionDecl *accessor);
  
      Decl *VisitFunctionDecl(const clang::FunctionDecl *decl) {
        // Import the name of the function.
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(decl, correctSwiftName);
        if (!importedName)
          return nullptr;
  
        AbstractStorageDecl *owningStorage;
        switch (importedName.getAccessorKind()) {
        case ImportedAccessorKind::None:
          owningStorage = nullptr;
          break;
  
        case ImportedAccessorKind::SubscriptGetter:
        case ImportedAccessorKind::SubscriptSetter:
          llvm_unreachable("Not possible for a function");
  
        case ImportedAccessorKind::PropertyGetter: {
          auto property = getImplicitProperty(importedName, decl);
          if (!property) return nullptr;
          return property->getGetter();
        }
  
        case ImportedAccessorKind::PropertySetter:
          auto property = getImplicitProperty(importedName, decl);
          if (!property) return nullptr;
          return property->getSetter();
        }
  
        return importFunctionDecl(decl, importedName, correctSwiftName, nullptr);
      }
  
      Decl *importFunctionDecl(const clang::FunctionDecl *decl,
                               ImportedName importedName,
                               Optional<ImportedName> correctSwiftName,
                               AbstractStorageDecl *owningStorage) {
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
  
        DeclName name = owningStorage ? DeclName() : importedName.getDeclName();
        if (importedName.importAsMember()) {
          // Handle initializers.
          if (name.getBaseName() == Impl.SwiftContext.Id_init)
            return importGlobalAsInitializer(decl, name, dc,
                                             importedName.getInitKind(),
                                             correctSwiftName);
  
          // Everything else is a method.
          return importGlobalAsMethod(decl, name, dc,
                                      importedName.getSelfIndex(),
                                      correctSwiftName);
        }
  
        // Import the function type. If we have parameters, make sure their names
        // get into the resulting function type.
        ParameterList *bodyParams = nullptr;
        Type type = Impl.importFunctionType(dc,
                                            decl,
                                            { decl->param_begin(),
                                              decl->param_size() },
                                            decl->isVariadic(),
                                            isInSystemModule(dc),
                                            name, bodyParams);
        if (!type)
          return nullptr;
  
        auto resultTy = type->castTo<FunctionType>()->getResult();
        auto loc = Impl.importSourceLoc(decl->getLocation());
  
        if (name && name.isSimpleName()) {
          assert(importedName.hasCustomName() &&
                 "imported function with simple name?");
          // Just fill in empty argument labels.
          name = DeclName(Impl.SwiftContext, name.getBaseName(), bodyParams);
        }
  
        // FIXME: Poor location info.
        auto nameLoc = Impl.importSourceLoc(decl->getLocation());
        auto result = FuncDecl::create(
            Impl.SwiftContext, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
            /*FuncLoc=*/loc, name, nameLoc,
            /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
            /*AccessorKeywordLoc=*/SourceLoc(),
            /*GenericParams=*/nullptr, bodyParams,
            TypeLoc::withoutLoc(resultTy), dc, decl);
  
        result->setInterfaceType(type);
        result->setValidationStarted();
  
        // Someday, maybe this will need to be 'open' for C++ virtual methods.
        result->setAccess(AccessLevel::Public);
        finishFuncDecl(decl, result);
  
        // If this is a compatibility stub, mark it as such.
        if (correctSwiftName)
          markAsVariant(result, *correctSwiftName);
  
        return result;
      }
  
      void finishFuncDecl(const clang::FunctionDecl *decl,
                          AbstractFunctionDecl *result) {
        // Keep track of inline function bodies so that we can generate
        // IR from them using Clang's IR generator.
        if ((decl->isInlined() || decl->hasAttr<clang::AlwaysInlineAttr>() ||
             !decl->isExternallyVisible()) &&
            decl->hasBody()) {
          Impl.registerExternalDecl(result);
        }
  
        // Set availability.
        if (decl->isVariadic()) {
          Impl.markUnavailable(result, "Variadic function is unavailable");
        }
  
        if (decl->hasAttr<clang::ReturnsTwiceAttr>()) {
          // The Clang 'returns_twice' attribute is used for functions like
          // 'vfork' or 'setjmp'. Because these functions may return control flow
          // of a Swift program to an arbitrary point, Swift's guarantees of
          // definitive initialization of variables cannot be upheld. As a result,
          // functions like these cannot be used in Swift.
          Impl.markUnavailable(
            result,
            "Functions that may return more than one time (annotated with the "
            "'returns_twice' attribute) are unavailable in Swift");
        }
      }
  
      Decl *VisitCXXMethodDecl(const clang::CXXMethodDecl *decl) {
        // FIXME: Import C++ member functions as methods.
        return nullptr;
      }
  
      Decl *VisitFieldDecl(const clang::FieldDecl *decl) {
        // Fields are imported as variables.
        Optional<ImportedName> correctSwiftName;
        ImportedName importedName;
  
        if (!decl->isAnonymousStructOrUnion()) {
          importedName = importFullName(decl, correctSwiftName);
          if (!importedName) {
            return nullptr;
          }
        } else {
          // Generate a field name for anonymous fields, this will be used in
          // order to be able to expose the indirect fields injected from there
          // as computed properties forwarding the access to the subfield.
          std::string Id;
          llvm::raw_string_ostream IdStream(Id);
  
          IdStream << "__Anonymous_field" << decl->getFieldIndex();
          importedName.setDeclName(Impl.SwiftContext.getIdentifier(IdStream.str()));
          importedName.setEffectiveContext(decl->getDeclContext());
        }
  
        auto name = importedName.getDeclName().getBaseIdentifier();
  
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
  
        auto type = Impl.importType(decl->getType(),
                                    ImportTypeKind::RecordField,
                                    isInSystemModule(dc),
                                    Bridgeability::None);
        if (!type)
          return nullptr;
  
        auto result =
          Impl.createDeclWithClangNode<VarDecl>(decl, AccessLevel::Public,
                                /*IsStatic*/ false,
                                VarDecl::Specifier::Var,
                                /*IsCaptureList*/false,
                                Impl.importSourceLoc(decl->getLocation()),
                                name, dc->mapTypeIntoContext(type), dc);
        result->setInterfaceType(type);
  
        // Handle attributes.
        if (decl->hasAttr<clang::IBOutletAttr>())
          result->getAttrs().add(
              new (Impl.SwiftContext) IBOutletAttr(/*IsImplicit=*/false));
        // FIXME: Handle IBOutletCollection.
  
        // If this is a compatibility stub, handle it as such.
        if (correctSwiftName)
          markAsVariant(result, *correctSwiftName);
  
        return result;
      }
  
      Decl *VisitObjCIvarDecl(const clang::ObjCIvarDecl *decl) {
        // Disallow direct ivar access (and avoid conflicts with property names).
        return nullptr;
      }
  
      Decl *VisitObjCAtDefsFieldDecl(const clang::ObjCAtDefsFieldDecl *decl) {
        // @defs is an anachronism; ignore it.
        return nullptr;
      }
  
      Decl *VisitVarDecl(const clang::VarDecl *decl) {
        // FIXME: Swift does not have static variables in structs/classes yet.
        if (decl->getDeclContext()->isRecord())
          return nullptr;
  
        // Variables are imported as... variables.
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(decl, correctSwiftName);
        if (!importedName) return nullptr;
  
        auto name = importedName.getDeclName().getBaseIdentifier();
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
  
        // If the declaration is const, consider it audited.
        // We can assume that loading a const global variable doesn't
        // involve an ownership transfer.
        bool isAudited = decl->getType().isConstQualified();
  
        auto declType = decl->getType();
  
        // Special case: NS Notifications
        if (isNSNotificationGlobal(decl))
          if (auto newtypeDecl = findSwiftNewtype(decl, Impl.getClangSema(),
                                                  Impl.CurrentVersion))
            declType = Impl.getClangASTContext().getTypedefType(newtypeDecl);
  
        // Note that we deliberately don't bridge most globals because we want to
        // preserve pointer identity.
        Type type = Impl.importType(declType,
                                    (isAudited ? ImportTypeKind::AuditedVariable
                                     : ImportTypeKind::Variable),
                                    isInSystemModule(dc),
                                    Bridgeability::None);
  
        if (!type)
          return nullptr;
  
        // If we've imported this variable as a member, it's a static
        // member.
        bool isStatic = false;
        if (dc->isTypeContext())
          isStatic = true;
  
        auto specifier = Impl.shouldImportGlobalAsLet(decl->getType())
                       ? VarDecl::Specifier::Let
                       : VarDecl::Specifier::Var;
        auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
                         AccessLevel::Public,
                         /*IsStatic*/isStatic,
                         specifier,
                         /*IsCaptureList*/false,
                         Impl.importSourceLoc(decl->getLocation()),
                         name, dc->mapTypeIntoContext(type), dc);
        result->setInterfaceType(type);
  
        // If imported as member, the member should be final.
        if (dc->getAsClassOrClassExtensionContext())
          result->getAttrs().add(new (Impl.SwiftContext)
                                   FinalAttr(/*IsImplicit=*/true));
  
        if (!decl->hasExternalStorage())
          Impl.registerExternalDecl(result);
  
        // If this is a compatibility stub, mark it as such.
        if (correctSwiftName)
          markAsVariant(result, *correctSwiftName);
  
        return result;
      }
  
      Decl *VisitImplicitParamDecl(const clang::ImplicitParamDecl *decl) {
        // Parameters are never directly imported.
        return nullptr;
      }
  
      Decl *VisitParmVarDecl(const clang::ParmVarDecl *decl) {
        // Parameters are never directly imported.
        return nullptr;
      }
  
      Decl *
      VisitNonTypeTemplateParmDecl(const clang::NonTypeTemplateParmDecl *decl) {
        // Note: templates are not imported.
        return nullptr;
      }
  
      Decl *VisitTemplateDecl(const clang::TemplateDecl *decl) {
        // Note: templates are not imported.
        return nullptr;
      }
  
      Decl *VisitUsingDecl(const clang::UsingDecl *decl) {
        // Using declarations are not imported.
        return nullptr;
      }
  
      Decl *VisitUsingShadowDecl(const clang::UsingShadowDecl *decl) {
        // Using shadow declarations are not imported; rather, name lookup just
        // looks through them.
        return nullptr;
      }
  
      /// Add an @objc(name) attribute with the given, optional name expressed as
      /// selector.
      ///
      /// The importer should use this rather than adding the attribute directly.
      void addObjCAttribute(ValueDecl *decl, Optional<ObjCSelector> name) {
        auto &ctx = Impl.SwiftContext;
        decl->getAttrs().add(ObjCAttr::create(ctx, name, /*implicitName=*/true));
  
        // If the declaration we attached the 'objc' attribute to is within a
        // class, record it in the class.
        if (auto contextTy = decl->getDeclContext()->getDeclaredInterfaceType()) {
          if (auto classDecl = contextTy->getClassOrBoundGenericClass()) {
            if (auto method = dyn_cast<AbstractFunctionDecl>(decl)) {
              classDecl->recordObjCMethod(method);
            }
          }
        }
      }
  
      /// Add an @objc(name) attribute with the given, optional name expressed as
      /// selector.
      ///
      /// The importer should use this rather than adding the attribute directly.
      void addObjCAttribute(ValueDecl *decl, Identifier name) {
        addObjCAttribute(decl, ObjCSelector(Impl.SwiftContext, 0, name));
      }
  
      Decl *VisitObjCMethodDecl(const clang::ObjCMethodDecl *decl) {
        auto dc = Impl.importDeclContextOf(decl, decl->getDeclContext());
        if (!dc)
          return nullptr;
  
        // While importing the DeclContext, we might have imported the decl
        // itself.
        if (auto Known = Impl.importDeclCached(decl, getVersion()))
          return Known;
  
        return importObjCMethodDecl(decl, dc);
      }
  
      /// Check whether we have already imported a method with the given
      /// selector in the given context.
      bool methodAlreadyImported(ObjCSelector selector, bool isInstance,
                                 DeclContext *dc) {
        // We only need to perform this check for classes.
        auto classDecl
          = dc->getDeclaredInterfaceType()->getClassOrBoundGenericClass();
        if (!classDecl)
          return false;
  
        // Make sure we don't search in Clang modules for this method.
        ++Impl.ActiveSelectors[{selector, isInstance}];
  
        // Look for a matching imported or deserialized member.
        bool result = false;
        for (auto decl : classDecl->lookupDirect(selector, isInstance)) {
          if (decl->getClangDecl()
              || !decl->getDeclContext()->getParentSourceFile()) {
            result = true;
            break;
          }
        }
  
        // Restore the previous active count in the active-selector mapping.
        auto activeCount = Impl.ActiveSelectors.find({selector, isInstance});
        --activeCount->second;
        if (activeCount->second == 0)
          Impl.ActiveSelectors.erase(activeCount);
  
        return result;
      }
  
      Decl *importObjCMethodDecl(const clang::ObjCMethodDecl *decl,
                                DeclContext *dc) {
        return importObjCMethodDecl(decl, dc, false);
      }
  
    private:
      Decl *importObjCMethodDecl(const clang::ObjCMethodDecl *decl,
                                DeclContext *dc,
                                bool forceClassMethod) {
        // If we have an init method, import it as an initializer.
        if (isInitMethod(decl)) {
          // Cannot force initializers into class methods.
          if (forceClassMethod)
            return nullptr;
  
          return importConstructor(decl, dc, /*implicit=*/false, None,
                                   /*required=*/false);
        }
  
        // Check whether we already imported this method.
        if (!forceClassMethod &&
            dc == Impl.importDeclContextOf(decl, decl->getDeclContext())) {
          // FIXME: Should also be able to do this for forced class
          // methods.
          auto known = Impl.ImportedDecls.find({decl->getCanonicalDecl(),
                                                getVersion()});
          if (known != Impl.ImportedDecls.end())
            return known->second;
        }
  
        // Check whether another method with the same selector has already been
        // imported into this context.
        ObjCSelector selector = Impl.importSelector(decl->getSelector());
        bool isInstance = decl->isInstanceMethod() && !forceClassMethod;
        if (isActiveSwiftVersion() &&
            methodAlreadyImported(selector, isInstance, dc))
          return nullptr;
  
  
        ImportedName importedName;
        Optional<ImportedName> correctSwiftName;
        importedName = importFullName(decl, correctSwiftName);
        if (!importedName)
          return nullptr;
  
        // Normal case applies when we're importing an older name, or when we're
        // not an init
        if (!isActiveSwiftVersion() || !isFactoryInit(importedName)) {
          auto result = importNonInitObjCMethodDecl(decl, dc, importedName,
                                                    selector, forceClassMethod);
          if (!isActiveSwiftVersion() && result)
            markAsVariant(result, *correctSwiftName);
          return result;
        }
  
        // We don't want to suppress init formation in Swift 3 names. Instead, we
        // want the normal Swift 3 name, and a "raw" name for diagnostics. The
        // "raw" name will be imported as unavailable with a more helpful and
        // specific message.
        ++NumFactoryMethodsAsInitializers;
        bool redundant = false;
        auto result =
            importConstructor(decl, dc, false, importedName.getInitKind(),
                              /*required=*/false, selector, importedName,
                              {decl->param_begin(), decl->param_size()},
                              decl->isVariadic(), redundant);
  
        return result;
      }
  
      Decl *importNonInitObjCMethodDecl(const clang::ObjCMethodDecl *decl,
                                        DeclContext *dc,
                                        ImportedName importedName,
                                        ObjCSelector selector,
                                        bool forceClassMethod) {
        assert(dc->isTypeContext() && "Method in non-type context?");
        assert(isa<ClangModuleUnit>(dc->getModuleScopeContext()) &&
               "Clang method in Swift context?");
  
        // FIXME: We should support returning "Self.Type" for a root class
        // instance method mirrored as a class method, but it currently causes
        // problems for the type checker.
        if (forceClassMethod && decl->hasRelatedResultType())
          return nullptr;
  
        // Hack: avoid importing methods named "print" that aren't available in
        // the current version of Swift. We'd rather just let the user use
        // Swift.print in that case.
        if (!isActiveSwiftVersion() &&
            isPrintLikeMethod(importedName.getDeclName(), dc)) {
          return nullptr;
        }
  
        // Add the implicit 'self' parameter patterns.
        bool isInstance = decl->isInstanceMethod() && !forceClassMethod;
        SmallVector<ParameterList *, 4> bodyParams;
        auto selfVar =
          ParamDecl::createSelf(SourceLoc(), dc, /*isStatic*/!isInstance);
        bodyParams.push_back(ParameterList::createWithoutLoc(selfVar));
        Type selfInterfaceType = dc->getSelfInterfaceType();
        if (!isInstance) {
          selfInterfaceType = MetatypeType::get(selfInterfaceType);
        }
  
        SpecialMethodKind kind = SpecialMethodKind::Regular;
        if (isNSDictionaryMethod(decl, Impl.objectForKeyedSubscript))
          kind = SpecialMethodKind::NSDictionarySubscriptGetter;
  
        // Import the type that this method will have.
        Optional<ForeignErrorConvention> errorConvention;
        bodyParams.push_back(nullptr);
        Type type;
  
        // If we have a property accessor, find the corresponding property
        // declaration.
        const clang::ObjCPropertyDecl *prop = nullptr;
        if (decl->isPropertyAccessor()) {
          prop = decl->findPropertyDecl();
          if (!prop) return nullptr;
  
          // If we're importing just the accessors (not the property), ignore
          // the property.
          if (shouldImportPropertyAsAccessors(prop))
            prop = nullptr;
        }
  
        if (prop) {
          // If the matching property is in a superclass, or if the getter and
          // setter are redeclared in a potentially incompatible way, bail out.
          if (prop->getGetterMethodDecl() != decl &&
              prop->getSetterMethodDecl() != decl)
            return nullptr;
          type = Impl.importAccessorMethodType(dc, prop, decl,
                                               isInSystemModule(dc), importedName,
                                               &bodyParams.back());
        } else {
          type = Impl.importMethodType(dc, decl, decl->parameters(),
                                       decl->isVariadic(), isInSystemModule(dc),
                                       &bodyParams.back(), importedName,
                                       errorConvention, kind);
        }
        if (!type)
          return nullptr;
  
        // Check whether we recursively imported this method
        if (!forceClassMethod &&
            dc == Impl.importDeclContextOf(decl, decl->getDeclContext())) {
          // FIXME: Should also be able to do this for forced class
          // methods.
          auto known = Impl.ImportedDecls.find({decl->getCanonicalDecl(),
                                                getVersion()});
          if (known != Impl.ImportedDecls.end())
            return known->second;
        }
  
        auto result = FuncDecl::create(
            Impl.SwiftContext, /*StaticLoc=*/SourceLoc(),
            StaticSpellingKind::None, /*FuncLoc=*/SourceLoc(),
            importedName.getDeclName(), /*NameLoc=*/SourceLoc(),
            /*Throws=*/importedName.getErrorInfo().hasValue(),
            /*ThrowsLoc=*/SourceLoc(), /*AccessorKeywordLoc=*/SourceLoc(),
            /*GenericParams=*/nullptr, bodyParams, TypeLoc(), dc, decl);
  
        result->setAccess(getOverridableAccessLevel(dc));
  
        auto resultTy = type->castTo<FunctionType>()->getResult();
  
        // If the method has a related result type that is representable
        // in Swift as DynamicSelf, do so.
        if (!prop && decl->hasRelatedResultType()) {
          result->setDynamicSelf(true);
          resultTy = DynamicSelfType::get(dc->getSelfInterfaceType(),
                                          Impl.SwiftContext);
  
          OptionalTypeKind nullability = OTK_ImplicitlyUnwrappedOptional;
          if (auto typeNullability = decl->getReturnType()->getNullability(
                                       Impl.getClangASTContext())) {
            // If the return type has nullability, use it.
            nullability = translateNullability(*typeNullability);
          }
          if (nullability != OTK_None && !errorConvention.hasValue()) {
            resultTy = OptionalType::get(nullability, resultTy);
          }
  
          // Update the method type with the new result type.
          auto methodTy = type->castTo<FunctionType>();
          type = FunctionType::get(methodTy->getInput(), resultTy, 
                                   methodTy->getExtInfo());
        }
  
        // Add the 'self' parameter to the function type. NB. a method's formal
        // type should be (Type) -> (Args...) -> Ret, not Type -> (Args...) ->
        // Ret.
        auto parenSelfType = ParenType::get(Impl.SwiftContext, selfInterfaceType);
        type = FunctionType::get(parenSelfType, type);
  
        auto interfaceType = getGenericMethodType(dc, type->castTo<AnyFunctionType>());
        result->setInterfaceType(interfaceType);
        result->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
        result->setValidationStarted();
  
        // Optional methods in protocols.
        if (decl->getImplementationControl() == clang::ObjCMethodDecl::Optional &&
            isa<ProtocolDecl>(dc))
          result->getAttrs().add(new (Impl.SwiftContext)
                                        OptionalAttr(/*implicit*/false));
  
        // Mark class methods as static.
        if (decl->isClassMethod() || forceClassMethod)
          result->setStatic();
        if (forceClassMethod)
          result->setImplicit();
  
        // Mark this method @objc.
        addObjCAttribute(result, selector);
  
        // If this method overrides another method, mark it as such.
        recordObjCOverride(result);
  
        // Record the error convention.
        if (errorConvention) {
          result->setForeignErrorConvention(*errorConvention);
        }
  
        // Handle attributes.
        if (decl->hasAttr<clang::IBActionAttr>() &&
            isa<FuncDecl>(result) &&
            cast<FuncDecl>(result)->isPotentialIBActionTarget()) {
          result->getAttrs().add(
              new (Impl.SwiftContext) IBActionAttr(/*IsImplicit=*/false));
        }
  
        // Check whether there's some special method to import.
        if (!forceClassMethod) {
          if (dc == Impl.importDeclContextOf(decl, decl->getDeclContext()) &&
              !Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}])
            Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}]
              = result;
  
          if (importedName.isSubscriptAccessor()) {
            // If this was a subscript accessor, try to create a
            // corresponding subscript declaration.
            (void)importSubscript(result, decl);
          } else if (shouldAlsoImportAsClassMethod(result)) {
            // If we should import this instance method also as a class
            // method, do so and mark the result as an alternate
            // declaration.
            if (auto imported = importObjCMethodDecl(decl, dc,
                                                    /*forceClassMethod=*/true))
              Impl.addAlternateDecl(result, cast<ValueDecl>(imported));
          }
        }
  
        return result;
      }
  
    public:
      /// Record the function or initializer overridden by the given Swift method.
      void recordObjCOverride(AbstractFunctionDecl *decl);
  
      /// \brief Given an imported method, try to import it as a constructor.
      ///
      /// Objective-C methods in the 'init' family are imported as
      /// constructors in Swift, enabling object construction syntax, e.g.,
      ///
      /// \code
      /// // in objc: [[NSArray alloc] initWithCapacity:1024]
      /// NSArray(capacity: 1024)
      /// \endcode
      ConstructorDecl *importConstructor(const clang::ObjCMethodDecl *objcMethod,
                                         DeclContext *dc,
                                         bool implicit,
                                         Optional<CtorInitializerKind> kind,
                                         bool required);
  
      /// Returns the latest "introduced" version on the current platform for
      /// \p D.
      clang::VersionTuple findLatestIntroduction(const clang::Decl *D);
  
      /// Returns true if importing \p objcMethod will produce a "better"
      /// initializer than \p existingCtor.
      bool
      existingConstructorIsWorse(const ConstructorDecl *existingCtor,
                                 const clang::ObjCMethodDecl *objcMethod,
                                 CtorInitializerKind kind);
  
      /// \brief Given an imported method, try to import it as a constructor.
      ///
      /// Objective-C methods in the 'init' family are imported as
      /// constructors in Swift, enabling object construction syntax, e.g.,
      ///
      /// \code
      /// // in objc: [[NSArray alloc] initWithCapacity:1024]
      /// NSArray(capacity: 1024)
      /// \endcode
      ///
      /// This variant of the function is responsible for actually binding the
      /// constructor declaration appropriately.
      ConstructorDecl *importConstructor(const clang::ObjCMethodDecl *objcMethod,
                                         DeclContext *dc,
                                         bool implicit,
                                         Optional<CtorInitializerKind> kindIn,
                                         bool required,
                                         ObjCSelector selector,
                                         ImportedName importedName,
                                         ArrayRef<const clang::ParmVarDecl*> args,
                                         bool variadic,
                                         bool &redundant);
  
      void recordObjCOverride(SubscriptDecl *subscript);
  
      /// \brief Given either the getter or setter for a subscript operation,
      /// create the Swift subscript declaration.
      SubscriptDecl *importSubscript(Decl *decl,
                                     const clang::ObjCMethodDecl *objcMethod);
  
      /// Import the accessor and its attributes.
      FuncDecl *importAccessor(clang::ObjCMethodDecl *clangAccessor,
                               DeclContext *dc);
  
    public:
  
      /// Recursively add the given protocol and its inherited protocols to the
      /// given vector, guarded by the known set of protocols.
      void addProtocols(ProtocolDecl *protocol,
                        SmallVectorImpl<ProtocolDecl *> &protocols,
                        llvm::SmallPtrSet<ProtocolDecl *, 4> &known);
  
      // Import the given Objective-C protocol list, along with any
      // implicitly-provided protocols, and attach them to the given
      // declaration.
      void importObjCProtocols(Decl *decl,
                               const clang::ObjCProtocolList &clangProtocols,
                               SmallVectorImpl<TypeLoc> &inheritedTypes);
  
      /// Add conformances to the given Objective-C protocols to the
      /// given declaration.
      void addObjCProtocolConformances(Decl *decl,
                                       ArrayRef<ProtocolDecl*> protocols);
  
      // Returns None on error. Returns nullptr if there is no type param list to
      // import or we suppress its import, as in the case of NSArray, NSSet, and
      // NSDictionary.
      Optional<GenericParamList *>
      importObjCGenericParams(const clang::ObjCInterfaceDecl *decl,
                              DeclContext *dc);
  
      /// \brief Import the members of all of the protocols to which the given
      /// Objective-C class, category, or extension explicitly conforms into
      /// the given list of members, so long as the method was not already
      /// declared in the class.
      ///
      /// FIXME: This whole thing is a hack, because name lookup should really
      /// just find these members when it looks in the protocol. Unfortunately,
      /// that's not something the name lookup code can handle right now, and
      /// it may still be necessary when the protocol's instance methods become
      /// class methods on a root class (e.g. NSObject-the-protocol's instance
      /// methods become class methods on NSObject).
      void importMirroredProtocolMembers(const clang::ObjCContainerDecl *decl,
                                         DeclContext *dc,
                                         ArrayRef<ProtocolDecl *> protocols,
                                         SmallVectorImpl<Decl *> &members,
                                         ASTContext &Ctx);
  
      void importNonOverriddenMirroredMethods(DeclContext *dc,
                                    MutableArrayRef<MirroredMethodEntry> entries,
                                    SmallVectorImpl<Decl *> &newMembers);
  
      /// \brief Import constructors from our superclasses (and their
      /// categories/extensions), effectively "inheriting" constructors.
      void importInheritedConstructors(ClassDecl *classDecl,
                                       SmallVectorImpl<Decl *> &newMembers);
  
      Decl *VisitObjCCategoryDecl(const clang::ObjCCategoryDecl *decl) {
        // If the declaration is invalid, fail.
        if (decl->isInvalidDecl()) return nullptr;
  
        // Objective-C categories and extensions map to Swift extensions.
        if (importer::hasNativeSwiftDecl(decl))
          return nullptr;
  
        // Find the Swift class being extended.
        auto objcClass = castIgnoringCompatibilityAlias<ClassDecl>(
            Impl.importDecl(decl->getClassInterface(), getActiveSwiftVersion()));
        if (!objcClass)
          return nullptr;
  
        auto dc = Impl.importDeclContextOf(decl, decl->getDeclContext());
        if (!dc)
          return nullptr;
  
        auto loc = Impl.importSourceLoc(decl->getLocStart());
        auto result = ExtensionDecl::create(
                        Impl.SwiftContext, loc,
                        TypeLoc::withoutLoc(objcClass->getDeclaredType()),
                        { }, dc, nullptr, decl);
  
        // Determine the type and generic args of the extension.
        if (objcClass->getGenericParams()) {
          // Clone generic parameters.
          SmallVector<GenericTypeParamDecl *, 2> toGenericParams;
          for (auto fromGP : *objcClass->getGenericParams()) {
            // Create the new generic parameter.
            auto toGP = new (Impl.SwiftContext) GenericTypeParamDecl(
                result, fromGP->getName(), SourceLoc(), fromGP->getDepth(),
                fromGP->getIndex());
            toGP->setImplicit(true);
            toGP->setInherited(
                Impl.SwiftContext.AllocateCopy(fromGP->getInherited()));
            // Record new generic parameter.
            toGenericParams.push_back(toGP);
          }
  
          auto genericParams = GenericParamList::create(Impl.SwiftContext,
              SourceLoc(), toGenericParams, SourceLoc());
          result->setGenericParams(genericParams);
  
          auto *env = Impl.buildGenericEnvironment(genericParams, result);
          result->setGenericEnvironment(env);
  
          // Calculate the correct bound-generic extended type.
          SmallVector<Type, 2> genericArgs;
          for (auto paramTy :
               env->getGenericSignature()->getInnermostGenericParams()) {
            genericArgs.push_back(env->mapTypeIntoContext(paramTy));
          }
          Type extendedType =
            BoundGenericClassType::get(objcClass, nullptr, genericArgs);
          result->getExtendedTypeLoc().setType(extendedType);
        }
  
        // Create the extension declaration and record it.
        objcClass->addExtension(result);
        Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
        SmallVector<TypeLoc, 4> inheritedTypes;
        importObjCProtocols(result, decl->getReferencedProtocols(),
                            inheritedTypes);
        result->setValidationStarted();
        result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
        result->setCheckedInheritanceClause();
        result->setMemberLoader(&Impl, 0);
  
        return result;
      }
  
      template <typename T, typename U>
      T *resolveSwiftDeclImpl(const U *decl, Identifier name, ModuleDecl *adapter) {
        const auto &languageVersion =
            Impl.SwiftContext.LangOpts.EffectiveLanguageVersion;
  
        SmallVector<ValueDecl *, 4> results;
        adapter->lookupValue({}, name, NLKind::QualifiedLookup, results);
        T *found = nullptr;
        for (auto result : results) {
          if (auto singleResult = dyn_cast<T>(result)) {
            if (auto typeResolver = Impl.getTypeResolver())
              typeResolver->resolveDeclSignature(singleResult);
  
            // Skip versioned variants.
            const DeclAttributes &attrs = singleResult->getAttrs();
            if (attrs.isUnavailableInSwiftVersion(languageVersion))
              continue;
  
            if (found)
              return nullptr;
  
            found = singleResult;
          }
        }
  
        if (found)
          Impl.ImportedDecls[{decl->getCanonicalDecl(),
                              getActiveSwiftVersion()}] = found;
  
        return found;
      }
  
      template <typename T, typename U>
      T *resolveSwiftDecl(const U *decl, Identifier name,
                          ClangModuleUnit *clangModule) {
        if (auto adapter = clangModule->getAdapterModule())
          return resolveSwiftDeclImpl<T>(decl, name, adapter);
        if (clangModule == Impl.ImportedHeaderUnit) {
          // Use an index-based loop because new owners can come in as we're
          // iterating.
          for (size_t i = 0; i < Impl.ImportedHeaderOwners.size(); ++i) {
            ModuleDecl *owner = Impl.ImportedHeaderOwners[i];
            if (T *result = resolveSwiftDeclImpl<T>(decl, name, owner))
              return result;
          }
        }
        return nullptr;
      }
  
      template <typename T, typename U>
      bool hasNativeSwiftDecl(const U *decl, Identifier name,
                              const DeclContext *dc, T *&swiftDecl) {
        if (!importer::hasNativeSwiftDecl(decl))
          return false;
        auto wrapperUnit = cast<ClangModuleUnit>(dc->getModuleScopeContext());
        swiftDecl = resolveSwiftDecl<T>(decl, name, wrapperUnit);
        return true;
      }
  
      void markMissingSwiftDecl(ValueDecl *VD) {
        const char *message;
        if (isa<ClassDecl>(VD))
          message = "cannot find Swift declaration for this class";
        else if (isa<ProtocolDecl>(VD))
          message = "cannot find Swift declaration for this protocol";
        else
          llvm_unreachable("unknown bridged decl kind");
        auto attr = AvailableAttr::createPlatformAgnostic(Impl.SwiftContext,
                                                          message);
        VD->getAttrs().add(attr);
      }
  
      Decl *VisitObjCProtocolDecl(const clang::ObjCProtocolDecl *decl) {
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(decl, correctSwiftName);
        if (!importedName) return nullptr;
  
        // If we've been asked to produce a compatibility stub, handle it via a
        // typealias.
        if (correctSwiftName)
          return importCompatibilityTypeAlias(decl, importedName,
                                              *correctSwiftName);
  
        Identifier name = importedName.getDeclName().getBaseIdentifier();
  
        // FIXME: Figure out how to deal with incomplete protocols, since that
        // notion doesn't exist in Swift.
        if (!decl->hasDefinition()) {
          // Check if this protocol is implemented in its adapter.
          if (auto clangModule = Impl.getClangModuleForDecl(decl, true))
            if (auto native = resolveSwiftDecl<ProtocolDecl>(decl, name,
                                                             clangModule))
              return native;
  
          forwardDeclaration = true;
          return nullptr;
        }
  
        decl = decl->getDefinition();
  
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
  
        ProtocolDecl *nativeDecl;
        bool declaredNative = hasNativeSwiftDecl(decl, name, dc, nativeDecl);
        if (declaredNative && nativeDecl)
          return nativeDecl;
  
        // Create the protocol declaration and record it.
        auto result = Impl.createDeclWithClangNode<ProtocolDecl>(
            decl, AccessLevel::Public, dc,
            Impl.importSourceLoc(decl->getLocStart()),
            Impl.importSourceLoc(decl->getLocation()), name, None,
            /*TrailingWhere=*/nullptr);
        result->computeType();
  
        // FIXME: Kind of awkward that we have to do this here
        result->getGenericParams()->getParams()[0]->setDepth(0);
  
        addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
  
        if (declaredNative)
          markMissingSwiftDecl(result);
  
        Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
  
        result->setCircularityCheck(CircularityCheck::Checked);
  
        // Import protocols this protocol conforms to.
        SmallVector<TypeLoc, 4> inheritedTypes;
        importObjCProtocols(result, decl->getReferencedProtocols(),
                            inheritedTypes);
        result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
        result->setCheckedInheritanceClause();
  
        // Compute the requirement signature.
        if (!result->isRequirementSignatureComputed())
          result->computeRequirementSignature();
  
        auto *env = Impl.buildGenericEnvironment(result->getGenericParams(), dc);
        result->setGenericEnvironment(env);
  
        result->setMemberLoader(&Impl, 0);
  
        // Add the protocol decl to ExternalDefinitions so that IRGen can emit
        // metadata for it.
        // FIXME: There might be better ways to do this.
        Impl.registerExternalDecl(result);
  
        return result;
      }
  
      // Add inferred attributes.
      void addInferredAttributes(Decl *decl, unsigned attributes) {
        using namespace inferred_attributes;
        if (attributes & requires_stored_property_inits) {
          auto a = new (Impl.SwiftContext)
            RequiresStoredPropertyInitsAttr(/*IsImplicit=*/true);
          decl->getAttrs().add(a);
          cast<ClassDecl>(decl)->setRequiresStoredPropertyInits(true);
        }
      }
  
      Decl *VisitObjCInterfaceDecl(const clang::ObjCInterfaceDecl *decl) {
        auto createRootClass = [=](Identifier name,
                                   DeclContext *dc = nullptr) -> ClassDecl * {
          if (!dc) {
            dc = Impl.getClangModuleForDecl(decl->getCanonicalDecl(),
                                            /*allowForwardDeclaration=*/true);
          }
  
          auto result = Impl.createDeclWithClangNode<ClassDecl>(decl,
                                                          AccessLevel::Open,
                                                          SourceLoc(), name,
                                                          SourceLoc(), None,
                                                          nullptr, dc);
          result->computeType();
          Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
          result->setCircularityCheck(CircularityCheck::Checked);
          result->setSuperclass(Type());
          result->setCheckedInheritanceClause();
          result->setAddedImplicitInitializers(); // suppress all initializers
          addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
          result->addImplicitDestructor();
          return result;
        };
  
        // Special case for Protocol, which gets forward-declared as an ObjC
        // class which is hidden in modern Objective-C runtimes.
        // We treat it as a foreign class (like a CF type) because it doesn't
        // have a real public class object.
        clang::ASTContext &clangCtx = Impl.getClangASTContext();
        if (decl->getCanonicalDecl() ==
            clangCtx.getObjCProtocolDecl()->getCanonicalDecl()) {
          Type nsObjectTy = Impl.getNSObjectType();
          if (!nsObjectTy)
            return nullptr;
          const ClassDecl *nsObjectDecl =
            nsObjectTy->getClassOrBoundGenericClass();
  
          auto result = createRootClass(Impl.SwiftContext.Id_Protocol,
                                        nsObjectDecl->getDeclContext());
          result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
          return result;
        }
  
        if (auto *definition = decl->getDefinition())
          decl = definition;
  
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(decl, correctSwiftName);
        if (!importedName) return nullptr;
  
        // If we've been asked to produce a compatibility stub, handle it via a
        // typealias.
        if (correctSwiftName)
          return importCompatibilityTypeAlias(decl, importedName,
                                              *correctSwiftName);
  
        auto name = importedName.getDeclName().getBaseIdentifier();
  
        if (!decl->hasDefinition()) {
          // Check if this class is implemented in its adapter.
          if (auto clangModule = Impl.getClangModuleForDecl(decl, true)) {
            if (auto native = resolveSwiftDecl<ClassDecl>(decl, name,
                                                          clangModule)) {
              return native;
            }
          }
  
          if (Impl.ImportForwardDeclarations) {
            // Fake it by making an unavailable opaque @objc root class.
            auto result = createRootClass(name);
            result->setImplicit();
            auto attr = AvailableAttr::createPlatformAgnostic(Impl.SwiftContext,
                "This Objective-C class has only been forward-declared; "
                "import its owning module to use it");
            result->getAttrs().add(attr);
            return result;
          }
  
          forwardDeclaration = true;
          return nullptr;
        }
  
        auto dc =
            Impl.importDeclContextOf(decl, importedName.getEffectiveContext());
        if (!dc)
          return nullptr;
  
        ClassDecl *nativeDecl;
        bool declaredNative = hasNativeSwiftDecl(decl, name, dc, nativeDecl);
        if (declaredNative && nativeDecl)
          return nativeDecl;
  
        // Create the class declaration and record it.
        auto result = Impl.createDeclWithClangNode<ClassDecl>(decl,
                                  AccessLevel::Open,
                                  Impl.importSourceLoc(decl->getLocStart()),
                                  name,
                                  Impl.importSourceLoc(decl->getLocation()),
                                  None, nullptr, dc);
  
        // Import generic arguments, if any.
        if (auto gpImportResult = importObjCGenericParams(decl, dc)) {
          auto genericParams = *gpImportResult;
          if (genericParams) {
            result->setGenericParams(genericParams);
  
            auto *env = Impl.buildGenericEnvironment(genericParams, dc);
            result->setGenericEnvironment(env);
          }
        } else {
          return nullptr;
        }
  
        result->computeType();
  
        Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = result;
        result->setCircularityCheck(CircularityCheck::Checked);
        result->setAddedImplicitInitializers();
        addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
  
        if (declaredNative)
          markMissingSwiftDecl(result);
        if (decl->getAttr<clang::ObjCRuntimeVisibleAttr>()) {
          result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
        }
  
        // If this Objective-C class has a supertype, import it.
        SmallVector<TypeLoc, 4> inheritedTypes;
        Type superclassType;
        if (decl->getSuperClass()) {
          clang::QualType clangSuperclassType =
            decl->getSuperClassType()->stripObjCKindOfTypeAndQuals(clangCtx);
          clangSuperclassType =
            clangCtx.getObjCObjectPointerType(clangSuperclassType);
          superclassType = Impl.importType(clangSuperclassType,
                                           ImportTypeKind::Abstract,
                                           isInSystemModule(dc),
                                           Bridgeability::None);
          if (superclassType) {
            assert(superclassType->is<ClassType>() ||
                   superclassType->is<BoundGenericClassType>());
            inheritedTypes.push_back(TypeLoc::withoutLoc(superclassType));
          }
        }
        result->setSuperclass(superclassType);
  
        // Mark the class as runtime-only if it is named 'OS_object', even
        // if it doesn't have the runtime-only Clang attribute. This is a
        // targeted fix allowing IRGen to emit convenience initializers
        // correctly.
        //
        // FIXME: Remove this once SILGen gets proper support for factory
        // initializers.
        if (decl->getName() == "OS_object" ||
            decl->getName() == "OS_os_log") {
          result->setForeignClassKind(ClassDecl::ForeignKind::RuntimeOnly);
        }
  
        // If the superclass is runtime-only, our class is also. This only
        // matters in the case above.
        if (superclassType) {
          auto superclassDecl = cast<ClassDecl>(superclassType->getAnyNominal());
          auto kind = superclassDecl->getForeignClassKind();
          if (kind != ClassDecl::ForeignKind::Normal)
            result->setForeignClassKind(kind);
        }
  
        // Import protocols this class conforms to.
        importObjCProtocols(result, decl->getReferencedProtocols(),
                            inheritedTypes);
        result->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
        result->setCheckedInheritanceClause();
  
        // Add inferred attributes.
  #define INFERRED_ATTRIBUTES(ModuleName, ClassName, AttributeSet)               \
    if (name.str().equals(#ClassName) &&                                         \
        result->getParentModule()->getName().str().equals(#ModuleName)) {        \
      using namespace inferred_attributes;                                       \
      addInferredAttributes(result, AttributeSet);                               \
    }
  #include "InferredAttributes.def"
  
        result->setMemberLoader(&Impl, 0);
        result->addImplicitDestructor();
  
        return result;
      }
  
      Decl *VisitObjCImplDecl(const clang::ObjCImplDecl *decl) {
        // Implementations of Objective-C classes and categories are not
        // reflected into Swift.
        return nullptr;
      }
  
      Decl *VisitObjCPropertyDecl(const clang::ObjCPropertyDecl *decl) {
        auto dc = Impl.importDeclContextOf(decl, decl->getDeclContext());
        if (!dc)
          return nullptr;
  
        // While importing the DeclContext, we might have imported the decl
        // itself.
        if (auto Known = Impl.importDeclCached(decl, getVersion()))
          return Known;
  
        return importObjCPropertyDecl(decl, dc);
      }
  
      /// Hack: Handle the case where a property is declared \c readonly in the
      /// main class interface (either explicitly or because of an adopted
      /// protocol) and then \c readwrite in a category/extension.
      ///
      /// \see VisitObjCPropertyDecl
      void handlePropertyRedeclaration(VarDecl *original,
                                       const clang::ObjCPropertyDecl *redecl) {
        // If the property isn't from Clang, we can't safely update it.
        if (!original->hasClangNode())
          return;
  
        // If the original declaration was implicit, we may want to change that.
        if (original->isImplicit() && !redecl->isImplicit() &&
            !isa<clang::ObjCProtocolDecl>(redecl->getDeclContext()))
          original->setImplicit(false);
  
        if (!original->getAttrs().hasAttribute<OwnershipAttr>() &&
            !original->getAttrs().hasAttribute<NSCopyingAttr>()) {
          applyPropertyOwnership(original,
                                 redecl->getPropertyAttributesAsWritten());
        }
  
        auto clangSetter = redecl->getSetterMethodDecl();
        if (!clangSetter)
          return;
  
        // The only other transformation we know how to do safely is add a
        // setter. If the property is already settable, we're done.
        if (original->isSettable(nullptr))
          return;
  
        FuncDecl *setter = importAccessor(clangSetter,
                                          original->getDeclContext());
        if (!setter)
          return;
  
        // Check that the redeclared property's setter uses the same type as the
        // original property. Objective-C can get away with the types being
        // different (usually in something like nullability), but for Swift it's
        // an AST invariant that's assumed and asserted elsewhere. If the type is
        // different, just drop the setter, and leave the property as get-only.
        assert(setter->getParameterLists().back()->size() == 1);
        const ParamDecl *param = setter->getParameterLists().back()->get(0);
        if (!param->getInterfaceType()->isEqual(original->getInterfaceType()))
          return;
  
        original->setComputedSetter(setter);
      }
  
      Decl *importObjCPropertyDecl(const clang::ObjCPropertyDecl *decl,
                                  DeclContext *dc) {
        assert(dc);
  
        Optional<ImportedName> correctSwiftName;
        auto name = importFullName(decl, correctSwiftName)
                        .getDeclName()
                        .getBaseIdentifier();
        if (name.empty())
          return nullptr;
  
        if (shouldImportPropertyAsAccessors(decl))
          return nullptr;
  
        // Check whether there is a function with the same name as this
        // property. If so, suppress the property; the user will have to use
        // the methods directly, to avoid ambiguities.
        Type containerTy = dc->getDeclaredInterfaceType();
        Type lookupContextTy = containerTy;
        if (auto *classDecl = dyn_cast<ClassDecl>(dc)) {
          // If we're importing into the primary @interface for something, as
          // opposed to an extension, make sure we don't try to load any
          // categories...by just looking into the super type.
          lookupContextTy = classDecl->getSuperclass();
        }
  
        VarDecl *overridden = nullptr;
        if (lookupContextTy) {
          SmallVector<ValueDecl *, 2> lookup;
          dc->lookupQualified(lookupContextTy, name,
                              NL_QualifiedDefault | NL_KnownNoDependency,
                              Impl.getTypeResolver(), lookup);
          for (auto result : lookup) {
            if (isa<FuncDecl>(result) &&
                result->isInstanceMember() == decl->isInstanceProperty() &&
                result->getFullName().getArgumentNames().empty())
              return nullptr;
  
            if (auto var = dyn_cast<VarDecl>(result)) {
              // If the selectors of the getter match in Objective-C, we have an
              // override.
              if (var->isInstanceMember() == decl->isInstanceProperty() &&
                  var->getObjCGetterSelector() ==
                    Impl.importSelector(decl->getGetterName()))
                overridden = var;
            }
          }
        }
  
        if (overridden) {
          const DeclContext *overrideContext = overridden->getDeclContext();
          // It's okay to compare interface types directly because Objective-C
          // does not have constrained extensions.
          if (overrideContext != dc && overridden->hasClangNode() &&
              overrideContext->getDeclaredInterfaceType()->isEqual(containerTy)) {
            // We've encountered a redeclaration of the property.
            // HACK: Just update the original declaration instead of importing a
            // second property.
            handlePropertyRedeclaration(overridden, decl);
            return nullptr;
          }
        }
  
        Type type = Impl.importPropertyType(decl, isInSystemModule(dc));
        if (!type)
          return nullptr;
  
        // Import the getter.
        FuncDecl *getter = nullptr;
        if (auto clangGetter = decl->getGetterMethodDecl()) {
          getter = importAccessor(clangGetter, dc);
          if (!getter)
            return nullptr;
        }
  
        // Import the setter, if there is one.
        FuncDecl *setter = nullptr;
        if (auto clangSetter = decl->getSetterMethodDecl()) {
          setter = importAccessor(clangSetter, dc);
          if (!setter)
            return nullptr;
        }
  
        // Check whether the property already got imported.
        if (dc == Impl.importDeclContextOf(decl, decl->getDeclContext())) {
          auto known = Impl.ImportedDecls.find({decl->getCanonicalDecl(),
                                                getVersion()});
          if (known != Impl.ImportedDecls.end())
            return known->second;
        }
  
        auto result = Impl.createDeclWithClangNode<VarDecl>(decl,
            getOverridableAccessLevel(dc),
            /*IsStatic*/decl->isClassProperty(), VarDecl::Specifier::Var,
            /*IsCaptureList*/false, Impl.importSourceLoc(decl->getLocation()),
            name, dc->mapTypeIntoContext(type), dc);
        result->setInterfaceType(type);
  
        // Turn this into a computed property.
        // FIXME: Fake locations for '{' and '}'?
        result->setIsSetterMutating(false);
        result->makeComputed(SourceLoc(), getter, setter, nullptr, SourceLoc());
        addObjCAttribute(result, Impl.importIdentifier(decl->getIdentifier()));
        applyPropertyOwnership(result, decl->getPropertyAttributesAsWritten());
  
        // Handle attributes.
        if (decl->hasAttr<clang::IBOutletAttr>())
          result->getAttrs().add(
              new (Impl.SwiftContext) IBOutletAttr(/*IsImplicit=*/false));
        if (decl->getPropertyImplementation() == clang::ObjCPropertyDecl::Optional
            && isa<ProtocolDecl>(dc) &&
            !result->getAttrs().hasAttribute<OptionalAttr>())
          result->getAttrs().add(new (Impl.SwiftContext)
                                        OptionalAttr(/*implicit*/false));
        // FIXME: Handle IBOutletCollection.
  
        if (overridden) {
          result->setOverriddenDecl(overridden);
          getter->setOverriddenDecl(overridden->getGetter());
          if (auto parentSetter = overridden->getSetter())
            if (setter)
              setter->setOverriddenDecl(parentSetter);
        }
  
        // If this is a compatibility stub, mark it as such.
        if (correctSwiftName)
          markAsVariant(result, *correctSwiftName);
  
        return result;
      }
  
      Decl *
      VisitObjCCompatibleAliasDecl(const clang::ObjCCompatibleAliasDecl *decl) {
        // Import Objective-C's @compatibility_alias as typealias.
        EffectiveClangContext effectiveContext(decl->getDeclContext()->getRedeclContext());
        auto dc = Impl.importDeclContextOf(decl, effectiveContext);
        if (!dc) return nullptr;
  
        Optional<ImportedName> correctSwiftName;
        auto importedName = importFullName(decl, correctSwiftName);
        auto name = importedName.getDeclName().getBaseIdentifier();
  
        if (name.empty()) return nullptr;
  
        auto importedDecl =
            Impl.importDecl(decl->getClassInterface(), getActiveSwiftVersion());
        auto typeDecl = dyn_cast_or_null<TypeDecl>(importedDecl);
        if (!typeDecl) return nullptr;
  
        // Create typealias.
        TypeAliasDecl *typealias = nullptr;
        typealias = Impl.createDeclWithClangNode<TypeAliasDecl>(
                      decl, AccessLevel::Public,
                      Impl.importSourceLoc(decl->getLocStart()),
                      SourceLoc(), name,
                      Impl.importSourceLoc(decl->getLocation()),
                      /*genericparams=*/nullptr, dc);
  
        typealias->setUnderlyingType(typeDecl->getDeclaredInterfaceType());
        return typealias;
      }
  
      Decl *VisitLinkageSpecDecl(const clang::LinkageSpecDecl *decl) {
        // Linkage specifications are not imported.
        return nullptr;
      }
  
      Decl *VisitObjCPropertyImplDecl(const clang::ObjCPropertyImplDecl *decl) {
        // @synthesize and @dynamic are not imported, since they are not part
        // of the interface to a class.
        return nullptr;
      }
  
      Decl *VisitFileScopeAsmDecl(const clang::FileScopeAsmDecl *decl) {
        return nullptr;
      }
  
      Decl *VisitAccessSpecDecl(const clang::AccessSpecDecl *decl) {
        return nullptr;
      }
  
      Decl *VisitFriendDecl(const clang::FriendDecl *decl) {
        // Friends are not imported; Swift has a different access control
        // mechanism.
        return nullptr;
      }
  
      Decl *VisitFriendTemplateDecl(const clang::FriendTemplateDecl *decl) {
        // Friends are not imported; Swift has a different access control
        // mechanism.
        return nullptr;
      }
  
      Decl *VisitStaticAssertDecl(const clang::StaticAssertDecl *decl) {
        // Static assertions are an implementation detail.
        return nullptr;
      }
  
      Decl *VisitBlockDecl(const clang::BlockDecl *decl) {
        // Blocks are not imported (although block types can be imported).
        return nullptr;
      }
  
      Decl *VisitClassScopeFunctionSpecializationDecl(
                   const clang::ClassScopeFunctionSpecializationDecl *decl) {
        // Note: templates are not imported.
        return nullptr;
      }
  
      Decl *VisitImportDecl(const clang::ImportDecl *decl) {
        // Transitive module imports are not handled at the declaration level.
        // Rather, they are understood from the module itself.
        return nullptr;
      }
    };
  } // end anonymous namespace
  
  /// Try to strip "Mutable" out of a type name.
  static clang::IdentifierInfo *
  getImmutableCFSuperclassName(const clang::TypedefNameDecl *decl, clang::ASTContext &ctx) {
    StringRef name = decl->getName();
  
    // Split at the first occurrence of "Mutable".
    StringRef _mutable = "Mutable";
    auto mutableIndex = camel_case::findWord(name, _mutable);
    if (mutableIndex == StringRef::npos)
      return nullptr;
  
    StringRef namePrefix = name.substr(0, mutableIndex);
    StringRef nameSuffix = name.substr(mutableIndex + _mutable.size());
  
    // Abort if "Mutable" appears twice.
    if (camel_case::findWord(nameSuffix, _mutable) != StringRef::npos)
      return nullptr;
  
    llvm::SmallString<128> buffer;
    buffer += namePrefix;
    buffer += nameSuffix;
    return &ctx.Idents.get(buffer.str());
  }
  
  /// Check whether this CF typedef is a Mutable type, and if so,
  /// look for a non-Mutable typedef.
  ///
  /// If the "subclass" is:
  ///   typedef struct __foo *XXXMutableYYY;
  /// then we look for a "superclass" that matches:
  ///   typedef const struct __foo *XXXYYY;
  static Type findImmutableCFSuperclass(ClangImporter::Implementation &impl,
                                        const clang::TypedefNameDecl *decl,
                                        CFPointeeInfo subclassInfo) {
    // If this type is already immutable, it has no immutable
    // superclass.
    if (subclassInfo.isConst())
      return Type();
  
    // If this typedef name does not contain "Mutable", it has no
    // immutable superclass.
    auto superclassName =
        getImmutableCFSuperclassName(decl, impl.getClangASTContext());
    if (!superclassName)
      return Type();
  
    // Look for a typedef that successfully classifies as a CF
    // typedef with the same underlying record.
    auto superclassTypedef = impl.lookupTypedef(superclassName);
    if (!superclassTypedef)
      return Type();
    auto superclassInfo = CFPointeeInfo::classifyTypedef(superclassTypedef);
    if (!superclassInfo || !superclassInfo.isRecord() ||
        !declaresSameEntity(superclassInfo.getRecord(), subclassInfo.getRecord()))
      return Type();
  
    // Try to import the superclass.
    Decl *importedSuperclassDecl =
        impl.importDeclReal(superclassTypedef, impl.CurrentVersion);
    if (!importedSuperclassDecl)
      return Type();
  
    auto importedSuperclass =
        cast<TypeDecl>(importedSuperclassDecl)->getDeclaredInterfaceType();
    assert(importedSuperclass->is<ClassType>() && "must have class type");
    return importedSuperclass;
  }
  
  /// Attempt to find a superclass for the given CF typedef.
  static Type findCFSuperclass(ClangImporter::Implementation &impl,
                               const clang::TypedefNameDecl *decl,
                               CFPointeeInfo info) {
    if (Type immutable = findImmutableCFSuperclass(impl, decl, info))
      return immutable;
  
    // TODO: use NSObject if it exists?
    return Type();
  }
  
  ClassDecl *
  SwiftDeclConverter::importCFClassType(const clang::TypedefNameDecl *decl,
                                        Identifier className, CFPointeeInfo info,
                                        EffectiveClangContext effectiveContext) {
    auto dc = Impl.importDeclContextOf(decl, effectiveContext);
    if (!dc)
      return nullptr;
  
    Type superclass = findCFSuperclass(Impl, decl, info);
  
    // TODO: maybe use NSObject as the superclass if we can find it?
    // TODO: try to find a non-mutable type to use as the superclass.
  
    auto theClass = Impl.createDeclWithClangNode<ClassDecl>(
        decl, AccessLevel::Public, SourceLoc(), className, SourceLoc(), None,
        nullptr, dc);
    theClass->computeType();
    theClass->setCircularityCheck(CircularityCheck::Checked);
    theClass->setSuperclass(superclass);
    theClass->setAddedImplicitInitializers(); // suppress all initializers
    theClass->setForeignClassKind(ClassDecl::ForeignKind::CFType);
    addObjCAttribute(theClass, None);
    Impl.registerExternalDecl(theClass);
  
    if (superclass) {
      SmallVector<TypeLoc, 4> inheritedTypes;
      inheritedTypes.push_back(TypeLoc::withoutLoc(superclass));
      theClass->setInherited(Impl.SwiftContext.AllocateCopy(inheritedTypes));
      theClass->setCheckedInheritanceClause();
    }
  
    addSynthesizedProtocolAttrs(Impl, theClass, {KnownProtocolKind::CFObject});
  
    // Look for bridging attributes on the clang record.  We can
    // just check the most recent redeclaration, which will inherit
    // any attributes from earlier declarations.
    auto record = info.getRecord()->getMostRecentDecl();
    if (info.isConst()) {
      if (auto attr = record->getAttr<clang::ObjCBridgeAttr>()) {
        // Record the Objective-C class to which this CF type is toll-free
        // bridged.
        if (ClassDecl *objcClass = dynCastIgnoringCompatibilityAlias<ClassDecl>(
                Impl.importDeclByName(attr->getBridgedType()->getName()))) {
          theClass->getAttrs().add(new (Impl.SwiftContext)
                                       ObjCBridgedAttr(objcClass));
        }
      }
    } else {
      if (auto attr = record->getAttr<clang::ObjCBridgeMutableAttr>()) {
        // Record the Objective-C class to which this CF type is toll-free
        // bridged.
        if (ClassDecl *objcClass = dynCastIgnoringCompatibilityAlias<ClassDecl>(
                Impl.importDeclByName(attr->getBridgedType()->getName()))) {
          theClass->getAttrs().add(new (Impl.SwiftContext)
                                       ObjCBridgedAttr(objcClass));
        }
      }
    }
  
    return theClass;
  }
  
  Decl *SwiftDeclConverter::importCompatibilityTypeAlias(
      const clang::NamedDecl *decl,
      ImportedName compatibilityName,
      ImportedName correctSwiftName) {
    // Import the referenced declaration. If it doesn't come in as a type,
    // we don't care.
    Decl *importedDecl = nullptr;
    if (getVersion() >= getActiveSwiftVersion())
      importedDecl = Impl.importDecl(decl, ImportNameVersion::forTypes());
    if (!importedDecl && getVersion() != getActiveSwiftVersion())
      importedDecl = Impl.importDecl(decl, getActiveSwiftVersion());
    auto typeDecl = dyn_cast_or_null<TypeDecl>(importedDecl);
    if (!typeDecl)
      return nullptr;
  
    // Deliberately use an UnboundGenericType to avoid having to translate over
    // generic parameters.
    Type underlyingType;
    if (auto *underlyingAlias = dyn_cast<TypeAliasDecl>(typeDecl)) {
      if (underlyingAlias->isGeneric())
        underlyingType = underlyingAlias->getUnboundGenericType();
      else
        underlyingType = underlyingAlias->getDeclaredInterfaceType();
    } else {
      underlyingType = cast<NominalTypeDecl>(typeDecl)->getDeclaredType();
    }
  
    auto dc = Impl.importDeclContextOf(decl,
                                       compatibilityName.getEffectiveContext());
    if (!dc)
      return nullptr;
  
    // Create the type alias.
    auto alias = Impl.createDeclWithClangNode<TypeAliasDecl>(
        decl, AccessLevel::Public, Impl.importSourceLoc(decl->getLocStart()),
        SourceLoc(), compatibilityName.getDeclName().getBaseIdentifier(),
        Impl.importSourceLoc(decl->getLocation()), /*generic params*/nullptr, dc);
    alias->setUnderlyingType(underlyingType);
  
    // Record that this is the official version of this declaration.
    Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = alias;
    markAsVariant(alias, correctSwiftName);
    return alias;
  }
  
  static bool inheritanceListContainsProtocol(ArrayRef<TypeLoc> inherited,
                                              const ProtocolDecl *proto) {
    return llvm::any_of(inherited, [proto](TypeLoc type) -> bool {
      if (!type.getType()->isExistentialType())
        return false;
  
      auto layout = type.getType()->getExistentialLayout();
      for (auto protoTy : layout.getProtocols()) {
        auto *protoDecl = protoTy->getDecl();
        if (protoDecl == proto || protoDecl->inheritsFrom(proto))
          return true;
      }
  
      return false;
    });
  }
  
  static bool conformsToProtocolInOriginalModule(NominalTypeDecl *nominal,
                                                 const ProtocolDecl *proto,
                                                 ModuleDecl *foundationModule,
                                                 LazyResolver *resolver) {
    auto &ctx = nominal->getASTContext();
  
    if (resolver)
      resolver->resolveInheritanceClause(nominal);
    if (inheritanceListContainsProtocol(nominal->getInherited(), proto))
      return true;
  
    for (auto attr : nominal->getAttrs().getAttributes<SynthesizedProtocolAttr>())
      if (auto *otherProto = ctx.getProtocol(attr->getProtocolKind()))
        if (otherProto == proto)
          return true;
  
    // Only consider extensions from the original module...or from an overlay
    // or the Swift half of a mixed-source framework.
    const DeclContext *containingFile = nominal->getModuleScopeContext();
    ModuleDecl *originalModule = containingFile->getParentModule();
  
    ModuleDecl *adapterModule = nullptr;
    if (auto *clangUnit = dyn_cast<ClangModuleUnit>(containingFile))
      adapterModule = clangUnit->getAdapterModule();
  
    for (ExtensionDecl *extension : nominal->getExtensions()) {
      ModuleDecl *extensionModule = extension->getParentModule();
      if (extensionModule != originalModule && extensionModule != adapterModule &&
          extensionModule != foundationModule) {
        continue;
      }
      if (resolver)
        resolver->resolveInheritanceClause(extension);
      if (inheritanceListContainsProtocol(extension->getInherited(), proto))
        return true;
    }
  
    return false;
  }
  
  Decl *
  SwiftDeclConverter::importSwiftNewtype(const clang::TypedefNameDecl *decl,
                                         clang::SwiftNewtypeAttr *newtypeAttr,
                                         DeclContext *dc, Identifier name) {
    // The only (current) difference between swift_newtype(struct) and
    // swift_newtype(enum), until we can get real enum support, is that enums
    // have no un-labeled inits(). This is because enums are to be considered
    // closed, and if constructed from a rawValue, should be very explicit.
    bool unlabeledCtor = false;
  
    switch (newtypeAttr->getNewtypeKind()) {
    case clang::SwiftNewtypeAttr::NK_Enum:
      unlabeledCtor = false;
      // TODO: import as enum instead
      break;
  
    case clang::SwiftNewtypeAttr::NK_Struct:
      unlabeledCtor = true;
      break;
      // No other cases yet
    }
  
    auto &ctx = Impl.SwiftContext;
    auto Loc = Impl.importSourceLoc(decl->getLocation());
  
    auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
        decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
    structDecl->computeType();
    structDecl->setCheckedInheritanceClause();
  
    // Import the type of the underlying storage
    auto storedUnderlyingType = Impl.importType(
        decl->getUnderlyingType(), ImportTypeKind::Value, isInSystemModule(dc),
        Bridgeability::None, OTK_None);
  
    if (!storedUnderlyingType)
      return nullptr;
  
    if (auto objTy = storedUnderlyingType->getAnyOptionalObjectType())
      storedUnderlyingType = objTy;
  
    // If the type is Unmanaged, that is it is not CF ARC audited,
    // we will store the underlying type and leave it up to the use site
    // to determine whether to use this new_type, or an Unmanaged<CF...> type.
    if (auto genericType = storedUnderlyingType->getAs<BoundGenericType>()) {
      if (genericType->getDecl() == Impl.SwiftContext.getUnmanagedDecl()) {
        assert(genericType->getGenericArgs().size() == 1 && "other args?");
        storedUnderlyingType = genericType->getGenericArgs()[0];
      }
    }
  
    // Find a bridged type, which may be different
    auto computedPropertyUnderlyingType = Impl.importType(
        decl->getUnderlyingType(), ImportTypeKind::Property, isInSystemModule(dc),
        Bridgeability::Full, OTK_None);
    if (auto objTy = computedPropertyUnderlyingType->getAnyOptionalObjectType())
      computedPropertyUnderlyingType = objTy;
  
    bool isBridged =
        !storedUnderlyingType->isEqual(computedPropertyUnderlyingType);
  
    // Determine the set of protocols to which the synthesized
    // type will conform.
    SmallVector<KnownProtocolKind, 4> synthesizedProtocols;
  
    // Local function to add a known protocol.
    auto addKnown = [&](KnownProtocolKind kind) {
      synthesizedProtocols.push_back(kind);
    };
  
    // Add conformances that are always available.
    addKnown(KnownProtocolKind::RawRepresentable);
    addKnown(KnownProtocolKind::SwiftNewtypeWrapper);
  
    // Local function to add a known protocol only when the
    // underlying type conforms to it.
    auto computedNominal = computedPropertyUnderlyingType->getAnyNominal();
    auto transferKnown = [&](KnownProtocolKind kind) {
      if (!computedNominal)
        return false;
  
      auto proto = ctx.getProtocol(kind);
      if (!proto)
        return false;
  
      // Break circularity by only looking for declared conformances in the
      // original module, or possibly its adapter.
      if (conformsToProtocolInOriginalModule(computedNominal, proto,
                                             Impl.tryLoadFoundationModule(),
                                             Impl.getTypeResolver())) {
        synthesizedProtocols.push_back(kind);
        return true;
      }
  
      return false;
    };
  
    // Transfer conformances. Each of these needs a forwarding
    // implementation in the standard library.
    transferKnown(KnownProtocolKind::Equatable);
    transferKnown(KnownProtocolKind::Hashable);
    bool transferredObjCBridgeable =
      transferKnown(KnownProtocolKind::ObjectiveCBridgeable);
  
    if (!isBridged) {
      // Simple, our stored type is equivalent to our computed
      // type.
      auto options = getDefaultMakeStructRawValuedOptions();
      if (unlabeledCtor)
        options |= MakeStructRawValuedFlags::MakeUnlabeledValueInit;
  
      makeStructRawValued(Impl, structDecl, storedUnderlyingType,
                          synthesizedProtocols, options);
    } else {
      // We need to make a stored rawValue or storage type, and a
      // computed one of bridged type.
      makeStructRawValuedWithBridge(Impl, structDecl, storedUnderlyingType,
                                    computedPropertyUnderlyingType,
                                    synthesizedProtocols,
                                    /*makeUnlabeledValueInit=*/unlabeledCtor);
  
      if (transferredObjCBridgeable)
        addSynthesizedTypealias(structDecl, ctx.Id_ObjectiveCType,
                                storedUnderlyingType);
    }
  
    Impl.ImportedDecls[{decl->getCanonicalDecl(), getVersion()}] = structDecl;
    Impl.registerExternalDecl(structDecl);
    return structDecl;
  }
  
  Decl *SwiftDeclConverter::importEnumCase(const clang::EnumConstantDecl *decl,
                                           const clang::EnumDecl *clangEnum,
                                           EnumDecl *theEnum,
                                           Decl *correctDecl) {
    auto &context = Impl.SwiftContext;
    Optional<ImportedName> correctSwiftName;
    auto name =
        importFullName(decl, correctSwiftName).getDeclName().getBaseIdentifier();
    if (name.empty())
      return nullptr;
  
    if (correctSwiftName) {
      // We're creating a compatibility stub. Treat it as an enum case alias.
      auto correctCase = dyn_cast_or_null<EnumElementDecl>(correctDecl);
      if (!correctCase)
        return nullptr;
  
      // If the correct declaration was unavailable, don't map to it.
      // FIXME: This eliminates spurious errors, but affects QoI.
      if (correctCase->getAttrs().isUnavailable(Impl.SwiftContext))
        return nullptr;
  
      auto compatibilityCase =
          importEnumCaseAlias(name, decl, correctCase, clangEnum, theEnum);
      if (compatibilityCase)
        markAsVariant(compatibilityCase, *correctSwiftName);
  
      return compatibilityCase;
    }
  
    // Use the constant's underlying value as its raw value in Swift.
    bool negative = false;
    llvm::APSInt rawValue = decl->getInitVal();
  
    if (clangEnum->getIntegerType()->isSignedIntegerOrEnumerationType() &&
        rawValue.slt(0)) {
      rawValue = -rawValue;
      negative = true;
    }
    llvm::SmallString<12> rawValueText;
    rawValue.toString(rawValueText, 10, /*signed*/ false);
    StringRef rawValueTextC = context.AllocateCopy(StringRef(rawValueText));
    auto rawValueExpr =
        new (context) IntegerLiteralExpr(rawValueTextC, SourceLoc(),
                                         /*implicit*/ false);
    if (negative)
      rawValueExpr->setNegative(SourceLoc());
  
    auto element = Impl.createDeclWithClangNode<EnumElementDecl>(
        decl, AccessLevel::Public, SourceLoc(), name, TypeLoc(), false,
        SourceLoc(), rawValueExpr, theEnum);
  
    // Give the enum element the appropriate type.
    element->computeType();
  
    Impl.importAttributes(decl, element);
  
    return element;
  }
  
  Decl *
  SwiftDeclConverter::importOptionConstant(const clang::EnumConstantDecl *decl,
                                           const clang::EnumDecl *clangEnum,
                                           NominalTypeDecl *theStruct) {
    Optional<ImportedName> correctSwiftName;
    ImportedName nameInfo = importFullName(decl, correctSwiftName);
    Identifier name = nameInfo.getDeclName().getBaseIdentifier();
    if (name.empty())
      return nullptr;
  
    // Create the constant.
    auto convertKind = ConstantConvertKind::Construction;
    if (isa<EnumDecl>(theStruct))
      convertKind = ConstantConvertKind::ConstructionWithUnwrap;
    Decl *CD = Impl.createConstant(
        name, theStruct, theStruct->getDeclaredTypeInContext(),
        clang::APValue(decl->getInitVal()), convertKind, /*isStatic*/ true, decl);
    Impl.importAttributes(decl, CD);
  
    // NS_OPTIONS members that have a value of 0 (typically named "None") do
    // not operate as a set-like member.  Mark them unavailable with a message
    // that says that they should be used as [].
    if (decl->getInitVal() == 0 && !nameInfo.hasCustomName() &&
        !CD->getAttrs().isUnavailable(Impl.SwiftContext)) {
      /// Create an AvailableAttr that indicates specific availability
      /// for all platforms.
      auto attr = AvailableAttr::createPlatformAgnostic(
          Impl.SwiftContext, "use [] to construct an empty option set");
      CD->getAttrs().add(attr);
    }
  
    // If this is a compatibility stub, mark it as such.
    if (correctSwiftName)
      markAsVariant(CD, *correctSwiftName);
  
    return CD;
  }
  
  Decl *SwiftDeclConverter::importEnumCaseAlias(
      Identifier name, const clang::EnumConstantDecl *alias, ValueDecl *original,
      const clang::EnumDecl *clangEnum, NominalTypeDecl *importedEnum,
      DeclContext *importIntoDC) {
    if (name.empty())
      return nullptr;
  
    // Default the DeclContext to the enum type.
    if (!importIntoDC)
      importIntoDC = importedEnum;
  
    // Construct the original constant. Enum constants without payloads look
    // like simple values, but actually have type 'MyEnum.Type -> MyEnum'.
    auto constantRef =
        new (Impl.SwiftContext) DeclRefExpr(original, DeclNameLoc(),
                                            /*implicit*/ true);
    Type importedEnumTy = importedEnum->getDeclaredTypeInContext();
    auto typeRef = TypeExpr::createImplicit(importedEnumTy, Impl.SwiftContext);
    auto instantiate = new (Impl.SwiftContext)
        DotSyntaxCallExpr(constantRef, SourceLoc(), typeRef);
    instantiate->setType(importedEnumTy);
  
    Decl *CD = Impl.createConstant(name, importIntoDC, importedEnumTy,
                                   instantiate, ConstantConvertKind::None,
                                   /*isStatic*/ true, alias);
    Impl.importAttributes(alias, CD);
    return CD;
  }
  
  NominalTypeDecl *
  SwiftDeclConverter::importAsOptionSetType(DeclContext *dc, Identifier name,
                                            const clang::EnumDecl *decl) {
    ASTContext &ctx = Impl.SwiftContext;
  
    // Compute the underlying type.
    auto underlyingType = Impl.importType(
        decl->getIntegerType(), ImportTypeKind::Enum, isInSystemModule(dc),
        Bridgeability::None);
    if (!underlyingType)
      return nullptr;
  
    auto Loc = Impl.importSourceLoc(decl->getLocation());
  
    // Create a struct with the underlying type as a field.
    auto structDecl = Impl.createDeclWithClangNode<StructDecl>(
        decl, AccessLevel::Public, Loc, name, Loc, None, nullptr, dc);
    structDecl->computeType();
    structDecl->setCheckedInheritanceClause();
  
    makeStructRawValued(Impl, structDecl, underlyingType,
                        {KnownProtocolKind::OptionSet});
    auto selfType = structDecl->getDeclaredInterfaceType();
    addSynthesizedTypealias(structDecl, ctx.Id_Element, selfType);
    addSynthesizedTypealias(structDecl, ctx.Id_ArrayLiteralElement, selfType);
    return structDecl;
  }
  
  Decl *SwiftDeclConverter::importGlobalAsInitializer(
      const clang::FunctionDecl *decl,
      DeclName name,
      DeclContext *dc,
      CtorInitializerKind initKind,
      Optional<ImportedName> correctSwiftName) {
    // TODO: Should this be an error? How can this come up?
    assert(dc->isTypeContext() && "cannot import as member onto non-type");
  
    // Check for some invalid imports
    if (dc->getAsProtocolOrProtocolExtensionContext()) {
      // FIXME: clang source location
      Impl.SwiftContext.Diags.diagnose({}, diag::swift_name_protocol_static,
                                       /*isInit=*/true);
      Impl.SwiftContext.Diags.diagnose({}, diag::note_while_importing,
                                       decl->getName());
      return nullptr;
    }
  
    bool allowNSUIntegerAsInt =
        Impl.shouldAllowNSUIntegerAsInt(isInSystemModule(dc), decl);
  
    ArrayRef<Identifier> argNames = name.getArgumentNames();
  
    ParameterList *parameterList = nullptr;
    if (argNames.size() == 1 && decl->getNumParams() == 0) {
      // Special case: We need to create an empty first parameter for our
      // argument label
      auto *paramDecl =
          new (Impl.SwiftContext) ParamDecl(
              VarDecl::Specifier::Let, SourceLoc(), SourceLoc(), argNames.front(),
              SourceLoc(), argNames.front(), Impl.SwiftContext.TheEmptyTupleType,
              dc);
      paramDecl->setInterfaceType(Impl.SwiftContext.TheEmptyTupleType);
      paramDecl->setValidationStarted();
  
      parameterList = ParameterList::createWithoutLoc(paramDecl);
    } else {
      parameterList = Impl.importFunctionParameterList(
          dc, decl, {decl->param_begin(), decl->param_end()}, decl->isVariadic(),
          allowNSUIntegerAsInt, argNames);
    }
    if (!parameterList)
      return nullptr;
  
    bool selfIsInOut = !dc->getDeclaredInterfaceType()->hasReferenceSemantics();
    auto selfParam = ParamDecl::createSelf(SourceLoc(), dc, /*isStatic=*/false,
                                           /*isInOut=*/selfIsInOut);
  
    OptionalTypeKind initOptionality;
    auto resultType = Impl.importFunctionReturnType(dc, decl,
                                                    allowNSUIntegerAsInt);
    (void)resultType->getAnyOptionalObjectType(initOptionality);
  
    auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
        decl, AccessLevel::Public, name, /*NameLoc=*/SourceLoc(),
        initOptionality, /*FailabilityLoc=*/SourceLoc(),
        /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(), selfParam, parameterList,
        /*GenericParams=*/nullptr, dc);
    result->setInitKind(initKind);
    result->setImportAsStaticMember();
  
    // Set the constructor's type(s).
    Type argType = parameterList->getType(Impl.SwiftContext);
    Type fnType = FunctionType::get(argType, resultType);
    Type selfType = selfParam->getType();
    Type initType = FunctionType::get(selfType, fnType);
    result->setInitializerInterfaceType(initType);
    Type selfMetaType = MetatypeType::get(selfType->getInOutObjectType());
    Type allocType = FunctionType::get(selfMetaType, fnType);
    result->setInterfaceType(allocType);
  
    finishFuncDecl(decl, result);
    if (correctSwiftName)
      markAsVariant(result, *correctSwiftName);
    return result;
  }
  
  Decl *SwiftDeclConverter::importGlobalAsMethod(
      const clang::FunctionDecl *decl,
      DeclName name,
      DeclContext *dc,
      Optional<unsigned> selfIdx,
      Optional<ImportedName> correctSwiftName) {
    if (dc->getAsProtocolOrProtocolExtensionContext() && !selfIdx) {
      // FIXME: source location...
      Impl.SwiftContext.Diags.diagnose({}, diag::swift_name_protocol_static,
                                       /*isInit=*/false);
      Impl.SwiftContext.Diags.diagnose({}, diag::note_while_importing,
                                       decl->getName());
      return nullptr;
    }
  
    if (!decl->hasPrototype()) {
      // FIXME: source location...
      Impl.SwiftContext.Diags.diagnose({}, diag::swift_name_no_prototype);
      Impl.SwiftContext.Diags.diagnose({}, diag::note_while_importing,
                                       decl->getName());
      return nullptr;
    }
  
    bool allowNSUIntegerAsInt =
        Impl.shouldAllowNSUIntegerAsInt(isInSystemModule(dc), decl);
  
    auto &C = Impl.SwiftContext;
    SmallVector<ParameterList *, 2> bodyParams;
  
    // There is an inout 'self' when the parameter is a pointer to a non-const
    // instance of the type we're importing onto. Importing this as a method means
    // that the method should be treated as mutating in this situation.
    bool selfIsInOut = false;
    if (selfIdx && !dc->getDeclaredInterfaceType()->hasReferenceSemantics()) {
      auto selfParam = decl->getParamDecl(*selfIdx);
      auto selfParamTy = selfParam->getType();
      if ((selfParamTy->isPointerType() || selfParamTy->isReferenceType()) &&
          !selfParamTy->getPointeeType().isConstQualified()) {
        selfIsInOut = true;
  
        // If there's a swift_newtype, check the levels of indirection: self is
        // only inout if this is a pointer to the typedef type (which itself is a
        // pointer).
        if (auto nominalTypeDecl =
                dc->getAsNominalTypeOrNominalTypeExtensionContext()) {
          if (auto clangDCTy = dyn_cast_or_null<clang::TypedefNameDecl>(
                  nominalTypeDecl->getClangDecl()))
            if (getSwiftNewtypeAttr(clangDCTy, getVersion()))
              if (clangDCTy->getUnderlyingType().getCanonicalType() !=
                  selfParamTy->getPointeeType().getCanonicalType())
                selfIsInOut = false;
        }
      }
    }
  
    bodyParams.push_back(ParameterList::createWithoutLoc(ParamDecl::createSelf(
        SourceLoc(), dc, !selfIdx.hasValue(), selfIsInOut)));
    bodyParams.push_back(getNonSelfParamList(
        dc, decl, selfIdx, name.getArgumentNames(), allowNSUIntegerAsInt, !name));
  
    auto swiftResultTy = Impl.importFunctionReturnType(dc, decl,
                                                       allowNSUIntegerAsInt);
    auto fnType =
        ParameterList::getFullInterfaceType(swiftResultTy, bodyParams, C);
  
    auto loc = Impl.importSourceLoc(decl->getLocation());
    auto nameLoc = Impl.importSourceLoc(decl->getLocation());
    auto result =
        FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
                         /*FuncLoc=*/loc, name, nameLoc,
                         /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                         /*AccessorKeywordLoc=*/SourceLoc(),
                         /*GenericParams=*/nullptr, bodyParams,
                         TypeLoc::withoutLoc(swiftResultTy), dc, decl);
  
    auto interfaceType = getGenericMethodType(dc, fnType->castTo<AnyFunctionType>());
    result->setInterfaceType(interfaceType);
    result->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
    result->setValidationStarted();
  
    result->setAccess(AccessLevel::Public);
    if (selfIsInOut)
      result->setSelfAccessKind(SelfAccessKind::Mutating);
    if (selfIdx) {
      result->setSelfIndex(selfIdx.getValue());
    } else {
      result->setStatic();
      result->setImportAsStaticMember();
    }
    assert(selfIdx ? result->getSelfIndex() == *selfIdx
                   : result->isImportAsStaticMember());
  
    if (dc->getAsClassOrClassExtensionContext())
      // FIXME: only if the class itself is not marked final
      result->getAttrs().add(new (C) FinalAttr(/*IsImplicit=*/true));
  
    finishFuncDecl(decl, result);
    if (correctSwiftName)
      markAsVariant(result, *correctSwiftName);
    return result;
  }
  
  /// Create an implicit property given the imported name of one of
  /// the accessors.
  VarDecl *
  SwiftDeclConverter::getImplicitProperty(ImportedName importedName,
                                           const clang::FunctionDecl *accessor) {
    // Check whether we already know about the property.
    auto knownProperty = Impl.FunctionsAsProperties.find(accessor);
    if (knownProperty != Impl.FunctionsAsProperties.end())
      return knownProperty->second;
  
    // Determine whether we have the getter or setter.
    const clang::FunctionDecl *getter = nullptr;
    ImportedName getterName;
    Optional<ImportedName> swift3GetterName;
    const clang::FunctionDecl *setter = nullptr;
    ImportedName setterName;
    Optional<ImportedName> swift3SetterName;
    switch (importedName.getAccessorKind()) {
    case ImportedAccessorKind::None:
    case ImportedAccessorKind::SubscriptGetter:
    case ImportedAccessorKind::SubscriptSetter:
      llvm_unreachable("Not a property accessor");
  
    case ImportedAccessorKind::PropertyGetter:
      getter = accessor;
      getterName = importedName;
      break;
  
    case ImportedAccessorKind::PropertySetter:
      setter = accessor;
      setterName = importedName;
      break;
    }
  
    // Find the other accessor, if it exists.
    auto propertyName = importedName.getDeclName().getBaseIdentifier();
    auto lookupTable =
        Impl.findLookupTable(*getClangSubmoduleForDecl(accessor));
    assert(lookupTable && "No lookup table?");
    bool foundAccessor = false;
    for (auto entry : lookupTable->lookup(SerializedSwiftName(propertyName),
                                          importedName.getEffectiveContext())) {
      auto decl = entry.dyn_cast<clang::NamedDecl *>();
      if (!decl)
        continue;
  
      auto function = dyn_cast<clang::FunctionDecl>(decl);
      if (!function)
        continue;
  
      if (function->getCanonicalDecl() == accessor->getCanonicalDecl()) {
        foundAccessor = true;
        continue;
      }
  
      if (!getter) {
        // Find the self index for the getter.
        getterName = importFullName(function, swift3GetterName);
        if (!getterName)
          continue;
  
        getter = function;
        continue;
      }
  
      if (!setter) {
        // Find the self index for the setter.
        setterName = importFullName(function, swift3SetterName);
        if (!setterName)
          continue;
  
        setter = function;
        continue;
      }
  
      // We already have both a getter and a setter; something is
      // amiss, so bail out.
      return nullptr;
    }
  
    assert(foundAccessor && "Didn't find the original accessor? "
                            "Try clearing your module cache");
  
    // If there is no getter, there's nothing we can do.
    if (!getter)
      return nullptr;
  
    // Retrieve the type of the property that is implied by the getter.
    auto propertyType =
        getAccessorPropertyType(getter, false, getterName.getSelfIndex());
    if (propertyType.isNull())
      return nullptr;
  
    // If there is a setter, check that the property it implies
    // matches that of the getter.
    if (setter) {
      auto setterPropertyType =
          getAccessorPropertyType(setter, true, setterName.getSelfIndex());
      if (setterPropertyType.isNull())
        return nullptr;
  
      // If the inferred property types don't match up, we can't
      // form a property.
      if (!getter->getASTContext().hasSameType(propertyType, setterPropertyType))
        return nullptr;
    }
  
    // Import the property's context.
    auto dc = Impl.importDeclContextOf(getter, getterName.getEffectiveContext());
    if (!dc)
      return nullptr;
  
    // Is this a static property?
    bool isStatic = false;
    if (dc->isTypeContext() && !getterName.getSelfIndex())
      isStatic = true;
  
    // Compute the property type.
    bool isFromSystemModule = isInSystemModule(dc);
    Type swiftPropertyType = Impl.importType(
        propertyType, ImportTypeKind::Property,
        Impl.shouldAllowNSUIntegerAsInt(isFromSystemModule, getter),
        Bridgeability::Full, OTK_ImplicitlyUnwrappedOptional);
    if (!swiftPropertyType)
      return nullptr;
  
    auto property = Impl.createDeclWithClangNode<VarDecl>(
        getter, AccessLevel::Public, /*IsStatic*/isStatic,
        VarDecl::Specifier::Var, /*IsCaptureList*/false, SourceLoc(),
        propertyName, dc->mapTypeIntoContext(swiftPropertyType), dc);
    property->setInterfaceType(swiftPropertyType);
  
    // Note that we've formed this property.
    Impl.FunctionsAsProperties[getter] = property;
    if (setter)
      Impl.FunctionsAsProperties[setter] = property;
  
    // If this property is in a class or class extension context,
    // add "final".
    if (dc->getAsClassOrClassExtensionContext())
      property->getAttrs().add(new (Impl.SwiftContext)
                                   FinalAttr(/*IsImplicit=*/true));
  
    // Import the getter.
    auto *swiftGetter = dyn_cast_or_null<FuncDecl>(
        importFunctionDecl(getter, getterName, None, property));
    if (!swiftGetter)
      return nullptr;
    Impl.importAttributes(getter, swiftGetter);
    Impl.ImportedDecls[{getter, getVersion()}] = swiftGetter;
    if (swift3GetterName)
      markAsVariant(swiftGetter, *swift3GetterName);
  
    // Import the setter.
    FuncDecl *swiftSetter = nullptr;
    if (setter) {
      swiftSetter = dyn_cast_or_null<FuncDecl>(
          importFunctionDecl(setter, setterName, None, property));
      if (!swiftSetter)
        return nullptr;
      Impl.importAttributes(setter, swiftSetter);
      Impl.ImportedDecls[{setter, getVersion()}] = swiftSetter;
      if (swift3SetterName)
        markAsVariant(swiftSetter, *swift3SetterName);
    }
  
    if (swiftGetter) property->setIsGetterMutating(swiftGetter->isMutating());
    if (swiftSetter) property->setIsSetterMutating(swiftSetter->isMutating());
  
    // Make this a computed property.
    property->makeComputed(SourceLoc(), swiftGetter, swiftSetter, nullptr,
                           SourceLoc());
  
    // Make the property the alternate declaration for the getter.
    Impl.addAlternateDecl(swiftGetter, property);
  
    return property;
  }
  
  ConstructorDecl *SwiftDeclConverter::importConstructor(
      const clang::ObjCMethodDecl *objcMethod, DeclContext *dc, bool implicit,
      Optional<CtorInitializerKind> kind, bool required) {
    // Only methods in the 'init' family can become constructors.
    assert(isInitMethod(objcMethod) && "Not a real init method");
  
    // Check whether we've already created the constructor.
    auto known =
        Impl.Constructors.find(std::make_tuple(objcMethod, dc, getVersion()));
    if (known != Impl.Constructors.end())
      return known->second;
  
    // Check whether there is already a method with this selector.
    auto selector = Impl.importSelector(objcMethod->getSelector());
    if (isActiveSwiftVersion() &&
        methodAlreadyImported(selector, /*isInstance=*/true, dc))
      return nullptr;
  
    // Map the name and complete the import.
    ArrayRef<const clang::ParmVarDecl *> params{objcMethod->param_begin(),
                                                objcMethod->param_end()};
  
    bool variadic = objcMethod->isVariadic();
    Optional<ImportedName> correctSwiftName;
    auto importedName = importFullName(objcMethod, correctSwiftName);
    if (!importedName)
      return nullptr;
  
    // If we dropped the variadic, handle it now.
    if (importedName.droppedVariadic()) {
      selector = ObjCSelector(Impl.SwiftContext, selector.getNumArgs() - 1,
                              selector.getSelectorPieces().drop_back());
      params = params.drop_back(1);
      variadic = false;
    }
  
    bool redundant;
    auto result =
        importConstructor(objcMethod, dc, implicit, kind, required, selector,
                          importedName, params, variadic, redundant);
  
    // If this is a compatibility stub, mark it as such.
    if (result && correctSwiftName)
      markAsVariant(result, *correctSwiftName);
  
    return result;
  }
  
  /// Returns the latest "introduced" version on the current platform for
  /// \p D.
  clang::VersionTuple
  SwiftDeclConverter::findLatestIntroduction(const clang::Decl *D) {
    clang::VersionTuple result;
  
    for (auto *attr : D->specific_attrs<clang::AvailabilityAttr>()) {
      if (attr->getPlatform()->getName() == "swift") {
        clang::VersionTuple maxVersion{~0U, ~0U, ~0U};
        return maxVersion;
      }
  
      // Does this availability attribute map to the platform we are
      // currently targeting?
      if (!Impl.platformAvailability.filter ||
          !Impl.platformAvailability.filter(attr->getPlatform()->getName()))
        continue;
  
      // Take advantage of the empty version being 0.0.0.0.
      result = std::max(result, attr->getIntroduced());
    }
  
    return result;
  }
  
  /// Returns true if importing \p objcMethod will produce a "better"
  /// initializer than \p existingCtor.
  bool SwiftDeclConverter::existingConstructorIsWorse(
      const ConstructorDecl *existingCtor,
      const clang::ObjCMethodDecl *objcMethod, CtorInitializerKind kind) {
    CtorInitializerKind existingKind = existingCtor->getInitKind();
  
    // If one constructor is unavailable in Swift and the other is
    // not, keep the available one.
    bool existingIsUnavailable =
        existingCtor->getAttrs().isUnavailable(Impl.SwiftContext);
    bool newIsUnavailable = Impl.isUnavailableInSwift(objcMethod);
    if (existingIsUnavailable != newIsUnavailable)
      return existingIsUnavailable;
  
    // If the new kind is the same as the existing kind, stick with
    // the existing constructor.
    if (existingKind == kind)
      return false;
  
    // Check for cases that are obviously better or obviously worse.
    if (kind == CtorInitializerKind::Designated ||
        existingKind == CtorInitializerKind::Factory)
      return true;
  
    if (kind == CtorInitializerKind::Factory ||
        existingKind == CtorInitializerKind::Designated)
      return false;
  
    assert(kind == CtorInitializerKind::Convenience ||
           kind == CtorInitializerKind::ConvenienceFactory);
    assert(existingKind == CtorInitializerKind::Convenience ||
           existingKind == CtorInitializerKind::ConvenienceFactory);
  
    // Between different kinds of convenience initializers, keep the one that
    // was introduced first.
    // FIXME: But if one of them is now deprecated, should we prefer the
    // other?
    clang::VersionTuple introduced = findLatestIntroduction(objcMethod);
    AvailabilityContext existingAvailability =
        AvailabilityInference::availableRange(existingCtor, Impl.SwiftContext);
    assert(!existingAvailability.isKnownUnreachable());
  
    if (existingAvailability.isAlwaysAvailable()) {
      if (!introduced.empty())
        return false;
    } else {
      VersionRange existingIntroduced = existingAvailability.getOSVersion();
      if (introduced != existingIntroduced.getLowerEndpoint()) {
        return introduced < existingIntroduced.getLowerEndpoint();
      }
    }
  
    // The "introduced" versions are the same. Prefer Convenience over
    // ConvenienceFactory, but otherwise prefer leaving things as they are.
    if (kind == CtorInitializerKind::Convenience &&
        existingKind == CtorInitializerKind::ConvenienceFactory)
      return true;
  
    return false;
  }
  
  /// \brief Given an imported method, try to import it as a constructor.
  ///
  /// Objective-C methods in the 'init' family are imported as
  /// constructors in Swift, enabling object construction syntax, e.g.,
  ///
  /// \code
  /// // in objc: [[NSArray alloc] initWithCapacity:1024]
  /// NSArray(capacity: 1024)
  /// \endcode
  ///
  /// This variant of the function is responsible for actually binding the
  /// constructor declaration appropriately.
  ConstructorDecl *SwiftDeclConverter::importConstructor(
      const clang::ObjCMethodDecl *objcMethod, DeclContext *dc, bool implicit,
      Optional<CtorInitializerKind> kindIn, bool required, ObjCSelector selector,
      ImportedName importedName, ArrayRef<const clang::ParmVarDecl *> args,
      bool variadic, bool &redundant) {
    redundant = false;
  
    // Figure out the type of the container.
    auto ownerNominal = dc->getAsNominalTypeOrNominalTypeExtensionContext();
    assert(ownerNominal && "Method in non-type context?");
  
    // Find the interface, if we can.
    const clang::ObjCInterfaceDecl *interface = nullptr;
    if (auto classDecl = dyn_cast<ClassDecl>(ownerNominal)) {
      interface =
          dyn_cast_or_null<clang::ObjCInterfaceDecl>(classDecl->getClangDecl());
    }
  
    // If we weren't told what kind of initializer this should be,
    // figure it out now.
    CtorInitializerKind kind;
  
    if (kindIn) {
      kind = *kindIn;
  
      // If we know this is a designated initializer, mark it as such.
      if (interface && hasDesignatedInitializers(interface) &&
          isDesignatedInitializer(interface, objcMethod))
        kind = CtorInitializerKind::Designated;
    } else {
      // If the owning Objective-C class has designated initializers and this
      // is not one of them, treat it as a convenience initializer.
      if (interface && hasDesignatedInitializers(interface) &&
          !isDesignatedInitializer(interface, objcMethod)) {
        kind = CtorInitializerKind::Convenience;
      } else {
        kind = CtorInitializerKind::Designated;
      }
    }
  
    // Add the implicit 'self' parameter patterns.
    SmallVector<ParameterList *, 4> bodyParams;
    auto selfMetaVar = ParamDecl::createSelf(SourceLoc(), dc, /*static*/ true);
    auto selfTy = dc->getSelfInterfaceType();
    auto selfMetaTy = MetatypeType::get(selfTy);
    bodyParams.push_back(ParameterList::createWithoutLoc(selfMetaVar));
  
    // Import the type that this method will have.
    Optional<ForeignErrorConvention> errorConvention;
    bodyParams.push_back(nullptr);
    auto type = Impl.importMethodType(
        dc, objcMethod, args, variadic, isInSystemModule(dc),
        &bodyParams.back(), importedName, errorConvention,
        SpecialMethodKind::Constructor);
    if (!type)
      return nullptr;
  
    // Determine the failability of this initializer.
    auto oldFnType = type->castTo<AnyFunctionType>();
    OptionalTypeKind failability;
    (void)oldFnType->getResult()->getAnyOptionalObjectType(failability);
  
    // Rebuild the function type with the appropriate result type;
    Type resultTy = selfTy;
    if (failability)
      resultTy = OptionalType::get(failability, resultTy);
  
    type = FunctionType::get(oldFnType->getInput(), resultTy,
                             oldFnType->getExtInfo());
  
    // Add the 'self' parameter to the function types.
    Type allocType = FunctionType::get(selfMetaTy, type);
    Type initType = FunctionType::get(selfTy, type);
  
    // Look for other imported constructors that occur in this context with
    // the same name.
    Type allocParamType = allocType->castTo<AnyFunctionType>()
                              ->getResult()
                              ->castTo<AnyFunctionType>()
                              ->getInput();
    bool ignoreNewExtensions = isa<ClassDecl>(dc);
    for (auto other : ownerNominal->lookupDirect(importedName.getDeclName(),
                                                 ignoreNewExtensions)) {
      auto ctor = dyn_cast<ConstructorDecl>(other);
      if (!ctor || ctor->isInvalid() ||
          ctor->getAttrs().isUnavailable(Impl.SwiftContext) ||
          !ctor->getClangDecl())
        continue;
  
      // Resolve the type of the constructor.
      if (!ctor->hasInterfaceType())
        Impl.getTypeResolver()->resolveDeclSignature(ctor);
  
      // If the types don't match, this is a different constructor with
      // the same selector. This can happen when an overlay overloads an
      // existing selector with a Swift-only signature.
      Type ctorParamType = ctor->getInterfaceType()
                               ->castTo<AnyFunctionType>()
                               ->getResult()
                               ->castTo<AnyFunctionType>()
                               ->getInput();
      if (!ctorParamType->isEqual(allocParamType)) {
        continue;
      }
  
      // If the existing constructor has a less-desirable kind, mark
      // the existing constructor unavailable.
      if (existingConstructorIsWorse(ctor, objcMethod, kind)) {
        // Show exactly where this constructor came from.
        llvm::SmallString<32> errorStr;
        errorStr += "superseded by import of ";
        if (objcMethod->isClassMethod())
          errorStr += "+[";
        else
          errorStr += "-[";
  
        auto objcDC = objcMethod->getDeclContext();
        if (auto objcClass = dyn_cast<clang::ObjCInterfaceDecl>(objcDC)) {
          errorStr += objcClass->getName();
          errorStr += ' ';
        } else if (auto objcCat = dyn_cast<clang::ObjCCategoryDecl>(objcDC)) {
          errorStr += objcCat->getClassInterface()->getName();
          auto catName = objcCat->getName();
          if (!catName.empty()) {
            errorStr += '(';
            errorStr += catName;
            errorStr += ')';
          }
          errorStr += ' ';
        } else if (auto objcProto = dyn_cast<clang::ObjCProtocolDecl>(objcDC)) {
          errorStr += objcProto->getName();
          errorStr += ' ';
        }
  
        errorStr += objcMethod->getSelector().getAsString();
        errorStr += ']';
  
        auto attr = AvailableAttr::createPlatformAgnostic(
            Impl.SwiftContext, Impl.SwiftContext.AllocateCopy(errorStr.str()));
        ctor->getAttrs().add(attr);
        continue;
      }
  
      // Otherwise, we shouldn't create a new constructor, because
      // it will be no better than the existing one.
      redundant = true;
      return nullptr;
    }
  
    // Check whether we've already created the constructor.
    auto known =
        Impl.Constructors.find(std::make_tuple(objcMethod, dc, getVersion()));
    if (known != Impl.Constructors.end())
      return known->second;
  
    auto *selfVar = ParamDecl::createSelf(SourceLoc(), dc);
  
    // Create the actual constructor.
    auto result = Impl.createDeclWithClangNode<ConstructorDecl>(
        objcMethod, AccessLevel::Public, importedName.getDeclName(),
        /*NameLoc=*/SourceLoc(), failability, /*FailabilityLoc=*/SourceLoc(),
        /*Throws=*/importedName.getErrorInfo().hasValue(),
        /*ThrowsLoc=*/SourceLoc(), selfVar, bodyParams.back(),
        /*GenericParams=*/nullptr, dc);
  
    // Make the constructor declaration immediately visible in its
    // class or protocol type.
    ownerNominal->makeMemberVisible(result);
  
    addObjCAttribute(result, selector);
  
    // Calculate the function type of the result.
    auto interfaceAllocType =
        getGenericMethodType(dc, allocType->castTo<AnyFunctionType>());
    auto interfaceInitType =
        getGenericMethodType(dc, initType->castTo<AnyFunctionType>());
  
    result->setInitializerInterfaceType(interfaceInitType);
    result->setInterfaceType(interfaceAllocType);
    result->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
  
    if (implicit)
      result->setImplicit();
  
    // Set the kind of initializer.
    result->setInitKind(kind);
  
    // Consult API notes to determine whether this initializer is required.
    if (!required && isRequiredInitializer(objcMethod))
      required = true;
  
    // Check whether this initializer satisfies a requirement in a protocol.
    if (!required && !isa<ProtocolDecl>(dc) && objcMethod->isInstanceMethod()) {
      auto objcParent =
          cast<clang::ObjCContainerDecl>(objcMethod->getDeclContext());
  
      if (isa<clang::ObjCProtocolDecl>(objcParent)) {
        // An initializer declared in a protocol is required.
        required = true;
      } else {
        // If the class in which this initializer was declared conforms to a
        // protocol that requires this initializer, then this initializer is
        // required.
        SmallPtrSet<clang::ObjCProtocolDecl *, 8> objcProtocols;
        objcParent->getASTContext().CollectInheritedProtocols(objcParent,
                                                              objcProtocols);
        for (auto objcProto : objcProtocols) {
          for (auto decl : objcProto->lookup(objcMethod->getSelector())) {
            if (cast<clang::ObjCMethodDecl>(decl)->isInstanceMethod()) {
              required = true;
              break;
            }
          }
  
          if (required)
            break;
        }
      }
    }
  
    // If this initializer is required, add the appropriate attribute.
    if (required) {
      result->getAttrs().add(new (Impl.SwiftContext)
                                 RequiredAttr(/*IsImplicit=*/true));
    }
  
    // Record the error convention.
    if (errorConvention) {
      result->setForeignErrorConvention(*errorConvention);
    }
  
    // Record the constructor for future re-use.
    Impl.Constructors[std::make_tuple(objcMethod, dc, getVersion())] = result;
  
    // If this constructor overrides another constructor, mark it as such.
    recordObjCOverride(result);
  
    // Inform the context that we have external definitions.
    Impl.registerExternalDecl(result);
  
    return result;
  }
  
  void SwiftDeclConverter::recordObjCOverride(AbstractFunctionDecl *decl) {
    // Figure out the class in which this method occurs.
    auto classTy = decl->getDeclContext()->getDeclaredInterfaceType()
        ->getAs<ClassType>();
    if (!classTy)
      return;
    auto superTy = classTy->getSuperclass();
    if (!superTy)
      return;
    // Dig out the Objective-C superclass.
    auto superDecl = superTy->getAnyNominal();
    SmallVector<ValueDecl *, 4> results;
    superDecl->lookupQualified(superTy, decl->getFullName(),
                               NL_QualifiedDefault | NL_KnownNoDependency,
                               Impl.getTypeResolver(), results);
    for (auto member : results) {
      if (member->getKind() != decl->getKind() ||
          member->isInstanceMember() != decl->isInstanceMember())
        continue;
      // Set function override.
      if (auto func = dyn_cast<FuncDecl>(decl)) {
        auto foundFunc = cast<FuncDecl>(member);
        // Require a selector match.
        if (func->getObjCSelector() != foundFunc->getObjCSelector())
          continue;
        func->setOverriddenDecl(foundFunc);
        return;
      }
      // Set constructor override.
      auto ctor = cast<ConstructorDecl>(decl);
      auto memberCtor = cast<ConstructorDecl>(member);
      // Require a selector match.
      if (ctor->getObjCSelector() != memberCtor->getObjCSelector())
        continue;
      ctor->setOverriddenDecl(memberCtor);
      // Propagate 'required' to subclass initializers.
      if (memberCtor->isRequired() &&
          !ctor->getAttrs().hasAttribute<RequiredAttr>()) {
        ctor->getAttrs().add(new (Impl.SwiftContext)
                                 RequiredAttr(/*IsImplicit=*/true));
      }
    }
  }
  
  void SwiftDeclConverter::recordObjCOverride(SubscriptDecl *subscript) {
    // Figure out the class in which this subscript occurs.
    auto classTy =
        subscript->getDeclContext()->getAsClassOrClassExtensionContext();
    if (!classTy)
      return;
  
    auto superTy = classTy->getSuperclass();
    if (!superTy)
      return;
  
    // Determine whether this subscript operation overrides another subscript
    // operation.
    SmallVector<ValueDecl *, 2> lookup;
    subscript->getModuleContext()->lookupQualified(
        superTy, subscript->getFullName(),
        NL_QualifiedDefault | NL_KnownNoDependency, Impl.getTypeResolver(),
        lookup);
    Type unlabeledIndices;
    for (auto result : lookup) {
      auto parentSub = dyn_cast<SubscriptDecl>(result);
      if (!parentSub)
        continue;
  
      // Compute the type of indices for our own subscript operation, lazily.
      if (!unlabeledIndices) {
        unlabeledIndices = subscript->getIndices()
                               ->getInterfaceType(Impl.SwiftContext)
                               ->getUnlabeledType(Impl.SwiftContext);
      }
  
      // Compute the type of indices for the subscript we found.
      auto parentUnlabeledIndices = parentSub->getIndices()
                                        ->getInterfaceType(Impl.SwiftContext)
                                        ->getUnlabeledType(Impl.SwiftContext);
      if (!unlabeledIndices->isEqual(parentUnlabeledIndices))
        continue;
  
      // The index types match. This is an override, so mark it as such.
      subscript->setOverriddenDecl(parentSub);
      auto getterThunk = subscript->getGetter();
      getterThunk->setOverriddenDecl(parentSub->getGetter());
      if (auto parentSetter = parentSub->getSetter()) {
        if (auto setterThunk = subscript->getSetter())
          setterThunk->setOverriddenDecl(parentSetter);
      }
  
      // FIXME: Eventually, deal with multiple overrides.
      break;
    }
  }
  
  /// \brief Given either the getter or setter for a subscript operation,
  /// create the Swift subscript declaration.
  SubscriptDecl *
  SwiftDeclConverter::importSubscript(Decl *decl,
                                      const clang::ObjCMethodDecl *objcMethod) {
    assert(objcMethod->isInstanceMethod() && "Caller must filter");
  
    // If the method we're attempting to import has the
    // swift_private attribute, don't import as a subscript.
    if (objcMethod->hasAttr<clang::SwiftPrivateAttr>())
      return nullptr;
  
    // Figure out where to look for the counterpart.
    const clang::ObjCInterfaceDecl *interface = nullptr;
    const clang::ObjCProtocolDecl *protocol =
        dyn_cast<clang::ObjCProtocolDecl>(objcMethod->getDeclContext());
    if (!protocol)
      interface = objcMethod->getClassInterface();
    auto lookupInstanceMethod = [&](
        clang::Selector Sel) -> const clang::ObjCMethodDecl * {
      if (interface)
        return interface->lookupInstanceMethod(Sel);
  
      return protocol->lookupInstanceMethod(Sel);
    };
  
    auto findCounterpart = [&](clang::Selector sel) -> FuncDecl * {
      // If the declaration we're starting from is in a class, first
      // look for a class member with the appropriate selector.
      if (auto classDecl =
              decl->getDeclContext()->getAsClassOrClassExtensionContext()) {
        auto swiftSel = Impl.importSelector(sel);
        for (auto found : classDecl->lookupDirect(swiftSel, true)) {
          if (auto foundFunc = dyn_cast<FuncDecl>(found))
            return foundFunc;
        }
      }
  
      // Find based on selector within the current type.
      auto counterpart = lookupInstanceMethod(sel);
      if (!counterpart)
        return nullptr;
  
      return cast_or_null<FuncDecl>(
          Impl.importDecl(counterpart, getActiveSwiftVersion()));
    };
  
    // Determine the selector of the counterpart.
    FuncDecl *getter = nullptr, *setter = nullptr;
    clang::Selector counterpartSelector;
    if (objcMethod->getSelector() == Impl.objectAtIndexedSubscript) {
      getter = cast<FuncDecl>(decl);
      counterpartSelector = Impl.setObjectAtIndexedSubscript;
    } else if (objcMethod->getSelector() == Impl.setObjectAtIndexedSubscript) {
      setter = cast<FuncDecl>(decl);
      counterpartSelector = Impl.objectAtIndexedSubscript;
    } else if (objcMethod->getSelector() == Impl.objectForKeyedSubscript) {
      getter = cast<FuncDecl>(decl);
      counterpartSelector = Impl.setObjectForKeyedSubscript;
    } else if (objcMethod->getSelector() == Impl.setObjectForKeyedSubscript) {
      setter = cast<FuncDecl>(decl);
      counterpartSelector = Impl.objectForKeyedSubscript;
    } else {
      llvm_unreachable("Unknown getter/setter selector");
    }
  
    // Find the counterpart.
    bool optionalMethods = (objcMethod->getImplementationControl() ==
                            clang::ObjCMethodDecl::Optional);
  
    if (auto *counterpart = findCounterpart(counterpartSelector)) {
      // If the counterpart to the method we're attempting to import has the
      // swift_private attribute, don't import as a subscript.
      if (auto importedFrom = counterpart->getClangDecl()) {
        if (importedFrom->hasAttr<clang::SwiftPrivateAttr>())
          return nullptr;
  
        auto counterpartMethod = dyn_cast<clang::ObjCMethodDecl>(importedFrom);
        if (optionalMethods)
          optionalMethods = (counterpartMethod->getImplementationControl() ==
                             clang::ObjCMethodDecl::Optional);
      }
  
      assert(!counterpart || !counterpart->isStatic());
  
      if (getter)
        setter = counterpart;
      else
        getter = counterpart;
    }
  
    // Swift doesn't have write-only subscripting.
    if (!getter)
      return nullptr;
  
    // Check whether we've already created a subscript operation for
    // this getter/setter pair.
    if (auto subscript = Impl.Subscripts[{getter, setter}]) {
      return subscript->getDeclContext() == decl->getDeclContext() ? subscript
                                                                   : nullptr;
    }
  
    // Find the getter indices and make sure they match.
    ParamDecl *getterIndex;
    {
      auto params = getter->getParameterList(1);
      if (params->size() != 1)
        return nullptr;
      getterIndex = params->get(0);
    }
  
    // Compute the element type based on the getter, looking through
    // the implicit 'self' parameter and the normal function
    // parameters.
    auto elementTy = getter->getInterfaceType()
                         ->castTo<AnyFunctionType>()
                         ->getResult()
                         ->castTo<AnyFunctionType>()
                         ->getResult();
    auto elementContextTy = getter->mapTypeIntoContext(elementTy);
  
    // Local function to mark the setter unavailable.
    auto makeSetterUnavailable = [&] {
      if (setter && !setter->getAttrs().isUnavailable(Impl.SwiftContext))
        Impl.markUnavailable(setter, "use subscripting");
    };
  
    // If we have a setter, rectify it with the getter.
    ParamDecl *setterIndex;
    bool getterAndSetterInSameType = false;
    if (setter) {
      // Whether there is an existing read-only subscript for which
      // we have now found a setter.
      SubscriptDecl *existingSubscript = Impl.Subscripts[{getter, nullptr}];
  
      // Are the getter and the setter in the same type.
      getterAndSetterInSameType =
          (getter->getDeclContext()
               ->getAsNominalTypeOrNominalTypeExtensionContext() ==
           setter->getDeclContext()
               ->getAsNominalTypeOrNominalTypeExtensionContext());
      // TODO: Possible that getter and setter are different instantiations
      // of the same objc generic type?
  
      // Whether we can update the types involved in the subscript
      // operation.
      bool canUpdateSubscriptType =
          !existingSubscript && getterAndSetterInSameType;
  
      // Determine the setter's element type and indices.
      Type setterElementTy;
      std::tie(setterElementTy, setterIndex) = decomposeSubscriptSetter(setter);
  
      // Rectify the setter element type with the getter's element type.
      Type newElementTy = rectifySubscriptTypes(elementTy, setterElementTy,
                                                canUpdateSubscriptType);
      if (!newElementTy)
        return decl == getter ? existingSubscript : nullptr;
  
      // Update the element type.
      elementTy = newElementTy;
  
      // Make sure that the index types are equivalent.
      // FIXME: Rectify these the same way we do for element types.
      if (!setterIndex->getType()->isEqual(getterIndex->getType())) {
        // If there is an existing subscript operation, we're done.
        if (existingSubscript)
          return decl == getter ? existingSubscript : nullptr;
  
        // Otherwise, just forget we had a setter.
        // FIXME: This feels very, very wrong.
        setter = nullptr;
        setterIndex = nullptr;
      }
  
      // If there is an existing subscript within this context, we
      // cannot create a new subscript. Update it if possible.
      if (setter && existingSubscript && getterAndSetterInSameType) {
        // Can we update the subscript by adding the setter?
        if (existingSubscript->hasClangNode() &&
            !existingSubscript->isSettable()) {
          // Create the setter thunk.
          auto setterThunk = buildSubscriptSetterDecl(
              Impl, setter, elementTy, setter->getDeclContext(), setterIndex);
  
          // Set the computed setter.
          existingSubscript->setComputedSetter(setterThunk);
  
          // Mark the setter as unavailable; one should use
          // subscripting when it is present.
          makeSetterUnavailable();
        }
  
        return decl == getter ? existingSubscript : nullptr;
      }
    }
  
    // The context into which the subscript should go.
    bool associateWithSetter = setter && !getterAndSetterInSameType;
    DeclContext *dc =
        associateWithSetter ? setter->getDeclContext() : getter->getDeclContext();
  
    // Build the thunks.
    FuncDecl *getterThunk =
        buildSubscriptGetterDecl(Impl, getter, elementTy, dc, getterIndex);
  
    FuncDecl *setterThunk = nullptr;
    if (setter)
      setterThunk =
          buildSubscriptSetterDecl(Impl, setter, elementTy, dc, setterIndex);
  
    // Build the subscript declaration.
    auto &C = Impl.SwiftContext;
    auto bodyParams = getterThunk->getParameterList(1)->clone(C);
    DeclName name(C, DeclBaseName::createSubscript(), {Identifier()});
    auto subscript = Impl.createDeclWithClangNode<SubscriptDecl>(
        getter->getClangNode(), getOverridableAccessLevel(dc), name,
        decl->getLoc(), bodyParams, decl->getLoc(),
        TypeLoc::withoutLoc(elementContextTy), dc,
        /*GenericParams=*/nullptr);
  
    /// Record the subscript as an alternative declaration.
    Impl.addAlternateDecl(associateWithSetter ? setter : getter, subscript);
  
    subscript->setGenericEnvironment(dc->getGenericEnvironmentOfContext());
  
    subscript->setIsSetterMutating(false);
    subscript->makeComputed(SourceLoc(), getterThunk, setterThunk, nullptr,
                            SourceLoc());
    auto indicesType = bodyParams->getType(C);
  
    AnyFunctionType *fnType;
    if (auto *sig = dc->getGenericSignatureOfContext())
      fnType = GenericFunctionType::get(sig, indicesType, elementTy,
                                        AnyFunctionType::ExtInfo());
    else
      fnType = FunctionType::get(indicesType, elementTy);
    subscript->setInterfaceType(fnType);
  
    addObjCAttribute(subscript, None);
  
    // Optional subscripts in protocols.
    if (optionalMethods && isa<ProtocolDecl>(dc))
      subscript->getAttrs().add(new (Impl.SwiftContext) OptionalAttr(true));
  
    // Note that we've created this subscript.
    Impl.Subscripts[{getter, setter}] = subscript;
    if (setter && !Impl.Subscripts[{getter, nullptr}])
      Impl.Subscripts[{getter, nullptr}] = subscript;
  
    // Make the getter/setter methods unavailable.
    if (!getter->getAttrs().isUnavailable(Impl.SwiftContext))
      Impl.markUnavailable(getter, "use subscripting");
    makeSetterUnavailable();
  
    // Wire up overrides.
    recordObjCOverride(subscript);
  
    return subscript;
  }
  
  FuncDecl *
  SwiftDeclConverter::importAccessor(clang::ObjCMethodDecl *clangAccessor,
                                     DeclContext *dc) {
    SwiftDeclConverter converter(Impl, getActiveSwiftVersion());
    auto *accessor =
        cast_or_null<FuncDecl>(converter.importObjCMethodDecl(clangAccessor, dc));
    if (!accessor) {
      return nullptr;
    }
  
    Impl.importAttributes(clangAccessor, accessor);
  
    return accessor;
  }
  
  void SwiftDeclConverter::addProtocols(
      ProtocolDecl *protocol, SmallVectorImpl<ProtocolDecl *> &protocols,
      llvm::SmallPtrSet<ProtocolDecl *, 4> &known) {
    if (!known.insert(protocol).second)
      return;
  
    protocols.push_back(protocol);
    for (auto inherited : protocol->getInheritedProtocols())
      addProtocols(inherited, protocols, known);
  }
  
  void SwiftDeclConverter::importObjCProtocols(
      Decl *decl, const clang::ObjCProtocolList &clangProtocols,
      SmallVectorImpl<TypeLoc> &inheritedTypes) {
    SmallVector<ProtocolDecl *, 4> protocols;
    llvm::SmallPtrSet<ProtocolDecl *, 4> knownProtocols;
    if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
      nominal->getImplicitProtocols(protocols);
      knownProtocols.insert(protocols.begin(), protocols.end());
    }
  
    for (auto cp = clangProtocols.begin(), cpEnd = clangProtocols.end();
         cp != cpEnd; ++cp) {
      if (auto proto = castIgnoringCompatibilityAlias<ProtocolDecl>(
              Impl.importDecl(*cp, getActiveSwiftVersion()))) {
        addProtocols(proto, protocols, knownProtocols);
        inheritedTypes.push_back(TypeLoc::withoutLoc(proto->getDeclaredType()));
      }
    }
  
    addObjCProtocolConformances(decl, protocols);
  }
  
  void SwiftDeclConverter::addObjCProtocolConformances(
      Decl *decl, ArrayRef<ProtocolDecl *> protocols) {
    // Nothing to do for protocols.
    if (isa<ProtocolDecl>(decl)) return;
  
    Impl.recordImportedProtocols(decl, protocols);
  
    // Synthesize trivial conformances for each of the protocols.
    SmallVector<ProtocolConformance *, 4> conformances;
  
    auto dc = decl->getInnermostDeclContext();
    auto &ctx = Impl.SwiftContext;
    for (unsigned i = 0, n = protocols.size(); i != n; ++i) {
      // FIXME: Build a superclass conformance if the superclass
      // conforms.
      auto conformance = ctx.getConformance(dc->getDeclaredInterfaceType(),
                                            protocols[i], SourceLoc(), dc,
                                            ProtocolConformanceState::Incomplete);
      conformance->setLazyLoader(&Impl, /*context*/0);
      conformance->setState(ProtocolConformanceState::Complete);
      conformances.push_back(conformance);
    }
  
    // Set the conformances.
    // FIXME: This could be lazier.
    unsigned id = Impl.allocateDelayedConformance(std::move(conformances));
    if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
      nominal->setConformanceLoader(&Impl, id);
    } else {
      auto ext = cast<ExtensionDecl>(decl);
      ext->setConformanceLoader(&Impl, id);
    }
  }
  
  Optional<GenericParamList *> SwiftDeclConverter::importObjCGenericParams(
      const clang::ObjCInterfaceDecl *decl, DeclContext *dc) {
    auto typeParamList = decl->getTypeParamList();
    if (!typeParamList) {
      return nullptr;
    }
    if (shouldSuppressGenericParamsImport(Impl.SwiftContext.LangOpts, decl)) {
      return nullptr;
    }
    assert(typeParamList->size() > 0);
    SmallVector<GenericTypeParamDecl *, 4> genericParams;
    for (auto *objcGenericParam : *typeParamList) {
      auto genericParamDecl = Impl.createDeclWithClangNode<GenericTypeParamDecl>(
          objcGenericParam, AccessLevel::Public, dc,
          Impl.SwiftContext.getIdentifier(objcGenericParam->getName()),
          Impl.importSourceLoc(objcGenericParam->getLocation()),
          /*depth*/ 0, /*index*/ genericParams.size());
      // NOTE: depth is always 0 for ObjC generic type arguments, since only
      // classes may have generic types in ObjC, and ObjC classes cannot be
      // nested.
  
      // Import parameter constraints.
      SmallVector<TypeLoc, 1> inherited;
      if (objcGenericParam->hasExplicitBound()) {
        assert(!objcGenericParam->getUnderlyingType().isNull());
        auto clangBound = objcGenericParam->getUnderlyingType()
                              ->castAs<clang::ObjCObjectPointerType>();
        if (clangBound->getInterfaceDecl()) {
          auto unqualifiedClangBound =
              clangBound->stripObjCKindOfTypeAndQuals(Impl.getClangASTContext());
          Type superclassType =
              Impl.importType(clang::QualType(unqualifiedClangBound, 0),
                              ImportTypeKind::Abstract, false,
                              Bridgeability::None);
          if (!superclassType) {
            return None;
          }
          inherited.push_back(TypeLoc::withoutLoc(superclassType));
        }
        for (clang::ObjCProtocolDecl *clangProto : clangBound->quals()) {
          ProtocolDecl *proto = castIgnoringCompatibilityAlias<ProtocolDecl>(
              Impl.importDecl(clangProto, getActiveSwiftVersion()));
          if (!proto) {
            return None;
          }
          inherited.push_back(TypeLoc::withoutLoc(proto->getDeclaredType()));
        }
      }
      if (inherited.empty()) {
        inherited.push_back(
          TypeLoc::withoutLoc(Impl.SwiftContext.getAnyObjectType()));
      }
      genericParamDecl->setInherited(Impl.SwiftContext.AllocateCopy(inherited));
  
      genericParams.push_back(genericParamDecl);
    }
    return GenericParamList::create(
        Impl.SwiftContext, Impl.importSourceLoc(typeParamList->getLAngleLoc()),
        genericParams, Impl.importSourceLoc(typeParamList->getRAngleLoc()));
  }
  
  void SwiftDeclConverter::importMirroredProtocolMembers(
      const clang::ObjCContainerDecl *decl, DeclContext *dc,
      ArrayRef<ProtocolDecl *> protocols, SmallVectorImpl<Decl *> &members,
      ASTContext &Ctx) {
    assert(dc);
    const clang::ObjCInterfaceDecl *interfaceDecl = nullptr;
    const ClangModuleUnit *declModule;
    const ClangModuleUnit *interfaceModule;
  
    // 'protocols' is, for some reason, the full recursive expansion of
    // the protocol hierarchy, so there's no need to recursively descend
    // into inherited protocols.
  
    // Try to import only the most specific methods with a particular name.
    // We use a MapVector to get deterministic iteration order later.
    llvm::MapVector<clang::Selector, std::vector<MirroredMethodEntry>>
      methodsByName;
  
    for (auto proto : protocols) {
      auto clangProto =
          cast_or_null<clang::ObjCProtocolDecl>(proto->getClangDecl());
      if (!clangProto)
        continue;
  
      if (!interfaceDecl) {
        declModule = Impl.getClangModuleForDecl(decl);
        if ((interfaceDecl = dyn_cast<clang::ObjCInterfaceDecl>(decl))) {
          interfaceModule = declModule;
        } else {
          auto category = cast<clang::ObjCCategoryDecl>(decl);
          interfaceDecl = category->getClassInterface();
          interfaceModule = Impl.getClangModuleForDecl(interfaceDecl);
        }
      }
  
      // Don't import a protocol's members if the superclass already adopts
      // the protocol, or (for categories) if the class itself adopts it
      // in its main @interface.
      if (decl != interfaceDecl)
        if (classImplementsProtocol(interfaceDecl, clangProto, false))
          continue;
      if (auto superInterface = interfaceDecl->getSuperClass())
        if (classImplementsProtocol(superInterface, clangProto, true))
          continue;
  
      const auto &languageVersion =
          Impl.SwiftContext.LangOpts.EffectiveLanguageVersion;
      for (auto member : proto->getMembers()) {
        // Skip compatibility stubs; there's no reason to mirror them.
        if (member->getAttrs().isUnavailableInSwiftVersion(languageVersion))
          continue;
  
        if (auto prop = dyn_cast<VarDecl>(member)) {
          auto objcProp =
              dyn_cast_or_null<clang::ObjCPropertyDecl>(prop->getClangDecl());
          if (!objcProp)
            continue;
  
          // We can't import a property if there's already a method with this
          // name. (This also covers other properties with that same name.)
          // FIXME: We should still mirror the setter as a method if it's
          // not already there.
          clang::Selector sel = objcProp->getGetterName();
          if (interfaceDecl->getInstanceMethod(sel))
            continue;
  
          bool inNearbyCategory =
              std::any_of(interfaceDecl->visible_categories_begin(),
                          interfaceDecl->visible_categories_end(),
                          [=](const clang::ObjCCategoryDecl *category) -> bool {
                            if (category != decl) {
                              auto *categoryModule =
                                  Impl.getClangModuleForDecl(category);
                              if (categoryModule != declModule &&
                                  categoryModule != interfaceModule) {
                                return false;
                              }
                            }
                            return category->getInstanceMethod(sel);
                          });
          if (inNearbyCategory)
            continue;
  
          if (auto imported =
                  Impl.importMirroredDecl(objcProp, dc, getVersion(), proto)) {
            members.push_back(imported);
            // FIXME: We should mirror properties of the root class onto the
            // metatype.
          }
  
          continue;
        }
  
        auto afd = dyn_cast<AbstractFunctionDecl>(member);
        if (!afd)
          continue;
  
        if (auto func = dyn_cast<FuncDecl>(afd))
          if (func->isAccessor())
            continue;
  
        auto objcMethod =
            dyn_cast_or_null<clang::ObjCMethodDecl>(member->getClangDecl());
        if (!objcMethod)
          continue;
  
        // For now, just remember that we saw this method.
        methodsByName[objcMethod->getSelector()]
          .push_back(MirroredMethodEntry{objcMethod, proto});
      }
    }
  
    // Process all the methods, now that we've arranged them by selector.
    for (auto &mapEntry : methodsByName) {
      importNonOverriddenMirroredMethods(dc, mapEntry.second, members);
    }
  }
  
  enum MirrorImportComparison {
    // There's no suppression relationship between the methods.
    NoSuppression,
  
    // The first method suppresses the second.
    Suppresses,
  
    // The second method suppresses the first.
    IsSuppressed,
  };
  
  /// Should the mirror import of the first method be suppressed in favor
  /// of the second method?  The methods are known to have the same selector
  /// and (because this is mirror-import) to be declared on protocols.
  ///
  /// The algorithm that uses this assumes that it is transitive.
  static bool isMirrorImportSuppressedBy(ClangImporter::Implementation &importer,
                                         const clang::ObjCMethodDecl *first,
                                         const clang::ObjCMethodDecl *second) {
    auto firstProto = cast<clang::ObjCProtocolDecl>(first->getDeclContext());
    auto secondProto = cast<clang::ObjCProtocolDecl>(second->getDeclContext());
  
    // If the first method's protocol is a super-protocol of the second's,
    // then the second method overrides the first and we should suppress.
    // Clang provides a function to check that, phrased in terms of whether
    // a value of one protocol (the RHS) can be assigned to an l-value of
    // the other (the LHS).
    auto &ctx = importer.getClangASTContext();
    return ctx.ProtocolCompatibleWithProtocol(
                            const_cast<clang::ObjCProtocolDecl*>(firstProto),
                            const_cast<clang::ObjCProtocolDecl*>(secondProto));
  }
  
  /// Compare two methods for mirror-import purposes.
  static MirrorImportComparison
  compareMethodsForMirrorImport(ClangImporter::Implementation &importer,
                                const clang::ObjCMethodDecl *first,
                                const clang::ObjCMethodDecl *second) {
    if (isMirrorImportSuppressedBy(importer, first, second))
      return IsSuppressed;
    if (isMirrorImportSuppressedBy(importer, second, first))
      return Suppresses;
    return NoSuppression;
  }
  
  /// Mark any methods in the given array that are overridden by this method
  /// as suppressed by nulling their entries out.
  /// Return true if this method is overridden by any methods in the array.
  static bool suppressOverriddenMethods(ClangImporter::Implementation &importer,
                                        const clang::ObjCMethodDecl *method,
                                 MutableArrayRef<MirroredMethodEntry> entries) {
    assert(method && "method was already suppressed");
  
    for (auto &entry: entries) {
      auto otherMethod = entry.first;
      if (!otherMethod) continue;
  
      assert(method != otherMethod && "found same method twice?");
      switch (compareMethodsForMirrorImport(importer, method, otherMethod)) {
      // If the second method is suppressed, null it out.
      case Suppresses:
        entry.first = nullptr;
        continue;
  
      // If the first method is suppressed, return immediately.  We should
      // be able to suppress any following methods.
      case IsSuppressed:
        return true;
  
      case NoSuppression:
        continue;
      }
      llvm_unreachable("bad comparison result");
    }
  
    return false;
  }
  
  /// Given a set of methods with the same selector, each taken from a
  /// different protocol in the protocol hierarchy of a class into which
  /// we want to introduce mirror imports, import only the methods which
  /// are not overridden by another method in the set.
  ///
  /// It's possible that we'll end up selecting multiple methods to import
  /// here, in the cases where there's no hierarchical relationship between
  /// two methods.  The importer already has code to handle this case.
  void SwiftDeclConverter::importNonOverriddenMirroredMethods(DeclContext *dc,
                                 MutableArrayRef<MirroredMethodEntry> entries,
                                             SmallVectorImpl<Decl *> &members) {
    for (size_t i = 0, e = entries.size(); i != e; ++i) {
      auto objcMethod = entries[i].first;
  
      // If the method was suppressed by a previous method, ignore it.
      if (!objcMethod)
        continue;
  
      // Compare this method to all the following methods, suppressing any
      // that it overrides.  If it is overridden by any of them, suppress it
      // instead; but there's no need to mark that in the array, just continue
      // on to the next method.
      if (suppressOverriddenMethods(Impl, objcMethod, entries.slice(i + 1)))
        continue;
  
      // Okay, the method wasn't suppressed, import it.
  
      // When mirroring an initializer, make it designated and required.
      if (isInitMethod(objcMethod)) {
        // Import the constructor.
        if (auto imported = importConstructor(objcMethod, dc, /*implicit=*/true,
                                              CtorInitializerKind::Designated,
                                              /*required=*/true)) {
          members.push_back(imported);
        }
        continue;
      }
  
      // Import the method.
      auto proto = entries[i].second;
      if (auto imported =
              Impl.importMirroredDecl(objcMethod, dc, getVersion(), proto)) {
        members.push_back(imported);
  
        for (auto alternate : Impl.getAlternateDecls(imported))
          if (imported->getDeclContext() == alternate->getDeclContext())
            members.push_back(alternate);
      }
    }
  }
  
  void SwiftDeclConverter::importInheritedConstructors(
      ClassDecl *classDecl, SmallVectorImpl<Decl *> &newMembers) {
    if (!classDecl->hasSuperclass())
      return;
  
    auto curObjCClass = cast<clang::ObjCInterfaceDecl>(classDecl->getClangDecl());
  
    auto inheritConstructors = [&](ArrayRef<ValueDecl *> members,
                                   Optional<CtorInitializerKind> kind) {
      const auto &languageVersion =
          Impl.SwiftContext.LangOpts.EffectiveLanguageVersion;
  
      for (auto member : members) {
        auto ctor = dyn_cast<ConstructorDecl>(member);
        if (!ctor)
          continue;
  
        // Don't inherit compatibility stubs.
        if (ctor->getAttrs().isUnavailableInSwiftVersion(languageVersion))
          continue;
  
        // Don't inherit (non-convenience) factory initializers.
        // Note that convenience factories return instancetype and can be
        // inherited.
        switch (ctor->getInitKind()) {
        case CtorInitializerKind::Factory:
          continue;
        case CtorInitializerKind::ConvenienceFactory:
        case CtorInitializerKind::Convenience:
        case CtorInitializerKind::Designated:
          break;
        }
  
        auto objcMethod =
            dyn_cast_or_null<clang::ObjCMethodDecl>(ctor->getClangDecl());
        if (!objcMethod)
          continue;
  
        auto &clangSourceMgr = Impl.getClangASTContext().getSourceManager();
        clang::PrettyStackTraceDecl trace(objcMethod, clang::SourceLocation(),
                                          clangSourceMgr,
                                          "importing (inherited)");
  
        // If this initializer came from a factory method, inherit
        // it as an initializer.
        if (objcMethod->isClassMethod()) {
          assert(ctor->getInitKind() == CtorInitializerKind::ConvenienceFactory);
  
          Optional<ImportedName> correctSwiftName;
          ImportedName importedName =
              importFullName(objcMethod, correctSwiftName);
          assert(
              !correctSwiftName &&
              "Import inherited initializers never references correctSwiftName");
          importedName.setHasCustomName();
          bool redundant;
          if (auto newCtor =
                  importConstructor(objcMethod, classDecl,
                                    /*implicit=*/true, ctor->getInitKind(),
                                    /*required=*/false, ctor->getObjCSelector(),
                                    importedName, objcMethod->parameters(),
                                    objcMethod->isVariadic(), redundant)) {
            // If this is a compatibility stub, mark it as such.
            if (correctSwiftName)
              markAsVariant(newCtor, *correctSwiftName);
  
            Impl.importAttributes(objcMethod, newCtor, curObjCClass);
            newMembers.push_back(newCtor);
          }
          continue;
        }
  
        // Figure out what kind of constructor this will be.
        CtorInitializerKind myKind;
        bool isRequired = false;
        if (ctor->isRequired()) {
          // Required initializers are always considered designated.
          isRequired = true;
          myKind = CtorInitializerKind::Designated;
        } else if (kind) {
          myKind = *kind;
        } else {
          myKind = ctor->getInitKind();
        }
  
        // Import the constructor into this context.
        if (auto newCtor =
                importConstructor(objcMethod, classDecl,
                                  /*implicit=*/true, myKind, isRequired)) {
          Impl.importAttributes(objcMethod, newCtor, curObjCClass);
          newMembers.push_back(newCtor);
        }
      }
    };
  
    // The kind of initializer to import. If this class has designated
    // initializers, everything it imports is a convenience initializer.
    Optional<CtorInitializerKind> kind;
    if (hasDesignatedInitializers(curObjCClass))
      kind = CtorInitializerKind::Convenience;
  
    auto superclass =
        cast<ClassDecl>(classDecl->getSuperclass()->getAnyNominal());
  
    // If we have a superclass, import from it.
    if (auto superclassClangDecl = superclass->getClangDecl()) {
      if (isa<clang::ObjCInterfaceDecl>(superclassClangDecl)) {
        inheritConstructors(superclass->lookupDirect(Impl.SwiftContext.Id_init),
                            kind);
      }
    }
  }
  
  Decl *ClangImporter::Implementation::importDeclCached(
      const clang::NamedDecl *ClangDecl,
      ImportNameVersion version) {
    auto Known = ImportedDecls.find({ClangDecl->getCanonicalDecl(), version});
    if (Known != ImportedDecls.end())
      return Known->second;
  
    return nullptr;
  }
  
  /// Checks if we don't need to import the typedef itself.  If the typedef
  /// should be skipped, returns the underlying declaration that the typedef
  /// refers to -- this declaration should be imported instead.
  static const clang::TagDecl *
  canSkipOverTypedef(ClangImporter::Implementation &Impl,
                     const clang::NamedDecl *D,
                     bool &TypedefIsSuperfluous) {
    // If we have a typedef that refers to a tag type of the same name,
    // skip the typedef and import the tag type directly.
  
    TypedefIsSuperfluous = false;
  
    auto *ClangTypedef = dyn_cast<clang::TypedefNameDecl>(D);
    if (!ClangTypedef)
      return nullptr;
  
    const clang::DeclContext *RedeclContext =
        ClangTypedef->getDeclContext()->getRedeclContext();
    if (!RedeclContext->isTranslationUnit())
      return nullptr;
  
    clang::QualType UnderlyingType = ClangTypedef->getUnderlyingType();
  
    // A typedef to a typedef should get imported as a typealias.
    auto *TypedefT = UnderlyingType->getAs<clang::TypedefType>();
    if (TypedefT)
      return nullptr;
  
    auto *TT = UnderlyingType->getAs<clang::TagType>();
    if (!TT)
      return nullptr;
  
    clang::TagDecl *UnderlyingDecl = TT->getDecl();
    if (UnderlyingDecl->getDeclContext()->getRedeclContext() != RedeclContext)
      return nullptr;
  
    if (UnderlyingDecl->getDeclName().isEmpty())
      return UnderlyingDecl;
  
    auto TypedefName = ClangTypedef->getDeclName();
    auto TagDeclName = UnderlyingDecl->getDeclName();
    if (TypedefName != TagDeclName)
      return nullptr;
  
    TypedefIsSuperfluous = true;
    return UnderlyingDecl;
  }
  
  StringRef ClangImporter::Implementation::
  getSwiftNameFromClangName(StringRef replacement) {
    auto &clangSema = getClangSema();
  
    clang::IdentifierInfo *identifier =
        &clangSema.getASTContext().Idents.get(replacement);
    clang::LookupResult lookupResult(clangSema, identifier,
                                     clang::SourceLocation(),
                                     clang::Sema::LookupOrdinaryName);
    if (!clangSema.LookupName(lookupResult, nullptr))
      return "";
  
    auto clangDecl = lookupResult.getAsSingle<clang::NamedDecl>();
    if (!clangDecl)
      return "";
  
    auto importedName = importFullName(clangDecl, CurrentVersion);
    if (!importedName)
      return "";
  
    llvm::SmallString<64> renamed;
    {
      // Render a swift_name string.
      llvm::raw_svector_ostream os(renamed);
      printSwiftName(importedName, CurrentVersion, /*fullyQualified=*/true, os);
    }
  
    return SwiftContext.AllocateCopy(StringRef(renamed));
  }
  
  /// Import Clang attributes as Swift attributes.
  void ClangImporter::Implementation::importAttributes(
      const clang::NamedDecl *ClangDecl,
      Decl *MappedDecl,
      const clang::ObjCContainerDecl *NewContext)
  {
    ASTContext &C = SwiftContext;
  
    if (auto maybeDefinition = getDefinitionForClangTypeDecl(ClangDecl))
      if (maybeDefinition.getValue())
        ClangDecl = cast<clang::NamedDecl>(maybeDefinition.getValue());
  
    // Scan through Clang attributes and map them onto Swift
    // equivalents.
    bool AnyUnavailable = MappedDecl->getAttrs().isUnavailable(C);
    for (clang::NamedDecl::attr_iterator AI = ClangDecl->attr_begin(),
         AE = ClangDecl->attr_end(); AI != AE; ++AI) {
      //
      // __attribute__((unavailable))
      //
      // Mapping: @available(*,unavailable)
      //
      if (auto unavailable = dyn_cast<clang::UnavailableAttr>(*AI)) {
        auto Message = unavailable->getMessage();
        auto attr = AvailableAttr::createPlatformAgnostic(C, Message);
        MappedDecl->getAttrs().add(attr);
        AnyUnavailable = true;
        continue;
      }
  
      //
      // __attribute__((annotate(swift1_unavailable)))
      //
      // Mapping: @available(*, unavailable)
      //
      if (auto unavailable_annot = dyn_cast<clang::AnnotateAttr>(*AI))
        if (unavailable_annot->getAnnotation() == "swift1_unavailable") {
          auto attr = AvailableAttr::createPlatformAgnostic(
              C, "", "", PlatformAgnosticAvailabilityKind::UnavailableInSwift);
          MappedDecl->getAttrs().add(attr);
          AnyUnavailable = true;
          continue;
        }
  
      //
      // __attribute__((deprecated))
      //
      // Mapping: @available(*,deprecated)
      //
      if (auto deprecated = dyn_cast<clang::DeprecatedAttr>(*AI)) {
        auto Message = deprecated->getMessage();
        auto attr = AvailableAttr::createPlatformAgnostic(C, Message, "",
                      PlatformAgnosticAvailabilityKind::Deprecated);
        MappedDecl->getAttrs().add(attr);
        continue;
      }
  
      // __attribute__((availability))
      //
      if (auto avail = dyn_cast<clang::AvailabilityAttr>(*AI)) {
        StringRef Platform = avail->getPlatform()->getName();
  
        // Is this our special "availability(swift, unavailable)" attribute?
        if (Platform == "swift") {
          auto replacement = avail->getReplacement();
          StringRef swiftReplacement = "";
          if (!replacement.empty())
            swiftReplacement = getSwiftNameFromClangName(replacement);
  
          auto attr = AvailableAttr::createPlatformAgnostic(
              C, avail->getMessage(), swiftReplacement,
              PlatformAgnosticAvailabilityKind::UnavailableInSwift);
          MappedDecl->getAttrs().add(attr);
          AnyUnavailable = true;
          continue;
        }
  
        // Does this availability attribute map to the platform we are
        // currently targeting?
        if (!platformAvailability.filter ||
            !platformAvailability.filter(Platform))
          continue;
  
        auto platformK =
          llvm::StringSwitch<Optional<PlatformKind>>(Platform)
            .Case("ios", PlatformKind::iOS)
            .Case("macos", PlatformKind::OSX)
            .Case("tvos", PlatformKind::tvOS)
            .Case("watchos", PlatformKind::watchOS)
            .Case("ios_app_extension", PlatformKind::iOSApplicationExtension)
            .Case("macos_app_extension",
                  PlatformKind::OSXApplicationExtension)
            .Case("tvos_app_extension",
                  PlatformKind::tvOSApplicationExtension)
            .Case("watchos_app_extension",
                  PlatformKind::watchOSApplicationExtension)
            .Default(None);
        if (!platformK)
          continue;
  
        // Is this declaration marked platform-agnostically unavailable?
        auto PlatformAgnostic = PlatformAgnosticAvailabilityKind::None;
        if (avail->getUnavailable()) {
          PlatformAgnostic = PlatformAgnosticAvailabilityKind::Unavailable;
          AnyUnavailable = true;
        }
  
        StringRef message = avail->getMessage();
  
        const auto &deprecated = avail->getDeprecated();
        if (!deprecated.empty()) {
          if (platformAvailability.deprecatedAsUnavailableFilter &&
              platformAvailability.deprecatedAsUnavailableFilter(
                  deprecated.getMajor(), deprecated.getMinor())) {
            AnyUnavailable = true;
            PlatformAgnostic = PlatformAgnosticAvailabilityKind::Unavailable;
            if (message.empty())
              message = platformAvailability.deprecatedAsUnavailableMessage;
          }
        }
  
        const auto &obsoleted = avail->getObsoleted();
        const auto &introduced = avail->getIntroduced();
        const auto &replacement = avail->getReplacement();
  
        StringRef swiftReplacement = "";
        if (!replacement.empty())
          swiftReplacement = getSwiftNameFromClangName(replacement);
  
        auto AvAttr = new (C) AvailableAttr(SourceLoc(), SourceRange(),
                                            platformK.getValue(),
                                            message, swiftReplacement,
                                            introduced,
                                            /*IntroducedRange=*/SourceRange(),
                                            deprecated,
                                            /*DeprecatedRange=*/SourceRange(),
                                            obsoleted,
                                            /*ObsoletedRange=*/SourceRange(),
                                            PlatformAgnostic, /*Implicit=*/false);
  
        MappedDecl->getAttrs().add(AvAttr);
  
        // For enum cases introduced in the 2017 SDKs, add
        // @_downgrade_exhaustivity_check in Swift 3.
        if (C.LangOpts.isSwiftVersion3() && isa<EnumElementDecl>(MappedDecl)) {
          bool downgradeExhaustivity = false;
          switch (*platformK) {
          case PlatformKind::OSX:
          case PlatformKind::OSXApplicationExtension:
            downgradeExhaustivity = (introduced.getMajor() == 10 &&
                                     introduced.getMinor() &&
                                     *introduced.getMinor() == 13);
            break;
  
          case PlatformKind::iOS:
          case PlatformKind::iOSApplicationExtension:
          case PlatformKind::tvOS:
          case PlatformKind::tvOSApplicationExtension:
            downgradeExhaustivity = (introduced.getMajor() == 11);
            break;
  
          case PlatformKind::watchOS:
          case PlatformKind::watchOSApplicationExtension:
            downgradeExhaustivity = (introduced.getMajor() == 4);
            break;
  
          case PlatformKind::none:
            break;
          }
  
          if (downgradeExhaustivity) {
            auto attr =
              new (C) DowngradeExhaustivityCheckAttr(/*isImplicit=*/true);
            MappedDecl->getAttrs().add(attr);
          }
        }
      }
    }
  
    // If the declaration is unavailable, we're done.
    if (AnyUnavailable)
      return;
  
    if (auto ID = dyn_cast<clang::ObjCInterfaceDecl>(ClangDecl)) {
      // Ban NSInvocation.
      if (ID->getName() == "NSInvocation") {
        auto attr = AvailableAttr::createPlatformAgnostic(C, "");
        MappedDecl->getAttrs().add(attr);
        return;
      }
  
      // Map Clang's swift_objc_members attribute to @objcMembers. Also handle
      // inheritance of @objcMembers by looking at the superclass.
      if (ID->hasAttr<clang::SwiftObjCMembersAttr>() ||
          (isa<ClassDecl>(MappedDecl) &&
           cast<ClassDecl>(MappedDecl)->hasSuperclass() &&
           cast<ClassDecl>(MappedDecl)->getSuperclassDecl()
             ->getAttrs().hasAttribute<ObjCMembersAttr>())) {
        if (!MappedDecl->getAttrs().hasAttribute<ObjCMembersAttr>()) {
          auto attr = new (C) ObjCMembersAttr(/*IsImplicit=*/true);
          MappedDecl->getAttrs().add(attr);
        }
      }
  
      // Infer @objcMembers on XCTestCase.
      if (ID->getName() == "XCTestCase") {
        if (!MappedDecl->getAttrs().hasAttribute<ObjCMembersAttr>()) {
          auto attr = new (C) ObjCMembersAttr(/*IsImplicit=*/true);
          MappedDecl->getAttrs().add(attr);
        }
      }
    }
  
    // Ban CFRelease|CFRetain|CFAutorelease(CFTypeRef) as well as custom ones
    // such as CGColorRelease(CGColorRef).
    if (auto FD = dyn_cast<clang::FunctionDecl>(ClangDecl)) {
      if (FD->getNumParams() == 1 &&
           (FD->getName().endswith("Release") ||
            FD->getName().endswith("Retain") ||
            FD->getName().endswith("Autorelease")))
        if (auto t = FD->getParamDecl(0)->getType()->getAs<clang::TypedefType>())
          if (isCFTypeDecl(t->getDecl())) {
            auto attr = AvailableAttr::createPlatformAgnostic(C,
              "Core Foundation objects are automatically memory managed");
            MappedDecl->getAttrs().add(attr);
            return;
          }
    }
  
    // Hack: mark any method named "print" with less than two parameters as
    // warn_unqualified_access.
    if (auto MD = dyn_cast<FuncDecl>(MappedDecl)) {
      if (isPrintLikeMethod(MD->getFullName(), MD->getDeclContext())) {
        // Use a non-implicit attribute so it shows up in the generated
        // interface.
        MD->getAttrs().add(new (C) WarnUnqualifiedAccessAttr(/*implicit*/false));
      }
    }
  
    // Map __attribute__((warn_unused_result)).
    if (!ClangDecl->hasAttr<clang::WarnUnusedResultAttr>()) {
      if (auto MD = dyn_cast<FuncDecl>(MappedDecl)) {
        if (!MD->getResultInterfaceType()->isVoid()) {
          MD->getAttrs().add(new (C) DiscardableResultAttr(/*implicit*/true));
        }
      }
    }
    // Map __attribute__((const)).
    if (ClangDecl->hasAttr<clang::ConstAttr>()) {
      MappedDecl->getAttrs().add(new (C) EffectsAttr(EffectsKind::ReadNone));
    }
    // Map __attribute__((pure)).
    if (ClangDecl->hasAttr<clang::PureAttr>()) {
      MappedDecl->getAttrs().add(new (C) EffectsAttr(EffectsKind::ReadOnly));
    }
  }
  
  Decl *
  ClangImporter::Implementation::importDeclImpl(const clang::NamedDecl *ClangDecl,
                                                ImportNameVersion version,
                                                bool &TypedefIsSuperfluous,
                                                bool &HadForwardDeclaration) {
    assert(ClangDecl);
  
    bool SkippedOverTypedef = false;
    Decl *Result = nullptr;
    if (auto *UnderlyingDecl = canSkipOverTypedef(*this, ClangDecl,
                                                  TypedefIsSuperfluous)) {
      Result = importDecl(UnderlyingDecl, version);
      SkippedOverTypedef = true;
    }
  
    if (!Result) {
      SwiftDeclConverter converter(*this, version);
      Result = converter.Visit(ClangDecl);
      HadForwardDeclaration = converter.hadForwardDeclaration();
    }
    if (!Result && version == CurrentVersion) {
      // If we couldn't import this Objective-C entity, determine
      // whether it was a required member of a protocol, or a designated
      // initializer of a class.
      bool hasMissingRequiredMember = false;
      if (auto clangProto
            = dyn_cast<clang::ObjCProtocolDecl>(ClangDecl->getDeclContext())) {
        if (auto method = dyn_cast<clang::ObjCMethodDecl>(ClangDecl)) {
          if (method->getImplementationControl()
                == clang::ObjCMethodDecl::Required)
            hasMissingRequiredMember = true;
        } else if (auto prop = dyn_cast<clang::ObjCPropertyDecl>(ClangDecl)) {
          if (prop->getPropertyImplementation()
                == clang::ObjCPropertyDecl::Required)
            hasMissingRequiredMember = true;
        }
  
        if (hasMissingRequiredMember) {
          // Mark the protocol as having missing requirements.
          if (auto proto = castIgnoringCompatibilityAlias<ProtocolDecl>(
                  importDecl(clangProto, CurrentVersion))) {
            proto->setHasMissingRequirements(true);
          }
        }
      }
      if (auto method = dyn_cast<clang::ObjCMethodDecl>(ClangDecl)) {
        if (!SwiftContext.LangOpts.isSwiftVersion3() &&
            method->isDesignatedInitializerForTheInterface()) {
          const clang::ObjCInterfaceDecl *theClass = method->getClassInterface();
          assert(theClass && "cannot be a protocol method here");
          // Only allow this to affect declarations in the same top-level module
          // as the original class.
          if (getClangModuleForDecl(theClass) == getClangModuleForDecl(method)) {
            if (auto swiftClass = castIgnoringCompatibilityAlias<ClassDecl>(
                    importDecl(theClass, CurrentVersion))) {
              swiftClass->setHasMissingDesignatedInitializers();
            }
          }
        }
      }
  
      return nullptr;
    }
  
    // Finalize the imported declaration.
    auto finalizeDecl = [&](Decl *result) {
      importAttributes(ClangDecl, result);
  
      // Hack to deal with Objective-C protocols without availability annotation.
      // If the protocol comes from clang and is not annotated and the protocol
      // requirement itself is not annotated, then infer availability of the
      // requirement based on its types. This makes it possible for a type to
      // conform to an Objective-C protocol that is missing annotations but whose
      // requirements use types that are less available than the conforming type.
      auto dc = result->getDeclContext();
      auto *proto = dyn_cast<ProtocolDecl>(dc);
      if (!proto || proto->getAttrs().hasAttribute<AvailableAttr>())
        return;
  
      inferProtocolMemberAvailability(*this, dc, result);
    };
  
    if (Result) {
      finalizeDecl(Result);
  
      for (auto alternate : getAlternateDecls(Result))
        finalizeDecl(alternate);
    }
  
  #ifndef NDEBUG
    auto Canon = cast<clang::NamedDecl>(ClangDecl->getCanonicalDecl());
  
    // Note that the decl was imported from Clang.  Don't mark Swift decls as
    // imported.
    if (Result &&
        (!Result->getDeclContext()->isModuleScopeContext() ||
         isa<ClangModuleUnit>(Result->getDeclContext()))) {
      // Either the Swift declaration was from stdlib,
      // or we imported the underlying decl of the typedef,
      // or we imported the decl itself.
      bool ImportedCorrectly =
          !Result->getClangDecl() || SkippedOverTypedef ||
          Result->getClangDecl()->getCanonicalDecl() == Canon;
  
      // Or the other type is a typedef,
      if (!ImportedCorrectly &&
          isa<clang::TypedefNameDecl>(Result->getClangDecl())) {
        // both types are ValueDecls:
        if (isa<clang::ValueDecl>(Result->getClangDecl())) {
          ImportedCorrectly =
              getClangASTContext().hasSameType(
                  cast<clang::ValueDecl>(Result->getClangDecl())->getType(),
                  cast<clang::ValueDecl>(Canon)->getType());
        } else if (isa<clang::TypeDecl>(Result->getClangDecl())) {
          // both types are TypeDecls:
          ImportedCorrectly =
              getClangASTContext().hasSameUnqualifiedType(
                  getClangASTContext().getTypeDeclType(
                      cast<clang::TypeDecl>(Result->getClangDecl())),
                  getClangASTContext().getTypeDeclType(
                      cast<clang::TypeDecl>(Canon)));
        }
        assert(ImportedCorrectly);
      }
      assert(Result->hasClangNode());
    }
  #else
    (void)SkippedOverTypedef;
  #endif
  
    return Result;
  }
  
  void ClangImporter::Implementation::startedImportingEntity() {
    ++NumCurrentImportingEntities;
    ++NumTotalImportedEntities;
    // FIXME: (transitional) increment the redundant "always-on" counter.
    if (SwiftContext.Stats)
      SwiftContext.Stats->getFrontendCounters().NumTotalClangImportedEntities++;
  }
  
  void ClangImporter::Implementation::finishedImportingEntity() {
    assert(NumCurrentImportingEntities &&
           "finishedImportingEntity not paired with startedImportingEntity");
    if (NumCurrentImportingEntities == 1) {
      // We decrease NumCurrentImportingEntities only after pending actions
      // are finished, to avoid recursively re-calling finishPendingActions().
      finishPendingActions();
    }
    --NumCurrentImportingEntities;
  }
  
  void ClangImporter::Implementation::finishPendingActions() {
    while (true) {
      // The odd shape of this loop comes from previously having more than one
      // possible kind of pending action. It's left this way to make it easy to
      // add another one back in an `else if` clause.
      if (!RegisteredExternalDecls.empty()) {
        if (hasFinishedTypeChecking()) {
          RegisteredExternalDecls.clear();
        } else {
          Decl *D = RegisteredExternalDecls.pop_back_val();
          SwiftContext.addExternalDecl(D);
          if (auto typeResolver = getTypeResolver())
            if (auto *nominal = dyn_cast<NominalTypeDecl>(D))
              if (!nominal->hasDelayedMembers())
                typeResolver->resolveExternalDeclImplicitMembers(nominal);
        }
      } else {
        break;
      }
    }
  }
  
  /// Look up associated type requirements in the conforming type.
  static void finishTypeWitnesses(
      NormalProtocolConformance *conformance) {
    auto *dc = conformance->getDeclContext();
    auto *module = dc->getParentModule();
    auto &ctx = module->getASTContext();
  
    auto *proto = conformance->getProtocol();
    auto selfType = conformance->getType();
  
    for (auto *req : proto->getMembers()) {
      if (auto *assocType = dyn_cast<AssociatedTypeDecl>(req)) {
        // FIXME: This should not happen?
        if (conformance->hasTypeWitness(assocType)) continue;
  
        bool satisfied = false;
  
        SmallVector<ValueDecl *, 4> lookupResults;
        NLOptions options = (NL_QualifiedDefault |
                             NL_OnlyTypes |
                             NL_ProtocolMembers);
  
        dc->lookupQualified(selfType, assocType->getFullName(), options,
                            ctx.getLazyResolver(), lookupResults);
        for (auto member : lookupResults) {
          auto typeDecl = cast<TypeDecl>(member);
          if (isa<AssociatedTypeDecl>(typeDecl)) continue;
  
          auto memberType = typeDecl->getDeclaredInterfaceType();
          auto subMap = selfType->getContextSubstitutionMap(
              module, typeDecl->getDeclContext());
          memberType = memberType.subst(subMap);
          conformance->setTypeWitness(assocType, memberType, typeDecl);
          satisfied = true;
          break;
        }
  
        if (!satisfied) {
          llvm::errs() << ("Cannot look up associated type for "
                           "imported conformance:\n");
          conformance->getType().dump(llvm::errs());
          assocType->dump(llvm::errs());
          abort();
        }
      }
    }
  }
  
  /// Make sure any inherited conformances also get completed, if necessary.
  static void finishInheritedConformances(
      NormalProtocolConformance *conformance) {
    auto *proto = conformance->getProtocol();
  
    SmallVector<ProtocolDecl *, 2> inheritedProtos;
    for (auto *inherited : proto->getInheritedProtocols())
      inheritedProtos.push_back(inherited);
  
    // Sort for deterministic import.
    ProtocolType::canonicalizeProtocols(inheritedProtos);
  
    // Schedule any that aren't complete.
    for (auto *inherited : inheritedProtos) {
      ModuleDecl *M = conformance->getDeclContext()->getParentModule();
      auto inheritedConformance = M->lookupConformance(conformance->getType(),
                                                       inherited);
      assert(inheritedConformance && inheritedConformance->isConcrete() &&
             "inherited conformance not found");
    }
  }
  
  /// Collect conformances for the requirement signature.
  static void finishSignatureConformances(
      NormalProtocolConformance *conformance) {
    auto *proto = conformance->getProtocol();
  
    SmallVector<ProtocolConformanceRef, 4> reqConformances;
    for (const auto &req : proto->getRequirementSignature()) {
      if (req.getKind() != RequirementKind::Conformance)
        continue;
  
      Type substTy;
      auto origTy = req.getFirstType();
      if (origTy->isEqual(proto->getSelfInterfaceType())) {
        substTy = conformance->getType();
      } else {
        auto *depMemTy = origTy->castTo<DependentMemberType>();
        assert(depMemTy->getBase()->isEqual(proto->getSelfInterfaceType()));
        substTy = conformance->getTypeWitness(depMemTy->getAssocType(),
                                              /*resolver=*/nullptr);
      }
      auto reqProto = req.getSecondType()->castTo<ProtocolType>()->getDecl();
  
      ModuleDecl *M = conformance->getDeclContext()->getParentModule();
      auto reqConformance = M->lookupConformance(substTy, reqProto);
      assert(reqConformance && reqConformance->isConcrete() &&
             "required conformance not found");
      reqConformances.push_back(*reqConformance);
    }
    conformance->setSignatureConformances(reqConformances);
  }
  
  /// Create witnesses for requirements not already met.
  static void finishMissingOptionalWitnesses(
      NormalProtocolConformance *conformance) {
    auto *proto = conformance->getProtocol();
  
    for (auto req : proto->getMembers()) {
      auto valueReq = dyn_cast<ValueDecl>(req);
      if (!valueReq)
        continue;
  
      if (!conformance->hasWitness(valueReq)) {
        if (auto func = dyn_cast<AbstractFunctionDecl>(valueReq)){
          // For an optional requirement, record an empty witness:
          // we'll end up querying this at runtime.
          auto Attrs = func->getAttrs();
          if (Attrs.hasAttribute<OptionalAttr>()) {
            conformance->setWitness(valueReq, Witness());
            continue;
          }
        }
  
        conformance->setWitness(valueReq, valueReq);
      } else {
        // An initializer that conforms to a requirement is required.
        auto witness = conformance->getWitness(valueReq, nullptr).getDecl();
        if (auto ctor = dyn_cast_or_null<ConstructorDecl>(witness)) {
          if (!ctor->getAttrs().hasAttribute<RequiredAttr>()) {
            auto &ctx = proto->getASTContext();
            ctor->getAttrs().add(new (ctx) RequiredAttr(/*IsImplicit=*/true));
          }
        }
      }
    }
  }
  
  void ClangImporter::Implementation::finishNormalConformance(
      NormalProtocolConformance *conformance,
      uint64_t unused) {
    (void)unused;
  
    auto *proto = conformance->getProtocol();
    PrettyStackTraceType trace(SwiftContext, "completing conformance for",
                               conformance->getType());
    PrettyStackTraceDecl traceTo("... to", proto);
  
    if (!proto->isRequirementSignatureComputed())
      proto->computeRequirementSignature();
  
    finishTypeWitnesses(conformance);
    finishInheritedConformances(conformance);
    finishSignatureConformances(conformance);
  
    // Imported conformances to @objc protocols also require additional
    // initialization to complete the requirement to witness mapping.
    if (!proto->isObjC())
      return;
  
    assert(conformance->isComplete());
    conformance->setState(ProtocolConformanceState::Incomplete);
  
    finishMissingOptionalWitnesses(conformance);
  
    conformance->setState(ProtocolConformanceState::Complete);
  }
  
  Decl *ClangImporter::Implementation::importDeclAndCacheImpl(
      const clang::NamedDecl *ClangDecl,
      ImportNameVersion version,
      bool SuperfluousTypedefsAreTransparent) {
    if (!ClangDecl)
      return nullptr;
  
    clang::PrettyStackTraceDecl trace(ClangDecl, clang::SourceLocation(),
                                      Instance->getSourceManager(), "importing");
  
    auto Canon = cast<clang::NamedDecl>(ClangDecl->getCanonicalDecl());
  
    if (auto Known = importDeclCached(Canon, version)) {
      if (!SuperfluousTypedefsAreTransparent &&
          SuperfluousTypedefs.count(Canon))
        return nullptr;
      return Known;
    }
  
    bool TypedefIsSuperfluous = false;
    bool HadForwardDeclaration = false;
  
    ImportingEntityRAII ImportingEntity(*this);
    Decl *Result = importDeclImpl(ClangDecl, version, TypedefIsSuperfluous,
                                  HadForwardDeclaration);
    if (!Result)
      return nullptr;
  
    if (TypedefIsSuperfluous) {
      SuperfluousTypedefs.insert(Canon);
      if (auto tagDecl = dyn_cast_or_null<clang::TagDecl>(Result->getClangDecl()))
        DeclsWithSuperfluousTypedefs.insert(tagDecl);
    }
  
    if (!HadForwardDeclaration)
      ImportedDecls[{Canon, version}] = Result;
  
    if (!SuperfluousTypedefsAreTransparent && TypedefIsSuperfluous)
      return nullptr;
  
    return Result;
  }
  
  Decl *
  ClangImporter::Implementation::importMirroredDecl(const clang::NamedDecl *decl,
                                                    DeclContext *dc,
                                                    ImportNameVersion version,
                                                    ProtocolDecl *proto) {
    assert(dc);
    if (!decl)
      return nullptr;
  
    clang::PrettyStackTraceDecl trace(decl, clang::SourceLocation(),
                                      Instance->getSourceManager(),
                                      "importing (mirrored)");
  
    auto canon = decl->getCanonicalDecl();
    auto known = ImportedProtocolDecls.find(std::make_tuple(canon, dc, version));
    if (known != ImportedProtocolDecls.end())
      return known->second;
  
    SwiftDeclConverter converter(*this, version);
    Decl *result;
    if (auto method = dyn_cast<clang::ObjCMethodDecl>(decl)) {
      result = converter.importObjCMethodDecl(method, dc);
    } else if (auto prop = dyn_cast<clang::ObjCPropertyDecl>(decl)) {
      result = converter.importObjCPropertyDecl(prop, dc);
    } else {
      llvm_unreachable("unexpected mirrored decl");
    }
  
    if (result) {
      assert(result->getClangDecl() && result->getClangDecl() == canon);
  
      auto updateMirroredDecl = [&](Decl *result) {
        result->setImplicit();
      
        // Map the Clang attributes onto Swift attributes.
        importAttributes(decl, result);
  
        if (proto->getAttrs().hasAttribute<AvailableAttr>()) {
          if (!result->getAttrs().hasAttribute<AvailableAttr>()) {
            AvailabilityContext protoRange =
              AvailabilityInference::availableRange(proto, SwiftContext);
            applyAvailableAttribute(result, protoRange, SwiftContext);
          }
        } else {
          // Infer the same availability for the mirrored declaration as
          // we would for the protocol member it is mirroring.
          inferProtocolMemberAvailability(*this, dc, result);
        }
      };
  
      updateMirroredDecl(result);
  
      // Update the alternate declaration as well.
      for (auto alternate : getAlternateDecls(result))
        updateMirroredDecl(alternate);
    }
    if (result || !converter.hadForwardDeclaration())
      ImportedProtocolDecls[std::make_tuple(canon, dc, version)] = result;
    return result;
  }
  
  DeclContext *ClangImporter::Implementation::importDeclContextImpl(
      const clang::DeclContext *dc) {
    // Every declaration should come from a module, so we should not see the
    // TranslationUnit DeclContext here.
    assert(!dc->isTranslationUnit());
  
    auto decl = dyn_cast<clang::NamedDecl>(dc);
    if (!decl)
      return nullptr;
  
    auto swiftDecl = importDecl(decl, CurrentVersion);
    if (!swiftDecl)
      return nullptr;
  
    if (auto nominal = dynCastIgnoringCompatibilityAlias<NominalTypeDecl>(swiftDecl))
      return nominal;
    if (auto extension = dyn_cast<ExtensionDecl>(swiftDecl))
      return extension;
    if (auto constructor = dyn_cast<ConstructorDecl>(swiftDecl))
      return constructor;
    if (auto destructor = dyn_cast<DestructorDecl>(swiftDecl))
      return destructor;
    return nullptr;
  }
  
  GenericSignature *ClangImporter::Implementation::buildGenericSignature(
      GenericParamList *genericParams, DeclContext *dc) {
    GenericSignatureBuilder builder(SwiftContext);
    SmallVector<GenericTypeParamType *, 4> allGenericParams;
    for (auto param : *genericParams) {
      builder.addGenericParameter(param);
      allGenericParams.push_back(
        param->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
    }
    for (auto param : *genericParams) {
      bool result = builder.addGenericParameterRequirements(param);
      assert(!result);
      (void) result;
    }
  
    return std::move(builder).computeGenericSignature(SourceLoc());
  }
  
  // Calculate the generic environment from an imported generic param list.
  GenericEnvironment *ClangImporter::Implementation::buildGenericEnvironment(
      GenericParamList *genericParams, DeclContext *dc) {
    return buildGenericSignature(genericParams, dc)->createGenericEnvironment();
  }
  
  DeclContext *
  ClangImporter::Implementation::importDeclContextOf(
    const clang::Decl *decl,
    EffectiveClangContext context)
  {
    DeclContext *importedDC = nullptr;
    switch (context.getKind()) {
    case EffectiveClangContext::DeclContext: {
      auto dc = context.getAsDeclContext();
      if (dc->isTranslationUnit()) {
        if (auto *module = getClangModuleForDecl(decl))
          return module;
        else
          return nullptr;
      }
  
      // Import the DeclContext.
      importedDC = importDeclContextImpl(dc);
      break;
    }
  
    case EffectiveClangContext::TypedefContext: {
      // Import the typedef-name as a declaration.
      auto importedDecl = importDecl(context.getTypedefName(), CurrentVersion);
      if (!importedDecl) return nullptr;
  
      // Dig out the imported DeclContext.
      importedDC = dynCastIgnoringCompatibilityAlias<NominalTypeDecl>(importedDecl);
      break;
    }
  
    case EffectiveClangContext::UnresolvedContext: {
      // FIXME: Resolve through name lookup. This is brittle.
      auto submodule =
        getClangSubmoduleForDecl(decl, /*allowForwardDeclaration=*/false);
      if (!submodule) return nullptr;
  
      if (auto lookupTable = findLookupTable(*submodule)) {
        if (auto clangDecl
              = lookupTable->resolveContext(context.getUnresolvedName())) {
          // Import the Clang declaration.
          auto decl = importDecl(clangDecl, CurrentVersion);
          if (!decl) return nullptr;
  
          // Look through typealiases.
          if (auto typealias = dyn_cast<TypeAliasDecl>(decl))
            importedDC = typealias->getDeclaredInterfaceType()->getAnyNominal();
          else // Map to a nominal type declaration.
            importedDC = dyn_cast<NominalTypeDecl>(decl);
          break;
        }
      }
    }
    }
  
    // If we didn't manage to import the declaration context, we're done.
    if (!importedDC) return nullptr;
  
    // If the declaration was not global to start with, we're done.
    bool isGlobal =
      decl->getDeclContext()->getRedeclContext()->isTranslationUnit();
    if (!isGlobal) return importedDC;
  
    // If the resulting declaration context is not a nominal type,
    // we're done.
    auto nominal = dyn_cast<NominalTypeDecl>(importedDC);
    if (!nominal) return importedDC;
  
    // Look for the extension for the given nominal type within the
    // Clang submodule of the declaration.
    const clang::Module *declSubmodule = *getClangSubmoduleForDecl(decl);
    auto extensionKey = std::make_pair(nominal, declSubmodule);
    auto knownExtension = extensionPoints.find(extensionKey);
    if (knownExtension != extensionPoints.end())
      return knownExtension->second;
  
    // Create a new extension for this nominal type/Clang submodule pair.
    auto swiftTyLoc = TypeLoc::withoutLoc(nominal->getDeclaredType());
    auto ext = ExtensionDecl::create(SwiftContext, SourceLoc(), swiftTyLoc, {},
                                     getClangModuleForDecl(decl), nullptr);
    ext->setValidationStarted();
    ext->setCheckedInheritanceClause();
    ext->setMemberLoader(this, reinterpret_cast<uintptr_t>(declSubmodule));
  
    if (auto protoDecl = ext->getAsProtocolExtensionContext()) {
      ext->setGenericParams(protoDecl->createGenericParams(ext));
  
      auto *env = buildGenericEnvironment(ext->getGenericParams(), ext);
      ext->setGenericEnvironment(env);
    }
  
    // Add the extension to the nominal type.
    nominal->addExtension(ext);
  
    // Record this extension so we can find it later.
    extensionPoints[extensionKey] = ext;
    return ext;
  }
  
  ValueDecl *
  ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
                                                Type type,
                                                const clang::APValue &value,
                                                ConstantConvertKind convertKind,
                                                bool isStatic,
                                                ClangNode ClangN) {
    auto &context = SwiftContext;
  
    // Create the integer literal value.
    Expr *expr = nullptr;
    switch (value.getKind()) {
    case clang::APValue::AddrLabelDiff:
    case clang::APValue::Array:
    case clang::APValue::ComplexFloat:
    case clang::APValue::ComplexInt:
    case clang::APValue::LValue:
    case clang::APValue::MemberPointer:
    case clang::APValue::Struct:
    case clang::APValue::Uninitialized:
    case clang::APValue::Union:
    case clang::APValue::Vector:
      llvm_unreachable("Unhandled APValue kind");
  
    case clang::APValue::Float:
    case clang::APValue::Int: {
      // Print the value.
      llvm::SmallString<16> printedValueBuf;
      if (value.getKind() == clang::APValue::Int) {
        value.getInt().toString(printedValueBuf);
      } else {
        assert(value.getFloat().isFinite() && "can't handle infinities or NaNs");
        value.getFloat().toString(printedValueBuf);
      }
      StringRef printedValue = printedValueBuf.str();
  
      // If this was a negative number, record that and strip off the '-'.
      bool isNegative = printedValue.front() == '-';
      if (isNegative)
        printedValue = printedValue.drop_front();
  
      // Create the expression node.
      StringRef printedValueCopy(context.AllocateCopy(printedValue));
      if (value.getKind() == clang::APValue::Int) {
        if (type->getCanonicalType()->isBool()) {
          expr = new (context) BooleanLiteralExpr(value.getInt().getBoolValue(),
                                                  SourceLoc(),
                                                  /**Implicit=*/true);
        } else {
          expr = new (context) IntegerLiteralExpr(printedValueCopy, SourceLoc(),
                                                  /*Implicit=*/true);
        }
      } else {
        expr = new (context) FloatLiteralExpr(printedValueCopy, SourceLoc(),
                                              /*Implicit=*/true);
      }
  
      if (isNegative)
        cast<NumberLiteralExpr>(expr)->setNegative(SourceLoc());
  
      break;
    }
    }
  
    assert(expr);
    return createConstant(name, dc, type, expr, convertKind, isStatic, ClangN);
  }
  
  
  ValueDecl *
  ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
                                                Type type, StringRef value,
                                                ConstantConvertKind convertKind,
                                                bool isStatic,
                                                ClangNode ClangN) {
    auto expr = new (SwiftContext) StringLiteralExpr(value, SourceRange());
    return createConstant(name, dc, type, expr, convertKind, isStatic, ClangN);
  }
  
  
  ValueDecl *
  ClangImporter::Implementation::createConstant(Identifier name, DeclContext *dc,
                                                Type type, Expr *valueExpr,
                                                ConstantConvertKind convertKind,
                                                bool isStatic,
                                                ClangNode ClangN) {
    auto &C = SwiftContext;
  
    VarDecl *var = nullptr;
    if (ClangN) {
      var = createDeclWithClangNode<VarDecl>(ClangN, AccessLevel::Public,
                                             /*IsStatic*/isStatic, VarDecl::Specifier::Var,
                                             /*IsCaptureList*/false, SourceLoc(),
                                             name, dc->mapTypeIntoContext(type), dc);
    } else {
      var = new (SwiftContext)
          VarDecl(/*IsStatic*/isStatic, VarDecl::Specifier::Var, /*IsCaptureList*/false,
                  SourceLoc(), name, dc->mapTypeIntoContext(type), dc);
      var->setValidationStarted();
    }
  
    var->setInterfaceType(type);
  
    // Form the argument patterns.
    SmallVector<ParameterList*, 3> getterArgs;
    
    // 'self'
    if (dc->isTypeContext()) {
      auto *selfDecl = ParamDecl::createSelf(SourceLoc(), dc, isStatic);
      getterArgs.push_back(ParameterList::createWithoutLoc(selfDecl));
    }
    
    // empty tuple
    getterArgs.push_back(ParameterList::createEmpty(C));
  
    // Form the type of the getter.
    auto getterType = ParameterList::getFullInterfaceType(type, getterArgs, C);
  
    // Create the getter function declaration.
    auto func =
      FuncDecl::create(C, /*StaticLoc=*/SourceLoc(), StaticSpellingKind::None,
                       /*FuncLoc=*/SourceLoc(),
                       /*Name=*/Identifier(), /*NameLoc=*/SourceLoc(),
                       /*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
                       /*AccessorKeywordLoc=*/SourceLoc(),
                       /*GenericParams=*/nullptr, getterArgs,
                       TypeLoc::withoutLoc(type), dc);
    func->setStatic(isStatic);
    func->setInterfaceType(getterType);
    func->setAccess(getOverridableAccessLevel(dc));
    func->setValidationStarted();
    func->setImplicit();
  
    // If we're not done type checking, build the getter body.
    if (!hasFinishedTypeChecking()) {
      auto expr = valueExpr;
  
      // If we need a conversion, add one now.
      switch (convertKind) {
      case ConstantConvertKind::None:
        break;
  
      case ConstantConvertKind::Construction:
      case ConstantConvertKind::ConstructionWithUnwrap: {
        auto typeRef = TypeExpr::createImplicit(type, C);
        
        expr = CallExpr::createImplicit(C, typeRef, { expr }, { C.Id_rawValue });
        if (convertKind == ConstantConvertKind::ConstructionWithUnwrap)
          expr = new (C) ForceValueExpr(expr, SourceLoc());
        break;
      }
  
      case ConstantConvertKind::Coerce:
        break;
  
      case ConstantConvertKind::Downcast: {
        expr = new (C) ForcedCheckedCastExpr(expr, SourceLoc(), SourceLoc(),
                                             TypeLoc::withoutLoc(type));
        expr->setImplicit();
        break;
      }
      }
  
      // Create the return statement.
      auto ret = new (C) ReturnStmt(SourceLoc(), expr);
  
      // Finally, set the body.
      func->setBody(BraceStmt::create(C, SourceLoc(),
                                      ASTNode(ret),
                                      SourceLoc()));
    }
  
    // Mark the function transparent so that we inline it away completely.
    func->getAttrs().add(new (C) TransparentAttr(/*implicit*/ true));
    
    // Set the function up as the getter.
    var->makeComputed(SourceLoc(), func, nullptr, nullptr, SourceLoc());
  
    // Register this thunk as an external definition.
    registerExternalDecl(func);
  
    return var;
  }
  
  /// \brief Create a decl with error type and an "unavailable" attribute on it
  /// with the specified message.
  void ClangImporter::Implementation::
  markUnavailable(ValueDecl *decl, StringRef unavailabilityMsgRef) {
  
    unavailabilityMsgRef = SwiftContext.AllocateCopy(unavailabilityMsgRef);
    auto ua = AvailableAttr::createPlatformAgnostic(SwiftContext,
                                                    unavailabilityMsgRef);
    decl->getAttrs().add(ua);
  }
  
  /// \brief Create a decl with error type and an "unavailable" attribute on it
  /// with the specified message.
  ValueDecl *ClangImporter::Implementation::
  createUnavailableDecl(Identifier name, DeclContext *dc, Type type,
                        StringRef UnavailableMessage, bool isStatic,
                        ClangNode ClangN) {
  
    // Create a new VarDecl with dummy type.
    auto var = createDeclWithClangNode<VarDecl>(ClangN, AccessLevel::Public,
                                                /*IsStatic*/isStatic,
                                                VarDecl::Specifier::Var,
                                                /*IsCaptureList*/false,
                                                SourceLoc(), name, type, dc);
    var->setInterfaceType(type);
    markUnavailable(var, UnavailableMessage);
  
    return var;
  }
  
  
  void
  ClangImporter::Implementation::loadAllMembers(Decl *D, uint64_t extra) {
    RecursiveSharedTimer::Guard guard;
    if (auto s = D->getASTContext().Stats) {
      guard = s->getFrontendRecursiveSharedTimers()
                  .ClangImporter__Implementation__loadAllMembers.getGuard();
    }
  
    assert(D);
  
    // Check whether we're importing an Objective-C container of some sort.
    auto objcContainer =
      dyn_cast_or_null<clang::ObjCContainerDecl>(D->getClangDecl());
  
    // If not, we're importing globals-as-members into an extension.
    if (objcContainer) {
      loadAllMembersOfObjcContainer(D, objcContainer);
      return;
    }
    loadAllMembersIntoExtension(D, extra);
  }
  
  void ClangImporter::Implementation::loadAllMembersIntoExtension(
      Decl *D, uint64_t extra) {
    // We have extension.
    auto ext = cast<ExtensionDecl>(D);
    auto nominal = ext->getExtendedType()->getAnyNominal();
  
    // The submodule of the extension is encoded in the extra data.
    clang::Module *submodule =
        reinterpret_cast<clang::Module *>(static_cast<uintptr_t>(extra));
  
    // Find the lookup table.
    auto topLevelModule = submodule;
    if (topLevelModule)
      topLevelModule = topLevelModule->getTopLevelModule();
    auto table = findLookupTable(topLevelModule);
    if (!table)
      return;
  
    PrettyStackTraceStringAction trace(
        "loading import-as-members from",
        topLevelModule ? topLevelModule->getTopLevelModuleName()
                       : "(bridging header)");
    PrettyStackTraceDecl trace2("...for", nominal);
  
    // Dig out the effective Clang context for this nominal type.
    auto effectiveClangContext = getEffectiveClangContext(nominal);
    if (!effectiveClangContext)
      return;
  
    // Get ready to actually load the members.
    ImportingEntityRAII Importing(*this);
  
    // Load the members.
    for (auto entry : table->lookupGlobalsAsMembers(effectiveClangContext)) {
      auto decl = entry.get<clang::NamedDecl *>();
  
      // Only include members in the same submodule as this extension.
      if (getClangSubmoduleForDecl(decl) != submodule)
        continue;
  
      forEachDistinctName(
          decl, [&](ImportedName newName, ImportNameVersion nameVersion) -> bool {
        return addMemberAndAlternatesToExtension(decl, newName, nameVersion, ext);
      });
    }
  }
  
  static Decl *findMemberThatWillLandInAnExtensionContext(Decl *member) {
    Decl *result = member;
    while (!isa<ExtensionDecl>(result->getDeclContext())) {
      auto nominal = dyn_cast<NominalTypeDecl>(result->getDeclContext());
      if (!nominal)
        return nullptr;
  
      result = nominal;
      if (result->hasClangNode())
        return nullptr;
    }
    return result;
  }
  
  bool ClangImporter::Implementation::addMemberAndAlternatesToExtension(
      clang::NamedDecl *decl, ImportedName newName, ImportNameVersion nameVersion,
      ExtensionDecl *ext) {
    // Quickly check the context and bail out if it obviously doesn't
    // belong here.
    if (auto *importDC = newName.getEffectiveContext().getAsDeclContext())
      if (importDC->isTranslationUnit())
        return true;
  
    // Then try to import the decl under the specified name.
    auto *member = importDecl(decl, nameVersion);
    if (!member)
      return false;
  
    member = findMemberThatWillLandInAnExtensionContext(member);
    if (!member || member->getDeclContext() != ext)
      return true;
    ext->addMember(member);
  
    for (auto alternate : getAlternateDecls(member)) {
      if (alternate->getDeclContext() == ext)
        ext->addMember(alternate);
    }
    return true;
  }
  
  static ExtensionDecl *
  figureOutTheDeclarationContextToImportInto(Decl *D, DeclContext *&DC,
                                             IterableDeclContext *&IDC) {
    if (auto *nominal = dyn_cast<NominalTypeDecl>(D)) {
      DC = nominal;
      IDC = nominal;
      return nullptr;
    }
    ExtensionDecl *ext = cast<ExtensionDecl>(D);
    DC = ext;
    IDC = ext;
    return ext;
  }
  
  static void loadMembersOfBaseImportedFromClang(ExtensionDecl *ext) {
    const NominalTypeDecl *base = ext->getExtendedType()->getAnyNominal();
    auto *clangBase = base->getClangDecl();
    if (!clangBase)
      return;
    base->loadAllMembers();
  
    // Sanity check: make sure we don't jump over to a category /while/
    // loading the original class's members. Right now we only check if this
    // happens on the first member.
    if (auto *clangContainer = dyn_cast<clang::ObjCContainerDecl>(clangBase))
      assert((clangContainer->decls_empty() || !base->getMembers().empty()) &&
             "can't load extension members before base has finished");
  }
  
  void ClangImporter::Implementation::loadAllMembersOfObjcContainer(
      Decl *D, const clang::ObjCContainerDecl *objcContainer) {
    clang::PrettyStackTraceDecl trace(objcContainer, clang::SourceLocation(),
                                      Instance->getSourceManager(),
                                      "loading members for");
  
    DeclContext *DC;
    IterableDeclContext *IDC;
    if (ExtensionDecl *ext =
            figureOutTheDeclarationContextToImportInto(D, DC, IDC)) {
      // If the base is also imported from Clang, load its members first.
      loadMembersOfBaseImportedFromClang(ext);
    }
  
    ImportingEntityRAII Importing(*this);
  
    SmallVector<Decl *, 16> members;
    collectMembersToAdd(objcContainer, D, DC, members);
  
    // Add the members now, before ~ImportingEntityRAII does work that might
    // involve them.
    for (auto member : members) {
      IDC->addMember(member);
    }
  }
  
  void ClangImporter::Implementation::insertMembersAndAlternates(
      const clang::NamedDecl *nd, SmallVectorImpl<Decl *> &members) {
    llvm::SmallPtrSet<Decl *, 4> knownAlternateMembers;
    forEachDistinctName(
        nd, [&](ImportedName name, ImportNameVersion nameVersion) -> bool {
      auto member = importDecl(nd, nameVersion);
      if (!member)
        return false;
  
      // If there are alternate declarations for this member, add them.
      for (auto alternate : getAlternateDecls(member)) {
        if (alternate->getDeclContext() == member->getDeclContext() &&
            knownAlternateMembers.insert(alternate).second) {
          members.push_back(alternate);
        }
      }
  
      // If this declaration shouldn't be visible, don't add it to
      // the list.
      if (shouldSuppressDeclImport(nd))
        return true;
  
      members.push_back(member);
      return true;
    });
  }
  
  void ClangImporter::Implementation::collectMembersToAdd(
      const clang::ObjCContainerDecl *objcContainer, Decl *D, DeclContext *DC,
      SmallVectorImpl<Decl *> &members) {
    for (const clang::Decl *m : objcContainer->decls()) {
      auto nd = dyn_cast<clang::NamedDecl>(m);
      if (nd && nd == nd->getCanonicalDecl() &&
          nd->getDeclContext() == objcContainer)
        insertMembersAndAlternates(nd, members);
    }
  
    SwiftDeclConverter converter(*this, CurrentVersion);
  
    SmallVector<ProtocolDecl *, 4> protos = takeImportedProtocols(D);
    if (auto clangClass = dyn_cast<clang::ObjCInterfaceDecl>(objcContainer)) {
      auto swiftClass = cast<ClassDecl>(D);
      objcContainer = clangClass = clangClass->getDefinition();
  
      // Imported inherited initializers.
      if (clangClass->getName() != "Protocol") {
        converter.importInheritedConstructors(const_cast<ClassDecl *>(swiftClass),
                                              members);
      }
  
    } else if (auto clangProto
                 = dyn_cast<clang::ObjCProtocolDecl>(objcContainer)) {
      objcContainer = clangProto->getDefinition();
    }
    // Import mirrored declarations for protocols to which this category
    // or extension conforms.
    // FIXME: This is supposed to be a short-term hack.
    converter.importMirroredProtocolMembers(objcContainer, DC,
                                            protos, members, SwiftContext);
  }
  
  void ClangImporter::Implementation::loadAllConformances(
         const Decl *D, uint64_t contextData,
         SmallVectorImpl<ProtocolConformance *> &Conformances) {
    Conformances = takeDelayedConformance(contextData);
  }
  
  Optional<MappedTypeNameKind>
  ClangImporter::Implementation::getSpecialTypedefKind(clang::TypedefNameDecl *decl) {
    auto iter = SpecialTypedefNames.find(decl->getCanonicalDecl());
    if (iter == SpecialTypedefNames.end())
      return None;
    return iter->second;
  }
  
  Identifier
  ClangImporter::getEnumConstantName(const clang::EnumConstantDecl *enumConstant){
    return Impl.importFullName(enumConstant, Impl.CurrentVersion)
        .getDeclName()
        .getBaseIdentifier();
  }
  
  