Skip to content

Commit d787c0f

Browse files
committed
Extend effects checking to the various expressions that reference declarations
Only "unsafe" checking is affected here.
1 parent 16b0538 commit d787c0f

File tree

2 files changed

+29
-3
lines changed

2 files changed

+29
-3
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,22 @@ class EffectsHandlingWalker : public ASTWalker {
591591
recurse = asImpl().checkWithSubstitutionMap(E, UTO->substitutions);
592592
} else if (auto *EE = dyn_cast<ErasureExpr>(E)) {
593593
recurse = asImpl().checkWithConformances(E, EE->getConformances());
594+
} else if (auto *OCD = dyn_cast<OtherConstructorDeclRefExpr>(E)) {
595+
recurse = asImpl().checkDeclRef(OCD, OCD->getDeclRef(), OCD->getLoc(),
596+
/*isImplicitlyAsync=*/false,
597+
/*isImplicitlyThrows=*/false);
598+
} else if (auto *ME = dyn_cast<MacroExpansionExpr>(E)) {
599+
recurse = asImpl().checkDeclRef(ME, ME->getMacroRef(), ME->getLoc(),
600+
/*isImplicitlyAsync=*/false,
601+
/*isImplicitlyThrows=*/false);
602+
} else if (auto *LE = dyn_cast<LiteralExpr>(E)) {
603+
recurse = asImpl().checkDeclRef(LE, LE->getInitializer(), LE->getLoc(),
604+
/*isImplicitlyAsync=*/false,
605+
/*isImplicitlyThrows=*/false);
606+
} else if (auto *CE = dyn_cast<CollectionExpr>(E)) {
607+
recurse = asImpl().checkDeclRef(CE, CE->getInitializer(), CE->getLoc(),
608+
/*isImplicitlyAsync=*/false,
609+
/*isImplicitlyThrows=*/false);
594610
}
595611
// Error handling validation (via checkTopLevelEffects) happens after
596612
// type checking. If an unchecked expression is still around, the code was
@@ -1879,7 +1895,7 @@ class ApplyClassifier {
18791895
Self.classifyDeclRef(
18801896
declRef, loc, isImplicitlyAsync, isImplicitlyThrows
18811897
).onlyThrowing());
1882-
return ShouldNotRecurse;
1898+
return ShouldRecurse;
18831899
}
18841900
ShouldRecurse_t checkAsyncLet(PatternBindingDecl *patternBinding) {
18851901
return ShouldRecurse;
@@ -2006,7 +2022,7 @@ class ApplyClassifier {
20062022
AsyncKind = ConditionalEffectKind::Always;
20072023
}
20082024

2009-
return ShouldNotRecurse;
2025+
return ShouldRecurse;
20102026
}
20112027
ShouldRecurse_t checkAsyncLet(PatternBindingDecl *patternBinding) {
20122028
AsyncKind = ConditionalEffectKind::Always;
@@ -3634,7 +3650,7 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
36343650
declRefExpr->setThrows(throwDest);
36353651
}
36363652

3637-
return ShouldNotRecurse;
3653+
return ShouldRecurse;
36383654
}
36393655

36403656
ShouldRecurse_t checkAsyncLet(PatternBindingDecl *patternBinding) {

test/Unsafe/safe.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ func returnsExistentialP() -> any P {
8181
// expected-note@-1{{@unsafe conformance of 'Int' to protocol 'P' involves unsafe code}}
8282
}
8383

84+
class MyRange {
85+
@unsafe init(unchecked bounds: Range<Int>) { }
86+
87+
convenience init(_ bounds: Range<Int>) {
88+
// bounds check
89+
self.init(unchecked: bounds) // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe'}}
90+
// expected-note@-1{{reference to unsafe initializer 'init(unchecked:)'}}
91+
}
92+
}
93+
8494
// Parsing of `unsafe` expressions.
8595
func testUnsafePositionError() -> Int {
8696
return 3 + unsafe unsafeInt() // expected-error{{'unsafe' cannot appear to the right of a non-assignment operator}}

0 commit comments

Comments
 (0)