profile
viewpoint

apple/swift 53917

The Swift Programming Language

apple/swift-evolution 11549

This maintains proposals for changes and user-visible enhancements to the Swift Programming Language.

apple/swift-package-manager 8007

The Package Manager for the Swift Programming Language

apple/swift-corelibs-foundation 4033

The Foundation Project, providing core utilities, internationalization, and OS independence

apple/swift-corelibs-libdispatch 1894

The libdispatch Project, (a.k.a. Grand Central Dispatch), for concurrency on multicore hardware

apple/swift-corelibs-xctest 862

The XCTest Project, A Swift core library for providing unit test support

apple/swift-llbuild 798

A low-level build system, used by Xcode and the Swift Package Manager

apple/swift-lldb 645

This is the version of LLDB that supports the Swift programming language & REPL.

push eventllvm/llvm-project

Dmitri Gribenko

commit sha b3876ef49093b17555ae058eb87bb9c70a525c49

Silence -Wunused-variable in NDEBUG mode

view details

push time in 16 days

push eventllvm/llvm-project

Dmitri Gribenko

commit sha 37c74dfe72ecf4e7def22702c5a944682a7865df

Revert "[c++17] Implement P0145R3 during constant evaluation." This reverts commit ded79be63555f4e5bfdb0db27ef22b71fe568474. It causes a crash (I sent the crash reproducer directly to the author).

view details

push time in 16 days

push eventllvm/llvm-project

Dmitri Gribenko

commit sha 8ed7946a7d94f9d23b7f33356a1903d481daa5a0

Revert "[llvm-objcopy][MachO] Add missing std::move." This reverts commit 6e25586990b93e2c9eaaa4f473b6720ccd646c46. It depends on 32c8435ef70031d7bd3dce48e41bdce65747e123, which I'm reverting due to ASan failures. Details in https://reviews.llvm.org/D88400.

view details

Dmitri Gribenko

commit sha 80f66ac0d544d2d9d3108033148d60bb4760b319

Revert "[llvm-objcopy][MachO] Add support for universal binaries" This reverts commit 32c8435ef70031d7bd3dce48e41bdce65747e123. It fails ASan, details in https://reviews.llvm.org/D88400.

view details

push time in 16 days

Pull request review commentapple/swift

