@@ -351,12 +351,77 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
351
351
// name/module qualifier to access top-level name.
352
352
lookupOptions |= NameLookupFlags::IncludeOuterResults;
353
353
354
- if (Loc.isInvalid ())
355
- DC = DC->getModuleScopeContext ();
354
+ LookupResult Lookup;
356
355
357
- auto Lookup = TypeChecker::lookupUnqualified (DC, Name, Loc, lookupOptions);
356
+ bool AllDeclRefs = true ;
357
+ SmallVector<ValueDecl*, 4 > ResultValues;
358
358
359
359
auto &Context = DC->getASTContext ();
360
+ if (Context.LangOpts .DisableParserLookup ) {
361
+ // First, look for a local binding in scope.
362
+ if (Loc.isValid () && !Name.isOperator ()) {
363
+ SmallVector<ValueDecl *, 2 > localDecls;
364
+ ASTScope::lookupLocalDecls (DC->getParentSourceFile (),
365
+ Name.getFullName (), Loc,
366
+ /* stopAfterInnermostBraceStmt=*/ false ,
367
+ ResultValues);
368
+ for (auto *localDecl : ResultValues) {
369
+ Lookup.add (LookupResultEntry (localDecl), /* isOuter=*/ false );
370
+ }
371
+ }
372
+ }
373
+
374
+ if (!Lookup) {
375
+ // Now, look for all local bindings, even forward references, as well
376
+ // as type members and top-level declarations.
377
+ if (Loc.isInvalid ())
378
+ DC = DC->getModuleScopeContext ();
379
+
380
+ Lookup = TypeChecker::lookupUnqualified (DC, Name, Loc, lookupOptions);
381
+
382
+ ValueDecl *localDeclAfterUse = nullptr ;
383
+ auto isValid = [&](ValueDecl *D) {
384
+ // If we find something in the current context, it must be a forward
385
+ // reference, because otherwise if it was in scope, it would have
386
+ // been returned by the call to ASTScope::lookupLocalDecls() above.
387
+ if (D->getDeclContext ()->isLocalContext () &&
388
+ D->getDeclContext () == DC &&
389
+ (Context.LangOpts .DisableParserLookup ||
390
+ (Loc.isValid () && D->getLoc ().isValid () &&
391
+ Context.SourceMgr .isBeforeInBuffer (Loc, D->getLoc ()) &&
392
+ !isa<TypeDecl>(D)))) {
393
+ localDeclAfterUse = D;
394
+ return false ;
395
+ }
396
+ return true ;
397
+ };
398
+ AllDeclRefs =
399
+ findNonMembers (Lookup.innerResults (), UDRE->getRefKind (),
400
+ /* breakOnMember=*/ true , ResultValues, isValid);
401
+
402
+ // If local declaration after use is found, check outer results for
403
+ // better matching candidates.
404
+ if (ResultValues.empty () && localDeclAfterUse) {
405
+ auto innerDecl = localDeclAfterUse;
406
+ while (localDeclAfterUse) {
407
+ if (Lookup.outerResults ().empty ()) {
408
+ Context.Diags .diagnose (Loc, diag::use_local_before_declaration, Name);
409
+ Context.Diags .diagnose (innerDecl, diag::decl_declared_here,
410
+ localDeclAfterUse->getName ());
411
+ Expr *error = new (Context) ErrorExpr (UDRE->getSourceRange ());
412
+ return error;
413
+ }
414
+
415
+ Lookup.shiftDownResults ();
416
+ ResultValues.clear ();
417
+ localDeclAfterUse = nullptr ;
418
+ AllDeclRefs =
419
+ findNonMembers (Lookup.innerResults (), UDRE->getRefKind (),
420
+ /* breakOnMember=*/ true , ResultValues, isValid);
421
+ }
422
+ }
423
+ }
424
+
360
425
if (!Lookup) {
361
426
// If we failed lookup of an operator, check to see if this is a range
362
427
// operator misspelling. Otherwise try to diagnose a juxtaposition
@@ -487,50 +552,6 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
487
552
488
553
// FIXME: Need to refactor the way we build an AST node from a lookup result!
489
554
490
- SmallVector<ValueDecl*, 4 > ResultValues;
491
- ValueDecl *localDeclAfterUse = nullptr ;
492
- auto isValid = [&](ValueDecl *D) {
493
- // FIXME: The source-location checks won't make sense once
494
- // EnableASTScopeLookup is the default.
495
- //
496
- // Note that we allow forward references to types, because they cannot
497
- // capture.
498
- if (Loc.isValid () && D->getLoc ().isValid () &&
499
- D->getDeclContext ()->isLocalContext () &&
500
- D->getDeclContext () == DC &&
501
- Context.SourceMgr .isBeforeInBuffer (Loc, D->getLoc ()) &&
502
- !isa<TypeDecl>(D)) {
503
- localDeclAfterUse = D;
504
- return false ;
505
- }
506
- return true ;
507
- };
508
- bool AllDeclRefs =
509
- findNonMembers (Lookup.innerResults (), UDRE->getRefKind (),
510
- /* breakOnMember=*/ true , ResultValues, isValid);
511
-
512
- // If local declaration after use is found, check outer results for
513
- // better matching candidates.
514
- if (localDeclAfterUse) {
515
- auto innerDecl = localDeclAfterUse;
516
- while (localDeclAfterUse) {
517
- if (Lookup.outerResults ().empty ()) {
518
- Context.Diags .diagnose (Loc, diag::use_local_before_declaration, Name);
519
- Context.Diags .diagnose (innerDecl, diag::decl_declared_here,
520
- localDeclAfterUse->getName ());
521
- Expr *error = new (Context) ErrorExpr (UDRE->getSourceRange ());
522
- return error;
523
- }
524
-
525
- Lookup.shiftDownResults ();
526
- ResultValues.clear ();
527
- localDeclAfterUse = nullptr ;
528
- AllDeclRefs =
529
- findNonMembers (Lookup.innerResults (), UDRE->getRefKind (),
530
- /* breakOnMember=*/ true , ResultValues, isValid);
531
- }
532
- }
533
-
534
555
// If we have an unambiguous reference to a type decl, form a TypeExpr.
535
556
if (Lookup.size () == 1 && UDRE->getRefKind () == DeclRefKind::Ordinary &&
536
557
isa<TypeDecl>(Lookup[0 ].getValueDecl ())) {
0 commit comments