diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 7c786d817eb74..889df2237d9b4 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -6727,6 +6727,12 @@ WARNING(has_symbol_decl_must_be_weak,none, (DescriptiveDeclKind, DeclName)) ERROR(has_symbol_invalid_expr,none, "'#_hasSymbol' condition must refer to a declaration", ()) +ERROR(has_symbol_invalid_decl_use_responds_to_selector,none, + "'#_hasSymbol' cannot be used with Objective-C %select{method|property}0 " + "'%1'; use respondsToSelector() instead", + (unsigned, StringRef)) +ERROR(has_symbol_invalid_decl,none, + "'#_hasSymbol' cannot be used with this declaration", ()) //------------------------------------------------------------------------------ // MARK: Type erasure diff --git a/include/swift/SIL/SILSymbolVisitor.h b/include/swift/SIL/SILSymbolVisitor.h index ebc5ce9253516..0d0cd0de8251d 100644 --- a/include/swift/SIL/SILSymbolVisitor.h +++ b/include/swift/SIL/SILSymbolVisitor.h @@ -128,6 +128,14 @@ class SILSymbolVisitor { template void enumerateFunctionsForHasSymbol(SILModule &M, ValueDecl *D, F Handler) { + // Handle clang decls separately. + if (auto *clangDecl = D->getClangDecl()) { + if (isa(clangDecl)) + Handler(SILDeclRef(D).asForeign()); + + return; + } + class SymbolVisitor : public SILSymbolVisitor { F Handler; diff --git a/lib/AST/ASTPrinter.cpp b/lib/AST/ASTPrinter.cpp index 26ce3ca99ab92..ae80c569e6730 100644 --- a/lib/AST/ASTPrinter.cpp +++ b/lib/AST/ASTPrinter.cpp @@ -7124,7 +7124,6 @@ swift::getInheritedForPrinting( } // Collect synthesized conformances. - auto &ctx = decl->getASTContext(); llvm::SetVector protocols; llvm::TinyPtrVector uncheckedProtocols; for (auto attr : decl->getAttrs().getAttributes()) { diff --git a/lib/IRGen/GenHasSymbol.cpp b/lib/IRGen/GenHasSymbol.cpp index 2f384cf9bf8c7..5d507ff4f8033 100644 --- a/lib/IRGen/GenHasSymbol.cpp +++ b/lib/IRGen/GenHasSymbol.cpp @@ -21,6 +21,8 @@ #include "swift/SIL/SILFunctionBuilder.h" #include "swift/SIL/SILModule.h" #include "swift/SIL/SILSymbolVisitor.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/GlobalDecl.h" #include "GenDecl.h" #include "IRGenFunction.h" @@ -68,9 +70,8 @@ class HasSymbolIRGenVisitor : public IRSymbolVisitor { SILFunction *silFn = IGM.getSILModule().lookUpFunction(name); // Definitions for each SIL function should have been emitted by SILGen. assert(silFn && "missing SIL function?"); - if (silFn) { + if (silFn) addFunction(silFn); - } } public: @@ -111,6 +112,39 @@ class HasSymbolIRGenVisitor : public IRSymbolVisitor { } }; +static llvm::Constant * +getAddrOfLLVMVariableForClangDecl(IRGenModule &IGM, ValueDecl *decl, + const clang::Decl *clangDecl) { + if (isa(clangDecl)) { + SILFunction *silFn = + IGM.getSILModule().lookUpFunction(SILDeclRef(decl).asForeign()); + assert(silFn && "missing SIL function?"); + return silFn ? IGM.getAddrOfSILFunction(silFn, NotForDefinition) : nullptr; + } + + if (auto var = dyn_cast(clangDecl)) + return IGM.getAddrOfObjCClass(cast(decl), NotForDefinition); + + llvm::report_fatal_error("Unexpected clang decl kind"); +} + +static void +getSymbolAddrsForDecl(IRGenModule &IGM, ValueDecl *decl, + llvm::SmallVector &addrs) { + if (auto *clangDecl = decl->getClangDecl()) { + if (auto *addr = getAddrOfLLVMVariableForClangDecl(IGM, decl, clangDecl)) + addrs.push_back(addr); + return; + } + + SILSymbolVisitorOptions opts; + opts.VisitMembers = false; + auto silCtx = SILSymbolVisitorContext(IGM.getSwiftModule(), opts); + auto linkInfo = UniversalLinkageInfo(IGM); + auto symbolVisitorCtx = IRSymbolVisitorContext(linkInfo, silCtx); + HasSymbolIRGenVisitor(IGM, addrs).visit(decl, symbolVisitorCtx); +} + llvm::Function *IRGenModule::emitHasSymbolFunction(ValueDecl *decl) { PrettyStackTraceDecl trace("emitting #_hasSymbol query for", decl); @@ -119,14 +153,9 @@ llvm::Function *IRGenModule::emitHasSymbolFunction(ValueDecl *decl) { auto func = cast(getOrCreateHelperFunction( mangler.mangleHasSymbolQuery(decl), Int1Ty, {}, [decl, this](IRGenFunction &IGF) { - SILSymbolVisitorOptions opts; - opts.VisitMembers = false; - auto silCtx = SILSymbolVisitorContext(getSwiftModule(), opts); - auto linkInfo = UniversalLinkageInfo(*this); - auto symbolVisitorCtx = IRSymbolVisitorContext(linkInfo, silCtx); auto &Builder = IGF.Builder; llvm::SmallVector addrs; - HasSymbolIRGenVisitor(*this, addrs).visit(decl, symbolVisitorCtx); + getSymbolAddrsForDecl(*this, decl, addrs); llvm::Value *ret = nullptr; for (llvm::Constant *addr : addrs) { diff --git a/lib/SILOptimizer/Transforms/COWOpts.cpp b/lib/SILOptimizer/Transforms/COWOpts.cpp index 2d953195f4fa6..2df462bedd677 100644 --- a/lib/SILOptimizer/Transforms/COWOpts.cpp +++ b/lib/SILOptimizer/Transforms/COWOpts.cpp @@ -267,8 +267,10 @@ void COWOptsPass::collectEscapePoints(SILValue v, escapePoints, handled); break; case SILInstructionKind::CondBranchInst: - collectEscapePoints(cast(user)->getArgForOperand(use), - escapePoints, handled); + if (use->getOperandNumber() != CondBranchInst::ConditionIdx) { + collectEscapePoints(cast(user)->getArgForOperand(use), + escapePoints, handled); + } break; case SILInstructionKind::StructInst: case SILInstructionKind::StructExtractInst: diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index ab8908dd00d6f..1f8bb283e1fef 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -38,6 +38,7 @@ #include "swift/Parse/Parser.h" #include "swift/Sema/ConstraintSystem.h" #include "swift/Sema/IDETypeChecking.h" +#include "clang/AST/DeclObjC.h" #include "llvm/ADT/MapVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/SaveAndRestore.h" @@ -4470,6 +4471,35 @@ static bool diagnoseAvailabilityCondition(PoundAvailableInfo *info, return false; } +/// Diagnoses whether the given clang::Decl can be referenced by a +/// `if #_hasSymbol(...)` condition. Returns true if a diagnostic was emitted. +static bool diagnoseHasSymbolConditionClangDecl(SourceLoc loc, + const clang::Decl *clangDecl, + ASTContext &ctx) { + if (isa(clangDecl) || + isa(clangDecl)) + return false; + + if (auto *method = dyn_cast(clangDecl)) { + // FIXME: Allow objc_direct methods when supported by IRGen. + ctx.Diags.diagnose(loc, + diag::has_symbol_invalid_decl_use_responds_to_selector, + /*isProperty*/ false, method->getNameAsString()); + return true; + } + + if (auto *property = dyn_cast(clangDecl)) { + // FIXME: Allow objc_direct properties when supported by IRGen. + ctx.Diags.diagnose(loc, + diag::has_symbol_invalid_decl_use_responds_to_selector, + /*isProperty*/ true, property->getNameAsString()); + return true; + } + + ctx.Diags.diagnose(loc, diag::has_symbol_invalid_decl); + return true; +} + /// Diagnoses a `if #_hasSymbol(...)` condition. Returns true if a diagnostic /// was emitted. static bool diagnoseHasSymbolCondition(PoundHasSymbolInfo *info, @@ -4495,6 +4525,12 @@ static bool diagnoseHasSymbolCondition(PoundHasSymbolInfo *info, return true; } + if (auto *clangDecl = decl->getClangDecl()) { + if (diagnoseHasSymbolConditionClangDecl(symbolExpr->getLoc(), clangDecl, + ctx)) + return true; + } + if (DC->getFragileFunctionKind().kind == FragileFunctionKind::None && !decl->isWeakImported(DC->getParentModule())) { // `if #_hasSymbol(someStronglyLinkedSymbol)` is functionally a no-op diff --git a/stdlib/public/core/StaticBigInt.swift b/stdlib/public/core/StaticBigInt.swift index f7b0237ffc714..4112d9ffb68f0 100644 --- a/stdlib/public/core/StaticBigInt.swift +++ b/stdlib/public/core/StaticBigInt.swift @@ -43,14 +43,6 @@ public struct StaticBigInt: public init(_builtinIntegerLiteral value: Builtin.IntLiteral) { _value = value } - - /// Returns the given value unchanged. - @_alwaysEmitIntoClient - @available(SwiftStdlib 5.8, *) - @inline(__always) - public static prefix func + (_ rhs: Self) -> Self { - rhs - } } //===----------------------------------------------------------------------===// @@ -117,7 +109,7 @@ extension StaticBigInt { /// negative[1] //-> 0xFFEEDDCCBBAA9988 /// negative[2] //-> 0xFFFFFFFFFFFFFFFF /// - /// let positive: StaticBigInt = +0x0011223344556677_8899AABBCCDDEEFF + /// let positive: StaticBigInt = 0x0011223344556677_8899AABBCCDDEEFF /// positive.signum() //-> +1 /// positive.bitWidth //-> 118 /// positive[0] //-> 0x8899AABBCCDDEEFF diff --git a/test/IRGen/Inputs/has_symbol_helper.swift b/test/IRGen/Inputs/has_symbol/has_symbol_helper.swift similarity index 100% rename from test/IRGen/Inputs/has_symbol_helper.swift rename to test/IRGen/Inputs/has_symbol/has_symbol_helper.swift diff --git a/test/IRGen/Inputs/has_symbol/has_symbol_helper_clang.h b/test/IRGen/Inputs/has_symbol/has_symbol_helper_clang.h new file mode 100644 index 0000000000000..8ed99ef852f3c --- /dev/null +++ b/test/IRGen/Inputs/has_symbol/has_symbol_helper_clang.h @@ -0,0 +1,3 @@ +// NOTE: This header is used on platforms that do not support Obj-C. + +extern void clangFunc(int x); diff --git a/test/IRGen/Inputs/has_symbol/has_symbol_helper_objc.h b/test/IRGen/Inputs/has_symbol/has_symbol_helper_objc.h new file mode 100644 index 0000000000000..f62c088f9c477 --- /dev/null +++ b/test/IRGen/Inputs/has_symbol/has_symbol_helper_objc.h @@ -0,0 +1,4 @@ +@import Foundation; + +@interface ObjCClass : NSObject +@end diff --git a/test/IRGen/Inputs/has_symbol/module.modulemap b/test/IRGen/Inputs/has_symbol/module.modulemap new file mode 100644 index 0000000000000..dfc520990c1d0 --- /dev/null +++ b/test/IRGen/Inputs/has_symbol/module.modulemap @@ -0,0 +1,9 @@ +module has_symbol_helper_clang { + header "has_symbol_helper_clang.h" + export * +} + +module has_symbol_helper_objc { + header "has_symbol_helper_objc.h" + export * +} diff --git a/test/IRGen/has_symbol.swift b/test/IRGen/has_symbol.swift index 20d3bc221ee2c..e8f81cdbb5826 100644 --- a/test/IRGen/has_symbol.swift +++ b/test/IRGen/has_symbol.swift @@ -1,6 +1,6 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking -// RUN: %target-swift-frontend -emit-irgen %s -I %t -module-name test | %FileCheck %s +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking +// RUN: %target-swift-frontend -emit-irgen %s -I %t -I %S/Inputs/has_symbol -module-name test | %FileCheck %s // UNSUPPORTED: OS=windows-msvc diff --git a/test/IRGen/has_symbol_async.swift b/test/IRGen/has_symbol_async.swift index ad2b544af2828..5526872652f5a 100644 --- a/test/IRGen/has_symbol_async.swift +++ b/test/IRGen/has_symbol_async.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking -DCONCURRENCY +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol/has_symbol_helper.swift -enable-library-evolution -disable-availability-checking -DCONCURRENCY // RUN: %target-swift-frontend -emit-irgen %s -I %t -module-name test | %FileCheck %s // REQUIRES: concurrency diff --git a/test/IRGen/has_symbol_clang.swift b/test/IRGen/has_symbol_clang.swift new file mode 100644 index 0000000000000..161164885d42b --- /dev/null +++ b/test/IRGen/has_symbol_clang.swift @@ -0,0 +1,15 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-irgen %s -I %t -I %S/Inputs/has_symbol -module-name test | %FileCheck %s + +// UNSUPPORTED: OS=windows-msvc + +@_weakLinked import has_symbol_helper_clang + +public func testClangDecls() { + // CHECK: %{{[0-9]+}} = call i1 @"$sSo9clangFuncyys5Int32VFTwS"() + if #_hasSymbol(clangFunc(_:)) {} +} + +// --- clangFunc(_:) --- +// CHECK: define linkonce_odr hidden i1 @"$sSo9clangFuncyys5Int32VFTwS"() #1 { +// CHECK: ret i1 icmp ne (void (i32)* @clangFunc, void (i32)* null) diff --git a/test/IRGen/has_symbol_objc.swift b/test/IRGen/has_symbol_objc.swift new file mode 100644 index 0000000000000..28a7a57507a8e --- /dev/null +++ b/test/IRGen/has_symbol_objc.swift @@ -0,0 +1,14 @@ +// RUN: %empty-directory(%t) +// RUN: %target-swift-frontend -emit-irgen %s -I %t -I %S/Inputs/has_symbol -module-name test | %FileCheck %s + +// REQUIRES: objc_interop + +@_weakLinked import has_symbol_helper_objc + +public func testClassTypes() { + // CHECK: %{{[0-9]+}} = call i1 @"$sSo9ObjCClassCTwS"() + if #_hasSymbol(ObjCClass.self) {} +} + +// CHECK: define linkonce_odr hidden i1 @"$sSo9ObjCClassCTwS"() +// CHECK: ret i1 icmp ne (%objc_class* @"OBJC_CLASS_$_ObjCClass", %objc_class* null) diff --git a/test/SILOptimizer/cow_opts.sil b/test/SILOptimizer/cow_opts.sil index c6b52e59583a7..a20733ec6a418 100644 --- a/test/SILOptimizer/cow_opts.sil +++ b/test/SILOptimizer/cow_opts.sil @@ -15,6 +15,11 @@ struct Str { @_hasStorage var b: Buffer { get set } } +struct BufferAndBool { + @_hasStorage var b: Buffer { get set } + @_hasStorage var x: Bool { get set } +} + sil @unknown : $@convention(thin) (@guaranteed Buffer) -> () // CHECK-LABEL: sil @test_simple @@ -109,6 +114,29 @@ bb2: return %t : $(Builtin.Int1, Buffer) } +// CHECK-LABEL: sil @test_cond_br_condition +// CHECK: [[I:%[0-9]+]] = integer_literal $Builtin.Int1, -1 +// CHECK: ({{.*}}, [[B:%[0-9]+]]) = begin_cow_mutation +// CHECK: [[T:%[0-9]+]] = tuple ([[I]] : $Builtin.Int1, [[B]] : $Buffer) +// CHECK: return [[T]] +// CHECK: } // end sil function 'test_cond_br_condition' +sil @test_cond_br_condition : $@convention(thin) (@owned Buffer, Bool) -> (Builtin.Int1, @owned Buffer) { +bb0(%0 : $Buffer, %1 : $Bool): + %e = end_cow_mutation %0 : $Buffer + %s1 = struct $BufferAndBool (%e: $Buffer, %1 : $Bool) + %x = struct_extract %s1 : $BufferAndBool, #BufferAndBool.x + %c = struct_extract %x : $Bool, #Bool._value + cond_br %c, bb1, bb2 +bb1: + br bb3 +bb2: + br bb3 +bb3: + (%u, %b) = begin_cow_mutation %e : $Buffer + %t = tuple (%u : $Builtin.Int1, %b : $Buffer) + return %t : $(Builtin.Int1, Buffer) +} + // CHECK-LABEL: sil @not_all_incoming_values_are_end_cow_mutation // CHECK: ([[U:%[0-9]+]], {{.*}}) = begin_cow_mutation // CHECK: [[B:%[0-9]+]] = end_cow_mutation diff --git a/test/Sema/Inputs/has_symbol_helper.swift b/test/Sema/Inputs/has_symbol/has_symbol_helper.swift similarity index 100% rename from test/Sema/Inputs/has_symbol_helper.swift rename to test/Sema/Inputs/has_symbol/has_symbol_helper.swift diff --git a/test/Sema/Inputs/has_symbol/has_symbol_helper_clang.h b/test/Sema/Inputs/has_symbol/has_symbol_helper_clang.h new file mode 100644 index 0000000000000..0e9f034364ae3 --- /dev/null +++ b/test/Sema/Inputs/has_symbol/has_symbol_helper_clang.h @@ -0,0 +1,9 @@ +// NOTE: This header is used on platforms that do not support Obj-C. + +extern void clangFunc(int x); +extern int clangGlobalVar; +struct ClangStruct { + int x; +}; +#define CONSTANT_MACRO 42 +enum ClangEnum { ClangEnumMember = 0 }; diff --git a/test/Sema/Inputs/has_symbol/has_symbol_helper_objc.h b/test/Sema/Inputs/has_symbol/has_symbol_helper_objc.h new file mode 100644 index 0000000000000..50ce6acda5385 --- /dev/null +++ b/test/Sema/Inputs/has_symbol/has_symbol_helper_objc.h @@ -0,0 +1,15 @@ +@import Foundation; + +extern NSString *const StringConstant; + +@interface ObjCClass : NSObject +@property int classMemberProperty; +@property(direct) int directClassMemberProperty; +- (void)classMemberMethod; +- (void)directClassMemberMethod __attribute__((objc_direct)); +@end + +@protocol ObjCProtocol +@property NSObject *protocolMemberProperty; +- (void)protocolMemberMethod; +@end diff --git a/test/Sema/Inputs/has_symbol/module.modulemap b/test/Sema/Inputs/has_symbol/module.modulemap new file mode 100644 index 0000000000000..dfc520990c1d0 --- /dev/null +++ b/test/Sema/Inputs/has_symbol/module.modulemap @@ -0,0 +1,9 @@ +module has_symbol_helper_clang { + header "has_symbol_helper_clang.h" + export * +} + +module has_symbol_helper_objc { + header "has_symbol_helper_objc.h" + export * +} diff --git a/test/Sema/has_symbol.swift b/test/Sema/has_symbol.swift index 60c315474594b..b6f114d4be407 100644 --- a/test/Sema/has_symbol.swift +++ b/test/Sema/has_symbol.swift @@ -1,5 +1,5 @@ // RUN: %empty-directory(%t) -// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol_helper.swift -enable-library-evolution +// RUN: %target-swift-frontend -emit-module -emit-module-path %t/has_symbol_helper.swiftmodule -parse-as-library %S/Inputs/has_symbol/has_symbol_helper.swift -enable-library-evolution // RUN: %target-typecheck-verify-swift -disable-availability-checking -I %t // RUN: %target-typecheck-verify-swift -disable-availability-checking -I %t -enable-experimental-feature ResultBuilderASTTransform diff --git a/test/Sema/has_symbol_clang.swift b/test/Sema/has_symbol_clang.swift new file mode 100644 index 0000000000000..ad4ba14964460 --- /dev/null +++ b/test/Sema/has_symbol_clang.swift @@ -0,0 +1,32 @@ +// RUN: %target-typecheck-verify-swift -disable-availability-checking -I %S/Inputs/has_symbol/ + +// UNSUPPORTED: OS=windows-msvc + +@_weakLinked import has_symbol_helper_clang + +func testFunctions() { + if #_hasSymbol(clangFunc) {} + if #_hasSymbol(clangFunc(_:)) {} +} + +func testGlobalVars() { + // FIXME: Add support for clang global vars + if #_hasSymbol(clangGlobalVar) {} // expected-error {{'#_hasSymbol' cannot be used with this declaration}} +} + +func testTypes() { + if #_hasSymbol(ClangStruct.self) {} // expected-error {{'#_hasSymbol' cannot be used with this declaration}} + if #_hasSymbol(ClangEnum.self) {} // expected-error {{'#_hasSymbol' cannot be used with this declaration}} +} + +func testMacros() { + if #_hasSymbol(CONSTANT_MACRO) {} // FIXME: This should be diagnosed +} + +func testEnum() { + if #_hasSymbol(ClangEnumMember) {} // expected-error {{'#_hasSymbol' cannot be used with this declaration}} +} + +func testStruct(_ s: ClangStruct) { + if #_hasSymbol(s.x) {} // expected-error {{'#_hasSymbol' cannot be used with this declaration}} +} diff --git a/test/Sema/has_symbol_objc.swift b/test/Sema/has_symbol_objc.swift new file mode 100644 index 0000000000000..ba8f73189b472 --- /dev/null +++ b/test/Sema/has_symbol_objc.swift @@ -0,0 +1,23 @@ +// RUN: %target-typecheck-verify-swift -disable-availability-checking -I %S/Inputs/has_symbol/ + +// REQUIRES: objc_interop + +@_weakLinked import has_symbol_helper_objc + +func testTypes() { + if #_hasSymbol(ObjCClass.self) {} + if #_hasSymbol(ObjCProtocol.self) {} // expected-error {{'#_hasSymbol' cannot be used with this declaration}} +} + +func testClassMembers(_ c: ObjCClass) { + if #_hasSymbol(c.classMemberProperty) {} // expected-error {{'#_hasSymbol' cannot be used with Objective-C property 'classMemberProperty'; use respondsToSelector() instead}} + if #_hasSymbol(c.classMemberMethod) {} // expected-error {{'#_hasSymbol' cannot be used with Objective-C method 'classMemberMethod'; use respondsToSelector() instead}} + + if #_hasSymbol(c.directClassMemberProperty) {} // expected-error {{'#_hasSymbol' cannot be used with Objective-C property 'directClassMemberProperty'; use respondsToSelector() instead}} + if #_hasSymbol(c.directClassMemberMethod) {} // expected-error {{'#_hasSymbol' cannot be used with Objective-C method 'directClassMemberMethod'; use respondsToSelector() instead}} +} + +func testProtocolMembers(_ p: ObjCProtocol) { + if #_hasSymbol(p.protocolMemberProperty) {} // expected-error {{'#_hasSymbol' cannot be used with Objective-C property 'protocolMemberProperty'; use respondsToSelector() instead}} + if #_hasSymbol(p.protocolMemberMethod) {} // expected-error {{'#_hasSymbol' cannot be used with Objective-C method 'protocolMemberMethod'; use respondsToSelector() instead}} +} diff --git a/test/stdlib/StaticBigInt.swift b/test/stdlib/StaticBigInt.swift index 246e7c5cbe9b2..395e9a867fae1 100644 --- a/test/stdlib/StaticBigInt.swift +++ b/test/stdlib/StaticBigInt.swift @@ -13,13 +13,11 @@ // RUN: %target-run-simple-swift(-parse-as-library) // REQUIRES: executable_test // REQUIRES: reflection +// UNSUPPORTED: use_os_stdlib // END. // //===----------------------------------------------------------------------===// -// rdar://103369837 -// UNSUPPORTED: OS=watchos || OS=macos - import StdlibUnittest @available(SwiftStdlib 5.8, *) @@ -32,6 +30,8 @@ final class StaticBigIntTests { let testSuite = TestSuite("StaticBigIntTests") testSuite.test("BinaryRepresentation", testCase.testBinaryRepresentation) testSuite.test("TextualRepresentation", testCase.testTextualRepresentation) + testSuite.test("PrefixPlusTypeInference", testCase.testPrefixPlusTypeInference) + testSuite.test("PrefixMinusTypeInference", testCase.testPrefixMinusTypeInference) testSuite.test("WrapperAssociatedType", testCase.testWrapperAssociatedType) runAllTests() } @@ -57,29 +57,31 @@ extension StaticBigIntTests { -0x3: (-1, 3, [~2, ~0, ~0, ~0, ~0], [~2, ~0, ~0]), -0x2: (-1, 2, [~1, ~0, ~0, ~0, ~0], [~1, ~0, ~0]), -0x1: (-1, 1, [~0, ~0, ~0, ~0, ~0], [~0, ~0, ~0]), - +0x0: ( 0, 1, [ 0, 0, 0, 0, 0], [ 0, 0, 0]), - +0x1: (+1, 2, [ 1, 0, 0, 0, 0], [ 1, 0, 0]), - +0x2: (+1, 3, [ 2, 0, 0, 0, 0], [ 2, 0, 0]), - +0x3: (+1, 3, [ 3, 0, 0, 0, 0], [ 3, 0, 0]), - +0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE: (+1, 128, [~1, ~0, ~0, ~m, 0], [~1, ~m, 0]), - +0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF: (+1, 128, [~0, ~0, ~0, ~m, 0], [~0, ~m, 0]), - +0x80000000000000000000000000000000: (+1, 129, [ 0, 0, 0, m, 0], [ 0, m, 0]), - +0x80000000000000000000000000000001: (+1, 129, [ 1, 0, 0, m, 0], [ 1, m, 0]), + 0x0: ( 0, 1, [ 0, 0, 0, 0, 0], [ 0, 0, 0]), + 0x1: (+1, 2, [ 1, 0, 0, 0, 0], [ 1, 0, 0]), + 0x2: (+1, 3, [ 2, 0, 0, 0, 0], [ 2, 0, 0]), + 0x3: (+1, 3, [ 3, 0, 0, 0, 0], [ 3, 0, 0]), + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE: (+1, 128, [~1, ~0, ~0, ~m, 0], [~1, ~m, 0]), + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF: (+1, 128, [~0, ~0, ~0, ~m, 0], [~0, ~m, 0]), + 0x80000000000000000000000000000000: (+1, 129, [ 0, 0, 0, m, 0], [ 0, m, 0]), + 0x80000000000000000000000000000001: (+1, 129, [ 1, 0, 0, m, 0], [ 1, m, 0]), ] for (actual, expected) in keyValuePairs { expectEqual(expected.signum, actual.signum()) expectEqual(expected.bitWidth, actual.bitWidth) - if getInt(UInt.bitWidth) == 32 { - expectEqual(expected._32bit[0], actual[0]) - expectEqual(expected._32bit[1], actual[1]) - expectEqual(expected._32bit[2], actual[2]) - expectEqual(expected._32bit[3], actual[3]) - expectEqual(expected._32bit[4], actual[4]) - } else if getInt(UInt.bitWidth) == 64 { - expectEqual(expected._64bit[0], actual[0]) - expectEqual(expected._64bit[1], actual[1]) - expectEqual(expected._64bit[2], actual[2]) - } +#if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) || arch(powerpc) + expectEqual(expected._32bit[0], actual[0]) + expectEqual(expected._32bit[1], actual[1]) + expectEqual(expected._32bit[2], actual[2]) + expectEqual(expected._32bit[3], actual[3]) + expectEqual(expected._32bit[4], actual[4]) +#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) || arch(riscv64) + expectEqual(expected._64bit[0], actual[0]) + expectEqual(expected._64bit[1], actual[1]) + expectEqual(expected._64bit[2], actual[2]) +#else +#error("Unimplemented") +#endif } } } @@ -108,20 +110,20 @@ extension StaticBigIntTests { -0x3: "-0x3", -0x2: "-0x2", -0x1: "-0x1", - +0x0: "+0x0", - +0x1: "+0x1", - +0x2: "+0x2", - +0x3: "+0x3", - +0x10: "+0x10", - +0x100: "+0x100", - +0x1000: "+0x1000", - +0x123456789ABC: "+0x123456789ABC", - +0x123456789ABCD: "+0x123456789ABCD", - +0x123456789ABCDE: "+0x123456789ABCDE", - +0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE: "+0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE", - +0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF: "+0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", - +0x80000000000000000000000000000000: "+0x80000000000000000000000000000000", - +0x80000000000000000000000000000001: "+0x80000000000000000000000000000001", + 0x0: "+0x0", + 0x1: "+0x1", + 0x2: "+0x2", + 0x3: "+0x3", + 0x10: "+0x10", + 0x100: "+0x100", + 0x1000: "+0x1000", + 0x123456789ABC: "+0x123456789ABC", + 0x123456789ABCD: "+0x123456789ABCD", + 0x123456789ABCDE: "+0x123456789ABCDE", + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE: "+0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE", + 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF: "+0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", + 0x80000000000000000000000000000000: "+0x80000000000000000000000000000000", + 0x80000000000000000000000000000001: "+0x80000000000000000000000000000001", ] for (actual, expected) in keyValuePairs { expectEqual(expected, String(reflecting: actual)) @@ -147,6 +149,26 @@ extension StaticBigIntTests { self.actual = actual } } + + func testPrefixPlusTypeInference() { + let a: Int = 7 + // An earlier version of StaticBigInt contained a prefix + operation, + // which caused b to be inferred to have type StaticBigInt rather than + // Int: + let b = +1 + // and then this would fail to typecheck, because there's no + // Int + StaticBigInt operation. + let c = a + b + } + + func testPrefixMinusTypeInference() { + // This example shouldn't suffer from the same problem as above, because + // -1 is a literal, not a prefix operator followed by a literal. + // Nonetheless, let's test it. + let a: Int = 7 + let b = -1 + let c = a + b + } @available(SwiftStdlib 5.8, *) func testWrapperAssociatedType() { @@ -154,39 +176,46 @@ extension StaticBigIntTests { let negative = Wrapper(-0x00112233_44556677_8899AABB_CCDDEEFF) expectEqual( -1, negative.actual.signum()) expectEqual(118, negative.actual.bitWidth) -#if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) +#if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) || arch(powerpc) expectEqual(0x33221101, negative.actual[0]) expectEqual(0x77665544, negative.actual[1]) expectEqual(0xBBAA9988, negative.actual[2]) expectEqual(0xFFEEDDCC, negative.actual[3]) expectEqual(0xFFFFFFFF, negative.actual[4]) expectEqual(0xFFFFFFFF, negative.actual[.max]) -#else +#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) || arch(riscv64) expectEqual(0x77665544_33221101, negative.actual[0]) expectEqual(0xFFEEDDCC_BBAA9988, negative.actual[1]) expectEqual(0xFFFFFFFF_FFFFFFFF, negative.actual[2]) expectEqual(0xFFFFFFFF_FFFFFFFF, negative.actual[.max]) +#else +#error("Unimplemented") #endif } do { let positive = Wrapper(0x00112233_44556677_8899AABB_CCDDEEFF) expectEqual( +1, positive.actual.signum()) expectEqual(118, positive.actual.bitWidth) -#if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) +#if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) || arch(powerpc) expectEqual(0xCCDDEEFF, positive.actual[0]) expectEqual(0x8899AABB, positive.actual[1]) expectEqual(0x44556677, positive.actual[2]) expectEqual(0x00112233, positive.actual[3]) expectEqual(0x00000000, positive.actual[4]) expectEqual(0x00000000, positive.actual[.max]) -#else +#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) || arch(riscv64) expectEqual(0x8899AABB_CCDDEEFF, positive.actual[0]) expectEqual(0x00112233_44556677, positive.actual[1]) expectEqual(0x00000000_00000000, positive.actual[2]) expectEqual(0x00000000_00000000, positive.actual[.max]) +#else +#error("Unimplemented") #endif } - if getInt(UInt.bitWidth) == 64 { + do { +#if arch(i386) || arch(arm) || arch(arm64_32) || arch(wasm32) || arch(powerpc) + // Unimplemented. +#elseif arch(x86_64) || arch(arm64) || arch(powerpc64) || arch(powerpc64le) || arch(s390x) || arch(riscv64) let fibonacciSequence = Wrapper( 0xA94FAD42221F2702_68A3DD8E61ECCFBD_40ABCFB3C0325745_27F80DDAA1BA7878_18B3C1D91E77DECD_0F444C01834299AB_096F75D79B354522_05D4D629E80D5489_039A9FADB327F099_023A367C34E563F0_016069317E428CA9_00D9CD4AB6A2D747_00869BE6C79FB562_00533163EF0321E5_00336A82D89C937D_001FC6E116668E68_0013A3A1C2360515_000C233F54308953_000780626E057BC2_0004A2DCE62B0D91_0002DD8587DA6E31_0001C5575E509F60_0001182E2989CED1_0000AD2934C6D08F_00006B04F4C2FE42_000042244003D24D_000028E0B4BF2BF5_000019438B44A658_00000F9D297A859D_000009A661CA20BB_000005F6C7B064E2_000003AF9A19BBD9_000002472D96A909_000001686C8312D0_000000DEC1139639_00000089AB6F7C97_0000005515A419A2_0000003495CB62F5_000000207FD8B6AD_0000001415F2AC48_0000000C69E60A65_00000007AC0CA1E3_00000004BDD96882_00000002EE333961_00000001CFA62F21_000000011E8D0A40_00000000B11924E1_000000006D73E55F_0000000043A53F82_0000000029CEA5DD_0000000019D699A5_000000000FF80C38_0000000009DE8D6D_0000000006197ECB_0000000003C50EA2_0000000002547029_0000000001709E79_0000000000E3D1B0_00000000008CCCC9_00000000005704E7_000000000035C7E2_0000000000213D05_0000000000148ADD_00000000000CB228_000000000007D8B5_000000000004D973_000000000002FF42_000000000001DA31_0000000000012511_000000000000B520_0000000000006FF1_000000000000452F_0000000000002AC2_0000000000001A6D_0000000000001055_0000000000000A18_000000000000063D_00000000000003DB_0000000000000262_0000000000000179_00000000000000E9_0000000000000090_0000000000000059_0000000000000037_0000000000000022_0000000000000015_000000000000000D_0000000000000008_0000000000000005_0000000000000003_0000000000000002_0000000000000001_0000000000000001_0000000000000000 ) @@ -201,6 +230,9 @@ extension StaticBigIntTests { fibonacciSequence.actual[wordIndex - 2] ) } +#else +#error("Unimplemented") +#endif } } }