Skip to content

Commit d7401b5

Browse files
authored
Merge pull request #8441 from gottesmm/rdar_31313534
2 parents 51e6f92 + ba5be9d commit d7401b5

File tree

7 files changed

+74
-10
lines changed

7 files changed

+74
-10
lines changed

lib/SILGen/Cleanup.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -276,3 +276,9 @@ void CleanupManager::dump(CleanupHandle handle) const {
276276
llvm::errs() << "CLEANUP DEPTH: " << handle.getDepth() << "\n";
277277
stackCleanup.dump(SGF);
278278
}
279+
280+
void CleanupManager::checkIterator(CleanupHandle handle) const {
281+
#ifndef NDEBUG
282+
stack.checkIterator(handle);
283+
#endif
284+
}

lib/SILGen/Cleanup.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,9 @@ class LLVM_LIBRARY_VISIBILITY CleanupManager {
209209

210210
/// Dump the given cleanup handle if it is on the current stack.
211211
void dump(CleanupHandle handle) const;
212+
213+
/// Verify that the given cleanup handle is valid.
214+
void checkIterator(CleanupHandle handle) const;
212215
};
213216

214217
/// An RAII object that allows the state of a cleanup to be

lib/SILGen/FormalEvaluation.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,26 @@ using namespace Lowering;
2323

2424
void FormalAccess::_anchor() {}
2525

26+
void FormalAccess::verify(SILGenFunction &SGF) const {
27+
#ifndef NDEBUG
28+
// If this access was already finished, continue. This can happen if an
29+
// owned formal access was forwarded.
30+
if (isFinished()) {
31+
assert(getKind() == FormalAccess::Owned &&
32+
"Only owned formal accesses should be forwarded.");
33+
// We can not check that our cleanup is actually dead since the cleanup
34+
// may have been popped at this point and the stack may have new values.
35+
return;
36+
}
37+
38+
assert(!isFinished() && "Can not finish a formal access cleanup "
39+
"twice");
40+
41+
// Now try to look up the cleanup handle of the formal access.
42+
SGF.Cleanups.checkIterator(getCleanup());
43+
#endif
44+
}
45+
2646
//===----------------------------------------------------------------------===//
2747
// Shared Borrow Formal Evaluation
2848
//===----------------------------------------------------------------------===//
@@ -141,6 +161,24 @@ void FormalEvaluationScope::popImpl() {
141161
context.pop(savedDepth.getValue());
142162
}
143163

164+
void FormalEvaluationScope::verify() const {
165+
// Check to see if there is anything going on here.
166+
auto &context = SGF.FormalEvalContext;
167+
using iterator = FormalEvaluationContext::iterator;
168+
169+
iterator unwrappedSavedDepth = context.find(savedDepth.getValue());
170+
iterator iter = context.begin();
171+
if (iter == unwrappedSavedDepth)
172+
return;
173+
174+
// Then working down the stack until we visit unwrappedSavedDepth...
175+
for (; iter != unwrappedSavedDepth; ++iter) {
176+
// Grab the next evaluation verify that we can successfully access this
177+
// formal access.
178+
(*iter).verify(SGF);
179+
}
180+
}
181+
144182
//===----------------------------------------------------------------------===//
145183
// Formal Evaluation Context
146184
//===----------------------------------------------------------------------===//

lib/SILGen/FormalEvaluation.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ class FormalAccess {
6565

6666
bool isFinished() const { return finished; }
6767

68+
void verify(SILGenFunction &SGF) const;
69+
6870
protected:
6971
virtual void finishImpl(SILGenFunction &SGF) = 0;
7072
};
@@ -202,6 +204,10 @@ class FormalEvaluationScope {
202204
FormalEvaluationScope(FormalEvaluationScope &&o);
203205
FormalEvaluationScope &operator=(FormalEvaluationScope &&o) = delete;
204206

207+
/// Verify that we can successfully access all of the inner lexical scopes
208+
/// that would be popped by this scope.
209+
void verify() const;
210+
205211
private:
206212
void popImpl();
207213
};

lib/SILGen/SILGenApply.cpp

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1744,12 +1744,8 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
17441744
}
17451745

