Skip to content

Commit 18c04b5

Browse files
authored
Merge pull request #61503 from tshortli/diagnose-has-symbol-on-non-darwin
Sema: Diagnose `if #_hasSymbol` as unsupported on non-Darwin targets
2 parents 2f06546 + 64e8a03 commit 18c04b5

File tree

5 files changed

+71
-41
lines changed

5 files changed

+71
-41
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6618,9 +6618,9 @@ WARNING(has_symbol_decl_must_be_weak,none,
66186618
"%0 %1 is not a weakly linked declaration",
66196619
(DescriptiveDeclKind, DeclName))
66206620
ERROR(has_symbol_invalid_expr,none,
6621-
"#_hasSymbol condition must refer to a declaration", ())
6622-
ERROR(has_symbol_unsupported_in_closures,none,
6623-
"#_hasSymbol is not supported in closures", ())
6621+
"'#_hasSymbol' condition must refer to a declaration", ())
6622+
ERROR(has_symbol_unsupported,none,
6623+
"'#_hasSymbol' is unsupported on target '%0'", (StringRef))
66246624

66256625
//------------------------------------------------------------------------------
66266626
// MARK: Type erasure

lib/Sema/MiscDiagnostics.cpp

Lines changed: 47 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4390,6 +4390,51 @@ checkImplicitPromotionsInCondition(const StmtConditionElement &cond,
43904390
}
43914391
}
43924392

