Skip to content

Commit bda17b0

Browse files
authored
Merge pull request #79265 from DougGregor/unsafe-fixit-fixes
Fix Fix-It locations for "unsafe" insertion
2 parents 41b043e + 929836d commit bda17b0

File tree

3 files changed

+32
-8
lines changed

3 files changed

+32
-8
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3167,12 +3167,13 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
31673167
/// anchor expression, so we can emit diagnostics at the end.
31683168
llvm::MapVector<Expr *, std::vector<UnsafeUse>> uncoveredUnsafeUses;
31693169

3170-
static bool isEffectAnchor(Expr *e) {
3170+
static bool isEffectAnchor(Expr *e, bool stopAtAutoClosure) {
31713171
if (e->getLoc().isInvalid())
31723172
return false;
31733173

3174-
return isa<AbstractClosureExpr>(e) || isa<DiscardAssignmentExpr>(e) ||
3175-
isa<AssignExpr>(e) || (isa<DeclRefExpr>(e) && e->isImplicit());
3174+
return isa<ClosureExpr>(e) || isa<DiscardAssignmentExpr>(e) ||
3175+
isa<AssignExpr>(e) ||
3176+
(stopAtAutoClosure && isa<AutoClosureExpr>(e));
31763177
}
31773178

31783179
static bool isAnchorTooEarly(Expr *e) {
@@ -3181,11 +3182,12 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
31813182

31823183
/// Find the top location where we should put the await
31833184
static Expr *walkToAnchor(Expr *e, llvm::DenseMap<Expr *, Expr *> &parentMap,
3184-
bool isInterpolatedString) {
3185+
bool isInterpolatedString,
3186+
bool stopAtAutoClosure) {
31853187
llvm::SmallPtrSet<Expr *, 4> visited;
31863188
Expr *parent = e;
31873189
Expr *lastParent = e;
3188-
while (parent && !isEffectAnchor(parent)) {
3190+
while (parent && !isEffectAnchor(parent, stopAtAutoClosure)) {
31893191
lastParent = parent;
31903192
parent = parentMap[parent];
31913193

@@ -3890,7 +3892,8 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
38903892
Flags.has(ContextFlags::InAsyncLet))) {
38913893
Expr *expr = E.dyn_cast<Expr*>();
38923894
Expr *anchor = walkToAnchor(expr, parentMap,
3893-
CurContext.isWithinInterpolatedString());
3895+
CurContext.isWithinInterpolatedString(),
3896+
/*stopAtAutoClosure=*/true);
38943897
if (Flags.has(ContextFlags::StmtExprCoversAwait))
38953898
classification.setDowngradeToWarning(true);
38963899
if (uncoveredAsync.find(anchor) == uncoveredAsync.end())
@@ -3915,7 +3918,8 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
39153918
if (!Flags.has(ContextFlags::IsUnsafeCovered)) {
39163919
Expr *expr = E.dyn_cast<Expr*>();
39173920
Expr *anchor = walkToAnchor(expr, parentMap,
3918-
CurContext.isWithinInterpolatedString());
3921+
CurContext.isWithinInterpolatedString(),
3922+
/*stopAtAutoClosure=*/false);
39193923

39203924
// Figure out a location to use if the unsafe use didn't have one.
39213925
SourceLoc replacementLoc;

test/Unsafe/safe.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ func testKeyPath() {
140140
func takesAutoclosure<T>(_ body: @autoclosure () -> T) { }
141141

142142
func testAutoclosure() {
143-
// expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{20-20=unsafe }}
143+
// expected-warning@+1{{expression uses unsafe constructs but is not marked with 'unsafe'}}{{3-3=unsafe }}
144144
takesAutoclosure(unsafeFunction()) // expected-note{{reference to unsafe global function 'unsafeFunction()'}}
145145

146146
unsafe takesAutoclosure(unsafeFunction())

test/Unsafe/unsafe.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,26 @@ class ExclusivityChecking {
123123
// TODO: diagnose the need for @unsafe when there's an unsafe superclass.
124124
class UnsafeSub: UnsafeSuper { }
125125

126+
// -----------------------------------------------------------------------
127+
// Miscellaneous expression issues
128+
// -----------------------------------------------------------------------
129+
130+
struct BufferThingy<T> {
131+
@unsafe init(count: Int) { }
132+
}
133+
134+
func testConstruction() {
135+
let _ = BufferThingy<Int>(count: 17) // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe' [Unsafe]}}{{11-11=unsafe }}
136+
// expected-note@-1{{reference to unsafe initializer 'init(count:)'}}
137+
}
138+
139+
func testRHS(b: Bool, x: Int) {
140+
@unsafe let limit = 17
141+
if b && x > limit { // expected-warning{{expression uses unsafe constructs but is not marked with 'unsafe' [Unsafe]}}{{6-6=unsafe }}
142+
// expected-note@-1{{reference to unsafe let 'limit'}}
143+
}
144+
}
145+
126146
// -----------------------------------------------------------------------
127147
// Declaration references
128148
// -----------------------------------------------------------------------

0 commit comments

Comments
 (0)