17461746
// If there's a foreign error parameter, fill it in.
1747-
Optional<FormalEvaluationScope> errorTempWriteback;
17481747
ManagedValue errorTemp;
17491748
if (auto foreignError = calleeTypeInfo.foreignError) {
1750-
// Error-temporary emission may need writeback.
1751-
errorTempWriteback.emplace(*this);
1752-
17531749
unsigned errorParamIndex =
17541750
calleeTypeInfo.foreignError->getErrorParameterIndex();
17551751

@@ -1850,9 +1846,6 @@ RValue SILGenFunction::emitApply(ResultPlanPtr &&resultPlan,
18501846
// TODO: maybe this should happen after managing the result if it's
18511847
// not a result-checking convention?
18521848
if (auto foreignError = calleeTypeInfo.foreignError) {
1853-
// Force immediate writeback to the error temporary.
1854-
errorTempWriteback.reset();
1855-
18561849
bool doesNotThrow = (options & ApplyOptions::DoesNotThrow);
18571850
emitForeignErrorCheck(loc, directResults, errorTemp,
18581851
doesNotThrow, *foreignError);
@@ -3644,6 +3637,8 @@ namespace {
36443637
}
36453638

36463639
RValue apply(SGFContext C = SGFContext()) {
3640+
initialWritebackScope.verify();
3641+
36473642
assert(!applied && "already applied!");
36483643

36493644
applied = true;
@@ -3664,12 +3659,12 @@ namespace {
36643659
foreignError, foreignSelf, uncurryLevel, C);
36653660

36663661
// End of the initial writeback scope.
3662+
initialWritebackScope.verify();
36673663
initialWritebackScope.pop();
36683664

36693665
// Then handle the remaining call sites.
36703666
result = applyRemainingCallSites(std::move(result), formalType,
36713667
foreignSelf, foreignError, C);
3672-
36733668
return result;
36743669
}
36753670

@@ -4231,9 +4226,10 @@ static CallEmission prepareApplyExpr(SILGenFunction &SGF, Expr *e) {
42314226
apply.AssumedPlusZeroSelf);
42324227

42334228
// Apply 'self' if provided.
4234-
if (apply.SelfParam)
4229+
if (apply.SelfParam) {
42354230
emission.addCallSite(RegularLocation(e), std::move(apply.SelfParam),
42364231
apply.SelfType->getCanonicalType(), /*throws*/ false);
4232+
}
42374233

42384234
// Apply arguments from call sites, innermost to outermost.
42394235
for (auto site = apply.CallSites.rbegin(), end = apply.CallSites.rend();
@@ -4246,7 +4242,8 @@ static CallEmission prepareApplyExpr(SILGenFunction &SGF, Expr *e) {
42464242
}
42474243

42484244
RValue SILGenFunction::emitApplyExpr(Expr *e, SGFContext c) {
4249-
return prepareApplyExpr(*this, e).apply(c);
4245+
CallEmission emission = prepareApplyExpr(*this, e);
4246+
return emission.apply(c);
42504247
}
42514248

42524249
RValue

test/Inputs/clang-importer-sdk/usr/include/Foundation.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,9 @@ __attribute__((warn_unused_result)) NSString *NSStringToNSString(NSString *str);
257257
@interface NSURL : NSObject
258258
- (instancetype)URLWithString:(NSString *)URLString;
259259
+ (instancetype)URLWithString:(NSString *)URLString;
260+
- (BOOL)getResourceValue:(out id _Nullable *)value
261+
forKey:(NSString *)key
262+
error:(out NSError *_Nullable *)error;
260263
@end
261264

262265
@interface NSAttributedString : NSString

test/SILGen/foreign_errors.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,3 +298,14 @@ func testPreservedResultInverted() throws {
298298
// CHECK-NOT: destroy_value
299299
// CHECK: return {{%.+}} : $()
300300
// CHECK: [[ERROR_BB]]
301+
302+
// Make sure that we do not crash when emitting the error value here.
303+
//
304+
// TODO: Add some additional filecheck tests.
305+
extension NSURL {
306+
func resourceValue<T>(forKey key: String) -> T? {
307+
var prop: AnyObject? = nil
308+
_ = try? self.getResourceValue(&prop, forKey: key)
309+
return prop as? T
310+
}
311+
}

0 commit comments

Comments
 (0)