diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index 0720569da9558..5628cfe170c5b 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -3589,7 +3589,13 @@ void ClangImporter::getMangledName(raw_ostream &os, if (!Impl.Mangler) Impl.Mangler.reset(Impl.getClangASTContext().createMangleContext()); - Impl.Mangler->mangleName(clangDecl, os); + if (auto ctor = dyn_cast(clangDecl)) { + auto ctorGlobalDecl = + clang::GlobalDecl(ctor, clang::CXXCtorType::Ctor_Complete); + Impl.Mangler->mangleCXXName(ctorGlobalDecl, os); + } else { + Impl.Mangler->mangleName(clangDecl, os); + } } // --------------------------------------------------------------------------- diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index 079ded2e02094..b2128bea8b732 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -1241,6 +1241,10 @@ synthesizeStructDefaultConstructorBody(AbstractFunctionDecl *afd, ASTContext &ctx = constructor->getASTContext(); auto structDecl = static_cast(context); + // We should call into C++ constructors directly. + assert(!isa(structDecl->getClangDecl()) && + "Should not synthesize a C++ object constructor."); + // Use a builtin to produce a zero initializer, and assign it to self. // Construct the left-hand reference to self. @@ -3378,6 +3382,11 @@ namespace { continue; } + if (auto CD = dyn_cast(member)) { + ctors.push_back(CD); + continue; + } + if (auto MD = dyn_cast(member)) { methods.push_back(MD); continue; @@ -3434,12 +3443,17 @@ namespace { bool hasReferenceableFields = !members.empty(); - if (hasZeroInitializableStorage) { - // Add constructors for the struct. + const clang::CXXRecordDecl *cxxRecordDecl = + dyn_cast(decl); + if (hasZeroInitializableStorage && !cxxRecordDecl) { + // Add default constructor for the struct if compiling in C mode. + // If we're compiling for C++, we'll import the C++ default constructor + // (if there is one), so we don't need to synthesize one here. ctors.push_back(createDefaultConstructor(Impl, result)); } - if (hasReferenceableFields && hasMemberwiseInitializer) { + bool isAggregate = !cxxRecordDecl || cxxRecordDecl->isAggregate(); + if (hasReferenceableFields && hasMemberwiseInitializer && isAggregate) { // The default zero initializer suppresses the implicit value // constructor that would normally be formed, so we have to add that // explicitly as well. @@ -3470,7 +3484,7 @@ namespace { result->setHasUnreferenceableStorage(hasUnreferenceableStorage); - if (auto cxxRecordDecl = dyn_cast(decl)) { + if (cxxRecordDecl) { result->setIsCxxNonTrivial(!cxxRecordDecl->isTriviallyCopyable()); for (auto ctor : cxxRecordDecl->ctors()) { @@ -3491,6 +3505,34 @@ namespace { return result; } + Decl *VisitCXXRecordDecl(const clang::CXXRecordDecl *decl) { + // This can be called from lldb without C++ interop being enabled: There + // may be C++ declarations in imported modules, but the interface for + // those modules may be a pure C or Objective-C interface. + // To avoid crashing in Clang's Sema, fall back to importing this as a + // plain RecordDecl. + if (!Impl.SwiftContext.LangOpts.EnableCXXInterop) + return VisitRecordDecl(decl); + + auto &clangSema = Impl.getClangSema(); + // Make Clang define the implicit default constructor if the class needs + // it. Make sure we only do this if the class has been fully defined and + // we're not in a dependent context (this is equivalent to the logic in + // CanDeclareSpecialMemberFunction in Clang's SemaLookup.cpp). + if (decl->getDefinition() && !decl->isBeingDefined() && + !decl->isDependentContext() && + decl->needsImplicitDefaultConstructor()) { + clang::CXXConstructorDecl *ctor = + clangSema.DeclareImplicitDefaultConstructor( + const_cast(decl)); + if (!ctor->isDeleted()) + clangSema.DefineImplicitDefaultConstructor(clang::SourceLocation(), + ctor); + } + + return VisitRecordDecl(decl); + } + Decl *VisitClassTemplateSpecializationDecl( const clang::ClassTemplateSpecializationDecl *decl) { // `Sema::isCompleteType` will try to instantiate the class template as a @@ -3514,7 +3556,7 @@ namespace { Impl.getClangSema().InstantiateClassTemplateSpecializationMembers( def->getLocation(), def, clang::TSK_ExplicitInstantiationDefinition); - return VisitRecordDecl(def); + return VisitCXXRecordDecl(def); } Decl *VisitClassTemplatePartialSpecializationDecl( @@ -3745,6 +3787,9 @@ namespace { ImportedName importedName, Optional correctSwiftName, Optional accessorInfo) { + if (decl->isDeleted()) + return nullptr; + auto dc = Impl.importDeclContextOf(decl, importedName.getEffectiveContext()); if (!dc) @@ -3753,7 +3798,6 @@ namespace { DeclName name = accessorInfo ? DeclName() : importedName.getDeclName(); auto selfIdx = importedName.getSelfIndex(); - FuncDecl *result = nullptr; ImportedType importedType; bool selfIsInOut = false; ParameterList *bodyParams = nullptr; @@ -3855,27 +3899,48 @@ namespace { if (!importedType) return nullptr; - auto resultTy = importedType.getType(); auto loc = Impl.importSourceLoc(decl->getLocation()); // FIXME: Poor location info. auto nameLoc = Impl.importSourceLoc(decl->getLocation()); - result = createFuncOrAccessor( - Impl.SwiftContext, loc, accessorInfo, name, - nameLoc, bodyParams, resultTy, - /*async*/ false, /*throws*/ false, dc, decl); - - if (!dc->isModuleScopeContext()) { - if (selfIsInOut) - result->setSelfAccessKind(SelfAccessKind::Mutating); - else - result->setSelfAccessKind(SelfAccessKind::NonMutating); - if (selfIdx) { - result->setSelfIndex(selfIdx.getValue()); - } else { - result->setStatic(); - result->setImportAsStaticMember(); + + AbstractFunctionDecl *result = nullptr; + if (auto *ctordecl = dyn_cast(decl)) { + // Don't import copy constructor or move constructor -- these will be + // provided through the value witness table. + if (ctordecl->isCopyConstructor() || ctordecl->isMoveConstructor()) + return nullptr; + + DeclName ctorName(Impl.SwiftContext, DeclBaseName::createConstructor(), + bodyParams); + result = Impl.createDeclWithClangNode( + decl, AccessLevel::Public, ctorName, loc, /*failable=*/false, + /*FailabilityLoc=*/SourceLoc(), /*Throws=*/false, + /*ThrowsLoc=*/SourceLoc(), bodyParams, /*GenericParams=*/nullptr, + dc); + } else { + auto resultTy = importedType.getType(); + + FuncDecl *func = + createFuncOrAccessor(Impl.SwiftContext, loc, accessorInfo, name, + nameLoc, bodyParams, resultTy, + /*async=*/false, /*throws=*/false, dc, decl); + result = func; + + if (!dc->isModuleScopeContext()) { + if (selfIsInOut) + func->setSelfAccessKind(SelfAccessKind::Mutating); + else + func->setSelfAccessKind(SelfAccessKind::NonMutating); + if (selfIdx) { + func->setSelfIndex(selfIdx.getValue()); + } else { + func->setStatic(); + func->setImportAsStaticMember(); + } } + // Someday, maybe this will need to be 'open' for C++ virtual methods. + func->setAccess(AccessLevel::Public); } result->setIsObjC(false); @@ -3889,8 +3954,6 @@ namespace { result->getAttrs().add(new (Impl.SwiftContext) FinalAttr(/*IsImplicit=*/true)); - // 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. diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp index cae15627ba7ef..9e22535c2fddf 100644 --- a/lib/ClangImporter/ImportName.cpp +++ b/lib/ClangImporter/ImportName.cpp @@ -1366,6 +1366,15 @@ static bool suppressFactoryMethodAsInit(const clang::ObjCMethodDecl *method, initKind == CtorInitializerKind::ConvenienceFactory); } +static void +addEmptyArgNamesForClangFunction(const clang::FunctionDecl *funcDecl, + SmallVectorImpl &argumentNames) { + for (size_t i = 0; i < funcDecl->param_size(); ++i) + argumentNames.push_back(StringRef()); + if (funcDecl->isVariadic()) + argumentNames.push_back(StringRef()); +} + ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, ImportNameVersion version, clang::DeclarationName givenName) { @@ -1599,7 +1608,19 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, SmallString<16> selectorSplitScratch; ArrayRef params; switch (D->getDeclName().getNameKind()) { - case clang::DeclarationName::CXXConstructorName: + case clang::DeclarationName::CXXConstructorName: { + isInitializer = true; + isFunction = true; + result.info.initKind = CtorInitializerKind::Designated; + baseName = "init"; + auto ctor = dyn_cast(D); + if (auto templateCtor = dyn_cast(D)) + ctor = cast(templateCtor->getAsFunction()); + assert(ctor && "Unkown decl with CXXConstructorName."); + addEmptyArgNamesForClangFunction(ctor, argumentNames); + break; + } + case clang::DeclarationName::CXXConversionFunctionName: case clang::DeclarationName::CXXDestructorName: case clang::DeclarationName::CXXLiteralOperatorName: @@ -1670,16 +1691,9 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, } } - // For C functions, create empty argument names. if (auto function = dyn_cast(D)) { isFunction = true; - params = {function->param_begin(), function->param_end()}; - for (auto param : params) { - (void)param; - argumentNames.push_back(StringRef()); - } - if (function->isVariadic()) - argumentNames.push_back(StringRef()); + addEmptyArgNamesForClangFunction(function, argumentNames); } break; diff --git a/lib/IRGen/GenCall.cpp b/lib/IRGen/GenCall.cpp index a544328dc0193..b795d16d433d8 100644 --- a/lib/IRGen/GenCall.cpp +++ b/lib/IRGen/GenCall.cpp @@ -1269,6 +1269,16 @@ void SignatureExpansion::expandExternalSignatureTypes() { SmallVector paramTys; auto const &clangCtx = IGM.getClangASTContext(); + bool formalIndirectResult = FnType->getNumResults() > 0 && + FnType->getSingleResult().isFormalIndirect(); + if (formalIndirectResult) { + auto resultType = getSILFuncConventions().getSingleSILResultType( + IGM.getMaximalTypeExpansionContext()); + auto clangTy = + IGM.getClangASTContext().getPointerType(IGM.getClangType(resultType)); + paramTys.push_back(clangTy); + } + switch (FnType->getRepresentation()) { case SILFunctionTypeRepresentation::ObjCMethod: { // ObjC methods take their 'self' argument first, followed by an @@ -1900,6 +1910,9 @@ class SyncCallEmission final : public CallEmission { // This can happen when calling C functions, or class method dispatch thunks // for methods that have covariant ABI-compatible overrides. auto expectedNativeResultType = nativeSchema.getExpandedType(IGF.IGM); + // If the expected result type is void, bail. + if (expectedNativeResultType->isVoidTy()) + return; if (result->getType() != expectedNativeResultType) { result = IGF.coerceValue(result, expectedNativeResultType, IGF.IGM.DataLayout); @@ -2797,6 +2810,11 @@ static void externalizeArguments(IRGenFunction &IGF, const Callee &callee, == SILFunctionTypeRepresentation::Block) { // Ignore the physical block-object parameter. firstParam += 1; + // Or the indirect result parameter. + } else if (fnType->getNumResults() > 0 && + fnType->getSingleResult().isFormalIndirect()) { + // Ignore the indirect result parameter. + firstParam += 1; } for (unsigned i = firstParam, e = FI.arg_size(); i != e; ++i) { diff --git a/lib/IRGen/GenDecl.cpp b/lib/IRGen/GenDecl.cpp index 15e88148e0afe..e8aff92311183 100644 --- a/lib/IRGen/GenDecl.cpp +++ b/lib/IRGen/GenDecl.cpp @@ -38,6 +38,8 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/GlobalDecl.h" +#include "clang/CodeGen/CodeGenABITypes.h" +#include "clang/CodeGen/ModuleBuilder.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalAlias.h" @@ -2761,6 +2763,77 @@ void IRGenModule::emitDynamicReplacementOriginalFunctionThunk(SILFunction *f) { IGF.Builder.CreateRet(Res); } +/// If the calling convention for `ctor` doesn't match the calling convention +/// that we assumed for it when we imported it as `initializer`, emit and +/// return a thunk that conforms to the assumed calling convention. The thunk +/// is marked `alwaysinline`, so it doesn't generate any runtime overhead. +/// If the assumed calling convention was correct, just return `ctor`. +/// +/// See also comments in CXXMethodConventions in SIL/IR/SILFunctionType.cpp. +static llvm::Constant * +emitCXXConstructorThunkIfNeeded(IRGenModule &IGM, SILFunction *initializer, + const clang::CXXConstructorDecl *ctor, + const LinkEntity &entity, + llvm::Constant *ctorAddress) { + Signature signature = IGM.getSignature(initializer->getLoweredFunctionType()); + + llvm::FunctionType *assumedFnType = signature.getType(); + llvm::FunctionType *ctorFnType = + cast(ctorAddress->getType()->getPointerElementType()); + + if (assumedFnType == ctorFnType) { + return ctorAddress; + } + + // The thunk has private linkage, so it doesn't need to have a predictable + // mangled name -- we just need to make sure the name is unique. + llvm::SmallString<32> name; + llvm::raw_svector_ostream stream(name); + stream << "__swift_cxx_ctor"; + entity.mangle(stream); + + llvm::Function *thunk = llvm::Function::Create( + assumedFnType, llvm::Function::PrivateLinkage, name, &IGM.Module); + + thunk->setCallingConv(llvm::CallingConv::C); + + llvm::AttrBuilder attrBuilder; + IGM.constructInitialFnAttributes(attrBuilder); + attrBuilder.addAttribute(llvm::Attribute::AlwaysInline); + llvm::AttributeList attr = signature.getAttributes().addAttributes( + IGM.getLLVMContext(), llvm::AttributeList::FunctionIndex, attrBuilder); + thunk->setAttributes(attr); + + IRGenFunction subIGF(IGM, thunk); + if (IGM.DebugInfo) + IGM.DebugInfo->emitArtificialFunction(subIGF, thunk); + + SmallVector Args; + for (auto i = thunk->arg_begin(), e = thunk->arg_end(); i != e; ++i) { + auto *argTy = i->getType(); + auto *paramTy = ctorFnType->getParamType(i - thunk->arg_begin()); + if (paramTy != argTy) + Args.push_back(subIGF.coerceValue(i, paramTy, IGM.DataLayout)); + else + Args.push_back(i); + } + + clang::CodeGen::ImplicitCXXConstructorArgs implicitArgs = + clang::CodeGen::getImplicitCXXConstructorArgs(IGM.ClangCodeGen->CGM(), + ctor); + for (size_t i = 0; i < implicitArgs.Prefix.size(); ++i) { + Args.insert(Args.begin() + 1 + i, implicitArgs.Prefix[i]); + } + for (const auto &arg : implicitArgs.Suffix) { + Args.push_back(arg); + } + + subIGF.Builder.CreateCall(ctorFnType, ctorAddress, Args); + subIGF.Builder.CreateRetVoid(); + + return thunk; +} + /// Find the entry point for a SIL function. llvm::Function *IRGenModule::getAddrOfSILFunction( SILFunction *f, ForDefinition_t forDefinition, @@ -2789,6 +2862,11 @@ llvm::Function *IRGenModule::getAddrOfSILFunction( if (auto clangDecl = f->getClangDecl()) { auto globalDecl = getClangGlobalDeclForFunction(clangDecl); clangAddr = getAddrOfClangGlobalDecl(globalDecl, forDefinition); + + if (auto ctor = dyn_cast(clangDecl)) { + clangAddr = + emitCXXConstructorThunkIfNeeded(*this, f, ctor, entity, clangAddr); + } } bool isDefinition = f->isDefinition(); diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index fc175f4460017..f1037df2b1550 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -2788,6 +2788,27 @@ class CXXMethodConventions : public CFunctionTypeConventions { return ParameterConvention::Indirect_In_Guaranteed; return ParameterConvention::Indirect_Inout; } + ResultConvention getResult(const TypeLowering &resultTL) const override { + if (isa(TheDecl)) { + // Represent the `this` pointer as an indirectly returned result. + // This gets us most of the way towards representing the ABI of a + // constructor correctly, but it's not guaranteed to be entirely correct. + // C++ constructor ABIs are complicated and can require passing additional + // "implicit" arguments that depend not only on the signature of the + // constructor but on the class on which it's defined (e.g. whether that + // class has a virtual base class). + // Effectively, we're making an assumption here that there are no implicit + // arguments and that the return type of the constructor ABI is void (and + // indeed we have no way to represent anything else here). If this assumed + // ABI doesn't match the actual ABI, we insert a thunk in IRGen. On some + // ABIs (e.g. Itanium x64), we get lucky and the ABI for a complete + // constructor call always matches the ABI we assume here. Even if the + // actual ABI doesn't match the assumed ABI, we try to get as close as + // possible to make it easy for LLVM to optimize away the thunk. + return ResultConvention::Indirect; + } + return CFunctionTypeConventions::getResult(resultTL); + } static bool classof(const Conventions *C) { return C->getKind() == ConventionsKind::CXXMethod; } @@ -4201,7 +4222,17 @@ TypeConverter::getLoweredFormalTypes(SILDeclRef constant, if (innerExtInfo.isAsync()) extInfo = extInfo.withAsync(true); - bridgedParams.push_back(selfParam); + // If this is a C++ constructor, don't add the metatype "self" parameter + // because we'll never use it and it will cause problems in IRGen. + if (constant.getDecl()->getClangDecl() && + isa(constant.getDecl()->getClangDecl())) { + // But, make sure it is actually a metatype that we're not adding. If + // changes to the self parameter are made in the future, this logic may + // need to be updated. + assert(selfParam.getParameterType()->is()); + } else { + bridgedParams.push_back(selfParam); + } auto uncurried = CanAnyFunctionType::get(genericSig, diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index 65c44598af668..70a2611f44e37 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -27,9 +27,9 @@ #include "swift/AST/ForeignErrorConvention.h" #include "swift/AST/GenericEnvironment.h" #include "swift/AST/GenericSignature.h" -#include "swift/AST/ParameterList.h" #include "swift/AST/Module.h" #include "swift/AST/ModuleLoader.h" +#include "swift/AST/ParameterList.h" #include "swift/AST/SubstitutionMap.h" #include "swift/Basic/ExternalUnion.h" #include "swift/Basic/Range.h" @@ -37,6 +37,7 @@ #include "swift/Basic/Unicode.h" #include "swift/SIL/PrettyStackTrace.h" #include "swift/SIL/SILArgument.h" +#include "clang/AST/DeclCXX.h" #include "llvm/Support/Compiler.h" using namespace swift; @@ -559,6 +560,11 @@ class Callee { result.foreignError = func->getForeignErrorConvention(); result.foreignSelf = func->getImportAsMemberStatus(); + // Remove the metatype "self" parameter by making this a static member. + if (constant->getDecl()->getClangDecl() && + isa(constant->getDecl()->getClangDecl())) + result.foreignSelf.setStatic(); + return result; } diff --git a/test/Interop/Cxx/class/Inputs/constructors-objc.h b/test/Interop/Cxx/class/Inputs/constructors-objc.h new file mode 100644 index 0000000000000..46d7667a0095d --- /dev/null +++ b/test/Interop/Cxx/class/Inputs/constructors-objc.h @@ -0,0 +1,5 @@ +#import + +struct ConstructorWithNSArrayParam { + ConstructorWithNSArrayParam(NSArray *array) {} +}; diff --git a/test/Interop/Cxx/class/Inputs/constructors.h b/test/Interop/Cxx/class/Inputs/constructors.h new file mode 100644 index 0000000000000..738b13472f70a --- /dev/null +++ b/test/Interop/Cxx/class/Inputs/constructors.h @@ -0,0 +1,45 @@ +struct ExplicitDefaultConstructor { + ExplicitDefaultConstructor() : x(42) {} + int x; +}; + +struct ImplicitDefaultConstructor { + int x = 42; +}; + +struct MemberOfClassType { + ImplicitDefaultConstructor member; +}; + +struct DefaultConstructorDeleted { + DefaultConstructorDeleted() = delete; + int &a; +}; + +struct ConstructorWithParam { + ConstructorWithParam(int val) : x(val + 42) {} + int x; +}; + +struct CopyAndMoveConstructor { + CopyAndMoveConstructor(const CopyAndMoveConstructor &) = default; + CopyAndMoveConstructor(CopyAndMoveConstructor &&) = default; +}; + +struct Base {}; + +struct ArgType { + int i = 42; +}; + +struct HasVirtualBase : public virtual Base { + HasVirtualBase() = delete; + HasVirtualBase(ArgType Arg) {} + int i; +}; + +struct EmptyStruct {}; + +struct IntWrapper { + int x; +}; diff --git a/test/Interop/Cxx/class/Inputs/module.modulemap b/test/Interop/Cxx/class/Inputs/module.modulemap index 04c3bdedfda87..53ee329a23d7a 100644 --- a/test/Interop/Cxx/class/Inputs/module.modulemap +++ b/test/Interop/Cxx/class/Inputs/module.modulemap @@ -6,6 +6,18 @@ module TypeClassification { header "type-classification.h" } +module Constructors { + header "constructors.h" +} + +module ConstructorsObjC { + header "constructors-objc.h" +} + +module LoadableTypes { + header "loadable-types.h" +} + module MemberwiseInitializer { header "memberwise-initializer.h" } diff --git a/test/Interop/Cxx/class/Inputs/synthesized-initializers.h b/test/Interop/Cxx/class/Inputs/synthesized-initializers.h deleted file mode 100644 index da20bf036bd10..0000000000000 --- a/test/Interop/Cxx/class/Inputs/synthesized-initializers.h +++ /dev/null @@ -1,5 +0,0 @@ -struct EmptyStruct {}; - -struct IntBox { - int x; -}; diff --git a/test/Interop/Cxx/class/Inputs/type-classification.h b/test/Interop/Cxx/class/Inputs/type-classification.h index 09322bb5d0d1e..176e22e1701af 100644 --- a/test/Interop/Cxx/class/Inputs/type-classification.h +++ b/test/Interop/Cxx/class/Inputs/type-classification.h @@ -157,6 +157,8 @@ struct StructDeletedDestructor { struct StructWithCopyConstructorAndValue { int value; + StructWithCopyConstructorAndValue() : value(0) {} + StructWithCopyConstructorAndValue(int value) : value(value) {} StructWithCopyConstructorAndValue( const StructWithCopyConstructorAndValue &other) : value(other.value) {} @@ -168,6 +170,9 @@ struct StructWithSubobjectCopyConstructorAndValue { struct StructWithCopyConstructorAndSubobjectCopyConstructorAndValue { StructWithCopyConstructorAndValue member; + StructWithCopyConstructorAndSubobjectCopyConstructorAndValue( + StructWithCopyConstructorAndValue member) + : member(member) {} StructWithCopyConstructorAndSubobjectCopyConstructorAndValue( const StructWithCopyConstructorAndSubobjectCopyConstructorAndValue &other) : member(other.member) {} diff --git a/test/Interop/Cxx/class/constructors-executable.swift b/test/Interop/Cxx/class/constructors-executable.swift new file mode 100644 index 0000000000000..04a8b9912b926 --- /dev/null +++ b/test/Interop/Cxx/class/constructors-executable.swift @@ -0,0 +1,34 @@ +// RUN: %target-run-simple-swift(-I %S/Inputs/ -Xfrontend -enable-cxx-interop) +// +// REQUIRES: executable_test + +import StdlibUnittest +import Constructors + +var CxxConstructorTestSuite = TestSuite("CxxConstructors") + +CxxConstructorTestSuite.test("ExplicitDefaultConstructor") { + let instance = ExplicitDefaultConstructor() + + expectEqual(42, instance.x) +} + +CxxConstructorTestSuite.test("ImplicitDefaultConstructor") { + let instance = ImplicitDefaultConstructor() + + expectEqual(42, instance.x) +} + +CxxConstructorTestSuite.test("MemberOfClassType") { + let instance = MemberOfClassType() + + expectEqual(42, instance.member.x) +} + +CxxConstructorTestSuite.test("ConstructorWithParam") { + let instance = ConstructorWithParam(2) + + expectEqual(44, instance.x) +} + +runAllTests() diff --git a/test/Interop/Cxx/class/constructors-irgen.swift b/test/Interop/Cxx/class/constructors-irgen.swift new file mode 100644 index 0000000000000..4c4999bac484e --- /dev/null +++ b/test/Interop/Cxx/class/constructors-irgen.swift @@ -0,0 +1,80 @@ +// Target-specific tests for C++ constructor call code generation. + +// RUN: %swift -module-name Swift -target x86_64-apple-macosx10.9 -dump-clang-diagnostics -I %S/Inputs -enable-cxx-interop -emit-ir %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=ITANIUM_X64 +// RUN: %swift -module-name Swift -target armv7-none-linux-androideabi -dump-clang-diagnostics -I %S/Inputs -enable-cxx-interop -emit-ir %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=ITANIUM_ARM +// RUN: %swift -module-name Swift -target x86_64-unknown-windows-msvc -dump-clang-diagnostics -I %S/Inputs -enable-cxx-interop -emit-ir %s -parse-stdlib -parse-as-library -disable-legacy-type-info | %FileCheck %s -check-prefix=MICROSOFT_X64 + +import Constructors +import TypeClassification + +typealias Void = () +struct UnsafePointer { } +struct UnsafeMutablePointer { } + +public func createHasVirtualBase() -> HasVirtualBase { + // ITANIUM_X64: define swiftcc void @"$ss20createHasVirtualBaseSo0bcD0VyF"(%TSo14HasVirtualBaseV* noalias nocapture sret %0) + // ITANIUM_X64-NOT: define + // ITANIUM_X64: call void @_ZN14HasVirtualBaseC1E7ArgType(%struct.HasVirtualBase* %{{[0-9]+}}, i32 %{{[0-9]+}}) + // + // ITANIUM_ARM: define protected swiftcc void @"$ss20createHasVirtualBaseSo0bcD0VyF"(%TSo14HasVirtualBaseV* noalias nocapture sret %0) + // To verify that the thunk is inlined, make sure there's no intervening + // `define`, i.e. the call to the C++ constructor happens in + // createHasVirtualBase(), not some later function. + // ITANIUM_ARM-NOT: define + // Note `this` return type. + // ITANIUM_ARM: call %struct.HasVirtualBase* @_ZN14HasVirtualBaseC1E7ArgType(%struct.HasVirtualBase* %{{[0-9]+}}, [1 x i32] %{{[0-9]+}}) + // + // MICROSOFT_X64: define dllexport swiftcc void @"$ss20createHasVirtualBaseSo0bcD0VyF"(%TSo14HasVirtualBaseV* noalias nocapture sret %0) + // MICROSOFT_X64-NOT: define + // Note `this` return type and implicit "most derived" argument. + // MICROSOFT_X64: call %struct.HasVirtualBase* @"??0HasVirtualBase@@QEAA@UArgType@@@Z"(%struct.HasVirtualBase* %{{[0-9]+}}, i32 %{{[0-9]+}}, i32 1) + return HasVirtualBase(ArgType()) +} + +public func createImplicitDefaultConstructor() -> ImplicitDefaultConstructor { + // ITANIUM_X64: define swiftcc i32 @"$ss32createImplicitDefaultConstructorSo0bcD0VyF"() + // ITANIUM_X64-NOT: define + // ITANIUM_X64: call void @_ZN26ImplicitDefaultConstructorC1Ev(%struct.ImplicitDefaultConstructor* %{{[0-9]+}}) + // + // ITANIUM_ARM: define protected swiftcc i32 @"$ss32createImplicitDefaultConstructorSo0bcD0VyF"() + // ITANIUM_ARM-NOT: define + // Note `this` return type. + // ITANIUM_ARM: call %struct.ImplicitDefaultConstructor* @_ZN26ImplicitDefaultConstructorC2Ev(%struct.ImplicitDefaultConstructor* %{{[0-9]+}}) + // + // MICROSOFT_X64: define dllexport swiftcc i32 @"$ss32createImplicitDefaultConstructorSo0bcD0VyF"() + // MICROSOFT_X64-NOT: define + // Note `this` return type but no implicit "most derived" argument. + // MICROSOFT_X64: call %struct.ImplicitDefaultConstructor* @"??0ImplicitDefaultConstructor@@QEAA@XZ"(%struct.ImplicitDefaultConstructor* %{{[0-9]+}}) + return ImplicitDefaultConstructor() +} + +public func createStructWithSubobjectCopyConstructorAndValue() { + // ITANIUM_X64-LABEL: define swiftcc void @"$ss48createStructWithSubobjectCopyConstructorAndValueyyF"() + // ITANIUM_X64: [[MEMBER:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV + // ITANIUM_X64: [[MEMBER_AS_STRUCT:%.*]] = bitcast %TSo33StructWithCopyConstructorAndValueV* %member to %struct.StructWithCopyConstructorAndValue* + // ITANIUM_X64: void @_ZN33StructWithCopyConstructorAndValueC1Ev(%struct.StructWithCopyConstructorAndValue* [[MEMBER_AS_STRUCT]]) + // ITANIUM_X64: call %TSo33StructWithCopyConstructorAndValueV* @"$sSo33StructWithCopyConstructorAndValueVWOc"(%TSo33StructWithCopyConstructorAndValueV* [[MEMBER]], %TSo33StructWithCopyConstructorAndValueV* [[TMP:%.*]]) + // ITANIUM_X64: [[OBJ_MEMBER:%.*]] = getelementptr inbounds %TSo42StructWithSubobjectCopyConstructorAndValueV, %TSo42StructWithSubobjectCopyConstructorAndValueV* %obj, i32 0, i32 0 + // ITANIUM_X64: call %TSo33StructWithCopyConstructorAndValueV* @"$sSo33StructWithCopyConstructorAndValueVWOb"(%TSo33StructWithCopyConstructorAndValueV* [[TMP]], %TSo33StructWithCopyConstructorAndValueV* [[OBJ_MEMBER]]) + // ITANIUM_X64: ret void + + // ITANIUM_ARM-LABEL: define protected swiftcc void @"$ss48createStructWithSubobjectCopyConstructorAndValueyyF"() + // ITANIUM_ARM: [[MEMBER:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV + // ITANIUM_ARM: [[MEMBER_AS_STRUCT:%.*]] = bitcast %TSo33StructWithCopyConstructorAndValueV* %member to %struct.StructWithCopyConstructorAndValue* + // ITANIUM_ARM: call %struct.StructWithCopyConstructorAndValue* @_ZN33StructWithCopyConstructorAndValueC2Ev(%struct.StructWithCopyConstructorAndValue* [[MEMBER_AS_STRUCT]]) + // ITANIUM_ARM: call %TSo33StructWithCopyConstructorAndValueV* @"$sSo33StructWithCopyConstructorAndValueVWOc"(%TSo33StructWithCopyConstructorAndValueV* [[MEMBER]], %TSo33StructWithCopyConstructorAndValueV* [[TMP:%.*]]) + // ITANIUM_ARM: [[OBJ_MEMBER:%.*]] = getelementptr inbounds %TSo42StructWithSubobjectCopyConstructorAndValueV, %TSo42StructWithSubobjectCopyConstructorAndValueV* %obj, i32 0, i32 0 + // ITANIUM_ARM: call %TSo33StructWithCopyConstructorAndValueV* @"$sSo33StructWithCopyConstructorAndValueVWOb"(%TSo33StructWithCopyConstructorAndValueV* [[TMP]], %TSo33StructWithCopyConstructorAndValueV* [[OBJ_MEMBER]]) + // ITANIUM_ARM: ret void + + // MICROSOFT_X64-LABEL: define dllexport swiftcc void @"$ss48createStructWithSubobjectCopyConstructorAndValueyyF"() + // MICROSOFT_X64: [[MEMBER:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV + // MICROSOFT_X64: [[MEMBER_AS_STRUCT:%.*]] = bitcast %TSo33StructWithCopyConstructorAndValueV* %member to %struct.StructWithCopyConstructorAndValue* + // MICROSOFT_X64: call %struct.StructWithCopyConstructorAndValue* @"??0StructWithCopyConstructorAndValue@@QEAA@XZ"(%struct.StructWithCopyConstructorAndValue* [[MEMBER_AS_STRUCT]]) + // MICROSOFT_X64: call %TSo33StructWithCopyConstructorAndValueV* @"$sSo33StructWithCopyConstructorAndValueVWOc"(%TSo33StructWithCopyConstructorAndValueV* [[MEMBER]], %TSo33StructWithCopyConstructorAndValueV* [[TMP:%.*]]) + // MICROSOFT_X64: [[OBJ_MEMBER:%.*]] = getelementptr inbounds %TSo42StructWithSubobjectCopyConstructorAndValueV, %TSo42StructWithSubobjectCopyConstructorAndValueV* %obj, i32 0, i32 0 + // MICROSOFT_X64: call %TSo33StructWithCopyConstructorAndValueV* @"$sSo33StructWithCopyConstructorAndValueVWOb"(%TSo33StructWithCopyConstructorAndValueV* [[TMP]], %TSo33StructWithCopyConstructorAndValueV* [[OBJ_MEMBER]]) + // MICROSOFT_X64: ret void + let member = StructWithCopyConstructorAndValue() + let obj = StructWithSubobjectCopyConstructorAndValue(member: member) +} diff --git a/test/Interop/Cxx/class/constructors-module-interface.swift b/test/Interop/Cxx/class/constructors-module-interface.swift new file mode 100644 index 0000000000000..672c11692641c --- /dev/null +++ b/test/Interop/Cxx/class/constructors-module-interface.swift @@ -0,0 +1,38 @@ +// RUN: %target-swift-ide-test -print-module -module-to-print=Constructors -I %S/Inputs/ -source-filename=x -enable-cxx-interop | %FileCheck %s + +// CHECK: struct ExplicitDefaultConstructor { +// CHECK-NEXT: var x: Int32 +// CHECK-NEXT: init() +// CHECK-NEXT: } +// CHECK-NEXT: struct ImplicitDefaultConstructor { +// CHECK-NEXT: var x: Int32 +// CHECK-NEXT: init() +// CHECK-NEXT: init(x: Int32) +// CHECK-NEXT: } +// CHECK-NEXT: struct MemberOfClassType { +// CHECK-NEXT: var member: ImplicitDefaultConstructor +// CHECK-NEXT: init() +// CHECK-NEXT: init(member: ImplicitDefaultConstructor) +// CHECK-NEXT: } +// CHECK-NEXT: struct DefaultConstructorDeleted { +// CHECK-NEXT: var a: UnsafeMutablePointer +// CHECK-NEXT: init(a: UnsafeMutablePointer) +// CHECK-NEXT: } +// CHECK-NEXT: struct ConstructorWithParam { +// CHECK-NEXT: var x: Int32 +// CHECK-NEXT: init(_ val: Int32) +// CHECK-NEXT: } +// CHECK-NEXT: struct CopyAndMoveConstructor { +// CHECK-NEXT: } +// CHECK-NEXT: struct Base { +// CHECK-NEXT: init() +// CHECK-NEXT: } +// CHECK-NEXT: struct ArgType { +// CHECK-NEXT: var i: Int32 +// CHECK-NEXT: init() +// CHECK-NEXT: init(i: Int32) +// CHECK-NEXT: } +// CHECK-NEXT: struct HasVirtualBase { +// CHECK-NEXT: var i: Int32 +// CHECK-NEXT: init(_ Arg: ArgType) +// CHECK-NEXT: } diff --git a/test/Interop/Cxx/class/constructors-objc-irgen.swift b/test/Interop/Cxx/class/constructors-objc-irgen.swift new file mode 100644 index 0000000000000..9b9a0c939708f --- /dev/null +++ b/test/Interop/Cxx/class/constructors-objc-irgen.swift @@ -0,0 +1,16 @@ +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs -enable-cxx-interop -emit-ir %s | %FileCheck %s + +// REQUIRES: CPU=x86_64 +// REQUIRES: objc_interop + +import ConstructorsObjC + +public func createConstructorWithNSArrayParam() -> ConstructorWithNSArrayParam { + // CHECK: define swiftcc void @"$s4main33createConstructorWithNSArrayParamSo0cdeF0VyF"() + // CHECK-NOT: define + // CHECK: [[VAR:%[0-9]+]] = alloca %TSo27ConstructorWithNSArrayParamV, align 1 + // CHECK: %{{[0-9]+}} = call swiftcc %TSo7NSArrayC* @"$sSa10FoundationE19_bridgeToObjectiveCSo7NSArrayCyF"(%swift.bridge* %{{[0-9]+}}, %swift.type* getelementptr inbounds (%swift.full_type, %swift.full_type* @"$sypN", i32 0, i32 1)) + // CHECK: [[CAST_VAR:%[0-9]+]] = bitcast %TSo27ConstructorWithNSArrayParamV* [[VAR]] to %struct.ConstructorWithNSArrayParam* + // CHECK: call void @_ZN27ConstructorWithNSArrayParamC1EP7NSArray(%struct.ConstructorWithNSArrayParam* [[CAST_VAR]], [[VAR]]* %{{[0-9]+}}) + return ConstructorWithNSArrayParam([]) +} diff --git a/test/Interop/Cxx/class/constructors-objc-module-interface.swift b/test/Interop/Cxx/class/constructors-objc-module-interface.swift new file mode 100644 index 0000000000000..b636bfae24c64 --- /dev/null +++ b/test/Interop/Cxx/class/constructors-objc-module-interface.swift @@ -0,0 +1,10 @@ +// Test that Objective-C types passed to a C++ constructor are bridged +// correctly. + +// RUN: %target-swift-ide-test(mock-sdk: %clang-importer-sdk) -print-module -module-to-print=ConstructorsObjC -I %S/Inputs/ -source-filename=x -enable-cxx-interop | %FileCheck %s + +// REQUIRES: objc_interop + +// CHECK: struct ConstructorWithNSArrayParam { +// CHECK-NEXT: init(_ array: [Any]!) +// CHECK-NEXT: } diff --git a/test/Interop/Cxx/class/constructors-objc-silgen.swift b/test/Interop/Cxx/class/constructors-objc-silgen.swift new file mode 100644 index 0000000000000..6e1b907d2b472 --- /dev/null +++ b/test/Interop/Cxx/class/constructors-objc-silgen.swift @@ -0,0 +1,11 @@ +// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -I %S/Inputs -enable-cxx-interop -emit-sil %s | %FileCheck %s + +// REQUIRES: objc_interop + +import ConstructorsObjC + +// CHECK: [[VAR:%[0-9]+]] = alloc_stack $ConstructorWithNSArrayParam +// CHECK: [[OPT_ARRAY:%[0-9]+]] = enum $Optional, #Optional.some!enumelt, %{{[0-9]+}} : $NSArray +// CHECK: [[FUNC:%[0-9]+]] = function_ref @_ZN27ConstructorWithNSArrayParamC1EP7NSArray : $@convention(c) (Optional) -> @out ConstructorWithNSArrayParam +// CHECK: %{{[0-9]+}} = apply [[FUNC]]([[VAR]], [[OPT_ARRAY]]) : $@convention(c) (Optional) -> @out ConstructorWithNSArrayParam +let _ = ConstructorWithNSArrayParam([]) diff --git a/test/Interop/Cxx/class/constructors-silgen.swift b/test/Interop/Cxx/class/constructors-silgen.swift new file mode 100644 index 0000000000000..3e256b4746e7e --- /dev/null +++ b/test/Interop/Cxx/class/constructors-silgen.swift @@ -0,0 +1,58 @@ +// RUN: %target-swift-frontend -I %S/Inputs -enable-cxx-interop -emit-silgen %s | %FileCheck %s + +import Constructors + +// The most important thing to test here is that the constructor result is +// returned with an @out attribute. +// CHECK-LABEL: sil [ossa] @$s4main24testConstructorWithParamyyF : $@convention(thin) () -> () +// CHECK: [[VAR:%[0-9]+]] = alloc_stack $ConstructorWithParam +// CHECK: [[LITERAL:%[0-9]+]] = integer_literal $Builtin.IntLiteral, 42 +// CHECK: [[INT:%[0-9]+]] = apply %{{[0-9]+}}([[LITERAL]], %{{[0-9]+}}) +// CHECK: [[FUNC:%[0-9]+]] = function_ref @{{_ZN20ConstructorWithParamC1Ei|\?\?0ConstructorWithParam@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out ConstructorWithParam +// CHECK: %{{[0-9]+}} = apply [[FUNC]]([[VAR]], [[INT]]) : $@convention(c) (Int32) -> @out ConstructorWithParam +// CHECK-LABEL: end sil function '$s4main24testConstructorWithParamyyF' + +// CHECK-LABEL: sil [clang ConstructorWithParam.init] @{{_ZN20ConstructorWithParamC1Ei|\?\?0ConstructorWithParam@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out ConstructorWithParam +public func testConstructorWithParam() { + let c = ConstructorWithParam(42) +} + +// CHECK-LABEL: sil [ossa] @$s4main18emptyTypeNoArgInityyF : $@convention(thin) () -> () +// CHECK: [[AS:%.*]] = alloc_stack $EmptyStruct +// CHECK: [[FN:%.*]] = function_ref @{{_ZN11EmptyStructC1Ev|\?\?0EmptyStruct@@QEAA@XZ}} : $@convention(c) () -> @out EmptyStruct +// CHECK: apply [[FN]]([[AS]]) : $@convention(c) () -> @out EmptyStruct +// CHECK-LABEL: end sil function '$s4main18emptyTypeNoArgInityyF' + +// CHECL-LABEL: sil [clang EmptyStruct.init] @{{_ZN11EmptyStructC1Ev|\?\?0EmptyStruct@@QEAA@XZ}} : $@convention(c) () -> @out EmptyStruct +public func emptyTypeNoArgInit() { + let e = EmptyStruct() +} + +// CHECK-LABEL: sil [ossa] @$s4main25singleMemberTypeNoArgInityyF : $@convention(thin) () -> () +// CHECK: [[AS:%.*]] = alloc_stack $IntWrapper +// CHECK: [[FN:%.*]] = function_ref @{{_ZN10IntWrapperC1Ev|\?\?0IntWrapper@@QEAA@XZ}} : $@convention(c) () -> @out IntWrapper +// CHECK: apply [[FN]]([[AS]]) : $@convention(c) () -> @out IntWrapper +// CHECK-LABEL: end sil function '$s4main25singleMemberTypeNoArgInityyF' + +//CHECK-LABEL: sil [clang IntWrapper.init] @{{_ZN10IntWrapperC1Ev|\?\?0IntWrapper@@QEAA@XZ}} : $@convention(c) () -> @out IntWrapper +public func singleMemberTypeNoArgInit() { + let i = IntWrapper() +} + +// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo10IntWrapperV1xABs5Int32V_tcfC : $@convention(method) (Int32, @thin IntWrapper.Type) -> IntWrapper +// CHECK: bb0([[I:%[0-9]+]] : $Int32, %{{[0-9]+}} : $@thin IntWrapper.Type): +// CHECK-NEXT: [[S:%.*]] = struct $IntWrapper ([[I]] : $Int32) +// CHECK-NEXT: return [[S]] +// CHECK-LABEL: end sil function '$sSo10IntWrapperV1xABs5Int32V_tcfC' +public func singleMemberTypeValueInit() { + let i = IntWrapper(x: 42) +} + +// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo25DefaultConstructorDeletedV1aABSpys5Int32VG_tcfC : $@convention(method) (UnsafeMutablePointer, @thin DefaultConstructorDeleted.Type) -> DefaultConstructorDeleted +// CHECK: bb0([[A:%.*]] : $UnsafeMutablePointer +// CHECK-NEXT: [[OUT:%.*]] = struct $DefaultConstructorDeleted ([[A]] : $UnsafeMutablePointer) +// CHECK-NEXT: return [[OUT]] : $DefaultConstructorDeleted +// CHECK-LABEL: end sil function '$sSo25DefaultConstructorDeletedV1aABSpys5Int32VG_tcfC' +public func deletedConstructor(a: UnsafeMutablePointer) { + let deletedExplicitly = DefaultConstructorDeleted(a: a) +} diff --git a/test/Interop/Cxx/class/constructors-typechecker.swift b/test/Interop/Cxx/class/constructors-typechecker.swift new file mode 100644 index 0000000000000..c78328c2b39c3 --- /dev/null +++ b/test/Interop/Cxx/class/constructors-typechecker.swift @@ -0,0 +1,13 @@ +// RUN: %target-typecheck-verify-swift -verify-ignore-unknown -I %S/Inputs -enable-cxx-interop + +import Constructors + +let explicit = ExplicitDefaultConstructor() + +let implicit = ImplicitDefaultConstructor() + +let deletedImplicitly = ConstructorWithParam() // expected-error {{missing argument for parameter #1 in call}} + +let deletedExplicitly = DefaultConstructorDeleted() // expected-error {{missing argument for parameter 'a' in call}} + +let withArg = ConstructorWithParam(42) diff --git a/test/Interop/Cxx/class/synthesized-initializers-silgen.swift b/test/Interop/Cxx/class/synthesized-initializers-silgen.swift deleted file mode 100644 index ea74f8ab4eecb..0000000000000 --- a/test/Interop/Cxx/class/synthesized-initializers-silgen.swift +++ /dev/null @@ -1,46 +0,0 @@ -// RUN: %target-swift-frontend -I %S/Inputs -enable-cxx-interop -emit-silgen %s | %FileCheck %s - -import SynthesizedInitializers - -// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo11EmptyStructVABycfC : $@convention(method) (@thin EmptyStruct.Type) -> EmptyStruct -// CHECK: bb0(%{{[0-9]+}} : $@thin EmptyStruct.Type): -// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ var EmptyStruct } -// CHECK-NEXT: [[UNINIT:%.*]] = mark_uninitialized [rootself] [[BOX]] : ${ var EmptyStruct } -// CHECK-NEXT: [[PTR:%.*]] = project_box [[UNINIT]] : ${ var EmptyStruct }, 0 -// CHECK-NEXT: [[OBJ:%.*]] = builtin "zeroInitializer"() : $EmptyStruct -// CHECK-NEXT: [[PA:%.*]] = begin_access [modify] [unknown] [[PTR]] : $*EmptyStruct -// CHECK-NEXT: assign [[OBJ]] to [[PA]] -// CHECK-NEXT: end_access [[PA]] -// CHECK-NEXT: [[OUT:%.*]] = load [trivial] [[PTR]] -// CHECK-NEXT: destroy_value [[UNINIT]] -// CHECK-NEXT: return [[OUT]] -// CHECK-LABEL: end sil function '$sSo11EmptyStructVABycfC' -public func emptyTypeNoArgInit() { - let e = EmptyStruct() -} - -// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo6IntBoxVABycfC : $@convention(method) (@thin IntBox.Type) -> IntBox -// CHECK: bb0(%{{[0-9]+}} : $@thin IntBox.Type): -// CHECK-NEXT: [[BOX:%.*]] = alloc_box ${ var IntBox } -// CHECK-NEXT: [[UNINIT:%.*]] = mark_uninitialized [rootself] [[BOX]] : ${ var IntBox } -// CHECK-NEXT: [[PTR:%.*]] = project_box [[UNINIT]] : ${ var IntBox }, 0 -// CHECK-NEXT: [[OBJ:%.*]] = builtin "zeroInitializer"() : $IntBox -// CHECK-NEXT: [[PA:%.*]] = begin_access [modify] [unknown] [[PTR]] : $*IntBox -// CHECK-NEXT: assign [[OBJ]] to [[PA]] -// CHECK-NEXT: end_access [[PA]] -// CHECK-NEXT: [[OUT:%.*]] = load [trivial] [[PTR]] -// CHECK-NEXT: destroy_value [[UNINIT]] -// CHECK-NEXT: return [[OUT]] -// CHECK-LABEL: end sil function '$sSo6IntBoxVABycfC' -public func singleMemberTypeNoArgInit() { - let i = IntBox() -} - -// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo6IntBoxV1xABs5Int32V_tcfC : $@convention(method) (Int32, @thin IntBox.Type) -> IntBox -// CHECK: bb0([[I:%[0-9]+]] : $Int32, %{{[0-9]+}} : $@thin IntBox.Type): -// CHECK-NEXT: [[S:%.*]] = struct $IntBox ([[I]] : $Int32) -// CHECK-NEXT: return [[S]] -// CHECK-LABEL: end sil function '$sSo6IntBoxV1xABs5Int32V_tcfC' -public func singleMemberTypeValueInit() { - let i = IntBox(x: 42) -} diff --git a/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift b/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift index c0a48574a1493..2939b78732840 100644 --- a/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift +++ b/test/Interop/Cxx/class/type-classification-non-trivial-irgen.swift @@ -12,12 +12,15 @@ import TypeClassification // CHECK-LABEL: define {{.*}}i1 @"$s4main37testStructWithCopyConstructorAndValueSbyF" // CHECK: [[OBJ:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV -// CHECK: [[VAL_ELEMENT:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[OBJ]], i32 0, i32 0 -// CHECK: [[VAL_INT:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[VAL_ELEMENT]], i32 0, i32 0 -// CHECK: store i32 42, i32* [[VAL_INT]] -// CHECK: ret i1 true +// CHECK: [[STRUCT:%.*]] = bitcast %TSo33StructWithCopyConstructorAndValueV* [[OBJ]] to %struct.StructWithCopyConstructorAndValue* +// CHECK: call {{.*}}@{{_ZN33StructWithCopyConstructorAndValueC(1|2)Ei|"\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z"}}(%struct.StructWithCopyConstructorAndValue* {{(noalias )?}}[[STRUCT]], i32 42) +// CHECK: [[OBJ_VAL:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[OBJ]], i32 0, i32 0 +// CHECK: [[I_VAL:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[OBJ_VAL]], i32 0, i32 0 +// CHECK: [[I_VAL_VAL:%.*]] = load i32, i32* [[OBJ_VAL]] +// CHECK: [[OUT:%.*]] = icmp eq i32 [[I_VAL_VAL]], 42 +// CHECK: ret i1 [[OUT]] public func testStructWithCopyConstructorAndValue() -> Bool { - let obj = StructWithCopyConstructorAndValue(value: 42) + let obj = StructWithCopyConstructorAndValue(42) return obj.value == 42 } @@ -26,38 +29,39 @@ public func testStructWithCopyConstructorAndValue() -> Bool { // CHECK: [[OBJ:%.*]] = alloca %TSo42StructWithSubobjectCopyConstructorAndValueV // CHECK: alloca %TSo33StructWithCopyConstructorAndValueV // CHECK: [[TMP:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV -// CHECK: [[MEMBER_ELEMENT:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[MEMBER]], i32 0, i32 0 -// CHECK: [[MEMBER_VALUE:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[MEMBER_ELEMENT]], i32 0, i32 0 -// CHECK: store i32 42, i32* [[MEMBER_VALUE]] +// CHECK: [[MEMBER_STRUCT:%.*]] = bitcast %TSo33StructWithCopyConstructorAndValueV* %member to %struct.StructWithCopyConstructorAndValue* +// CHECK: call {{.*}}@{{_ZN33StructWithCopyConstructorAndValueC(1|2)Ei|"\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z"}}(%struct.StructWithCopyConstructorAndValue* {{(noalias )?}}[[MEMBER_STRUCT]], i32 42) // CHECK: [[TEMP_MEMBER:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[TMP]], i32 0, i32 0 // CHECK: [[TEMP_MEMBER_VALUE:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[TEMP_MEMBER]], i32 0, i32 0 // CHECK: [[LHS:%.*]] = load i32, i32* [[TEMP_MEMBER_VALUE]] // CHECK: [[OUT:%.*]] = icmp eq i32 [[LHS]], 42 // CHECK: ret i1 [[OUT]] public func testStructWithSubobjectCopyConstructorAndValue() -> Bool { - let member = StructWithCopyConstructorAndValue(value: 42) + let member = StructWithCopyConstructorAndValue(42) let obj = StructWithSubobjectCopyConstructorAndValue(member: member) return obj.member.value == 42 } // CHECK-LABEL: define {{.*}}i1 @"$s4main041testStructWithCopyConstructorAndSubobjectefG5ValueSbyF"() // CHECK: [[MEMBER:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV -// CHECK: alloca %TSo037StructWithCopyConstructorAndSubobjectcdE5ValueV -// CHECK: alloca %TSo33StructWithCopyConstructorAndValueV +// CHECK: [[OBJ:%.*]] = alloca %TSo037StructWithCopyConstructorAndSubobjectcdE5ValueV // CHECK: [[TEMP:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV -// CHECK: [[MEMBER_VAL:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[MEMBER]], i32 0, i32 0 -// CHECK: [[MEMBER_VAL_VAL:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[MEMBER_VAL]], i32 0, i32 0 -// CHECK: store i32 42, i32* [[MEMBER_VAL_VAL]] -// CHECK: [[TEMP_MEMBER:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[TEMP]], i32 0, i32 0 +// CHECK: [[TEMP2:%.*]] = alloca %TSo33StructWithCopyConstructorAndValueV +// CHECK: [[MEMBER_STRUCT:%.*]] = bitcast %TSo33StructWithCopyConstructorAndValueV* %member to %struct.StructWithCopyConstructorAndValue* +// CHECK: call {{.*}}@{{_ZN33StructWithCopyConstructorAndValueC(1|2)Ei|"\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z"}}(%struct.StructWithCopyConstructorAndValue* {{(noalias )?}}[[MEMBER_STRUCT]], i32 42) +// CHECK: [[TEMP_AS_STRUCT:%.*]] = bitcast %TSo33StructWithCopyConstructorAndValueV* [[TEMP]] to %struct.StructWithCopyConstructorAndValue* +// CHECK: [[OBJ_AS_STRUCT:%.*]] = bitcast %TSo037StructWithCopyConstructorAndSubobjectcdE5ValueV* [[OBJ]] to %struct.StructWithCopyConstructorAndSubobjectCopyConstructorAndValue* +// CHECK: call {{.*}}@{{_ZN60StructWithCopyConstructorAndSubobjectCopyConstructorAndValueC(1|2)E33StructWithCopyConstructorAndValue|"\?\?0StructWithCopyConstructorAndSubobjectCopyConstructorAndValue@@QEAA@UStructWithCopyConstructorAndValue@@@Z"}}(%struct.StructWithCopyConstructorAndSubobjectCopyConstructorAndValue* {{(noalias )?}}[[OBJ_AS_STRUCT]], %struct.StructWithCopyConstructorAndValue* [[TEMP_AS_STRUCT]]) +// CHECK: [[TEMP_MEMBER:%.*]] = getelementptr inbounds %TSo33StructWithCopyConstructorAndValueV, %TSo33StructWithCopyConstructorAndValueV* [[TEMP2]], i32 0, i32 0 // CHECK: [[TEMP_MEMBER_VAL:%.*]] = getelementptr inbounds %Ts5Int32V, %Ts5Int32V* [[TEMP_MEMBER]], i32 0, i32 0 // CHECK: [[LHS:%.*]] = load i32, i32* [[TEMP_MEMBER_VAL]] // CHECK: [[OUT:%.*]] = icmp eq i32 [[LHS]], 42 // CHECK: ret i1 [[OUT]] public func testStructWithCopyConstructorAndSubobjectCopyConstructorAndValue() -> Bool { - let member = StructWithCopyConstructorAndValue(value: 42) + let member = StructWithCopyConstructorAndValue(42) let obj = StructWithCopyConstructorAndSubobjectCopyConstructorAndValue( - member: member + member ) return obj.member.value == 42 } diff --git a/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift b/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift index 87766b5a01bdb..156665a06912b 100644 --- a/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift +++ b/test/Interop/Cxx/class/type-classification-non-trivial-silgen.swift @@ -6,60 +6,35 @@ import TypeClassification // "destroy_addr". // CHECK-LABEL: sil [ossa] @$s4main24testStructWithDestructoryyF // CHECK: [[AS:%.*]] = alloc_stack $StructWithDestructor -// CHECK: [[META:%.*]] = metatype $@thin StructWithDestructor.Type -// CHECK: [[FN:%.*]] = function_ref @$sSo20StructWithDestructorVABycfC : $@convention(method) (@thin StructWithDestructor.Type) -> @out StructWithDestructor -// CHECK: apply [[FN]]([[AS]], [[META]]) : $@convention(method) (@thin StructWithDestructor.Type) -> @out StructWithDestructor +// CHECK: [[FN:%.*]] = function_ref @{{_ZN20StructWithDestructorC1Ev|\?\?0StructWithDestructor@@QEAA@XZ}} : $@convention(c) () -> @out StructWithDestructor +// CHECK: apply [[FN]]([[AS]]) : $@convention(c) () -> @out StructWithDestructor // CHECK: destroy_addr [[AS]] // CHECK: dealloc_stack %0 : $*StructWithDestructor // CHECK-LABEL: end sil function '$s4main24testStructWithDestructoryyF' + +// CHECK-LABEL: sil [clang StructWithDestructor.init] @{{_ZN20StructWithDestructorC1Ev|\?\?0StructWithDestructor@@QEAA@XZ}} : $@convention(c) () -> @out StructWithDestructor public func testStructWithDestructor() { let d = StructWithDestructor() } -// StructWithDestructor.init() -// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo20StructWithDestructorVABycfC : $@convention(method) (@thin StructWithDestructor.Type) -> @out StructWithDestructor -// CHECK: [[BOX:%.*]] = alloc_box ${ var StructWithDestructor } -// CHECK: [[UBOX:%.*]] = mark_uninitialized [rootself] [[BOX]] : ${ var StructWithDestructor } -// CHECK: [[BOX_ADDR:%.*]] = project_box [[UBOX]] : ${ var StructWithDestructor }, 0 -// CHECK: [[SA:%.*]] = alloc_stack $StructWithDestructor -// CHECK: builtin "zeroInitializer"([[SA]] : $*StructWithDestructor) : $() -// CHECK: [[BA:%.*]] = begin_access [modify] [unknown] [[BOX_ADDR]] : $*StructWithDestructor -// CHECK: copy_addr [take] [[SA]] to [[BA]] : $*StructWithDestructor -// CHECK: copy_addr [[BOX_ADDR]] to [initialization] %0 : $*StructWithDestructor -// CHECK: destroy_value [[UBOX]] : ${ var StructWithDestructor } -// CHECK-LABEL: end sil function '$sSo20StructWithDestructorVABycfC' - // Make sure that "HasMemberWithDestructor" is marked as non-trivial by checking // for a "destroy_addr". -// CHECK-LABEL: sil [ossa] @$s4main33testStructWithSubobjectDestructoryyF +// CHECK-LABEL: sil [ossa] @$s4main33testStructWithSubobjectDestructoryyF : $@convention(thin) () -> () // CHECK: [[AS:%.*]] = alloc_stack $StructWithSubobjectDestructor -// CHECK: [[META:%.*]] = metatype $@thin StructWithSubobjectDestructor.Type -// CHECK: [[FN:%.*]] = function_ref @$sSo29StructWithSubobjectDestructorVABycfC : $@convention(method) (@thin StructWithSubobjectDestructor.Type) -> @out StructWithSubobjectDestructor -// CHECK: apply [[FN]]([[AS]], [[META]]) : $@convention(method) (@thin StructWithSubobjectDestructor.Type) -> @out StructWithSubobjectDestructor +// CHECK: [[FN:%.*]] = function_ref @{{_ZN29StructWithSubobjectDestructorC1Ev|\?\?0StructWithSubobjectDestructor@@QEAA@XZ}} : $@convention(c) () -> @out StructWithSubobjectDestructor +// CHECK: apply [[FN]]([[AS]]) : $@convention(c) () -> @out StructWithSubobjectDestructor // CHECK: destroy_addr [[AS]] // CHECK-LABEL: end sil function '$s4main33testStructWithSubobjectDestructoryyF' + +// CHECK-LABEL: sil [clang StructWithSubobjectDestructor.init] @{{_ZN29StructWithSubobjectDestructorC1Ev|\?\?0StructWithSubobjectDestructor@@QEAA@XZ}} : $@convention(c) () -> @out StructWithSubobjectDestructor public func testStructWithSubobjectDestructor() { let d = StructWithSubobjectDestructor() } -// StructWithSubobjectDestructor.init() -// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo29StructWithSubobjectDestructorVABycfC : $@convention(method) (@thin StructWithSubobjectDestructor.Type) -> @out StructWithSubobjectDestructor -// CHECK: [[BOX:%.*]] = alloc_box ${ var StructWithSubobjectDestructor } -// CHECK: [[UBOX:%.*]] = mark_uninitialized [rootself] [[BOX]] : ${ var StructWithSubobjectDestructor } -// CHECK: [[ADDR:%.*]] = project_box [[UBOX]] : ${ var StructWithSubobjectDestructor }, 0 -// CHECK: [[AS:%.*]] = alloc_stack $StructWithSubobjectDestructor -// CHECK: builtin "zeroInitializer"([[AS]] : $*StructWithSubobjectDestructor) : $() -// CHECK: [[BA:%.*]] = begin_access [modify] [unknown] [[ADDR]] : $*StructWithSubobjectDestructor -// CHECK: copy_addr [take] [[AS]] to [[BA]] : $*StructWithSubobjectDestructor -// CHECK: copy_addr [[ADDR]] to [initialization] %0 : $*StructWithSubobjectDestructor -// CHECK: destroy_value [[UBOX]] : ${ var StructWithSubobjectDestructor } -// CHECK-LABEL: end sil function '$sSo29StructWithSubobjectDestructorVABycfC' - // CHECK-LABLE: sil [ossa] @$s4main37testStructWithCopyConstructorAndValueSbyF // CHECK: [[AS:%.*]] = alloc_stack $StructWithCopyConstructorAndValue -// CHECK: [[META:%.*]] = metatype $@thin StructWithCopyConstructorAndValue.Type -// CHECK: [[FN:%.*]] = function_ref @$sSo33StructWithCopyConstructorAndValueV5valueABs5Int32V_tcfC : $@convention(method) (Int32, @thin StructWithCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndValue -// CHECK: apply [[FN]]([[AS]], %{{.*}}, [[META]]) : $@convention(method) (Int32, @thin StructWithCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndValue +// CHECK: [[FN:%.*]] = function_ref @{{_ZN33StructWithCopyConstructorAndValueC1Ei|\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue +// CHECK: apply [[FN]]([[AS]], %{{.*}}) : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue // CHECK: [[OBJ_VAL_ADDR:%.*]] = struct_element_addr [[AS]] : $*StructWithCopyConstructorAndValue, #StructWithCopyConstructorAndValue.value // CHECK: [[OBJ_VAL:%.*]] = load [trivial] [[OBJ_VAL_ADDR]] : $*Int32 // CHECK: [[IL_42:%.*]] = integer_literal $Builtin.IntLiteral, 42 @@ -70,22 +45,17 @@ public func testStructWithSubobjectDestructor() { // CHECK: destroy_addr [[AS]] : $*StructWithCopyConstructorAndValue // CHECK: return [[OUT]] : $Bool // CHECK-LABLE: end sil function '$s4main37testStructWithCopyConstructorAndValueSbyF' + +// CHECK-LABEL: sil [clang StructWithCopyConstructorAndValue.init] @{{_ZN33StructWithCopyConstructorAndValueC1Ei|\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue public func testStructWithCopyConstructorAndValue() -> Bool { - let obj = StructWithCopyConstructorAndValue(value: 42) + let obj = StructWithCopyConstructorAndValue(42) return obj.value == 42 } -// StructWithCopyConstructorAndValue.init(value:) -// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo33StructWithCopyConstructorAndValueV5valueABs5Int32V_tcfC : $@convention(method) (Int32, @thin StructWithCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndValue -// CHECK: [[VAL:%.*]] = struct_element_addr %0 : $*StructWithCopyConstructorAndValue, #StructWithCopyConstructorAndValue.value -// CHECK: store %1 to [trivial] [[VAL]] : $*Int32 -// CHECK-LABEL: end sil function '$sSo33StructWithCopyConstructorAndValueV5valueABs5Int32V_tcfC' - // CHECK-LABEL: sil [ossa] @$s4main46testStructWithSubobjectCopyConstructorAndValueSbyF : $@convention(thin) () -> Bool // CHECK: [[MEMBER_0:%.*]] = alloc_stack $StructWithCopyConstructorAndValue -// CHECK: [[MEMBER_META:%.*]] = metatype $@thin StructWithCopyConstructorAndValue.Type -// CHECK: [[MAKE_MEMBER_FN:%.*]] = function_ref @$sSo33StructWithCopyConstructorAndValueV5valueABs5Int32V_tcfC : $@convention(method) (Int32, @thin StructWithCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndValue -// CHECK: apply [[MAKE_MEMBER_FN]]([[MEMBER_0]], %{{.*}}, [[MEMBER_META]]) : $@convention(method) (Int32, @thin StructWithCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndValue +// CHECK: [[MAKE_MEMBER_FN:%.*]] = function_ref @{{_ZN33StructWithCopyConstructorAndValueC1Ei|\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue +// CHECK: apply [[MAKE_MEMBER_FN]]([[MEMBER_0]], %{{.*}}) : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue // CHECK: [[AS:%.*]] = alloc_stack $StructWithSubobjectCopyConstructorAndValue // CHECK: [[META:%.*]] = metatype $@thin StructWithSubobjectCopyConstructorAndValue.Type // CHECK: [[MEMBER_1:%.*]] = alloc_stack $StructWithCopyConstructorAndValue @@ -104,7 +74,7 @@ public func testStructWithCopyConstructorAndValue() -> Bool { // CHECK: return [[OUT]] : $Bool // CHECK-LABEL: end sil function '$s4main46testStructWithSubobjectCopyConstructorAndValueSbyF' public func testStructWithSubobjectCopyConstructorAndValue() -> Bool { - let member = StructWithCopyConstructorAndValue(value: 42) + let member = StructWithCopyConstructorAndValue(42) let obj = StructWithSubobjectCopyConstructorAndValue(member: member) return obj.member.value == 42 } @@ -118,15 +88,13 @@ public func testStructWithSubobjectCopyConstructorAndValue() -> Bool { // testStructWithCopyConstructorAndSubobjectCopyConstructorAndValue() // CHECK-LABEL: sil [ossa] @$s4main041testStructWithCopyConstructorAndSubobjectefG5ValueSbyF : $@convention(thin) () -> Bool // CHECK: [[MEMBER_0:%.*]] = alloc_stack $StructWithCopyConstructorAndValue -// CHECK: [[META_MEMBER:%.*]] = metatype $@thin StructWithCopyConstructorAndValue.Type -// CHECK: [[CREATE_MEMBER_FN:%.*]] = function_ref @$sSo33StructWithCopyConstructorAndValueV5valueABs5Int32V_tcfC : $@convention(method) (Int32, @thin StructWithCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndValue -// CHECK: apply [[CREATE_MEMBER_FN]]([[MEMBER_0]], %{{.*}}, [[META_MEMBER]]) : $@convention(method) (Int32, @thin StructWithCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndValue +// CHECK: [[CREATE_MEMBER_FN:%.*]] = function_ref @{{_ZN33StructWithCopyConstructorAndValueC1Ei|\?\?0StructWithCopyConstructorAndValue@@QEAA@H@Z}} : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue +// CHECK: apply [[CREATE_MEMBER_FN]]([[MEMBER_0]], %{{.*}}) : $@convention(c) (Int32) -> @out StructWithCopyConstructorAndValue // CHECK: [[AS:%.*]] = alloc_stack $StructWithCopyConstructorAndSubobjectCopyConstructorAndValue -// CHECK: [[META:%.*]] = metatype $@thin StructWithCopyConstructorAndSubobjectCopyConstructorAndValue.Type // CHECK: [[MEMBER_1:%.*]] = alloc_stack $StructWithCopyConstructorAndValue // CHECK: copy_addr [[MEMBER_0]] to [initialization] [[MEMBER_1]] : $*StructWithCopyConstructorAndValue -// CHECK: [[FN:%.*]] = function_ref @$sSo037StructWithCopyConstructorAndSubobjectcdE5ValueV6memberABSo0abcdeG0V_tcfC : $@convention(method) (@in StructWithCopyConstructorAndValue, @thin StructWithCopyConstructorAndSubobjectCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndSubobjectCopyConstructorAndValue -// CHECK: apply [[FN]]([[AS]], [[MEMBER_1]], [[META]]) : $@convention(method) (@in StructWithCopyConstructorAndValue, @thin StructWithCopyConstructorAndSubobjectCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndSubobjectCopyConstructorAndValue +// CHECK: [[FN:%.*]] = function_ref @{{_ZN60StructWithCopyConstructorAndSubobjectCopyConstructorAndValueC1E33StructWithCopyConstructorAndValue|\?\?0StructWithCopyConstructorAndSubobjectCopyConstructorAndValue@@QEAA@UStructWithCopyConstructorAndValue@@@Z}} : $@convention(c) (@in StructWithCopyConstructorAndValue) -> @out StructWithCopyConstructorAndSubobjectCopyConstructorAndValue +// CHECK: apply [[FN]]([[AS]], [[MEMBER_1]]) : $@convention(c) (@in StructWithCopyConstructorAndValue) -> @out StructWithCopyConstructorAndSubobjectCopyConstructorAndValue // CHECK: [[OBJ_MEMBER_ADDR:%.*]] = struct_element_addr [[AS]] : $*StructWithCopyConstructorAndSubobjectCopyConstructorAndValue, #StructWithCopyConstructorAndSubobjectCopyConstructorAndValue.member // CHECK: [[MEMBER_2:%.*]] = alloc_stack $StructWithCopyConstructorAndValue // CHECK: copy_addr [[OBJ_MEMBER_ADDR]] to [initialization] [[MEMBER_2]] : $*StructWithCopyConstructorAndValue @@ -138,19 +106,13 @@ public func testStructWithSubobjectCopyConstructorAndValue() -> Bool { // CHECK-LABEL: end sil function '$s4main041testStructWithCopyConstructorAndSubobjectefG5ValueSbyF' public func testStructWithCopyConstructorAndSubobjectCopyConstructorAndValue() -> Bool { - let member = StructWithCopyConstructorAndValue(value: 42) + let member = StructWithCopyConstructorAndValue(42) let obj = StructWithCopyConstructorAndSubobjectCopyConstructorAndValue( - member: member + member ) return obj.member.value == 42 } -// StructWithCopyConstructorAndSubobjectCopyConstructorAndValue.init(member:) -// CHECK-LABEL: sil shared [transparent] [serializable] [ossa] @$sSo037StructWithCopyConstructorAndSubobjectcdE5ValueV6memberABSo0abcdeG0V_tcfC : $@convention(method) (@in StructWithCopyConstructorAndValue, @thin StructWithCopyConstructorAndSubobjectCopyConstructorAndValue.Type) -> @out StructWithCopyConstructorAndSubobjectCopyConstructorAndValue -// CHECK: [[MEMBER:%.*]] = struct_element_addr %0 : $*StructWithCopyConstructorAndSubobjectCopyConstructorAndValue, #StructWithCopyConstructorAndSubobjectCopyConstructorAndValue.member -// CHECK: copy_addr [take] %1 to [initialization] [[MEMBER]] : $*StructWithCopyConstructorAndValue -// CHECK-LABEL: end sil function '$sSo037StructWithCopyConstructorAndSubobjectcdE5ValueV6memberABSo0abcdeG0V_tcfC' - // CHECK-LABEL: sil [ossa] @$s4main4test3objSbSo33StructWithCopyConstructorAndValueV_tF : $@convention(thin) (@in_guaranteed StructWithCopyConstructorAndValue) -> Bool // CHECK: [[META_1:%.*]] = metatype $@thin Int32.Type // CHECK: [[OBJ_VAL_ADDR:%.*]] = struct_element_addr %0 : $*StructWithCopyConstructorAndValue, #StructWithCopyConstructorAndValue.value diff --git a/test/Interop/Cxx/class/type-classification-non-trivial.swift b/test/Interop/Cxx/class/type-classification-non-trivial.swift index 489e6f71c7a40..910651f7b5cb5 100644 --- a/test/Interop/Cxx/class/type-classification-non-trivial.swift +++ b/test/Interop/Cxx/class/type-classification-non-trivial.swift @@ -11,12 +11,12 @@ import StdlibUnittest var AddressOnlyTestSuite = TestSuite("Address Only Types") AddressOnlyTestSuite.test("Test struct with copy constructor") { - let obj = StructWithCopyConstructorAndValue(value: 42) + let obj = StructWithCopyConstructorAndValue(42) expectEqual(obj.value, 42) } AddressOnlyTestSuite.test("Test struct with member with copy constructor") { - let member = StructWithCopyConstructorAndValue(value: 42) + let member = StructWithCopyConstructorAndValue(42) let obj = StructWithSubobjectCopyConstructorAndValue(member: member) expectEqual(obj.member.value, 42) } @@ -24,9 +24,9 @@ AddressOnlyTestSuite.test("Test struct with member with copy constructor") { AddressOnlyTestSuite.test( "Test struct with copy constructor and member with copy constructor" ) { - let member = StructWithCopyConstructorAndValue(value: 42) + let member = StructWithCopyConstructorAndValue(42) let obj = StructWithCopyConstructorAndSubobjectCopyConstructorAndValue( - member: member + member ) expectEqual(obj.member.value, 42) } diff --git a/test/Interop/Cxx/templates/canonical-types-module-interface.swift b/test/Interop/Cxx/templates/canonical-types-module-interface.swift index 3a90d1d44311a..735e2dafe5257 100644 --- a/test/Interop/Cxx/templates/canonical-types-module-interface.swift +++ b/test/Interop/Cxx/templates/canonical-types-module-interface.swift @@ -1,15 +1,16 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=CanonicalTypes -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s // CHECK: struct __CxxTemplateInst12MagicWrapperI10IntWrapperE { -// CHECK: var t: IntWrapper -// CHECK: init() -// CHECK: init(t: IntWrapper) -// CHECK: mutating func getValuePlusArg(_ arg: Int32) -> Int32 -// CHECK: } -// CHECK: struct IntWrapper { -// CHECK: var value: Int32 -// CHECK: init() -// CHECK: mutating func getValue() -> Int32 -// CHECK: } -// CHECK: typealias WrappedMagicNumberA = __CxxTemplateInst12MagicWrapperI10IntWrapperE -// CHECK: typealias WrappedMagicNumberB = __CxxTemplateInst12MagicWrapperI10IntWrapperE +// CHECK-NEXT: var t: IntWrapper +// CHECK-NEXT: init() +// CHECK-NEXT: init(t: IntWrapper) +// CHECK-NEXT: mutating func getValuePlusArg(_ arg: Int32) -> Int32 +// CHECK-NEXT: } +// CHECK-NEXT: struct IntWrapper { +// CHECK-NEXT: var value: Int32 +// CHECK-NEXT: init() +// CHECK-NEXT: init(value: Int32) +// CHECK-NEXT: mutating func getValue() -> Int32 +// CHECK-NEXT: } +// CHECK-NEXT: typealias WrappedMagicNumberA = __CxxTemplateInst12MagicWrapperI10IntWrapperE +// CHECK-NEXT: typealias WrappedMagicNumberB = __CxxTemplateInst12MagicWrapperI10IntWrapperE diff --git a/test/Interop/Cxx/templates/not-pre-defined-class-template-module-interface.swift b/test/Interop/Cxx/templates/not-pre-defined-class-template-module-interface.swift index 7fd6b7cc0efc1..0f2b7f7b57c6e 100644 --- a/test/Interop/Cxx/templates/not-pre-defined-class-template-module-interface.swift +++ b/test/Interop/Cxx/templates/not-pre-defined-class-template-module-interface.swift @@ -1,15 +1,15 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=NotPreDefinedClassTemplate -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s // CHECK: struct __CxxTemplateInst12MagicWrapperI10IntWrapperE { -// CHECK: var t: IntWrapper -// CHECK: init() -// CHECK: init(t: IntWrapper) -// CHECK: mutating func getValuePlusArg(_ arg: Int32) -> Int32 -// CHECK: } -// CHECK: struct IntWrapper { -// CHECK: var value: Int32 -// CHECK: init() -// CHECK: init(value: Int32) -// CHECK: mutating func getValue() -> Int32 -// CHECK: } -// CHECK: typealias MagicallyWrappedIntWithoutDefinition = __CxxTemplateInst12MagicWrapperI10IntWrapperE +// CHECK-NEXT: var t: IntWrapper +// CHECK-NEXT: init() +// CHECK-NEXT: init(t: IntWrapper) +// CHECK-NEXT: mutating func getValuePlusArg(_ arg: Int32) -> Int32 +// CHECK-NEXT: } +// CHECK-NEXT: struct IntWrapper { +// CHECK-NEXT: var value: Int32 +// CHECK-NEXT: init() +// CHECK-NEXT: init(value: Int32) +// CHECK-NEXT: mutating func getValue() -> Int32 +// CHECK-NEXT: } +// CHECK-NEXT: typealias MagicallyWrappedIntWithoutDefinition = __CxxTemplateInst12MagicWrapperI10IntWrapperE diff --git a/test/Interop/Cxx/templates/using-directive-module-interface.swift b/test/Interop/Cxx/templates/using-directive-module-interface.swift index 81b445d21e3d7..cee692e4dc45c 100644 --- a/test/Interop/Cxx/templates/using-directive-module-interface.swift +++ b/test/Interop/Cxx/templates/using-directive-module-interface.swift @@ -1,15 +1,15 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=UsingDirective -I %S/Inputs -source-filename=x -enable-cxx-interop | %FileCheck %s // CHECK: struct __CxxTemplateInst12MagicWrapperI10IntWrapperE { -// CHECK: var t: IntWrapper -// CHECK: init() -// CHECK: init(t: IntWrapper) -// CHECK: mutating func getValuePlusArg(_ arg: Int32) -> Int32 -// CHECK: } -// CHECK: struct IntWrapper { -// CHECK: var value: Int32 -// CHECK: init() -// CHECK: init(value: Int32) -// CHECK: mutating func getValue() -> Int32 -// CHECK: } -// CHECK: typealias UsingWrappedMagicNumber = __CxxTemplateInst12MagicWrapperI10IntWrapperE +// CHECK-NEXT: var t: IntWrapper +// CHECK-NEXT: init() +// CHECK-NEXT: init(t: IntWrapper) +// CHECK-NEXT: mutating func getValuePlusArg(_ arg: Int32) -> Int32 +// CHECK-NEXT: } +// CHECK-NEXT: struct IntWrapper { +// CHECK-NEXT: var value: Int32 +// CHECK-NEXT: init() +// CHECK-NEXT: init(value: Int32) +// CHECK-NEXT: mutating func getValue() -> Int32 +// CHECK-NEXT: } +// CHECK-NEXT: typealias UsingWrappedMagicNumber = __CxxTemplateInst12MagicWrapperI10IntWrapperE