4393+
/// Diagnoses a `if #_hasSymbol(...)` condition. Returns true if a diagnostic
4394+
/// was emitted.
4395+
static bool diagnoseHasSymbolCondition(PoundHasSymbolInfo *info,
4396+
DeclContext *DC) {
4397+
// If we have an invalid info, null expression, or expression without a type
4398+
// then type checking failed already for this condition.
4399+
if (info->isInvalid())
4400+
return false;
4401+
4402+
auto symbolExpr = info->getSymbolExpr();
4403+
if (!symbolExpr)
4404+
return false;
4405+
4406+
if (!symbolExpr->getType())
4407+
return false;
4408+
4409+
auto &ctx = DC->getASTContext();
4410+
if (!ctx.LangOpts.Target.isOSDarwin()) {
4411+
// SILGen for #_hasSymbol is currently implemented assuming the target OS
4412+
// is a Darwin platform.
4413+
ctx.Diags.diagnose(info->getStartLoc(), diag::has_symbol_unsupported,
4414+
ctx.LangOpts.Target.str());
4415+
return true;
4416+
}
4417+
4418+
auto decl = info->getReferencedDecl().getDecl();
4419+
if (!decl) {
4420+
// Diagnose because we weren't able to interpret the expression as one
4421+
// that uniquely identifies a single declaration.
4422+
ctx.Diags.diagnose(symbolExpr->getLoc(), diag::has_symbol_invalid_expr);
4423+
return true;
4424+
}
4425+
4426+
if (!decl->isWeakImported(DC->getParentModule())) {
4427+
// `if #_hasSymbol(someStronglyLinkedSymbol)` is functionally a no-op
4428+
// and may indicate the developer has mis-identified the declaration
4429+
// they want to check (or forgot to import the module weakly).
4430+
ctx.Diags.diagnose(symbolExpr->getLoc(), diag::has_symbol_decl_must_be_weak,
4431+
decl->getDescriptiveKind(), decl->getName());
4432+
return true;
4433+
}
4434+
4435+
return false;
4436+
}
4437+
43934438
/// Perform MiscDiagnostics for the conditions belonging to a \c
43944439
/// LabeledConditionalStmt.
43954440
static void checkLabeledStmtConditions(ASTContext &ctx,
@@ -4407,32 +4452,9 @@ static void checkLabeledStmtConditions(ASTContext &ctx,
44074452

44084453
case StmtConditionElement::CK_HasSymbol: {
44094454
auto info = elt.getHasSymbolInfo();
4410-
if (info->isInvalid())
4411-
break;
4412-
4413-
auto symbolExpr = info->getSymbolExpr();
4414-
if (!symbolExpr)
4415-
break;
4416-
4417-
if (!symbolExpr->getType())
4418-
break;
4419-
4420-
if (auto decl = info->getReferencedDecl().getDecl()) {
4421-
// `if #_hasSymbol(someStronglyLinkedSymbol)` is functionally a no-op
4422-
// and may indicate the developer has mis-identified the declaration
4423-
// they want to check (or forgot to import the module weakly).
4424-
if (!decl->isWeakImported(DC->getParentModule())) {
4425-
ctx.Diags.diagnose(symbolExpr->getLoc(),
4426-
diag::has_symbol_decl_must_be_weak,
4427-
decl->getDescriptiveKind(), decl->getName());
4428-
info->setInvalid();
4429-
}
4430-
} else {
4431-
// Diagnose because we weren't able to interpret the expression as one
4432-
// that uniquely identifies a single declaration.
4433-
ctx.Diags.diagnose(symbolExpr->getLoc(), diag::has_symbol_invalid_expr);
4455+
if (diagnoseHasSymbolCondition(info, DC))
44344456
info->setInvalid();
4435-
}
4457+
44364458
break;
44374459
}
44384460
}

test/Parse/has_symbol.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %target-swift-frontend -emit-module -emit-module-path %t/Library.swiftmodule -parse-as-library %t/Library.swift -enable-library-evolution
44
// RUN: %target-swift-frontend -typecheck -verify %t/Client.swift -I %t
55

6-
// UNSUPPORTED: OS=windows-msvc
6+
// REQUIRES: VENDOR=apple
77

88
//--- Library.swift
99

test/Sema/has_symbol.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// RUN: %target-typecheck-verify-swift -disable-availability-checking -I %t
44
// RUN: %target-typecheck-verify-swift -disable-availability-checking -I %t -enable-experimental-feature ResultBuilderASTTransform
55

6-
// UNSUPPORTED: OS=windows-msvc
6+
// REQUIRES: VENDOR=apple
77

88
@_weakLinked import has_symbol_helper
99

@@ -95,11 +95,11 @@ func testNotWeakDeclDiagnostics(_ s: LocalStruct) {
9595

9696
func testInvalidExpressionsDiagnostics() {
9797
if #_hasSymbol(unknownDecl) {} // expected-error {{cannot find 'unknownDecl' in scope}}
98-
if #_hasSymbol(noArgFunc()) {} // expected-error {{#_hasSymbol condition must refer to a declaration}}
99-
if #_hasSymbol(global - 1) {} // expected-error {{#_hasSymbol condition must refer to a declaration}}
100-
if #_hasSymbol(S.staticFunc()) {} // expected-error {{#_hasSymbol condition must refer to a declaration}}
101-
if #_hasSymbol(C.classFunc()) {} // expected-error {{#_hasSymbol condition must refer to a declaration}}
102-
if #_hasSymbol(1 as Int) {} // expected-error {{#_hasSymbol condition must refer to a declaration}}
98+
if #_hasSymbol(noArgFunc()) {} // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
99+
if #_hasSymbol(global - 1) {} // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
100+
if #_hasSymbol(S.staticFunc()) {} // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
101+
if #_hasSymbol(C.classFunc()) {} // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
102+
if #_hasSymbol(1 as Int) {} // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
103103
if #_hasSymbol(1 as S) {} // expected-error {{cannot convert value of type 'Int' to type 'S' in coercion}}
104104
}
105105

@@ -127,11 +127,11 @@ func testClosure() {
127127
doIt { if #_hasSymbol(ambiguousFunc) {} } // expected-error {{ambiguous use of 'ambiguousFunc()'}}
128128
doIt { if #_hasSymbol(localFunc) {} } // expected-warning {{global function 'localFunc()' is not a weakly linked declaration}}
129129
doIt { if #_hasSymbol(unknownDecl) {} } // expected-error {{cannot find 'unknownDecl' in scope}}
130-
doIt { if #_hasSymbol(noArgFunc()) {} } // expected-error {{#_hasSymbol condition must refer to a declaration}}
131-
doIt { if #_hasSymbol(global - 1) {} } // expected-error {{#_hasSymbol condition must refer to a declaration}}
132-
doIt { if #_hasSymbol(S.staticFunc()) {} } // expected-error {{#_hasSymbol condition must refer to a declaration}}
133-
doIt { if #_hasSymbol(C.classFunc()) {} } // expected-error {{#_hasSymbol condition must refer to a declaration}}
134-
doIt { if #_hasSymbol(1 as Int) {} } // expected-error {{#_hasSymbol condition must refer to a declaration}}
130+
doIt { if #_hasSymbol(noArgFunc()) {} } // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
131+
doIt { if #_hasSymbol(global - 1) {} } // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
132+
doIt { if #_hasSymbol(S.staticFunc()) {} } // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
133+
doIt { if #_hasSymbol(C.classFunc()) {} } // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
134+
doIt { if #_hasSymbol(1 as Int) {} } // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
135135
doIt { if #_hasSymbol(1 as S) {} } // expected-error {{cannot convert value of type 'Int' to type 'S' in coercion}}
136136
}
137137

@@ -164,7 +164,7 @@ struct MyView {
164164
}
165165

166166
@ViewBuilder var noArgFuncView: some View {
167-
if #_hasSymbol(noArgFunc()) { image } // expected-error {{#_hasSymbol condition must refer to a declaration}}
167+
if #_hasSymbol(noArgFunc()) { image } // expected-error {{'#_hasSymbol' condition must refer to a declaration}}
168168
else { image }
169169
}
170170
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %target-typecheck-verify-swift
2+
// UNSUPPORTED: VENDOR=apple
3+
4+
// Verify that #_hasSymbol is rejected on non-Darwin platforms
5+
6+
func foo() {}
7+
8+
if #_hasSymbol(foo) { } // expected-error {{'#_hasSymbol' is unsupported on target}}

0 commit comments

Comments
 (0)