diff --git a/lib/ClangImporter/ClangImporter.cpp b/lib/ClangImporter/ClangImporter.cpp index c783ea0c2f736..11c9c7cd55f76 100644 --- a/lib/ClangImporter/ClangImporter.cpp +++ b/lib/ClangImporter/ClangImporter.cpp @@ -71,11 +71,13 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Memory.h" #include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" #include "llvm/Support/YAMLParser.h" #include "llvm/Support/YAMLTraits.h" -#include "llvm/Support/VirtualFileSystem.h" #include +#include #include +#include using namespace swift; using namespace importer; @@ -86,6 +88,17 @@ using clang::CompilerInvocation; #pragma mark Internal data structures +namespace { +static std::string getOperatorNameForToken(std::string OperatorToken) { +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + if (OperatorToken == Spelling) { \ + return #Name; \ + }; +#include "clang/Basic/OperatorKinds.def" + return "None"; +} +} // namespace + namespace { class HeaderImportCallbacks : public clang::PPCallbacks { ClangImporter::Implementation &Impl; @@ -2738,6 +2751,11 @@ ClangImporter::Implementation::lookupTypedef(clang::DeclarationName name) { static bool isDeclaredInModule(const ClangModuleUnit *ModuleFilter, const Decl *VD) { + // Sometimes imported decls get put into the clang header module. If we + // found one of these decls, don't filter it out. + if (VD->getModuleContext()->getName().str() == CLANG_HEADER_MODULE_NAME) { + return true; + } auto ContainingUnit = VD->getDeclContext()->getModuleScopeContext(); return ModuleFilter == ContainingUnit; } @@ -2795,7 +2813,6 @@ static bool isVisibleFromModule(const ClangModuleUnit *ModuleFilter, const clang::Decl *D = ClangNode.castAsDecl(); auto &ClangASTContext = ModuleFilter->getClangASTContext(); - // We don't handle Clang submodules; pop everything up to the top-level // module. auto OwningClangModule = getClangTopLevelOwningModule(ClangNode, @@ -2868,7 +2885,7 @@ class FilteringVisibleDeclConsumer : public swift::VisibleDeclConsumer { void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason, DynamicLookupInfo dynamicLookupInfo) override { - if (isVisibleFromModule(ModuleFilter, VD)) + if (!VD->hasClangNode() || isVisibleFromModule(ModuleFilter, VD)) NextConsumer.foundDecl(VD, Reason, dynamicLookupInfo); } }; @@ -2886,11 +2903,9 @@ class FilteringDeclaredDeclConsumer : public swift::VisibleDeclConsumer { void foundDecl(ValueDecl *VD, DeclVisibilityKind Reason, DynamicLookupInfo dynamicLookupInfo) override { - if (isDeclaredInModule(ModuleFilter, VD) || - // Sometimes imported decls get put into the clang header module. If we - // found one of these decls, don't filter it out. - VD->getModuleContext()->getName().str() == CLANG_HEADER_MODULE_NAME) + if (isDeclaredInModule(ModuleFilter, VD)) { NextConsumer.foundDecl(VD, Reason, dynamicLookupInfo); + } } }; @@ -4104,22 +4119,42 @@ bool ClangImporter::Implementation::forEachLookupTable( bool ClangImporter::Implementation::lookupValue(SwiftLookupTable &table, DeclName name, VisibleDeclConsumer &consumer) { + auto &clangCtx = getClangASTContext(); auto clangTU = clangCtx.getTranslationUnitDecl(); bool declFound = false; - // For operators we have to look up static member functions in addition to the - // top-level function lookup below. if (name.isOperator()) { - for (auto entry : table.lookupMemberOperators(name.getBaseName())) { - if (isVisibleClangEntry(entry)) { - if (auto decl = dyn_cast_or_null( - importDeclReal(entry->getMostRecentDecl(), CurrentVersion))) { - consumer.foundDecl(decl, DeclVisibilityKind::VisibleAtTopLevel); - declFound = true; + + auto findAndConsumeBaseNameFromTable = [this, &table, &consumer, &declFound, + &name](DeclBaseName declBaseName) { + for (auto entry : table.lookupMemberOperators(declBaseName)) { + if (isVisibleClangEntry(entry)) { + if (auto decl = dyn_cast_or_null( + importDeclReal(entry->getMostRecentDecl(), CurrentVersion))) { + consumer.foundDecl(decl, DeclVisibilityKind::VisibleAtTopLevel); + declFound = true; + for (auto alternate : getAlternateDecls(decl)) { + if (alternate->getName().matchesRef(name)) { + consumer.foundDecl(alternate, DeclVisibilityKind::DynamicLookup, + DynamicLookupInfo::AnyObject); + } + } + } } } + }; + + findAndConsumeBaseNameFromTable(name.getBaseName()); + + // If CXXInterop is enabled we need to check the modified operator name as + // well + if (SwiftContext.LangOpts.EnableCXXInterop) { + auto declBaseName = DeclBaseName(SwiftContext.getIdentifier( + "__operator" + getOperatorNameForToken( + name.getBaseName().getIdentifier().str().str()))); + findAndConsumeBaseNameFromTable(declBaseName); } } diff --git a/lib/ClangImporter/ImportDecl.cpp b/lib/ClangImporter/ImportDecl.cpp index c18e5a576069f..3a997677d34aa 100644 --- a/lib/ClangImporter/ImportDecl.cpp +++ b/lib/ClangImporter/ImportDecl.cpp @@ -3593,6 +3593,26 @@ namespace { // by changing the name of one. That changed method needs to be added // to the lookup table since it cannot be found lazily. if (auto cxxMethod = dyn_cast(m)) { + auto cxxOperatorKind = cxxMethod->getOverloadedOperator(); + + // Check if this method _is_ an overloaded operator but is not a + // call / subscript. Those 2 operators do not need static versions + if (cxxOperatorKind != clang::OverloadedOperatorKind::OO_None && + cxxOperatorKind != clang::OverloadedOperatorKind::OO_Call && + cxxOperatorKind != + clang::OverloadedOperatorKind::OO_Subscript) { + + auto opFuncDecl = makeOperator(MD, cxxMethod); + + Impl.addAlternateDecl(MD, opFuncDecl); + + auto msg = "use " + std::string{clang::getOperatorSpelling(cxxOperatorKind)} + " instead"; + Impl.markUnavailable(MD,msg); + + // Make the actual member operator private. + MD->overwriteAccess(AccessLevel::Private); + } + if (cxxMethod->getDeclName().isIdentifier()) { auto &mutableFuncPtrs = Impl.cxxMethods[cxxMethod->getName()].second; if(mutableFuncPtrs.contains(cxxMethod)) { @@ -4133,11 +4153,6 @@ namespace { if (!dc) return nullptr; - // Support for importing operators is temporarily disabled: rdar://91070109 - if (decl->getDeclName().getNameKind() == clang::DeclarationName::CXXOperatorName && - decl->getDeclName().getCXXOverloadedOperator() != clang::OO_Subscript) - return nullptr; - // Handle cases where 2 CXX methods differ strictly in "constness" // In such a case append a suffix ("Mutating") to the mutable version // of the method when importing to swift @@ -4285,16 +4300,7 @@ namespace { templateParams); if (auto *mdecl = dyn_cast(decl)) { - // Subscripts and call operators are imported as normal methods. - bool staticOperator = mdecl->isOverloadedOperator() && - mdecl->getOverloadedOperator() != clang::OO_Call && - mdecl->getOverloadedOperator() != clang::OO_Subscript; - if (mdecl->isStatic() || - // C++ operators that are implemented as non-static member - // functions get imported into Swift as static member functions - // that use an additional parameter for the left-hand side operand - // instead of the receiver object. - staticOperator) { + if (mdecl->isStatic()) { selfIdx = None; } else { // Swift imports the "self" param last, even for clang functions. @@ -5393,9 +5399,13 @@ namespace { /// \param setter function returning `UnsafeMutablePointer` /// \return subscript declaration SubscriptDecl *makeSubscript(FuncDecl *getter, FuncDecl *setter); + FuncDecl *makeOperator(FuncDecl *operatorMethod, + clang::CXXMethodDecl *clangOperator); + VarDecl *makeComputedPropertyFromCXXMethods(FuncDecl *getter, FuncDecl *setter); + /// Import the accessor and its attributes. AccessorDecl *importAccessor(const clang::ObjCMethodDecl *clangAccessor, AbstractStorageDecl *storage, @@ -8080,6 +8090,133 @@ SwiftDeclConverter::makeSubscript(FuncDecl *getter, FuncDecl *setter) { return subscript; } +static std::pair +synthesizeOperatorMethodBody(AbstractFunctionDecl *afd, void *context) { + ASTContext &ctx = afd->getASTContext(); + + auto funcDecl = cast(afd); + auto methodDecl = + static_cast(context); /* Swift version of CXXMethod */ + + SmallVector forwardingParams; + + // We start from +1 since the first param is our lhs. All other params are + // forwarded + for (auto itr = funcDecl->getParameters()->begin() + 1; + itr != funcDecl->getParameters()->end(); itr++) { + auto param = *itr; + Expr *paramRefExpr = + new (ctx) DeclRefExpr(param, DeclNameLoc(), /*Implicit=*/true); + paramRefExpr->setType(param->getType()); + + if (param->isInOut()) { + paramRefExpr->setType(LValueType::get(param->getType())); + + paramRefExpr = new (ctx) InOutExpr(SourceLoc(), paramRefExpr, + param->getType(), /*isImplicit*/ true); + paramRefExpr->setType(InOutType::get(param->getType())); + } + + forwardingParams.push_back(paramRefExpr); + } + + auto methodExpr = + new (ctx) DeclRefExpr(methodDecl, DeclNameLoc(), /*implicit*/ true); + methodExpr->setType(methodDecl->getInterfaceType()); + + // Lhs parameter + auto baseParam = funcDecl->getParameters()->front(); + Expr *baseExpr = + new (ctx) DeclRefExpr(baseParam, DeclNameLoc(), /*implicit*/ true); + baseExpr->setType(baseParam->getType()); + if (baseParam->isInOut()) { + baseExpr->setType(LValueType::get(baseParam->getType())); + + baseExpr = new (ctx) InOutExpr(SourceLoc(), baseExpr, baseParam->getType(), + /*isImplicit*/ true); + baseExpr->setType(InOutType::get(baseParam->getType())); + } + + auto dotCallExpr = + DotSyntaxCallExpr::create(ctx, methodExpr, SourceLoc(), baseExpr); + dotCallExpr->setType(methodDecl->getMethodInterfaceType()); + dotCallExpr->setThrows(false); + + auto *argList = ArgumentList::forImplicitUnlabeled(ctx, forwardingParams); + auto callExpr = CallExpr::createImplicit(ctx, dotCallExpr, argList); + callExpr->setType(funcDecl->getResultInterfaceType()); + callExpr->setThrows(false); + + auto returnStmt = new (ctx) ReturnStmt(SourceLoc(), callExpr, + /*implicit=*/true); + + auto body = BraceStmt::create(ctx, SourceLoc(), {returnStmt}, SourceLoc(), + /*implicit=*/true); + return {body, /*isTypeChecked=*/true}; +} + +FuncDecl * +SwiftDeclConverter::makeOperator(FuncDecl *operatorMethod, + clang::CXXMethodDecl *clangOperator) { + auto &ctx = Impl.SwiftContext; + auto opName = + clang::getOperatorSpelling(clangOperator->getOverloadedOperator()); + auto paramList = operatorMethod->getParameters(); + auto genericParamList = operatorMethod->getGenericParams(); + + auto opId = ctx.getIdentifier(opName); + + auto parentCtx = operatorMethod->getDeclContext(); + + auto lhsParam = new (ctx) ParamDecl( + SourceLoc(), + SourceLoc(),Identifier(), + SourceLoc(),ctx.getIdentifier("lhs"), + parentCtx); + + lhsParam->setInterfaceType(operatorMethod->getDeclContext()->getSelfInterfaceType()); + + if (operatorMethod->isMutating()) { + // This implicitly makes the parameter indirect. + lhsParam->setSpecifier(ParamSpecifier::InOut); + } else { + lhsParam->setSpecifier(ParamSpecifier::Default); + } + + SmallVector newParams; + newParams.push_back(lhsParam); + + for (auto param : *paramList) { + newParams.push_back(param); + } + + auto oldArgNames = operatorMethod->getName().getArgumentNames(); + SmallVector newArgNames; + newArgNames.push_back(Identifier()); + + for (auto id : oldArgNames) { + newArgNames.push_back(id); + } + + auto opDeclName = DeclName( + ctx,opId, + {newArgNames.begin(), newArgNames.end()}); + + auto topLevelStaticFuncDecl = FuncDecl::createImplicit( + ctx, StaticSpellingKind::None, opDeclName, SourceLoc(), + /*Async*/ false, /*Throws*/ false, genericParamList, + ParameterList::create(ctx, newParams), + operatorMethod->getResultInterfaceType(), parentCtx); + + topLevelStaticFuncDecl->setAccess(AccessLevel::Public); + topLevelStaticFuncDecl->setIsDynamic(false); + topLevelStaticFuncDecl->setStatic(); + topLevelStaticFuncDecl->setBodySynthesizer(synthesizeOperatorMethodBody, + operatorMethod); + + return topLevelStaticFuncDecl; +} + void SwiftDeclConverter::addProtocols( ProtocolDecl *protocol, SmallVectorImpl &protocols, llvm::SmallPtrSetImpl &known) { diff --git a/lib/ClangImporter/ImportName.cpp b/lib/ClangImporter/ImportName.cpp index 804067a769c75..d4c55ce326059 100644 --- a/lib/ClangImporter/ImportName.cpp +++ b/lib/ClangImporter/ImportName.cpp @@ -57,6 +57,20 @@ using namespace importer; using clang::CompilerInstance; using clang::CompilerInvocation; +static const char *getOperatorName(clang::OverloadedOperatorKind Operator) { + switch (Operator) { + case clang::OO_None: + case clang::NUM_OVERLOADED_OPERATORS: + return nullptr; + +#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemberOnly) \ + case clang::OO_##Name: \ + return #Name; +#include "clang/Basic/OperatorKinds.def" + } + + llvm_unreachable("Invalid OverloadedOperatorKind!"); +} /// Determine whether the given Clang selector matches the given /// selector pieces. @@ -1501,14 +1515,14 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, completionHandlerParamIndex = swiftAsyncAttr->getCompletionHandlerIndex().getASTIndex(); } - + if (const auto *asyncErrorAttr = D->getAttr()) { switch (auto convention = asyncErrorAttr->getConvention()) { // No flag parameter in these cases. case clang::SwiftAsyncErrorAttr::NonNullError: case clang::SwiftAsyncErrorAttr::None: break; - + // Get the flag argument index and polarity from the attribute. case clang::SwiftAsyncErrorAttr::NonZeroArgument: case clang::SwiftAsyncErrorAttr::ZeroArgument: @@ -1842,17 +1856,15 @@ ImportedName NameImporter::importNameImpl(const clang::NamedDecl *D, case clang::OverloadedOperatorKind::OO_LessEqual: case clang::OverloadedOperatorKind::OO_GreaterEqual: case clang::OverloadedOperatorKind::OO_AmpAmp: - case clang::OverloadedOperatorKind::OO_PipePipe: - baseName = clang::getOperatorSpelling(op); + case clang::OverloadedOperatorKind::OO_PipePipe: { + auto operatorName = isa(functionDecl) + ? "__operator" + std::string{getOperatorName(op)} + : clang::getOperatorSpelling(op); + baseName = swiftCtx.getIdentifier(operatorName).str(); isFunction = true; - argumentNames.resize( - functionDecl->param_size() + - // C++ operators that are implemented as non-static member functions - // get imported into Swift as static member functions that use an - // additional parameter for the left-hand side operand instead of - // the receiver object. - (isa(D) ? 1 : 0)); + addEmptyArgNamesForClangFunction(functionDecl, argumentNames); break; + } case clang::OverloadedOperatorKind::OO_Call: baseName = "callAsFunction"; isFunction = true; diff --git a/lib/ClangImporter/ImportType.cpp b/lib/ClangImporter/ImportType.cpp index e861b7e189cf3..a3e82d9ba91cc 100644 --- a/lib/ClangImporter/ImportType.cpp +++ b/lib/ClangImporter/ImportType.cpp @@ -2212,39 +2212,6 @@ ParameterList *ClangImporter::Implementation::importFunctionParameterList( unsigned index = 0; SmallBitVector nonNullArgs = getNonNullArgs(clangDecl, params); - // C++ operators that are implemented as non-static member functions get - // imported into Swift as static methods that have an additional - // parameter for the left-hand side operand instead of the receiver object. - if (auto CMD = dyn_cast(clangDecl)) { - // Subscripts and call operators are imported as normal methods. - bool staticOperator = clangDecl->isOverloadedOperator() && - clangDecl->getOverloadedOperator() != clang::OO_Call && - clangDecl->getOverloadedOperator() != clang::OO_Subscript; - if (staticOperator) { - auto param = new (SwiftContext) - ParamDecl(SourceLoc(), SourceLoc(), Identifier(), SourceLoc(), - SwiftContext.getIdentifier("lhs"), dc); - - auto parent = CMD->getParent(); - auto parentType = importType( - parent->getASTContext().getRecordType(parent), - ImportTypeKind::Parameter, ImportDiagnosticAdder(*this, clangDecl), - allowNSUIntegerAsInt, Bridgeability::None, - getImportTypeAttrs(clangDecl)); - - param->setInterfaceType(parentType.getType()); - - if (SwiftContext.getClangModuleLoader()->isCXXMethodMutating(CMD)) { - // This implicitly makes the parameter indirect. - param->setSpecifier(ParamSpecifier::InOut); - } else { - param->setSpecifier(ParamSpecifier::Default); - } - - parameters.push_back(param); - } - } - for (auto param : params) { auto paramTy = param->getType(); if (paramTy->isVoidType()) { diff --git a/lib/SIL/IR/SILFunctionType.cpp b/lib/SIL/IR/SILFunctionType.cpp index eda48adabad44..4119c3726ffe3 100644 --- a/lib/SIL/IR/SILFunctionType.cpp +++ b/lib/SIL/IR/SILFunctionType.cpp @@ -3477,11 +3477,9 @@ TypeConverter::getDeclRefRepresentation(SILDeclRef c) { bool staticOperator = method->isOverloadedOperator() && method->getOverloadedOperator() != clang::OO_Call && method->getOverloadedOperator() != clang::OO_Subscript; - return isa(method) || - method->isStatic() || - staticOperator - ? SILFunctionTypeRepresentation::CFunctionPointer - : SILFunctionTypeRepresentation::CXXMethod; + return isa(method) || method->isStatic() + ? SILFunctionTypeRepresentation::CFunctionPointer + : SILFunctionTypeRepresentation::CXXMethod; } diff --git a/lib/SILGen/SILGenApply.cpp b/lib/SILGen/SILGenApply.cpp index e10c1d9d167d6..9e14bcf80c72e 100644 --- a/lib/SILGen/SILGenApply.cpp +++ b/lib/SILGen/SILGenApply.cpp @@ -2924,7 +2924,6 @@ class ArgEmitter { // substituted argument type by abstraction and/or bridging. auto paramSlice = claimNextParameters(1); SILParameterInfo param = paramSlice.front(); - assert(arg.hasLValueType() == param.isIndirectInOut()); // Make sure we use the same value category for these so that we diff --git a/test/Interop/Cxx/implementation-only-imports/Inputs/module.modulemap b/test/Interop/Cxx/implementation-only-imports/Inputs/module.modulemap index f47a17ec7f168..976c56a3bf0ca 100644 --- a/test/Interop/Cxx/implementation-only-imports/Inputs/module.modulemap +++ b/test/Interop/Cxx/implementation-only-imports/Inputs/module.modulemap @@ -27,3 +27,10 @@ module DeclB { export * requires cplusplus } + +module Helper { + header "helper.h" + export * + requires cplusplus +} + diff --git a/test/Interop/Cxx/implementation-only-imports/check-operator-visibility-inversed.swift b/test/Interop/Cxx/implementation-only-imports/check-operator-visibility-inversed.swift index 7068b5fe22efa..8299794340a07 100644 --- a/test/Interop/Cxx/implementation-only-imports/check-operator-visibility-inversed.swift +++ b/test/Interop/Cxx/implementation-only-imports/check-operator-visibility-inversed.swift @@ -8,8 +8,6 @@ // that the operator decl can be found when at least one of the // modules is not `@_implementationOnly`. -// XFAIL: * - import UserA @_implementationOnly import UserB diff --git a/test/Interop/Cxx/implementation-only-imports/check-operator-visibility.swift b/test/Interop/Cxx/implementation-only-imports/check-operator-visibility.swift index 660eedea3b45a..1262796240575 100644 --- a/test/Interop/Cxx/implementation-only-imports/check-operator-visibility.swift +++ b/test/Interop/Cxx/implementation-only-imports/check-operator-visibility.swift @@ -8,8 +8,6 @@ // that the operator decl can be found when at least one of the // modules is not `@_implementationOnly`. -// XFAIL: * - @_implementationOnly import UserA import UserB diff --git a/test/Interop/Cxx/implementation-only-imports/skip-forward-declarations.swift b/test/Interop/Cxx/implementation-only-imports/skip-forward-declarations.swift index d1cf130344a59..0ecf1e1a7e695 100644 --- a/test/Interop/Cxx/implementation-only-imports/skip-forward-declarations.swift +++ b/test/Interop/Cxx/implementation-only-imports/skip-forward-declarations.swift @@ -12,4 +12,4 @@ public func createAWrapper() { let _ = MagicWrapper() } -// CHECK: struct 'MagicWrapper' cannot be used in an '@inlinable' function because 'UserA' was imported implementation-only +// CHECK: struct 'MagicWrapper' cannot be used in an '@inlinable' function because 'Helper' was imported implementation-only diff --git a/test/Interop/Cxx/namespace/free-functions-module-interface.swift b/test/Interop/Cxx/namespace/free-functions-module-interface.swift index 19fe747a3637d..10feeed33a166 100644 --- a/test/Interop/Cxx/namespace/free-functions-module-interface.swift +++ b/test/Interop/Cxx/namespace/free-functions-module-interface.swift @@ -7,8 +7,7 @@ // CHECK-NEXT: struct X { // CHECK-NEXT: init() // CHECK-NEXT: } -// TODO: check this again when operators are re-enabled: rdar://91070109 (also please enable this in the execution test "free-functions.swift") -// CHECK-NOT: static func + +// CHECK-NEXT: static func + (_: FunctionsNS1.X, _: FunctionsNS1.X) -> UnsafePointer! // CHECK-NEXT: static func sameNameInChild() -> UnsafePointer! // CHECK-NEXT: static func sameNameInSibling() -> UnsafePointer! // CHECK-NEXT: enum FunctionsNS2 { @@ -21,8 +20,7 @@ // CHECK-NEXT: static func definedInDefs() -> UnsafePointer! // CHECK-NEXT: } -// TODO: check this again when operators are re-enabled: rdar://91070109 (also please enable this in the execution test "free-functions.swift") -// CHECK-NOT: static func + +// CHECK-NEXT: static func + (_: FunctionsNS1.X, _: FunctionsNS1.X) -> UnsafePointer! // CHECK-NEXT: enum FunctionsNS4 { // CHECK-NEXT: static func sameNameInSibling() -> UnsafePointer! diff --git a/test/Interop/Cxx/namespace/free-functions.swift b/test/Interop/Cxx/namespace/free-functions.swift index 4c903ba97ce6b..28a3364990a55 100644 --- a/test/Interop/Cxx/namespace/free-functions.swift +++ b/test/Interop/Cxx/namespace/free-functions.swift @@ -20,10 +20,9 @@ NamespacesTestSuite.test("Basic functions") { expectEqual(String(cString: basicFunctionLowestLevelCString!), "FunctionsNS1::FunctionsNS2::FunctionsNS3::basicFunctionLowestLevel") -// TODO: check this again when operators are re-enabled: rdar://91070109 -// let x = FunctionsNS1.X() -// expectEqual(String(cString: x + x), -// "FunctionsNS1::operator+(X, X)") + let x = FunctionsNS1.X() + expectEqual(String(cString: x + x), + "FunctionsNS1::operator+(X, X)") } NamespacesTestSuite.test("Forward declared functions") { diff --git a/test/Interop/Cxx/operators/member-inline-irgen.swift b/test/Interop/Cxx/operators/member-inline-irgen.swift index 0b52663018a57..a9fd8ab8c0c14 100644 --- a/test/Interop/Cxx/operators/member-inline-irgen.swift +++ b/test/Interop/Cxx/operators/member-inline-irgen.swift @@ -1,14 +1,13 @@ // RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-experimental-cxx-interop | %FileCheck %s // -// We can't yet call member functions correctly on Windows (SR-13129). -// XFAIL: * +// We should be able to support windows now. We will remove XFAIL in follow up +// XFAIL: windows import MemberInline public func sub(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs - rhs } -// CHECK: call [[RES:i32|i64]] [[NAME:@(_ZN18LoadableIntWrappermiES_|"\?\?GLoadableIntWrapper@@QEAA\?AU0@U0@@Z")]](%struct.LoadableIntWrapper* {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\) align 4}} {{%[0-9]+}}) -// CHECK: define linkonce_odr [[RES]] [[NAME]](%struct.LoadableIntWrapper* nonnull align 4 dereferenceable(4) {{.*}}, {{i32 %.*.coerce|\[1 x i32\] %.*.coerce|i64 %.*.coerce|%struct.LoadableIntWrapper\* byval\(%struct.LoadableIntWrapper\) align 4 %.*}}) +// CHECK: call [[RESA:i32|i64]] [[NAMEA:@(_ZN18LoadableIntWrappermiES_|"\?\?GLoadableIntWrapper@@QEAA\?AU0@U0@@Z")]](%struct.LoadableIntWrapper* {{%[0-9]+}}, {{i32|\[1 x i32\]|i64|%struct.LoadableIntWrapper\* byval\(.*\) align 4}} {{%[0-9]+}}) public func call(_ wrapper: inout LoadableIntWrapper, _ arg: Int32) -> Int32 { wrapper(arg) } @@ -41,9 +40,12 @@ public func index(_ arr: inout ReadWriteIntArray, _ arg: Int32, _ val: Int32) { public func index(_ arr: inout NonTrivialIntArrayByVal, _ arg: Int32) -> Int32 { arr[arg] } // CHECK: call [[RES:i32|i64]] [[NAME:@(_ZNK23NonTrivialIntArrayByValixEi|"\?\?ANonTrivialIntArrayByVal@@QEBAAEBHH@Z")]](%struct.NonTrivialIntArrayByVal* {{%[0-9]+}}, {{i32|i64}} {{%[0-9]+}}) + // CHECK: define linkonce_odr [[RES]] [[NAME]](%struct.NonTrivialIntArrayByVal* nonnull align 4 dereferenceable(20) {{.*}}, {{i32 %.*|\[1 x i32\] %.*|i64 %.*|%struct.NonTrivialIntArrayByVal\* byval\(%struct.NonTrivialIntArrayByVal\) align 2 %.*}}) // CHECK: [[THIS:%.*]] = load %struct.NonTrivialIntArrayByVal*, %struct.NonTrivialIntArrayByVal** // CHECK: [[VALUES:%.*]] = getelementptr inbounds %struct.NonTrivialIntArrayByVal, %struct.NonTrivialIntArrayByVal* [[THIS]] // CHECK: [[VALUE:%.*]] = getelementptr inbounds [5 x {{i32|i64}}], [5 x {{i32|i64}}]* [[VALUES]] // CHECK: [[VALUE2:%.*]] = load {{i32|i64}}, {{i32|i64}}* [[VALUE]] // CHECK: ret {{i32|i64}} [[VALUE2]] + +// CHECK: define linkonce_odr [[RESA]] [[NAMEA]](%struct.LoadableIntWrapper* nonnull align 4 dereferenceable(4) {{.*}}, {{i32 %.*.coerce|\[1 x i32\] %.*.coerce|i64 %.*.coerce|%struct.LoadableIntWrapper\* byval\(%struct.LoadableIntWrapper\) align 4 %.*}}) \ No newline at end of file diff --git a/test/Interop/Cxx/operators/member-inline-module-interface.swift b/test/Interop/Cxx/operators/member-inline-module-interface.swift index 6c6c36c221668..88e9ef2cc8dd6 100644 --- a/test/Interop/Cxx/operators/member-inline-module-interface.swift +++ b/test/Interop/Cxx/operators/member-inline-module-interface.swift @@ -1,5 +1,4 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=MemberInline -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s -// XFAIL: * // CHECK: struct LoadableIntWrapper { // CHECK: static func - (lhs: inout LoadableIntWrapper, rhs: LoadableIntWrapper) -> LoadableIntWrapper diff --git a/test/Interop/Cxx/operators/member-inline-silgen.swift b/test/Interop/Cxx/operators/member-inline-silgen.swift index 5a028373f4969..2718e652daeec 100644 --- a/test/Interop/Cxx/operators/member-inline-silgen.swift +++ b/test/Interop/Cxx/operators/member-inline-silgen.swift @@ -1,29 +1,25 @@ // RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-experimental-cxx-interop | %FileCheck %s -// XFAIL: * import MemberInline public func sub(_ lhs: inout LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs - rhs } // CHECK: bb0([[SELF:%.*]] : $*LoadableIntWrapper, [[RHS:%.*]] : $LoadableIntWrapper): - +// CHECK: [[METATYPE:%.*]] = metatype $@thin LoadableIntWrapper.Type // CHECK: [[SELFACCESS:%.*]] = begin_access [modify] [static] [[SELF]] : $*LoadableIntWrapper -// CHECK: [[OP:%.*]] = function_ref [[NAME:@(_ZN18LoadableIntWrappermiES_|\?\?GLoadableIntWrapper@@QEAA\?AU0@U0@@Z)]] : $@convention(c) (@inout LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper -// CHECK: apply [[OP]]([[SELFACCESS]], [[RHS]]) : $@convention(c) (@inout LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper +// CHECK: [[OP:%.*]] = function_ref @$sSo18LoadableIntWrapperV1soiyA2Bz_ABtFZ : $@convention(method) (@inout LoadableIntWrapper, LoadableIntWrapper, @thin LoadableIntWrapper.Type) -> LoadableIntWrapper +// CHECK: apply [[OP]]([[SELFACCESS]], [[RHS]], [[METATYPE]]) : $@convention(method) (@inout LoadableIntWrapper, LoadableIntWrapper, @thin LoadableIntWrapper.Type) -> LoadableIntWrapper // CHECK: end_access [[SELFACCESS]] : $*LoadableIntWrapper -// CHECK: sil [clang LoadableIntWrapper."-"] [[NAME]] : $@convention(c) (@inout LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper - public func exclaim(_ wrapper: inout LoadableBoolWrapper) -> LoadableBoolWrapper { !wrapper } // CHECK: bb0([[SELF:%.*]] : $*LoadableBoolWrapper): +// CHECK: [[METATYPE:%.*]] = metatype $@thin LoadableBoolWrapper.Type // CHECK: [[SELFACCESS:%.*]] = begin_access [modify] [static] [[SELF]] : $*LoadableBoolWrapper -// CHECK: [[OP:%.*]] = function_ref [[NAME:@(_ZN19LoadableBoolWrapperntEv|\?\?7LoadableBoolWrapper@@QEAA\?AU0@XZ)]] : $@convention(c) (@inout LoadableBoolWrapper) -> LoadableBoolWrapper -// CHECK: apply [[OP]]([[SELFACCESS]]) : $@convention(c) (@inout LoadableBoolWrapper) -> LoadableBoolWrapper +// CHECK: [[OP:%.*]] = function_ref @$sSo19LoadableBoolWrapperV1noiyA2BzFZ : $@convention(method) (@inout LoadableBoolWrapper, @thin LoadableBoolWrapper.Type) -> LoadableBoolWrapper +// CHECK: apply [[OP]]([[SELFACCESS]], [[METATYPE]]) : $@convention(method) (@inout LoadableBoolWrapper, @thin LoadableBoolWrapper.Type) -> LoadableBoolWrapper // CHECK: end_access [[SELFACCESS]] -// CHECK: sil [clang LoadableBoolWrapper."!"] [[NAME]] : $@convention(c) (@inout LoadableBoolWrapper) -> LoadableBoolWrapper - public func call(_ wrapper: inout LoadableIntWrapper, _ arg: Int32) -> Int32 { wrapper(arg) } // CHECK: bb0([[SELF:%.*]] : $*LoadableIntWrapper, [[RHS:%.*]] : $Int32): diff --git a/test/Interop/Cxx/operators/member-inline-typechecker.swift b/test/Interop/Cxx/operators/member-inline-typechecker.swift index 9e0d9eedcd011..f8cd3706c194a 100644 --- a/test/Interop/Cxx/operators/member-inline-typechecker.swift +++ b/test/Interop/Cxx/operators/member-inline-typechecker.swift @@ -1,5 +1,4 @@ // RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop -// XFAIL: * import MemberInline diff --git a/test/Interop/Cxx/operators/member-inline.swift b/test/Interop/Cxx/operators/member-inline.swift index 63671e753680e..6de4df728d794 100644 --- a/test/Interop/Cxx/operators/member-inline.swift +++ b/test/Interop/Cxx/operators/member-inline.swift @@ -1,7 +1,6 @@ // RUN: %target-run-simple-swift(-I %S/Inputs -Xfrontend -enable-experimental-cxx-interop) // REQUIRES: executable_test -// XFAIL: * import MemberInline import StdlibUnittest diff --git a/test/Interop/Cxx/operators/member-out-of-line-irgen.swift b/test/Interop/Cxx/operators/member-out-of-line-irgen.swift index 98c7bdc3b204a..80c6a9ab9b312 100644 --- a/test/Interop/Cxx/operators/member-out-of-line-irgen.swift +++ b/test/Interop/Cxx/operators/member-out-of-line-irgen.swift @@ -1,7 +1,7 @@ // RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-experimental-cxx-interop | %FileCheck %s // -// We can't yet call member functions correctly on Windows (SR-13129). -// XFAIL: * +// We should be able to support windows now. We will remove XFAIL in follow up +// XFAIL: windows import MemberOutOfLine diff --git a/test/Interop/Cxx/operators/member-out-of-line-silgen.swift b/test/Interop/Cxx/operators/member-out-of-line-silgen.swift index 4195f6a6e2dbc..2836e281fba35 100644 --- a/test/Interop/Cxx/operators/member-out-of-line-silgen.swift +++ b/test/Interop/Cxx/operators/member-out-of-line-silgen.swift @@ -1,19 +1,19 @@ // RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-experimental-cxx-interop | %FileCheck %s -check-prefix CHECK-%target-abi -// XFAIL: * - import MemberOutOfLine public func add(_ lhs: LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs + rhs } // CHECK-SYSV: bb0([[LHS:%.*]] : $LoadableIntWrapper, [[RHS:%.*]] : $LoadableIntWrapper): -// CHECK-SYSV: [[FUNC:%.*]] = function_ref [[NAME:@_ZNK18LoadableIntWrapperplES_]] : $@convention(c) (@in LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper -// CHECK-SYSV: apply [[FUNC]]([[ACCESS:%.*]], [[RHS]]) : $@convention(c) (@in LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper +// CHECK-SYSV: store [[LHS]] to [[STORE_LOC:%.*]] : $*LoadableIntWrapper +// CHECK-SYSV: [[FUNC:%.*]] = function_ref [[NAME:@_ZNK18LoadableIntWrapperplES_]] : $@convention(cxx_method) (LoadableIntWrapper, @in_guaranteed LoadableIntWrapper) -> LoadableIntWrapper +// CHECK-SYSV: apply [[FUNC]]([[ACCESS:%.*]], [[STORE_LOC]]) : $@convention(cxx_method) (LoadableIntWrapper, @in_guaranteed LoadableIntWrapper) -> LoadableIntWrapper -// CHECK-SYSV: sil [clang LoadableIntWrapper."+"] [[NAME]] : $@convention(c) (@in LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper +// CHECK-SYSV: sil [clang LoadableIntWrapper.__operatorPlus] [[NAME]] : $@convention(cxx_method) (LoadableIntWrapper, @in_guaranteed LoadableIntWrapper) -> LoadableIntWrapper // CHECK-WIN: bb0([[LHS:%.*]] : $LoadableIntWrapper, [[RHS:%.*]] : $LoadableIntWrapper): -// CHECK-WIN: [[FUNC:%.*]] = function_ref [[NAME:@\?\?HLoadableIntWrapper@@QEBA\?AU0@U0@@Z]] : $@convention(c) (@in LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper -// CHECK-WIN: apply [[FUNC]]([[ACCESS:%.*]], [[RHS]]) : $@convention(c) (@in LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper +// CHECK-WIN: store [[LHS]] to [[STORE_LOC:%.*]] : $*LoadableIntWrapper +// CHECK-WIN: [[FUNC:%.*]] = function_ref [[NAME:@\?\?HLoadableIntWrapper@@QEBA\?AU0@U0@@Z]] : $@convention(cxx_method) (LoadableIntWrapper, @in_guaranteed LoadableIntWrapper) -> LoadableIntWrapper +// CHECK-WIN: apply [[FUNC]]([[ACCESS:%.*]], [[STORE_LOC]]) : $@convention(cxx_method) (LoadableIntWrapper, @in_guaranteed LoadableIntWrapper) -> LoadableIntWrapper -// CHECK-WIN: sil [clang LoadableIntWrapper."+"] [[NAME]] : $@convention(c) (@in LoadableIntWrapper, LoadableIntWrapper) -> LoadableIntWrapper +// CHECK-WIN: sil [clang LoadableIntWrapper.__operatorPlus] [[NAME]] : $@convention(cxx_method) (LoadableIntWrapper, @in_guaranteed LoadableIntWrapper) -> LoadableIntWrapper diff --git a/test/Interop/Cxx/operators/member-out-of-line.swift b/test/Interop/Cxx/operators/member-out-of-line.swift index f7c8da0380c78..97526a506c07e 100644 --- a/test/Interop/Cxx/operators/member-out-of-line.swift +++ b/test/Interop/Cxx/operators/member-out-of-line.swift @@ -6,8 +6,6 @@ // REQUIRES: executable_test -// XFAIL: * - import MemberOutOfLine import StdlibUnittest diff --git a/test/Interop/Cxx/operators/non-member-inline-module-interface.swift b/test/Interop/Cxx/operators/non-member-inline-module-interface.swift index 6e1f2ac006941..84036976f1fc1 100644 --- a/test/Interop/Cxx/operators/non-member-inline-module-interface.swift +++ b/test/Interop/Cxx/operators/non-member-inline-module-interface.swift @@ -1,7 +1,5 @@ // RUN: %target-swift-ide-test -print-module -module-to-print=NonMemberInline -I %S/Inputs -source-filename=x -enable-experimental-cxx-interop | %FileCheck %s -// XFAIL: * - // CHECK: func + (lhs: LoadableIntWrapper, rhs: LoadableIntWrapper) -> LoadableIntWrapper // CHECK-NEXT: func - (lhs: LoadableIntWrapper, rhs: LoadableIntWrapper) -> LoadableIntWrapper // CHECK-NEXT: func * (lhs: LoadableIntWrapper, rhs: LoadableIntWrapper) -> LoadableIntWrapper diff --git a/test/Interop/Cxx/operators/non-member-inline-typechecker.swift b/test/Interop/Cxx/operators/non-member-inline-typechecker.swift index fc2139a6bcec6..7553846128d93 100644 --- a/test/Interop/Cxx/operators/non-member-inline-typechecker.swift +++ b/test/Interop/Cxx/operators/non-member-inline-typechecker.swift @@ -1,7 +1,5 @@ // RUN: %target-typecheck-verify-swift -I %S/Inputs -enable-experimental-cxx-interop -// XFAIL: * - import NonMemberInline let lhs = LoadableIntWrapper(value: 42) diff --git a/test/Interop/Cxx/operators/non-member-inline.swift b/test/Interop/Cxx/operators/non-member-inline.swift index 95082f63578fa..b4ace6414072b 100644 --- a/test/Interop/Cxx/operators/non-member-inline.swift +++ b/test/Interop/Cxx/operators/non-member-inline.swift @@ -2,8 +2,6 @@ // // REQUIRES: executable_test -// XFAIL: * - import NonMemberInline import StdlibUnittest diff --git a/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift b/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift index cd74a17be6bdb..466945e5f1703 100644 --- a/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift +++ b/test/Interop/Cxx/operators/non-member-out-of-line-irgen.swift @@ -1,7 +1,5 @@ // RUN: %target-swift-emit-ir %s -I %S/Inputs -enable-experimental-cxx-interop | %FileCheck %s -// XFAIL: * - import NonMemberOutOfLine public func add(_ lhs: LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs + rhs } diff --git a/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift b/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift index 849a796ea23f2..196c6619a8750 100644 --- a/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift +++ b/test/Interop/Cxx/operators/non-member-out-of-line-silgen.swift @@ -1,7 +1,5 @@ // RUN: %target-swift-emit-sil %s -I %S/Inputs -enable-experimental-cxx-interop | %FileCheck %s -// XFAIL: * - import NonMemberOutOfLine public func add(_ lhs: LoadableIntWrapper, _ rhs: LoadableIntWrapper) -> LoadableIntWrapper { lhs + rhs } diff --git a/test/Interop/Cxx/operators/non-member-out-of-line.swift b/test/Interop/Cxx/operators/non-member-out-of-line.swift index c2fc95952e044..ea878c344a2e5 100644 --- a/test/Interop/Cxx/operators/non-member-out-of-line.swift +++ b/test/Interop/Cxx/operators/non-member-out-of-line.swift @@ -6,8 +6,6 @@ // // REQUIRES: executable_test -// XFAIL: * - import NonMemberOutOfLine import StdlibUnittest