@@ -210,7 +210,7 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
210
210
}
211
211
212
212
// Verify noescape parameter uses.
213
- checkNoEscapeParameterUse (DRE, nullptr );
213
+ checkNoEscapeParameterUse (DRE, nullptr , OperandKind::None );
214
214
215
215
// Verify warn_unqualified_access uses.
216
216
checkUnqualifiedAccessUse (DRE);
@@ -239,7 +239,7 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
239
239
if (auto MakeEsc = dyn_cast<MakeTemporarilyEscapableExpr>(E)) {
240
240
if (auto DRE =
241
241
dyn_cast<DeclRefExpr>(MakeEsc->getNonescapingClosureValue ()))
242
- checkNoEscapeParameterUse (DRE, MakeEsc);
242
+ checkNoEscapeParameterUse (DRE, MakeEsc, OperandKind::MakeEscapable );
243
243
}
244
244
245
245
// Check function calls, looking through implicit conversions on the
@@ -263,33 +263,11 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
263
263
while (auto ignoredBase = dyn_cast<DotSyntaxBaseIgnoredExpr>(Base))
264
264
Base = ignoredBase->getRHS ();
265
265
if (auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
266
- checkNoEscapeParameterUse (DRE, Call);
266
+ checkNoEscapeParameterUse (DRE, Call, OperandKind::Callee );
267
267
checkForSuspiciousBitCasts (DRE, Call);
268
268
}
269
269
270
- auto *Arg = Call->getArg ();
271
-
272
- // The argument could be shuffled if it includes default arguments,
273
- // label differences, or other exciting things like that.
274
- if (auto *TSE = dyn_cast<TupleShuffleExpr>(Arg))
275
- Arg = TSE->getSubExpr ();
276
-
277
- // The argument is either a ParenExpr or TupleExpr.
278
- ArrayRef<Expr*> arguments;
279
- SmallVector<Expr *, 1 > Scratch;
280
- if (auto *TE = dyn_cast<TupleExpr>(Arg))
281
- arguments = TE->getElements ();
282
- else if (auto *PE = dyn_cast<ParenExpr>(Arg)) {
283
- Scratch.push_back (PE->getSubExpr ());
284
- arguments = makeArrayRef (Scratch);
285
- }
286
- else {
287
- Scratch.push_back (Call->getArg ());
288
- arguments = makeArrayRef (Scratch);
289
- }
290
-
291
- // Check each argument.
292
- for (auto arg : arguments) {
270
+ visitArguments (Call, [&](Expr *arg) {
293
271
// InOutExpr's are allowed in argument lists directly.
294
272
if (auto *IOE = dyn_cast<InOutExpr>(arg)) {
295
273
if (isa<CallExpr>(Call))
@@ -307,18 +285,12 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
307
285
AcceptableInOutExprs.insert (IOE);
308
286
}
309
287
310
- while (1 ) {
311
- if (auto conv = dyn_cast<ImplicitConversionExpr>(arg))
312
- arg = conv->getSubExpr ();
313
- else if (auto *PE = dyn_cast<ParenExpr>(arg))
314
- arg = PE->getSubExpr ();
315
- else
316
- break ;
317
- }
288
+ // Also give special treatment to noescape function arguments.
289
+ arg = lookThroughArgument (arg);
318
290
319
291
if (auto *DRE = dyn_cast<DeclRefExpr>(arg))
320
- checkNoEscapeParameterUse (DRE, Call);
321
- }
292
+ checkNoEscapeParameterUse (DRE, Call, OperandKind::Argument );
293
+ });
322
294
}
323
295
324
296
// If we have an assignment expression, scout ahead for acceptable _'s.
@@ -359,6 +331,38 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
359
331
return { true , E };
360
332
}
361
333
334
+ static void visitArguments (ApplyExpr *apply,
335
+ llvm::function_ref<void (Expr*)> fn) {
336
+ auto *arg = apply->getArg ();
337
+
338
+ // The argument could be shuffled if it includes default arguments,
339
+ // label differences, or other exciting things like that.
340
+ if (auto *TSE = dyn_cast<TupleShuffleExpr>(arg))
341
+ arg = TSE->getSubExpr ();
342
+
343
+ // The argument is either a ParenExpr or TupleExpr.
344
+ if (auto *TE = dyn_cast<TupleExpr>(arg)) {
345
+ for (auto elt : TE->getElements ())
346
+ fn (elt);
347
+ } else if (auto *PE = dyn_cast<ParenExpr>(arg)) {
348
+ fn (PE->getSubExpr ());
349
+ } else {
350
+ fn (arg);
351
+ }
352
+ }
353
+
354
+ static Expr *lookThroughArgument (Expr *arg) {
355
+ while (1 ) {
356
+ if (auto conv = dyn_cast<ImplicitConversionExpr>(arg))
357
+ arg = conv->getSubExpr ();
358
+ else if (auto *PE = dyn_cast<ParenExpr>(arg))
359
+ arg = PE->getSubExpr ();
360
+ else
361
+ break ;
362
+ }
363
+ return arg;
364
+ }
365
+
362
366
Expr *walkToExprPost (Expr *E) override {
363
367
checkInvalidPartialApplication (E);
364
368
return E;
@@ -446,9 +450,118 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
446
450
TC.diagnose (E->getStartLoc (), diag::value_of_module_type);
447
451
}
448
452
453
+ class NoEscapeArgument {
454
+ llvm::PointerIntPair<ParamDecl*, 1 , bool > ParamAndIsCapture;
455
+ public:
456
+ NoEscapeArgument () {}
457
+ NoEscapeArgument (ParamDecl *param, bool isCapture)
458
+ : ParamAndIsCapture(param, isCapture) {
459
+ assert (param);
460
+ }
461
+
462
+ explicit operator bool () const {
463
+ return ParamAndIsCapture.getPointer () != nullptr ;
464
+ }
465
+
466
+ ParamDecl *getDecl () const { return ParamAndIsCapture.getPointer (); }
467
+ bool isDeclACapture () const { return ParamAndIsCapture.getInt (); }
468
+
469
+ static NoEscapeArgument find (TypeChecker &tc, ValueDecl *decl,
470
+ bool isCapture) {
471
+ if (auto param = dyn_cast<ParamDecl>(decl)) {
472
+ if (auto fnType =
473
+ param->getInterfaceType ()->getAs <AnyFunctionType>()) {
474
+ if (fnType->isNoEscape ())
475
+ return { param, isCapture };
476
+ }
477
+ return {};
478
+ }
479
+
480
+ if (auto fn = dyn_cast<AbstractFunctionDecl>(decl)) {
481
+ if (fn->getDeclContext ()->isLocalContext ()) {
482
+ return findInCaptures (tc, fn);
483
+ }
484
+ return {};
485
+ }
486
+
487
+ // FIXME: captures of computed local vars? Can these be non-escaping?
488
+ return {};
489
+ }
490
+
491
+ static NoEscapeArgument findInCaptures (TypeChecker &tc,
492
+ AnyFunctionRef fn) {
493
+ // Ensure we have accurate capture information for the function.
494
+ tc.computeCaptures (fn);
495
+
496
+ for (const auto &capture : fn.getCaptureInfo ().getCaptures ()) {
497
+ if (capture.isDynamicSelfMetadata ()) continue ;
498
+ if (auto param = find (tc, capture.getDecl (), true ))
499
+ return param;
500
+ }
501
+ return {};
502
+ }
503
+ };
504
+
505
+ // / Enforce the exclusivity rule against calling a non-escaping
506
+ // / function parameter with another non-escaping function parameter
507
+ // / as an argument.
508
+ void checkNoEscapeParameterCall (ApplyExpr *apply) {
509
+ NoEscapeArgument noescapeArgument;
510
+ Expr *problematicArg = nullptr ;
511
+
512
+ visitArguments (apply, [&](Expr *arg) {
513
+ // Just find the first problematic argument.
514
+ if (noescapeArgument) return ;
515
+
516
+ // Remember the expression which used the argument.
517
+ problematicArg = arg;
518
+
519
+ // Look through the same set of nodes that we look through when
520
+ // checking for no-escape functions.
521
+ arg = lookThroughArgument (arg);
522
+
523
+ // If the argument isn't noescape, ignore it.
524
+ auto fnType = arg->getType ()->getAs <AnyFunctionType>();
525
+ if (!fnType || !fnType->isNoEscape ())
526
+ return ;
527
+
528
+ // Okay, it should be a closure or a decl ref.
529
+ if (auto declRef = dyn_cast<DeclRefExpr>(arg)) {
530
+ noescapeArgument =
531
+ NoEscapeArgument::find (TC, declRef->getDecl (), false );
532
+ } else if (auto closure = dyn_cast<AbstractClosureExpr>(arg)) {
533
+ noescapeArgument =
534
+ NoEscapeArgument::findInCaptures (TC, closure);
535
+ } else {
536
+ // This can happen with withoutActuallyEscaping.
537
+ assert (isa<OpaqueValueExpr>(arg) &&
538
+ " unexpected expression yielding noescape closure" );
539
+ }
540
+ });
541
+
542
+ if (!noescapeArgument) return ;
543
+
544
+ // In Swift 3, this is just a warning.
545
+ TC.diagnose (apply->getLoc (),
546
+ TC.Context .isSwiftVersion3 ()
547
+ ? diag::warn_noescape_param_call
548
+ : diag::err_noescape_param_call,
549
+ noescapeArgument.getDecl ()->getName (),
550
+ noescapeArgument.isDeclACapture ())
551
+ .highlight (problematicArg->getSourceRange ());
552
+ }
553
+
554
+ enum class OperandKind {
555
+ None,
556
+ Callee,
557
+ Argument,
558
+ MakeEscapable,
559
+ };
560
+
449
561
// / The DRE argument is a reference to a noescape parameter. Verify that
450
562
// / its uses are ok.
451
- void checkNoEscapeParameterUse (DeclRefExpr *DRE, Expr *ParentExpr=nullptr ) {
563
+ void checkNoEscapeParameterUse (DeclRefExpr *DRE, Expr *parent,
564
+ OperandKind useKind) {
452
565
// This only cares about declarations of noescape function type.
453
566
auto AFT = DRE->getDecl ()->getInterfaceType ()->getAs <AnyFunctionType>();
454
567
if (!AFT || !AFT->isNoEscape ())
@@ -463,10 +576,15 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
463
576
// either as the callee or as an argument (in which case, the typechecker
464
577
// validates that the noescape bit didn't get stripped off), or as
465
578
// a special case, in the binding of a withoutActuallyEscaping block.
466
- if (ParentExpr
467
- && (isa<ApplyExpr>(ParentExpr) // param()
468
- || isa<MakeTemporarilyEscapableExpr>(ParentExpr)))
469
- return ;
579
+ if (parent) {
580
+ if (auto apply = dyn_cast<ApplyExpr>(parent)) {
581
+ if (isa<ParamDecl>(DRE->getDecl ()) && useKind == OperandKind::Callee)
582
+ checkNoEscapeParameterCall (apply);
583
+ return ;
584
+ } else if (isa<MakeTemporarilyEscapableExpr>(parent)) {
585
+ return ;
586
+ }
587
+ }
470
588
471
589
TC.diagnose (DRE->getStartLoc (), diag::invalid_noescape_use,
472
590
DRE->getDecl ()->getBaseName (),
0 commit comments