[cxx-interop] Support function templates.

 class ClangModuleLoader : public ModuleLoader {   /// based on subtleties like the target module interface format.   virtual bool isSerializable(const clang::Type *type,                               bool checkCanonical) const = 0;++  virtual clang::FunctionDecl *+  generateCXXFunctionTemplateSpecializations(ASTContext &ctx,+                                             clang::FunctionTemplateDecl *func,+                                             SubstitutionMap subst) = 0;+};++/// Used to describe an error when instanciated a template.
/// Describes a template instantiation error.
zoecarver

comment created time in 17 days

PullRequestReviewEvent

pull request commentapple/swift

[WIP] Move out enum tests into a separate CXXInterop/enum directory

@swift-ci Please test

sureyeaah

comment created time in a month

pull request commentapple/swift

[WIP] Move out enum tests into a separate CXXInterop/enum directory

@swift-ci Please test Windows platform

sureyeaah

comment created time in a month

push eventllvm/llvm-project

Dmitri Gribenko

commit sha e10df779f097e3a1fb02d901117ce71a5dd9dda2

Fix clang Wrange-loop-analysis in BuildTree.cpp Building on Mac OS with clang 12: ``` jhemphill@jhemphill-mbp build % clang --version Apple clang version 12.0.0 (clang-1200.0.26.2) Target: x86_64-apple-darwin19.6.0 Thread model: posix InstalledDir: /Library/Developer/CommandLineTools/usr/bin ``` yields one warning: ``` /Users/jhemphill/oss/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp:1126:22: warning: loop variable 'Arg' is always a copy because the range of type 'llvm::iterator_range<clang::Stmt::CastIterator<clang::Expr, clang::Expr *, clang::Stmt *> >' does not return a reference [-Wrange-loop-analysis] for (const auto &Arg : Args) { ^ /Users/jhemphill/oss/llvm-project/clang/lib/Tooling/Syntax/BuildTree.cpp:1126:10: note: use non-reference type 'clang::Expr *' for (const auto &Arg : Args) { ``` It appears that `Arg` is an `Expr*`, passed by value rather than by const reference. Reviewed By: eduucaldas, gribozavr2 Differential Revision: https://reviews.llvm.org/D87482

view details

push time in a month

push eventapple/swift-integration-tests

Saleem Abdulrasool

commit sha cf8e32dc53dd318b210f46c954d50e08b1d52030

add a test case for an invalid optimizatio A recent optimization was overly aggressive and resulted in a miscompile in FoundationNetworking. Add a test case.

view details

Dmitri Gribenko

commit sha 3ceb61d33ea8885938eace0add830d143a3059cd

Merge pull request #71 from compnerd/hang add a test case for an invalid optimization

view details

push time in a month

PR merged apple/swift-integration-tests

add a test case for an invalid optimization

A recent optimization was overly aggressive and resulted in a miscompile in FoundationNetworking. Add a test case.

+14 -0

2 comments

2 changed files

compnerd

pr closed time in a month

pull request commentapple/swift

[cxx-interop] Add class template tests

Could you rebase? I can open the diff view that you linked, but I can't leave comments there.

hlopko

comment created time in 2 months

push eventllvm/llvm-project

Michael Forster

commit sha a5b8757506b07e3091fe243b6c1e004220d3cba3

Introduce ns_error_domain attribute. ns_error_domain can be used by, e.g. NS_ERROR_ENUM, in order to identify a global declaration representing the domain constant. Introduces the attribute, Sema handling, diagnostics, and test case. This is cherry-picked from https://github.com/llvm/llvm-project-staging/commit/a14779f504b02ad0e4dbc39d6d10cadc7ed4cfd0 and adapted to updated Clang APIs. Reviewed By: gribozavr2, aaron.ballman Differential Revision: https://reviews.llvm.org/D84005

view details

push time in 2 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 We could ignore explicit specializations of function templates, because they don't affect the API. Explicit specializations of class templates can dramatically change the API of the type. +### Class templates: Importing full class template instantiations++A class template instantiation could be imported as a struct named+`__CxxTemplateInst` plus Itanium mangled type of the instantiation (see the

Yes we could. The benefit would be having shorter mangled names and smaller metadata. The downside is slight increase in implementation complexity. For my use cases, I'd definitely appreciate any shortening of mangled names I can get. However, we biased towards reducing implementation complexity.

What's your preference?

hlopko

comment created time in 2 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 nominal type descriptor symbol for ``CxxStruct`` while compiling the ``main`` mo .. code::    sSo9CxxStructVMn // -> nominal type descriptor for __C.CxxStruct++Importing C++ class template instantiations+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++A class template instantiation is imported as a struct named+``__CxxTemplateInst`` plus Itanium mangled type of the instantiation (see the+``type`` production in the Itanium specification). Note that Itanium mangling is+used on all platforms, regardless of the ABI of the C++ toolchain, to ensure+that the mangled name is a valid Swift type name (this is not the case for MSVC+mangled names). A prefix with a double underscore (to ensure we have a reserved+C++ identifier) is added to limit the possibility for conflicts with names of+user-defined structs. The struct is notionally defined in the ``__C`` module,+similarly to regular C and C++ structs and classes. Consider the following C+++module:++.. code-block:: c++++  template<class T>+  struct MagicWrapper {+    T t;+  };++  struct MagicNumber {};++  typedef MagicWrapper<MagicNumber> WrappedMagicNumber;++``WrappedMagicNumber`` will be imported as a typealias for a struct+``__CxxTemplateInst12MagicWrapperI11MagicNumberE``. Interface of the imported+module will look as follows:
``WrappedMagicNumber`` is imported as a typealias for a struct
``__CxxTemplateInst12MagicWrapperI11MagicNumberE``. Interface of the imported
module looks as follows:
hlopko

comment created time in 2 months

pull request commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

@zoecarver Congrats!

zoecarver

comment created time in 2 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

+// RUN: %target-swift-frontend -enable-cxx-interop -I %S/Inputs %s -emit-ir | %FileCheck %s++import TypeClassification++// TODO: C++ objects with destructors should be tested here once we fully+// support them.++// CHECK-LABEL: define {{.*}}i1 @"$s4main37testStructWithCopyConstructorAndValueSbyF"

Could you add an explanation of what these tests are verifying, so that future when IRGen patterns change people can update the CHECK lines appropriately, and not accidentally eliminate the part that we're thinking we are testing here.

zoecarver

comment created time in 2 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 public func testStructWithSubobjectDestructor() {   let d = StructWithSubobjectDestructor() } +// CHECK-LABLE: sil @$s4main37testStructWithCopyConstructorAndValueSbyF+// CHECK: [[OBJ:%.*]] = alloc_stack $StructWithCopyConstructorAndValue+// CHECK: [[IL_42:%.*]] = integer_literal $Builtin.Int32, 42+// CHECK: [[I_42:%.*]] = struct $Int32 ([[IL_42]] : $Builtin.Int32)+// CHECK: [[OBJ_VALUE:%.*]] = struct_element_addr [[OBJ]] : $*StructWithCopyConstructorAndValue, #StructWithCopyConstructorAndValue.value+// CHECK: store [[I_42]] to [[OBJ_VALUE]] : $*Int32+// CHECK: [[IL_FALSE:%.*]] = integer_literal $Builtin.Int1, -1

This code does not read from the field. It looks like mandatory optimizations have run and constant folded the read. That's probably because the RUN line says -emit-sil. I'd suggest using %target-swift-emit-silgen instead.

zoecarver

comment created time in 2 months

Pull request review commentapple/swift

Document conventions for constructing names in mangling docs

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for foreign symbols+-------------------------------++Swift interoperates with multiple other languages - C, C++, Objective-C, and+Objective-C++. Each of these languages defines their own mangling conventions,+so Swift must take care to follow them. However, these conventions do not cover+Swift-specific symbols like Swift type metadata for foreign types, so Swift uses+its own mangling scheme for those symbols.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~~~~~~~~~++Types imported from C and C++ are imported as if they are located in the ``__C``+module, regardless of the actual Clang module that they are coming from. This+can be observed when mangling a Swift function that accepts a C/C++ struct as a+parameter:++CxxStructModule:++.. code-block:: c++++  struct CxxStruct {};++  inline void cxxFunction(CxxStruct s) {}++Swift ``main`` module importing ``CxxStructModule``:
Swift module ``main`` that imports ``CxxStructModule``:
hlopko

comment created time in 2 months

Pull request review commentapple/swift

Document conventions for constructing names in mangling docs

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for foreign symbols+-------------------------------++Swift interoperates with multiple other languages - C, C++, Objective-C, and+Objective-C++. Each of these languages defines their own mangling conventions,+so Swift must take care to follow them. However, these conventions do not cover+Swift-specific symbols like Swift type metadata for foreign types, so Swift uses+its own mangling scheme for those symbols.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~~~~~~~~~++Types imported from C and C++ are imported as if they are located in the ``__C``+module, regardless of the actual Clang module that they are coming from. This+can be observed when mangling a Swift function that accepts a C/C++ struct as a+parameter:++CxxStructModule:++.. code-block:: c++++  struct CxxStruct {};++  inline void cxxFunction(CxxStruct s) {}++Swift ``main`` module importing ``CxxStructModule``:++.. code-block:: swift++  import CxxStructModule++  public func swiftFunction(_ s: CxxStruct) {}++Resulting symbols (showing only Itanium-mangled C++ symbols for brevity):++.. code::++  _Z11cxxFunction9CxxStruct // -> cxxFunction(CxxStruct)+  s4main13swiftFunctionyySo9CxxStructVF // -> main.swiftFunction(__C.CxxStruct) -> ()++The C/C++ compiler does not generate Swift metadata symbols and value witness+tables for C and C++ types. To make a foreign type usable in Swift in the same+way as a native type, the Swift compiler must generate these symbols.+Specifically, each Swift module that uses a given C or C++ type generates the+necessary Swift symbols. For the example above Swift will generate following+nominal type descriptor symbol for ``CxxStruct``:
necessary Swift symbols. For the example above the Swift compiler will generate following
nominal type descriptor symbol for ``CxxStruct`` while compiling the ``main`` module:
hlopko

comment created time in 2 months

Pull request review commentapple/swift

Document conventions for constructing names in mangling docs

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for foreign symbols+-------------------------------++Swift interoperates with multiple other languages - C, C++, Objective-C, and+Objective-C++. Each of these languages defines their own mangling conventions,+so Swift must take care to follow them. However, these conventions do not cover+Swift-specific symbols like Swift type metadata for foreign types, so Swift uses+its own mangling scheme for those symbols.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~~~~~~~~~++Types imported from C and C++ are imported as if they are located in the ``__C``+module, regardless of the actual Clang module that they are coming from. This+can be observed when mangling a Swift function that accepts a C/C++ struct as a+parameter:++CxxStructModule:
C++ module ``CxxStructModule``:
hlopko

comment created time in 2 months

Pull request review commentapple/swift

Document conventions for constructing names in mangling docs

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for foreign symbols+-------------------------------++Swift interoperates with multiple other languages - C, C++, Objective-C, and+Objective-C++. Each of these languages defines their own mangling conventions,+so Swift must take care to follow them. However, these conventions do not cover+Swift-specific symbols like Swift type metadata for foreign types, so Swift uses+its own mangling scheme for those symbols.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~~~~~~~~~++Types imported from C and C++ are imported as if they are located in the ``__C``+module, regardless of the actual Clang module that they are coming from. This+can be observed when mangling a Swift function that accepts a C/C++ struct as a+parameter:++CxxStructModule:++.. code-block:: c++++  struct CxxStruct {};++  inline void cxxFunction(CxxStruct s) {}++Swift ``main`` module importing ``CxxStructModule``:++.. code-block:: swift++  import CxxStructModule++  public func swiftFunction(_ s: CxxStruct) {}++Resulting symbols (showing only Itanium-mangled C++ symbols for brevity):++.. code::++  _Z11cxxFunction9CxxStruct // -> cxxFunction(CxxStruct)+  s4main13swiftFunctionyySo9CxxStructVF // -> main.swiftFunction(__C.CxxStruct) -> ()+
  • "The reason for ignoring the Clang module and always putting C and C++ types into __C at the Swift ABI level is that the Clang module is not a part of the C or C++ ABI. When owners of C and C++ Clang modules decide what changes are ABI-compatible or not, they will likely take into account C and C++ ABI, but not the Swift ABI. Therefore, Swift ABI can only encode information about a C or C++ type that the C and C++ ABI already encodes in order to remain compatible with future versions of libraries that evolve according to C and C++ ABI compatibility principles."
hlopko

comment created time in 2 months

pull request commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

I realize it is probably too big of a request for this PR, but maybe in a separate PR, could you add tests for typedefs for specializations of:

  • variadic templates,
  • templates with non-type template parameters,
  • templates with template template parameters?
hlopko

comment created time in 2 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITHOUT_DEFINITION_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITHOUT_DEFINITION_H++template<class T>+struct MagicWrapper {+  T t;+  int getValuePlusArg(int arg) const { return t.getValue() + arg; }+};++struct IntWrapper {+  int value;+  int getValue() const { return value; }+};++// MagicWrapper<IntWrapper> ClassTemplateSpecializationDecl doesn't have a
// The ClassTemplateSpecializationDecl node for MagicWrapper<IntWrapper> doesn't have a
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITHOUT_DEFINITION_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITHOUT_DEFINITION_H++template<class T>+struct MagicWrapper {+  T t;+  int getValuePlusArg(int arg) const { return t.getValue() + arg; }+};++struct IntWrapper {+  int value;+  int getValue() const { return value; }+};++// MagicWrapper<IntWrapper> ClassTemplateSpecializationDecl doesn't have a+// definition in Clang because nothing in this header required the+// instantiation. Therefore we have to construct the definition on the swift+// side.
// instantiation. Therefore, the Swift compiler must trigger instantiation.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_H++template<class T>+struct MagicWrapper {+  T t;+  int callGetInt() const {+    return t.getInt() + 5;+  }+};++struct MagicNumber {+  // Swift runtime defines many value witness tables for common types.
  // Swift runtime defines many value witness tables for types with some common layouts.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_H

I'd suggest to rename this header to "linkage-of-swift-symbols-for-imported-types" (and similarly the tests that use it).

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop -Xcc -std=c++17)+//+// REQUIRES: executable_test++import CanonicalTypes+import StdlibUnittest++var TemplatesTestSuite = TestSuite("TemplatesTestSuite")++TemplatesTestSuite.test("canonical-types") {+  // multiple typedeffed types with the same canonical type are the same type+  // from the typechecking perspective.
  // Different typedefs with the same C++ canonical type must have the same type from Swift's perspective as well.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_LINKAGE_H++template<class T>+struct MagicWrapper {+  T t;+  int callGetInt() const {+    return t.getInt() + 5;+  }+};++struct MagicNumber {+  // Swift runtime defines many value witness tables for common types.+  // The struct's uncommon size forces creation of its own witness table.
  // This struct's uncommon size forces the compiler to define a new value witness table instead of reusing one from the runtime.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | grep 'define.*swiftcc.*$' | grep -o '\$[[:alnum:]]\+__CxxTemplateInst[[:alnum:]]\+' | xargs %swift-demangle | %FileCheck %s++import Mangling++public func receiveInstantiation(_ i: inout WrappedMagicInt) {}++public func returnInstantiation() -> WrappedMagicInt {+  return WrappedMagicInt()+}++// CHECK: $s10demangling20receiveInstantiationyySo34__CxxTemplateInst12MagicWrapperIiEVzF ---> demangling.receiveInstantiation(inout __C.__CxxTemplateInst12MagicWrapperIiE) -> ()+// CHECK: $s10demangling19returnInstantiationSo34__CxxTemplateInst12MagicWrapperIiEVyF ---> demangling.returnInstantiation() -> __C.__CxxTemplateInst12MagicWrapperIiE

