Repository: apple/swift
File: lib/ClangImporter/ClangDerivedConformances.cpp (C++)

Code before:
      clangDeclTyInfo, clangDecl->getLocation(), constructExprArgs,
      clangDecl->getLocation(), /*ListInitialization*/ false);
  if (!constructExprResult.isUsable())
    return;

  auto constructExpr =
      dyn_cast_or_null<clang::CXXConstructExpr>(constructExprResult.get());
  if (!constructExpr)
    return;

  auto constructorDecl = constructExpr->getConstructor();
  auto importedConstructor =
      impl.importDecl(constructorDecl, impl.CurrentVersion);
  if (!importedConstructor)
    return;

  auto attr = AvailableAttr::createUniversallyDeprecated(
      importedConstructor->getASTContext(), "use 'init(_:)' instead.", "");
  importedConstructor->addAttribute(attr);

  decl->addMember(importedConstructor);
}

// Holds all the CxxStdTypes whose C++ stdlib overlay protocols are ~Copyable
static const llvm::DenseSet<CxxStdType> NonCopyableCxxStdTypeConformances = {
    CxxStdType::pair};

void swift::deriveAutomaticCxxConformances(
    ClangImporter::Implementation &Impl, NominalTypeDecl *result,
    const clang::CXXRecordDecl *clangDecl) {

  ASSERT(result && clangDecl && "this should not be called with nullptrs");

  // Skip synthesizing conformances if the associated Clang node is from
  // a module that doesn't require cplusplus, to prevent us from accidentally
  // pulling in Cxx/CxxStdlib modules when a client is importing a C library.
  //
  // We will still attempt to synthesize to account for scenarios where the
  // module specification is missing altogether.
  if (auto *clangModule = importer::getClangOwningModule(
          result->getClangNode(), Impl.getClangASTContext());
      clangModule && !requiresCPlusPlus(clangModule))
    return;

  // Automatic conformances: these may be applied to any type that fits the
  // requirements.
  conformToCxxIteratorIfNeeded(Impl, result, clangDecl);
  conformToCxxSequenceIfNeeded(Impl, result, clangDecl);
  conformToCxxConvertibleToBoolIfNeeded(Impl, result, clangDecl);

  // CxxStdlib conformances: these should only apply to known C++ stdlib types,

Review comment (suggestion):
Rather than enumerating the protocols that do not require `Copyable` here, I'm slightly in favor of adding a "is copyable" check in each of the protocol synthesis functions, to keep the per-protocol logic all in one place. That way if someone is looking at, say, the `StdMap` conformance logic, they don't need to look here to realize the conformance is being skipped because the type isn't copyable.

But I don't feel too strongly about this, since at the moment there's only one type that does not require copyable.

~~Just trying to envision what else might get added here: I guess the only other std types that don't require copyable are `std::optional` and `std::tuple`?~~ idk why I wrote that; I just considered those "simple" types that contain their type parameter by value, but I'm not sure why that reasoning is sound. 

Code after:
      clangDeclTyInfo, clangDecl->getLocation(), constructExprArgs,
      clangDecl->getLocation(), /*ListInitialization*/ false);
  if (!constructExprResult.isUsable())
    return;

  auto constructExpr =
      dyn_cast_or_null<clang::CXXConstructExpr>(constructExprResult.get());
  if (!constructExpr)
    return;

  auto constructorDecl = constructExpr->getConstructor();
  auto importedConstructor =
      impl.importDecl(constructorDecl, impl.CurrentVersion);
  if (!importedConstructor)
    return;

  auto attr = AvailableAttr::createUniversallyDeprecated(
      importedConstructor->getASTContext(), "use 'init(_:)' instead.", "");
  importedConstructor->addAttribute(attr);

  decl->addMember(importedConstructor);
}

void swift::deriveAutomaticCxxConformances(
    ClangImporter::Implementation &Impl, NominalTypeDecl *result,
    const clang::CXXRecordDecl *clangDecl) {

  ASSERT(result && clangDecl && "this should not be called with nullptrs");

  // Skip synthesizing conformances if the associated Clang node is from
  // a module that doesn't require cplusplus, to prevent us from accidentally
  // pulling in Cxx/CxxStdlib modules when a client is importing a C library.
  //
  // We will still attempt to synthesize to account for scenarios where the
  // module specification is missing altogether.
  if (auto *clangModule = importer::getClangOwningModule(
          result->getClangNode(), Impl.getClangASTContext());
      clangModule && !requiresCPlusPlus(clangModule))
    return;

  // Automatic conformances: these may be applied to any type that fits the
  // requirements.
  conformToCxxIteratorIfNeeded(Impl, result, clangDecl);
  conformToCxxSequenceIfNeeded(Impl, result, clangDecl);
  conformToCxxConvertibleToBoolIfNeeded(Impl, result, clangDecl);

  // CxxStdlib conformances: these should only apply to known C++ stdlib types,
  // which we determine by name and membership in the std namespace.
  if (!clangDecl->getIdentifier() || !clangDecl->isInStdNamespace())
    return;