@@ -352,6 +352,34 @@ static bool isMemberChainTail(Expr *expr, Expr *parent) {
352352 return parent == nullptr || !isMemberChainMember (parent);
353353}
354354
355+ static bool isValidForwardReference (ValueDecl *D, DeclContext *DC,
356+ ValueDecl **localDeclAfterUse) {
357+ *localDeclAfterUse = nullptr ;
358+
359+ // References to variables injected by lldb are always valid.
360+ if (isa<VarDecl>(D) && cast<VarDecl>(D)->isDebuggerVar ())
361+ return true ;
362+
363+ // If we find something in the current context, it must be a forward
364+ // reference, because otherwise if it was in scope, it would have
365+ // been returned by the call to ASTScope::lookupLocalDecls() above.
366+ if (D->getDeclContext ()->isLocalContext ()) {
367+ do {
368+ if (D->getDeclContext () == DC) {
369+ *localDeclAfterUse = D;
370+ return false ;
371+ }
372+
373+ // If we're inside of a 'defer' context, walk up to the parent
374+ // and check again. We don't want 'defer' bodies to forward
375+ // reference bindings in the immediate outer scope.
376+ } while (isa<FuncDecl>(DC) &&
377+ cast<FuncDecl>(DC)->isDeferBody () &&
378+ (DC = DC->getParent ()));
379+ }
380+ return true ;
381+ }
382+
355383// / Bind an UnresolvedDeclRefExpr by performing name lookup and
356384// / returning the resultant expression. Context is the DeclContext used
357385// / for the lookup.
@@ -422,24 +450,12 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
422450 Lookup = TypeChecker::lookupUnqualified (DC, LookupName, Loc, lookupOptions);
423451
424452 ValueDecl *localDeclAfterUse = nullptr ;
425- auto isValid = [&](ValueDecl *D) {
426- // References to variables injected by lldb are always valid.
427- if (isa<VarDecl>(D) && cast<VarDecl>(D)->isDebuggerVar ())
428- return true ;
429-
430- // If we find something in the current context, it must be a forward
431- // reference, because otherwise if it was in scope, it would have
432- // been returned by the call to ASTScope::lookupLocalDecls() above.
433- if (D->getDeclContext ()->isLocalContext () &&
434- D->getDeclContext () == DC) {
435- localDeclAfterUse = D;
436- return false ;
437- }
438- return true ;
439- };
440453 AllDeclRefs =
441454 findNonMembers (Lookup.innerResults (), UDRE->getRefKind (),
442- /* breakOnMember=*/ true , ResultValues, isValid);
455+ /* breakOnMember=*/ true , ResultValues,
456+ [&](ValueDecl *D) {
457+ return isValidForwardReference (D, DC, &localDeclAfterUse);
458+ });
443459
444460 // If local declaration after use is found, check outer results for
445461 // better matching candidates.
@@ -459,7 +475,10 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
459475 localDeclAfterUse = nullptr ;
460476 AllDeclRefs =
461477 findNonMembers (Lookup.innerResults (), UDRE->getRefKind (),
462- /* breakOnMember=*/ true , ResultValues, isValid);
478+ /* breakOnMember=*/ true , ResultValues,
479+ [&](ValueDecl *D) {
480+ return isValidForwardReference (D, DC, &localDeclAfterUse);
481+ });
463482 }
464483 }
465484 }
0 commit comments