Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions include/swift/SIL/SILSymbolVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,14 @@ class SILSymbolVisitor {

template <typename F>
void enumerateFunctionsForHasSymbol(SILModule &M, ValueDecl *D, F Handler) {
// Handle clang decls separately.
if (auto *clangDecl = D->getClangDecl()) {
if (isa<clang::FunctionDecl>(clangDecl))
Handler(SILDeclRef(D).asForeign());

return;
}

class SymbolVisitor : public SILSymbolVisitor {
F Handler;

Expand Down
1 change: 0 additions & 1 deletion lib/AST/ASTPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7124,7 +7124,6 @@ swift::getInheritedForPrinting(
}

// Collect synthesized conformances.
auto &ctx = decl->getASTContext();
llvm::SetVector<ProtocolDecl *> protocols;
llvm::TinyPtrVector<ProtocolDecl *> uncheckedProtocols;
for (auto attr : decl->getAttrs().getAttributes<SynthesizedProtocolAttr>()) {
Expand Down
45 changes: 37 additions & 8 deletions lib/IRGen/GenHasSymbol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -111,6 +112,39 @@ class HasSymbolIRGenVisitor : public IRSymbolVisitor {
}
};

static llvm::Constant *
getAddrOfLLVMVariableForClangDecl(IRGenModule &IGM, ValueDecl *decl,
const clang::Decl *clangDecl) {
if (isa<clang::FunctionDecl>(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<clang::ObjCInterfaceDecl>(clangDecl))
return IGM.getAddrOfObjCClass(cast<ClassDecl>(decl), NotForDefinition);

llvm::report_fatal_error("Unexpected clang decl kind");
}

static void
getSymbolAddrsForDecl(IRGenModule &IGM, ValueDecl *decl,
llvm::SmallVector<llvm::Constant *, 4> &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);
Expand All @@ -119,14 +153,9 @@ llvm::Function *IRGenModule::emitHasSymbolFunction(ValueDecl *decl) {
auto func = cast<llvm::Function>(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<llvm::Constant *, 4> addrs;
HasSymbolIRGenVisitor(*this, addrs).visit(decl, symbolVisitorCtx);
getSymbolAddrsForDecl(*this, decl, addrs);

llvm::Value *ret = nullptr;
for (llvm::Constant *addr : addrs) {
Expand Down
6 changes: 4 additions & 2 deletions lib/SILOptimizer/Transforms/COWOpts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,10 @@ void COWOptsPass::collectEscapePoints(SILValue v,
escapePoints, handled);
break;
case SILInstructionKind::CondBranchInst:
collectEscapePoints(cast<CondBranchInst>(user)->getArgForOperand(use),
escapePoints, handled);
if (use->getOperandNumber() != CondBranchInst::ConditionIdx) {
collectEscapePoints(cast<CondBranchInst>(user)->getArgForOperand(use),
escapePoints, handled);
}
break;
case SILInstructionKind::StructInst:
case SILInstructionKind::StructExtractInst:
Expand Down
36 changes: 36 additions & 0 deletions lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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<clang::ObjCInterfaceDecl>(clangDecl) ||
isa<clang::FunctionDecl>(clangDecl))
return false;

if (auto *method = dyn_cast<clang::ObjCMethodDecl>(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<clang::ObjCPropertyDecl>(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,
Expand All @@ -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
Expand Down
10 changes: 1 addition & 9 deletions stdlib/public/core/StaticBigInt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}

//===----------------------------------------------------------------------===//
Expand Down Expand Up @@ -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
Expand Down
3 changes: 3 additions & 0 deletions test/IRGen/Inputs/has_symbol/has_symbol_helper_clang.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// NOTE: This header is used on platforms that do not support Obj-C.

extern void clangFunc(int x);
4 changes: 4 additions & 0 deletions test/IRGen/Inputs/has_symbol/has_symbol_helper_objc.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
@import Foundation;

@interface ObjCClass : NSObject
@end
9 changes: 9 additions & 0 deletions test/IRGen/Inputs/has_symbol/module.modulemap
Original file line number Diff line number Diff line change
@@ -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 *
}
4 changes: 2 additions & 2 deletions test/IRGen/has_symbol.swift
Original file line number Diff line number Diff line change
@@ -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

Expand Down
2 changes: 1 addition & 1 deletion test/IRGen/has_symbol_async.swift
Original file line number Diff line number Diff line change
@@ -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
Expand Down
15 changes: 15 additions & 0 deletions test/IRGen/has_symbol_clang.swift
Original file line number Diff line number Diff line change
@@ -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)
14 changes: 14 additions & 0 deletions test/IRGen/has_symbol_objc.swift
Original file line number Diff line number Diff line change
@@ -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)
28 changes: 28 additions & 0 deletions test/SILOptimizer/cow_opts.sil
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 9 additions & 0 deletions test/Sema/Inputs/has_symbol/has_symbol_helper_clang.h
Original file line number Diff line number Diff line change
@@ -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 };
15 changes: 15 additions & 0 deletions test/Sema/Inputs/has_symbol/has_symbol_helper_objc.h
Original file line number Diff line number Diff line change
@@ -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 <NSObject>
@property NSObject *protocolMemberProperty;
- (void)protocolMemberMethod;
@end
9 changes: 9 additions & 0 deletions test/Sema/Inputs/has_symbol/module.modulemap
Original file line number Diff line number Diff line change
@@ -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 *
}
2 changes: 1 addition & 1 deletion test/Sema/has_symbol.swift
Original file line number Diff line number Diff line change
@@ -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

Expand Down
32 changes: 32 additions & 0 deletions test/Sema/has_symbol_clang.swift
Original file line number Diff line number Diff line change
@@ -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}}
}
Loading