Could you file a bug to enhance the demangler to handle these names?

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H++template<class T>+struct MagicWrapper {+  T t;+  int getValuePlusArg(int arg) const { return t.getValue() + arg; }+};++struct IntWrapper {+  int value;+  int getValue() const { return value; }+};++inline int forceInstantiation() {+  auto t = MagicWrapper<IntWrapper>();+  return t.getValuePlusArg(14);+}++// MagicWrapper<IntWrapper> ClassTemplateSpecializationDecl has a definition
// The ClassTemplateSpecializationDecl node for MagicWrapper<IntWrapper> already has a definition
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H++template<class T>+struct MagicWrapper {+  T t;+  int getValuePlusArg(int arg) const { return t.getValue() + arg; }+};++struct IntWrapper {+  int value;+  int getValue() const { return value; }+};++inline MagicWrapper<IntWrapper> forceInstantiation() {+  return MagicWrapper<IntWrapper>();+}++// MagicWrapper<IntWrapper> ClassTemplateSpecializationDecl has a definition
// The ClassTemplateSpecializationDecl node for MagicWrapper<IntWrapper> already has a definition
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,     }   } +  if (auto classTemplateSpecDecl =+          dyn_cast<clang::ClassTemplateSpecializationDecl>(D)) {+    if (!isa<clang::ClassTemplatePartialSpecializationDecl>(D)) {++      auto &astContext = classTemplateSpecDecl->getASTContext();+      // Itanium mangler produces valid Swift identifiers, use it to generate a name for+      // this instantiation. This name will not appear in the native code.+      clang::MangleContext *mangler = clang::ItaniumMangleContext::create(+          astContext, astContext.getDiagnostics());+      llvm::SmallString<128> storage;+      llvm::raw_svector_ostream buffer(storage);+      mangler->mangleTypeName(astContext.getRecordType(classTemplateSpecDecl),+                              buffer);++      // We reuse mangleTypeName() which returns RTTI typeinfo name, to get the mangled type.

Something like:

"The Itanium mangler does not provide a way to get the mangled representation of a type. Instead, we call mangleTypeName() that returns the name of the RTTI typeinfo symbol, and remove the _ZTS prefix. Then we prepend __CxxTemplateInst to reduce chances of conflict with regular C and C++ structs."

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,     }   } +  if (auto classTemplateSpecDecl =+          dyn_cast<clang::ClassTemplateSpecializationDecl>(D)) {+    if (!isa<clang::ClassTemplatePartialSpecializationDecl>(D)) {++      auto &astContext = classTemplateSpecDecl->getASTContext();+      // Itanium mangler produces valid Swift identifiers, use it to generate a name for+      // this instantiation. This name will not appear in the native code.+      clang::MangleContext *mangler = clang::ItaniumMangleContext::create(+          astContext, astContext.getDiagnostics());+      llvm::SmallString<128> storage;+      llvm::raw_svector_ostream buffer(storage);+      mangler->mangleTypeName(astContext.getRecordType(classTemplateSpecDecl),+                              buffer);++      // We reuse mangleTypeName() which returns RTTI typeinfo name, to get the mangled type.+      // Therefore we need to strip the '_ZTS' prefix, which we replace with '__CxxTemplateInst'+      // (a prefix reserved for C++ compiler usage).+      llvm::SmallString<128> mangledNameStorage;+      llvm::raw_svector_ostream mangledName(mangledNameStorage);+      mangledName << CXX_TEMPLATE_INST_PREFIX << buffer.str().drop_front(4);

It would be a good idea to assert that the characters that we're dropping are what we expect.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,     }   } +  if (auto classTemplateSpecDecl =+          dyn_cast<clang::ClassTemplateSpecializationDecl>(D)) {+    if (!isa<clang::ClassTemplatePartialSpecializationDecl>(D)) {++      auto &astContext = classTemplateSpecDecl->getASTContext();+      // Itanium mangler produces valid Swift identifiers, use it to generate a name for+      // this instantiation. This name will not appear in the native code.

WDYM by "This name will not appear in the native code"?

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 namespace {      Decl *VisitClassTemplateSpecializationDecl(                  const clang::ClassTemplateSpecializationDecl *decl) {-      // FIXME: We could import specializations, but perhaps only as unnamed-      // structural types.-      return nullptr;+      // `sema.isCompleteType` will try to instantiate the class template as a
      // `Sema::isCompleteType` will try to instantiate the class template as a
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {       appendIdentifier(interface->getObjCRuntimeNameAsString());     } else if (UseObjCRuntimeNames && protocol) {       appendIdentifier(protocol->getObjCRuntimeNameAsString());+    } else if (auto ctsd = dyn_cast<clang::ClassTemplateSpecializationDecl>(namedDecl)) {+      // If this is a `ClassTemplateSpecializationDecl` it means the decl was
      // If this is a `ClassTemplateSpecializationDecl`, it was
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop -Xcc -std=c++17)+//+// REQUIRES: executable_test++import ExplicitSpecialization+import StdlibUnittest++var TemplatesTestSuite = TestSuite("TemplatesTestSuite")++TemplatesTestSuite.test("explicit-specialization") {+  // Specialization doubles the argument.

I don't think this comment adds value.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {       appendIdentifier(interface->getObjCRuntimeNameAsString());     } else if (UseObjCRuntimeNames && protocol) {       appendIdentifier(protocol->getObjCRuntimeNameAsString());+    } else if (auto ctsd = dyn_cast<clang::ClassTemplateSpecializationDecl>(namedDecl)) {+      // If this is a `ClassTemplateSpecializationDecl` it means the decl was+      // imported as a Swift decl with `__CxxTemplateInst...` name.+      // `ClassTemplateSpecializationDecl`'s name does not include names of+      // template arguments, and in order to prevent name clashes we use the+      // name of the Swift decl which does includes template argument names.+      appendIdentifier(nominal->getName().str());
      // `ClassTemplateSpecializationDecl`'s name does not include information about
      // template arguments, and in order to prevent name clashes we use the
      // name of the Swift decl which does include template arguments.
      appendIdentifier(nominal->getName().str());
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 namespace {      Decl *VisitClassTemplateSpecializationDecl(                  const clang::ClassTemplateSpecializationDecl *decl) {-      // FIXME: We could import specializations, but perhaps only as unnamed-      // structural types.-      return nullptr;+      // `sema.isCompleteType` will try to instantiate the class template as a+      // side-effect and we rely on this here. `decl->getDefinition()` can+      // return nullptr before the call to sema and return its definition+      // afterwards.+      if (!Impl.getClangSema().isCompleteType(+              decl->getLocation(),+              Impl.getClangASTContext().getRecordType(decl))) {+        // If we got nullptr definition now it means the type is not complete.+        // We don't import incomplete types.+        return nullptr;+      }+      auto def = dyn_cast<clang::ClassTemplateSpecializationDecl>(+          decl->getDefinition());+      assert(def && "Class template instantiation didn't have definition");+      // This will instantiate all members of the specialization (and detect
      // FIXME: This will instantiate all members of the specialization (and detect
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for constructing names+----------------------------------++Swift is a language that integrates with multiple languages (C, C++, ObjC,+ObjC++). To achieve interoperability symbols from other languages have to be+adapted in order to be integrated into Swift.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~++C and C++ structs use their original names and their owning modules. Since Swift+metadata symbols and value-witness-tables are not generated by the C compiler,+Swift generates them when C/C++ module is imported and stores them in the `__C`+module. This can be observed when mangling a Swift function that accepts a C/C+++struct as a parameter.++Importing C++ template instantiations behind typedef+~~~~~~~~~~~~~~~~~~~++The template instantiation is imported as a struct named `__CxxTemplateInst`+plus Itanium mangled type of the instantiation. Double underscore (denoting a+reserved C++ identifier) is used to discourage direct usage. The struct is
A class template instantiation is imported as a struct named ``__CxxTemplateInst``
plus Itanium mangled type of the instantiation (see the ``type`` production in the Itanium specification). Note that Itanium mangling is used on all platforms, regardless of the ABI of the C++ toolchain, to ensure that the mangled name is a valid Swift type name (this is not the case for MSVC mangled names). A prefix with a double underscore (to ensure we have a
reserved C++ identifier) is added to limit the possibility for conflicts with names of user-defined structs. The struct is
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_EXPLICIT_SPECIALIZATION_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_EXPLICIT_SPECIALIZATION_H++struct SpecializedIntWrapper {+  int value;+  int getValue() const { return value; }+};++struct NonSpecializedIntWrapper {+  int value;+  int getValue() const { return value; }+};++template <class T>+struct MagicWrapper {+  T t;+  int doubleIfSpecializedElseTripple() const { return 3 * t.getValue(); }

"Triple"

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 We could ignore explicit specializations of function templates, because they don't affect the API. Explicit specializations of class templates can dramatically change the API of the type. +### Class templates: importing instantiation behind typedef++Typedefs having template instantiation as their underlying type could be+imported as a non-generit struct with the given name.++```c+++// C++ header.++template<typename T>+class ClassTemplate {};++typedef ClassTemplate<int> ClassTemplateOfInt;+```++```swift+// C++ header imported to Swift.++struct ClassTemplateOfInt {}+```++In C++, multiple distinct typedeffed instantiations must resolve to the same+canonical type. We could implement this by creating a hidden intermediate struct+that typedef aliasses.++The struct could be named as `__CxxTemplateInst` plus Itanium mangled type of+the instantiation. For the example above the name of the hidden struct is+`__CxxTemplateInst13ClassTemplateIiE`. Double underscore (denoting a reserved+C++ identifier) is used to discourage direct usage. We chose Itanium mangling

Same comments as in the mangling doc.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 We could ignore explicit specializations of function templates, because they don't affect the API. Explicit specializations of class templates can dramatically change the API of the type. +### Class templates: importing instantiation behind typedef++Typedefs having template instantiation as their underlying type could be
C++ typedefs for full specializations of class templates could be
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 We could ignore explicit specializations of function templates, because they don't affect the API. Explicit specializations of class templates can dramatically change the API of the type. +### Class templates: importing instantiation behind typedef
### Class templates: importing full specializations behind typedefs
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 We could ignore explicit specializations of function templates, because they don't affect the API. Explicit specializations of class templates can dramatically change the API of the type. +### Class templates: importing instantiation behind typedef++Typedefs having template instantiation as their underlying type could be+imported as a non-generit struct with the given name.
imported as non-generic structs with the name of the typedef.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for constructing names+----------------------------------++Swift is a language that integrates with multiple languages (C, C++, ObjC,+ObjC++). To achieve interoperability symbols from other languages have to be+adapted in order to be integrated into Swift.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~++C and C++ structs use their original names and their owning modules. Since Swift+metadata symbols and value-witness-tables are not generated by the C compiler,+Swift generates them when C/C++ module is imported and stores them in the `__C`+module. This can be observed when mangling a Swift function that accepts a C/C+++struct as a parameter.++Importing C++ template instantiations behind typedef+~~~~~~~~~~~~~~~~~~~++The template instantiation is imported as a struct named `__CxxTemplateInst`+plus Itanium mangled type of the instantiation. Double underscore (denoting a+reserved C++ identifier) is used to discourage direct usage. The struct is+stored in the `__C` module, similarly to plain C++ structs.+

Please add an example.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for constructing names+----------------------------------++Swift is a language that integrates with multiple languages (C, C++, ObjC,+ObjC++). To achieve interoperability symbols from other languages have to be+adapted in order to be integrated into Swift.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~++C and C++ structs use their original names and their owning modules. Since Swift+metadata symbols and value-witness-tables are not generated by the C compiler,+Swift generates them when C/C++ module is imported and stores them in the `__C`+module. This can be observed when mangling a Swift function that accepts a C/C+++struct as a parameter.++Importing C++ template instantiations behind typedef+~~~~~~~~~~~~~~~~~~~++The template instantiation is imported as a struct named `__CxxTemplateInst`+plus Itanium mangled type of the instantiation. Double underscore (denoting a+reserved C++ identifier) is used to discourage direct usage. The struct is+stored in the `__C` module, similarly to plain C++ structs.
notionally defined in the ``__C`` module, similarly to regular C and C++ structs and classes.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for constructing names+----------------------------------++Swift is a language that integrates with multiple languages (C, C++, ObjC,+ObjC++). To achieve interoperability symbols from other languages have to be+adapted in order to be integrated into Swift.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~++C and C++ structs use their original names and their owning modules. Since Swift+metadata symbols and value-witness-tables are not generated by the C compiler,+Swift generates them when C/C++ module is imported and stores them in the `__C`+module. This can be observed when mangling a Swift function that accepts a C/C+++struct as a parameter.++Importing C++ template instantiations behind typedef
Importing C++ class template instantiations

I don't think this is going to be specific to typedefs, we will treat all template instantiations the same way.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

Document conventions for constructing names in mangling docs

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for foreign symbols+-------------------------------++Swift interoperates with multiple other languages - C, C++, Objective-C, and+Objective-C++. Each of these languages defines their own mangling conventions,+so Swift must take care to follow them. However, these conventions do not+restrict Swift-specific constructs like Swift type metadata, so the Swift+language may impose its own conventions in these cases.++Importing C and C++ structs+~~~~~~~~~~~~~~~~~~~~~~~~~~~++We don't touch the mangling of the original symbol. Since Swift metadata symbols+and value-witness-tables are not generated by the C/C++ compiler, Swift generates+them when C/C++ module is imported and stores them in the ``__C`` module. This can
Types imported from C and C++ are imported as if they are located in the ``__C`` module, regardless of the actual Clang module that they are coming from. This can be observed ...

<add the mangling example here>

The C/C++ compiler does not generate Swift metadata symbols and value witness tables for C and C++ types. To make a foreign type usable in Swift in the same way as a native type, the Swift compiler must generate these symbols. Specifically, each Swift module that uses a given C or C++ type generates the necessary Swift symbols.

<show the symbols here>

hlopko

comment created time in 3 months

Pull request review commentapple/swift

Document conventions for constructing names in mangling docs

 Some kinds need arguments, which precede ``Tf``. If the first character of the string literal is a digit ``[0-9]`` or an underscore ``_``, the identifier for the string literal is prefixed with an additional underscore ``_``.++Conventions for foreign symbols+-------------------------------++Swift interoperates with multiple other languages - C, C++, Objective-C, and+Objective-C++. Each of these languages defines their own mangling conventions,+so Swift must take care to follow them. However, these conventions do not+restrict Swift-specific constructs like Swift type metadata, so the Swift+language may impose its own conventions in these cases.
so Swift must take care to follow them. However, these conventions do not
cover Swift-specific symbols like Swift type metadata for foreign types, so Swift uses
its own mangling scheme for those symbols.
hlopko

comment created time in 3 months

pull request commentapple/swift

[stdlib] Set, Dictionary: Fix (cocoa, native) equatable implementation

Assuming there is a bug in this code that this PR fixes, please add tests for it -- thanks!

AndrewSB

comment created time in 3 months

Pull request review commentapple/swift

[NFC] [cxx-interop] Rename IsCxxNotTriviallyCopyable -> IsCxxNonTrivial.

 class alignas(1 << DeclAlignInBits) Decl {     IsIncompatibleWithWeakReferences : 1   ); -  SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1+1,-    /// True if this struct has storage for fields that aren't accessible in-    /// Swift.-    HasUnreferenceableStorage : 1,-    /// True if this struct is imported from C++ and not trivially copyable.-    IsCxxNotTriviallyCopyable : 1-  );-  +  SWIFT_INLINE_BITFIELD(+      StructDecl, NominalTypeDecl, 1 + 1,+      /// True if this struct has storage for fields that aren't accessible in+      /// Swift.+      HasUnreferenceableStorage : 1,+      /// True if this struct is imported from C++ and not trivial (because of a

"and does not have trivial value witness functions"

C++ has its own definition of "trivial" and here we are interested specifically in Swift's VWT interpretation.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[NFC] [cxx-interop] Rename IsCxxNotTriviallyCopyable -> IsCxxNonTrivial.

 class alignas(1 << DeclAlignInBits) Decl {     IsIncompatibleWithWeakReferences : 1   ); -  SWIFT_INLINE_BITFIELD(StructDecl, NominalTypeDecl, 1+1,-    /// True if this struct has storage for fields that aren't accessible in-    /// Swift.-    HasUnreferenceableStorage : 1,-    /// True if this struct is imported from C++ and not trivially copyable.-    IsCxxNotTriviallyCopyable : 1-  );-  +  SWIFT_INLINE_BITFIELD(+      StructDecl, NominalTypeDecl, 1 + 1,+      /// True if this struct has storage for fields that aren't accessible in+      /// Swift.+      HasUnreferenceableStorage : 1,+      /// True if this struct is imported from C++ and not trivial (because of a

"and does not have trivial value witness functions"

C++ has its own definition of "trivial" and here we are interested specifically in Swift's VWT interpretation.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 namespace {     }   }; +  class AddressOnlyClangRecordTypeInfo final+      : public StructTypeInfoBase<AddressOnlyClangRecordTypeInfo, FixedTypeInfo,+                                  ClangFieldInfo> {+    const clang::RecordDecl *ClangDecl;++  public:+    AddressOnlyClangRecordTypeInfo(ArrayRef<ClangFieldInfo> fields,+                                   llvm::Type *storageType, Size size,+                                   Alignment align,+                                   const clang::RecordDecl *clangDecl)+        : StructTypeInfoBase(StructTypeInfoKind::AddressOnlyClangRecordTypeInfo,+                             fields, storageType, size,+                             // An address only type shouldn't assume any spare+                             // bits. So, give it an empty vector.
                             // We can't assume any spare bits in a C++ type with user-defined special member functions.
zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 template <class FieldImpl> class RecordField {  protected:   explicit RecordField(const TypeInfo &elementTI)-    : Layout(ElementLayout::getIncomplete(elementTI)) {}+      : Layout(ElementLayout::getIncomplete(elementTI)), Begin(0XFFF),+        End(0XFFF) {}

I think you meant 0xFFFF.

Maybe it is better to leave Begin and End uninitialized so that MSan can catch a bogus read? Or you could add an assert(Begin != 0xFFFF); in getProjectionRange().

zoecarver

comment created time in 3 months

pull request commentapple/swift

[Concurrency] Stub out an experimental concurrency support library.

@DougGregor I'm very interested in this work -- is there a proposal draft for it?

DougGregor

comment created time in 3 months

pull request commentapple/llvm-project

Upstream ns_error_domain attribute

LGTM!

@DougGregor could you review & merge?

MForster

comment created time in 3 months

push eventapple/swift

zoecarver

commit sha 98803ec9926f685be7f9bd76f6e76dec241a00a0

[cxx-interop] [nfc] HasMemberWithDestructor => StructWithSubobjectDestructor in comment. The type "HasMemberWithDestructor" doesn't exist. It was replaced with StructWithSubobjectDestructor but the comment wasn't updated.

view details

Dmitri Gribenko

commit sha 1465ee6b2902108be780cb49307a538efe04fa2c

Merge pull request #33150 from zoecarver/cxx/fix/struct-with-subobject-destructor-name [cxx-interop] [nfc] HasMemberWithDestructor => StructWithSubobjectDestructor in comment.

view details

push time in 3 months

PR merged apple/swift

[cxx-interop] [nfc] HasMemberWithDestructor => StructWithSubobjectDestructor in comment.

The type "HasMemberWithDestructor" doesn't exist. It was replaced with StructWithSubobjectDestructor but the comment wasn't updated.

+1 -1

2 comments

1 changed file

zoecarver

pr closed time in 3 months

Pull request review commentapple/swift

[cxx-interop] Mark types with a destructor a non-trivial.

+// RUN: %target-swift-frontend -I %S/Inputs -enable-cxx-interop -emit-sil %s | %FileCheck %s++import TypeClassification++// Make sure that "StructWithDestructor" is marked as non-trivial by checking for a+// "destroy_addr".+// CHECK-LABEL: @$s4main24testStructWithDestructoryyF+// CHECK: [[AS:%.*]] = alloc_stack $StructWithDestructor+// CHECK: destroy_addr [[AS]]+// CHECK-LABEL: end sil function '$s4main24testStructWithDestructoryyF'+public func testStructWithDestructor() {+  let d = StructWithDestructor()+}++// Make sure that "HasMemberWithDestructor" is marked as non-trivial by checking

@zoecarver ^^^

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[docs] Add comments clarifying roles of Type.h and Types.h.

 enum class TypeMatchFlags { }; using TypeMatchOptions = OptionSet<TypeMatchFlags>; -/// TypeBase - Base class for all types in Swift.+/// TypeBase - Base class for all types which describe the Swift and SIL ASTs.
/// Base class for all types which describe the Swift and SIL ASTs.
varungandhi-apple

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+// RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-cxx-interop | %FileCheck %s++import CanonicalTypes++public func testCanonicalTypes() -> Bool {+  // multiple typedeffed types with the same canonical type are the same type+  // from the typechecking perspective.+  let magicNumber = MagicNumber()+  var wrappedMagicNumberA = WrappedMagicNumberA(t: magicNumber)++  var wrappedMagicNumberB: WrappedMagicNumberA =+    WrappedMagicNumberB(t: magicNumber)+  return wrappedMagicNumberA.callGetInt() == wrappedMagicNumberB.callGetInt()+}++// CHECK_NOT: __CxxTemplateInst

Correct syntax is with a dash, CHECK-NOT.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,     }   } +  if (auto classTemplateSpecDecl =+          dyn_cast<clang::ClassTemplateSpecializationDecl>(D)) {+    if (!isa<clang::ClassTemplatePartialSpecializationDecl>(D)) {++      auto &astContext = classTemplateSpecDecl->getASTContext();+      // Itanium mangler produces valid Swift identifiers, use it to generate a name for+      // this instantiation. This name will not appear in the native code.+      clang::MangleContext *mangler = clang::ItaniumMangleContext::create(+          astContext, astContext.getDiagnostics());+      llvm::SmallString<128> storage;+      llvm::raw_svector_ostream buffer(storage);+      mangler->mangleTypeName(astContext.getRecordType(classTemplateSpecDecl),+                              buffer);++      // We reuse mangleTypeName() which returns RTTI typeinfo name, to get the mangled type.+      // Therefore we need to strip the '_ZTS' prefix, which we replace with '__CxxTemplateInst'+      // (a prefix reserved for C++ compiler usage).

Could you add a test that shows how we mangle one of Swift entities that includes an instantiated C++ class template? For example, a global function that takes an argument which is an instantiated C++ class template. What I want to check is which module we are putting that name in. I believe we should be putting it into the module abbreviated as SC, known to users as __C_Synthesized:

  known-module ::= 'SC'                      // Clang-importer-synthesized

(see docs/ABI/Mangling.rst)

Could you also add tests that show that the metadata symbols, value witness tables symbols, and other autogenerated symbols for these instantiated class templates have the right linkage -- the same as you'd see for regular structs imported from C. (The issue is that these symbols get emitted into multiple object files so they can't be all strong symbols, as that would make it impossible to link multiple objects together.) I suspect this just works, but very much worth testing!

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 namespace {      Decl *VisitClassTemplateSpecializationDecl(                  const clang::ClassTemplateSpecializationDecl *decl) {-      // FIXME: We could import specializations, but perhaps only as unnamed-      // structural types.-      return nullptr;+      if (!Impl.getClangSema().isCompleteType(

Please add a comment here that we are relying on a side-effect from isCompleteType where it tries to complete the type. Merely checking TagDecl::isCompleteDefinition() wouldn't be sufficient.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H++template<class T>+struct MagicWrapper {+  T t;+  int callGetInt() const {+    return t.getInt() + 5;+  }+};++struct MagicNumber {+  int getInt() const { return 48; }+};++inline int forceInstantiating() {+  auto t = MagicWrapper<MagicNumber>();+  return t.callGetInt();+}++// MagicWrapper<MagicNumber> ClassTemplateSpecializationDecl has definition+// because function above forced the instantiation. Its members are fully+// instantiated, so nothing needs to be explicitly instantiated in swift.
// MagicWrapper<MagicNumber> ClassTemplateSpecializationDecl has a definition
// because function above forced the instantiation. Its members are fully
// instantiated, so nothing needs to be explicitly instantiated by the Swift compiler.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_CANONICAL_TYPES_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_CANONICAL_TYPES_H++template<class T>+struct MagicWrapper {+  T t;+  int callGetInt() const {+    return t.getInt() + 5;+  }+};++struct MagicNumber {+  int getInt() const { return 24; }

I understand that it is a lot of stuff to rewrite, but I have a hard time keeping track of the various constants in these headers.

WDYT about changing MagicNumber to:

struct IntWrapper {
  int value;
  int getValue() const { return value; }
};

and callGetInt() to:

int getValuePlusArg(int arg) {
  return t.getValue() + arg;
}

This way the correct answer should become obvious in Swift tests.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop -Xcc -std=c++17)+//+// REQUIRES: executable_test++import EagerInstantiationProblems+import StdlibUnittest++var TemplatesTestSuite = TestSuite("TemplatesTestSuite")++TemplatesTestSuite.test("eager-instantiation-of-members") {+  // This will fail with:+  //+  // error: type 'int' cannot be used prior to '::' because it has no members+  //   T::getIntDoesNotExist();+  //+  // whereas in C++ this compiles. This is caused by ClangImporter eagerly+  // instantiating typedeffed templates and also its members.
  // instantiating typedeffed templates and also their members.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H++template<class T>+struct MagicWrapper {+  T t;+  int callGetInt() const {+    return t.getInt() + 5;+  }+};++struct MagicNumber {+  int getInt() const { return 24; }+};++inline MagicWrapper<MagicNumber> forceInstantiating() {+  return MagicWrapper<MagicNumber>();+}++// MagicWrapper<MagicNumber> ClassTemplateSpecializationDecl has definition+// because function above forced the instantiation. Its members are not+// instantiated though, we need to instantiate them in Swift.
// MagicWrapper<MagicNumber> ClassTemplateSpecializationDecl has a definition
// because function above forced the instantiation. Its members are not
// instantiated though, the Swift compiler needs to instantiate them.
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_H++template<class T>+struct MagicWrapper {+  T t;+  int callGetInt() const {+    return t.getInt() + 5;+  }+};++struct MagicNumber {+  int getInt() const { return 24; }+};++inline MagicWrapper<MagicNumber> forceInstantiating() {
inline MagicWrapper<MagicNumber> forceInstantiation() {
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+#ifndef TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H+#define TEST_INTEROP_CXX_TEMPLATES_INPUTS_DECL_WITH_DEFINITION_INCLUDING_MEMBERS_H++template<class T>+struct MagicWrapper {+  T t;+  int callGetInt() const {+    return t.getInt() + 5;+  }+};++struct MagicNumber {+  int getInt() const { return 48; }+};++inline int forceInstantiating() {
inline int forceInstantiation() {
hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

+// RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-cxx-interop -Xcc -std=c++17)+//+// REQUIRES: executable_test++import CanonicalTypes+import StdlibUnittest++var TemplatesTestSuite = TestSuite("TemplatesTestSuite")++TemplatesTestSuite.test("canonical-types") {+  // multiple typedeffed types with the same canonical type are the same type+  // from the typechecking perspective.

There is a more direct way to write a typechecker test:

expectEqualType(WrappedMagicNumberA.self, WrappedMagicNumberB.self)

I'm not sure it is valuable to keep the rest of this test (including the SILGen and IRGen counterparts) -- up to you. Do keep the module interface test though.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D,     }   } +  if (auto classTemplateSpecDecl =+          dyn_cast<clang::ClassTemplateSpecializationDecl>(D)) {+    if (!isa<clang::ClassTemplatePartialSpecializationDecl>(D)) {++      auto &astContext = classTemplateSpecDecl->getASTContext();+      // Itanium mangler produces valid Swift identifiers, use it to generate a name for+      // this instantiation. This name will not appear in the native code.+      clang::MangleContext *mangler = clang::ItaniumMangleContext::create(+          astContext, astContext.getDiagnostics());+      llvm::SmallString<128> storage;+      llvm::raw_svector_ostream buffer(storage);+      mangler->mangleTypeName(astContext.getRecordType(classTemplateSpecDecl),+                              buffer);++      // We reuse mangleTypeName() which returns RTTI typeinfo name, to get the mangled type.+      // Therefore we need to strip the '_ZTS' prefix, which we replace with '__CxxTemplateInst'+      // (a prefix reserved for C++ compiler usage).+      llvm::SmallString<128> mangledNameStorage;+      llvm::raw_svector_ostream mangledName(mangledNameStorage);+      mangledName << "__CxxTemplateInst" << buffer.str().drop_front(4);

We need to document this choice in docs/ABI/Mangling.rst.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] Import `typedef`-ed template instantiations

 namespace {      Decl *VisitClassTemplateSpecializationDecl(                  const clang::ClassTemplateSpecializationDecl *decl) {-      // FIXME: We could import specializations, but perhaps only as unnamed-      // structural types.-      return nullptr;+      if (!Impl.getClangSema().isCompleteType(+              decl->getLocation(),+              Impl.getClangASTContext().getRecordType(decl))) {+        // Not importing incomplete types+        return nullptr;+      }+      auto def = dyn_cast<clang::ClassTemplateSpecializationDecl>(+          decl->getDefinition());+      assert(def && "Class template instantiation didn't have definition");+      Impl.getClangSema().InstantiateClassTemplateSpecializationMembers(

Please add a comment here that we're instantiating more than necessary.

hlopko

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

+// RUN: %empty-directory(%t)+// RUN: %target-build-swift %s -I %S/Inputs -o %t/address_only -Xfrontend -enable-cxx-interop+// RUN: %target-codesign %t/address_only+// RUN: %target-run %t/address_only 2&>1++// REQUIRES: executable_test++import TypeClassification+import StdlibUnittest++var AddressOnlyTestSuite = TestSuite("Address Only Types")++AddressOnlyTestSuite.test("Test struct with copy constructor") {+  let obj = StructWithCopyConstructorAndValue(value: 42)+  expectEqual(obj.value, 42)+}++AddressOnlyTestSuite.test("Test struct with member with copy constructor") {+  let member = StructWithCopyConstructorAndValue(value: 42)+  let obj = StructWithMemberWithCopyConstructor(member: member)+  expectEqual(obj.member.value, 42)+}++AddressOnlyTestSuite.test(+  "Test struct with copy constructor and member with copy constructor"+) {+  let member = StructWithCopyConstructorAndValue(value: 42)+  let obj = StructWithCopyConstructorAndMemberWithCopyConstructor(+    member: member+  )+  expectEqual(obj.member.value, 42)+}

Could you add the relevant patterns to type-classification-non-trivial-silgen.swift & make an IRGen test?

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

+// RUN: %empty-directory(%t)

Please rename it to type-classification-non-trivial.swift to be in line with other tests.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 struct StructDeletedDestructor {   ~StructDeletedDestructor() = delete; }; +struct StructWithCopyConstructorAndValue {+  int value;+  StructWithCopyConstructorAndValue(+      const StructWithCopyConstructorAndValue &other)+      : value(other.value) {}+};++struct StructWithMemberWithCopyConstructor {+  StructWithCopyConstructorAndValue member;+};++struct StructWithCopyConstructorAndMemberWithCopyConstructor {

"StructWithCopyConstructorAndSubobjectCopyConstructorAndValue"

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 struct StructDeletedDestructor {   ~StructDeletedDestructor() = delete; }; +struct StructWithCopyConstructorAndValue {+  int value;+  StructWithCopyConstructorAndValue(+      const StructWithCopyConstructorAndValue &other)+      : value(other.value) {}+};++struct StructWithMemberWithCopyConstructor {

"StructWithSubobjectCopyConstructorAndValue"

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 class ClangRecordLowering {   }    /// Add information to track a value field at the current offset.-  void addFieldInfo(VarDecl *swiftField, const LoadableTypeInfo &fieldType) {-    unsigned explosionSize = fieldType.getExplosionSize();+  void addFieldInfo(VarDecl *swiftField, const FixedTypeInfo &fieldType) {+    unsigned explosionSize = SwiftDecl->getStoredProperties().size();

If I understand it correctly, the concept of explosion does not make sense for address-only types, so it is not a surprise that we don't have an appropriate API to call here.

This information is eventually written into RecordField::Begin / ::End. Note that only ClangFieldInfo is setting these fields. Even StructFieldInfo is not setting them. Since this data is not correct for native Swift structs, I suspect that users of this data are dead code. Could you take a look? It is quite possible you would be able to delete some/all of this stuff.

If this data is used, I think we should either change ClangFieldInfo to be like StructFieldInfo and not set the explosion begin/end, at least when we have an address-only type.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 namespace {     }   }; +  class AddressOnlyClangRecordTypeInfo final+      : public StructTypeInfoBase<AddressOnlyClangRecordTypeInfo, FixedTypeInfo,+                                  ClangFieldInfo> {+    const clang::RecordDecl *ClangDecl;++  public:+    AddressOnlyClangRecordTypeInfo(ArrayRef<ClangFieldInfo> fields,+                                   llvm::Type *storageType, Size size,+                                   Alignment align,+                                   const clang::RecordDecl *clangDecl)+        : StructTypeInfoBase(StructTypeInfoKind::AddressOnlyClangRecordTypeInfo,+                             fields, storageType, size,+                             // Create an empty SpareBitVector with a width of

This comment repeats what the code does -- everyone should be able to figure that out. Instead, could you add a comment that explains the reason for it?

zoecarver

comment created time in 3 months

pull request commentapple/swift

[cxx-interop] Support function templates.

The IDE tooling part aspect sounds appealing; will this approach work with static_assert+constexpr and similar features which require complex compile time evaluation to type-check, or does that require operating on SIL/LLVM IR?

Instantiating the templates on the AST level is sufficient to get all errors. Clang does not produce errors from IRGen.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 namespace {       }     }   };-  ++  class ClangRecordAddressOnlyTypeInfo final+      : public StructTypeInfoBase<ClangRecordAddressOnlyTypeInfo, FixedTypeInfo,+                                  ClangFieldInfo> {+    const clang::RecordDecl *ClangDecl;++  public:+    ClangRecordAddressOnlyTypeInfo(ArrayRef<ClangFieldInfo> fields,+                                   llvm::Type *storageType, Size size,+                                   SpareBitVector &&spareBits, Alignment align,+                                   const clang::RecordDecl *clangDecl)+        : StructTypeInfoBase(StructTypeInfoKind::ClangRecordAddressOnlyTypeInfo,+                             fields, storageType, size, std::move(spareBits),+                             align, IsPOD, IsNotBitwiseTakable, IsFixedSize),+          ClangDecl(clangDecl) {+      (void)ClangDecl;

SGTM.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 class ClangRecordLowering {    const TypeInfo *createTypeInfo(llvm::StructType *llvmType) {     llvmType->setBody(LLVMFields, /*packed*/ true);+    if (SwiftType.getStructOrBoundGenericStruct()+            ->isCxxNotTriviallyCopyable()) {+      return ClangRecordAddressOnlyTypeInfo::create(+          FieldInfos, llvmType, TotalStride, std::move(SpareBits),

SGTM!

zoecarver

comment created time in 3 months

push eventapple/swift

zoecarver

commit sha b2e6068d4f2444cd8a60e86d17b81a18df05cb1a

[cxx-interop] Rename ClangRecordTypeInfo -> LoadableClangRecordTypeInfo. This is a more accurate and clear name. This change will help further differenciate between LoadableClangRecordTypeInfo and (the soon to be added) AddressOnlyClangRecordTypeInfo.

view details

Dmitri Gribenko

commit sha 1f73684c67dd2f80be006840d5250584dcd95cb6

Merge pull request #33077 from zoecarver/cxx/rename-loadable-clang-type-conv [cxx-interop] Rename ClangRecordTypeInfo -> LoadableClangRecordTypeInfo.

view details

push time in 3 months

PR merged apple/swift

[cxx-interop] Rename ClangRecordTypeInfo -> LoadableClangRecordTypeInfo. C++ Interop

This is a more accurate and clear name. This change will help further differentiate between LoadableClangRecordTypeInfo and (the soon to be added) AddressOnlyClangRecordTypeInfo.

Refs #32973.

+9 -9

1 comment

1 changed file

zoecarver

pr closed time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 class ClangRecordLowering {    const TypeInfo *createTypeInfo(llvm::StructType *llvmType) {     llvmType->setBody(LLVMFields, /*packed*/ true);+    if (SwiftType.getStructOrBoundGenericStruct()+            ->isCxxNotTriviallyCopyable()) {+      return ClangRecordAddressOnlyTypeInfo::create(+          FieldInfos, llvmType, TotalStride, std::move(SpareBits),

ClangRecordLowering::addStructField assumes that all fields will have LoadableTypeInfo (by invoking cast<LoadableTypeInfo>()) -- but that's no longer true starting with this PR. Are you getting any assertions in the testsuite when processing types that aggregate other types which we consider non-trivial?

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 class ClangRecordLowering {    const TypeInfo *createTypeInfo(llvm::StructType *llvmType) {     llvmType->setBody(LLVMFields, /*packed*/ true);+    if (SwiftType.getStructOrBoundGenericStruct()+            ->isCxxNotTriviallyCopyable()) {+      return ClangRecordAddressOnlyTypeInfo::create(+          FieldInfos, llvmType, TotalStride, std::move(SpareBits),

The FieldInfos vector will contain private data members that we're not importing. It would be good to skip private data members in ClangRecordLowering (in a future PR).

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 class ClangRecordLowering {    const TypeInfo *createTypeInfo(llvm::StructType *llvmType) {     llvmType->setBody(LLVMFields, /*packed*/ true);+    if (SwiftType.getStructOrBoundGenericStruct()+            ->isCxxNotTriviallyCopyable()) {+      return ClangRecordAddressOnlyTypeInfo::create(+          FieldInfos, llvmType, TotalStride, std::move(SpareBits),

I don't think we can assume any spare bits in a non-trivial C++ type.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 namespace {       }     }   };-  ++  class ClangRecordAddressOnlyTypeInfo final+      : public StructTypeInfoBase<ClangRecordAddressOnlyTypeInfo, FixedTypeInfo,+                                  ClangFieldInfo> {+    const clang::RecordDecl *ClangDecl;++  public:+    ClangRecordAddressOnlyTypeInfo(ArrayRef<ClangFieldInfo> fields,+                                   llvm::Type *storageType, Size size,+                                   SpareBitVector &&spareBits, Alignment align,+                                   const clang::RecordDecl *clangDecl)+        : StructTypeInfoBase(StructTypeInfoKind::ClangRecordAddressOnlyTypeInfo,+                             fields, storageType, size, std::move(spareBits),+                             align, IsPOD, IsNotBitwiseTakable, IsFixedSize),+          ClangDecl(clangDecl) {+      (void)ClangDecl;+    }++    TypeLayoutEntry *buildTypeLayoutEntry(IRGenModule &IGM,+                                          SILType T) const override {+      return IGM.typeLayoutCache.getOrCreateScalarEntry(*this, T);+    }++    void initializeFromParams(IRGenFunction &IGF, Explosion &params,+                              Address addr, SILType T,+                              bool isOutlined) const override {+      llvm_unreachable("Cannot initialize address-only type from params.");

I think we can initialize address-only type from an explosion; the reason why nobody should call this specific method is to avoid violating C++ invariants about an object having a stable address (C++ types that are non-loadable should be created/copied/moved/destroyed only by C++ special member functions). I'd suggest to reword the error to point to that instead.

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 namespace {       }     }   };-  ++  class ClangRecordAddressOnlyTypeInfo final+      : public StructTypeInfoBase<ClangRecordAddressOnlyTypeInfo, FixedTypeInfo,

Should we use IndirectTypeInfo as the base type?

zoecarver

comment created time in 3 months

Pull request review commentapple/swift

[cxx-interop] [IRGen] TypeInfo for address-only types.

 namespace {       }     }   };-  ++  class ClangRecordAddressOnlyTypeInfo final

Could you move it after ClangRecordTypeInfo to keep the order in the enum and here identical?

zoecarver

comment created time in 3 months

more