@@ -518,11 +518,12 @@ diagnoseUnqualifiedInit(UnresolvedDeclRefExpr *initExpr, DeclContext *dc,
518518 initExpr->getNameLoc (), /* implicit=*/ true );
519519}
520520
521- // / Bind an UnresolvedDeclRefExpr by performing name lookup and
522- // / returning the resultant expression. Context is the DeclContext used
523- // / for the lookup.
524- Expr *TypeChecker::resolveDeclRefExpr (UnresolvedDeclRefExpr *UDRE,
525- DeclContext *DC) {
521+ // / Bind an UnresolvedDeclRefExpr by performing name lookup using the given
522+ // / options and returning the resultant expression. `DC` is the DeclContext
523+ // / used for the lookup. If the lookup doesn't find any results, returns
524+ // / `nullptr`.
525+ static Expr *resolveDeclRefExpr (UnresolvedDeclRefExpr *UDRE, DeclContext *DC,
526+ NameLookupOptions lookupOptions) {
526527 auto &Context = DC->getASTContext ();
527528 DeclNameRef Name = UDRE->getName ();
528529 SourceLoc Loc = UDRE->getLoc ();
@@ -562,14 +563,6 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
562563 LookupName = DeclNameRef (lookupName);
563564 }
564565
565- // Perform standard value name lookup.
566- NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
567- // TODO: Include all of the possible members to give a solver a
568- // chance to diagnose name shadowing which requires explicit
569- // name/module qualifier to access top-level name.
570- lookupOptions |= NameLookupFlags::IncludeOuterResults;
571- lookupOptions |= NameLookupFlags::IgnoreMissingImports;
572-
573566 LookupResult Lookup;
574567
575568 bool AllDeclRefs = true ;
@@ -628,17 +621,8 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
628621 }
629622
630623 if (!Lookup) {
631- // If we failed lookup of an operator, check to see if this is a range
632- // operator misspelling. Otherwise try to diagnose a juxtaposition
633- // e.g. (x*-4) that needs whitespace.
634- if (diagnoseRangeOperatorMisspell (Context.Diags , UDRE) ||
635- diagnoseIncDecOperator (Context.Diags , UDRE) ||
636- diagnoseOperatorJuxtaposition (UDRE, DC) ||
637- diagnoseNonexistentPowerOperator (Context.Diags , UDRE, DC)) {
638- return errorResult ();
639- }
640-
641- // Try ignoring access control.
624+ // For the purpose of diagnosing inaccessible results, try the lookup again
625+ // but ignore access control.
642626 NameLookupOptions relookupOptions = lookupOptions;
643627 relookupOptions |= NameLookupFlags::IgnoreAccessControl;
644628 auto inaccessibleResults =
@@ -663,117 +647,8 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
663647 return errorResult ();
664648 }
665649
666- // TODO: Name will be a compound name if it was written explicitly as
667- // one, but we should also try to propagate labels into this.
668- DeclNameLoc nameLoc = UDRE->getNameLoc ();
669-
670- Identifier simpleName = Name.getBaseIdentifier ();
671- const char *buffer = simpleName.get ();
672- llvm::SmallString<64 > expectedIdentifier;
673- bool isConfused = false ;
674- uint32_t codepoint;
675- uint32_t firstConfusableCodepoint = 0 ;
676- int totalCodepoints = 0 ;
677- int offset = 0 ;
678- while ((codepoint = validateUTF8CharacterAndAdvance (buffer,
679- buffer +
680- strlen (buffer)))
681- != ~0U ) {
682- int length = (buffer - simpleName.get ()) - offset;
683- if (auto expectedCodepoint =
684- confusable::tryConvertConfusableCharacterToASCII (codepoint)) {
685- if (firstConfusableCodepoint == 0 ) {
686- firstConfusableCodepoint = codepoint;
687- }
688- isConfused = true ;
689- expectedIdentifier += expectedCodepoint;
690- } else {
691- expectedIdentifier += (char )codepoint;
692- }
693-
694- totalCodepoints++;
695-
696- offset += length;
697- }
698-
699- auto emitBasicError = [&] {
700-
701- if (Name.isSimpleName (Context.Id_self )) {
702- // `self` gets diagnosed with a different error when it can't be found.
703- Context.Diags
704- .diagnose (Loc, diag::cannot_find_self_in_scope)
705- .highlight (UDRE->getSourceRange ());
706- } else {
707- Context.Diags
708- .diagnose (Loc, diag::cannot_find_in_scope, Name,
709- Name.isOperator ())
710- .highlight (UDRE->getSourceRange ());
711- }
712-
713- if (!Context.LangOpts .DisableExperimentalClangImporterDiagnostics ) {
714- Context.getClangModuleLoader ()->diagnoseTopLevelValue (
715- Name.getFullName ());
716- }
717- };
718-
719- if (!isConfused) {
720- if (Name.isSimpleName (Context.Id_Self )) {
721- if (DeclContext *typeContext = DC->getInnermostTypeContext ()){
722- Type SelfType = typeContext->getSelfInterfaceType ();
723-
724- if (typeContext->getSelfClassDecl () &&
725- !typeContext->getSelfClassDecl ()->isForeignReferenceType ())
726- SelfType = DynamicSelfType::get (SelfType, Context);
727- return new (Context)
728- TypeExpr (new (Context) SelfTypeRepr (SelfType, Loc));
729- }
730- }
731-
732- TypoCorrectionResults corrections (Name, nameLoc);
733-
734- // FIXME: Don't perform typo correction inside macro arguments, because it
735- // will invoke synthesizing declarations in this scope, which will attempt to
736- // expand this macro which leads to circular reference errors.
737- if (!namelookup::isInMacroArgument (DC->getParentSourceFile (), UDRE->getLoc ())) {
738- TypeChecker::performTypoCorrection (DC, UDRE->getRefKind (), Type (),
739- lookupOptions, corrections);
740- }
741-
742- if (auto typo = corrections.claimUniqueCorrection ()) {
743- auto diag = Context.Diags .diagnose (
744- Loc, diag::cannot_find_in_scope_corrected, Name,
745- Name.isOperator (), typo->CorrectedName .getBaseIdentifier ().str ());
746- diag.highlight (UDRE->getSourceRange ());
747- typo->addFixits (diag);
748- } else {
749- emitBasicError ();
750- }
751-
752- corrections.noteAllCandidates ();
753- } else {
754- emitBasicError ();
755-
756- if (totalCodepoints == 1 ) {
757- auto charNames = confusable::getConfusableAndBaseCodepointNames (
758- firstConfusableCodepoint);
759- Context.Diags
760- .diagnose (Loc, diag::single_confusable_character,
761- UDRE->getName ().isOperator (), simpleName.str (),
762- charNames.first , expectedIdentifier, charNames.second )
763- .fixItReplace (Loc, expectedIdentifier);
764- } else {
765- Context.Diags
766- .diagnose (Loc, diag::confusable_character,
767- UDRE->getName ().isOperator (), simpleName.str (),
768- expectedIdentifier)
769- .fixItReplace (Loc, expectedIdentifier);
770- }
771- }
772-
773- // TODO: consider recovering from here. We may want some way to suppress
774- // downstream diagnostics, though.
775-
776- return errorResult ();
650+ // No results were found.
651+ return nullptr ;
777652 }
778653
779654 // FIXME: Need to refactor the way we build an AST node from a lookup result!
@@ -892,8 +767,9 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
892767 UDRE->getNameLoc ().getStartLoc ());
893768 }
894769
895- return buildRefExpr (ResultValues, DC, UDRE->getNameLoc (),
896- UDRE->isImplicit (), UDRE->getFunctionRefInfo ());
770+ return TypeChecker::buildRefExpr (ResultValues, DC, UDRE->getNameLoc (),
771+ UDRE->isImplicit (),
772+ UDRE->getFunctionRefInfo ());
897773 }
898774
899775 ResultValues.clear ();
@@ -983,6 +859,157 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
983859 return errorResult ();
984860}
985861
862+ Expr *TypeChecker::resolveDeclRefExpr (UnresolvedDeclRefExpr *UDRE,
863+ DeclContext *DC) {
864+ auto &Context = DC->getASTContext ();
865+
866+ // Perform standard value name lookup.
867+ NameLookupOptions lookupOptions = defaultUnqualifiedLookupOptions;
868+ // TODO: Include all of the possible members to give a solver a
869+ // chance to diagnose name shadowing which requires explicit
870+ // name/module qualifier to access top-level name.
871+ lookupOptions |= NameLookupFlags::IncludeOuterResults;
872+
873+ Expr *result = ::resolveDeclRefExpr (UDRE, DC, lookupOptions);
874+ if (!result && Context.LangOpts .hasFeature (Feature::MemberImportVisibility,
875+ /* allowMigration=*/ true )) {
876+ // If we didn't find a result, try again but this time relax
877+ // MemberImportVisibility restrictions. Note that diagnosing the missing
878+ // import is already handled by resolveDeclRefExpr().
879+ lookupOptions |= NameLookupFlags::IgnoreMissingImports;
880+ result = ::resolveDeclRefExpr (UDRE, DC, lookupOptions);
881+ }
882+
883+ if (result)
884+ return result;
885+
886+ // We didn't find any results. Look for common mistakes to diagnose.
887+ DeclNameRef Name = UDRE->getName ();
888+ SourceLoc Loc = UDRE->getLoc ();
889+ if (Loc.isInvalid ())
890+ DC = DC->getModuleScopeContext ();
891+
892+ auto errorResult = [&]() -> Expr * {
893+ return new (Context) ErrorExpr (UDRE->getSourceRange ());
894+ };
895+
896+ // If we failed lookup of an operator, check to see if this is a range
897+ // operator misspelling. Otherwise try to diagnose a juxtaposition
898+ // e.g. (x*-4) that needs whitespace.
899+ if (diagnoseRangeOperatorMisspell (Context.Diags , UDRE) ||
900+ diagnoseIncDecOperator (Context.Diags , UDRE) ||
901+ diagnoseOperatorJuxtaposition (UDRE, DC) ||
902+ diagnoseNonexistentPowerOperator (Context.Diags , UDRE, DC)) {
903+ return errorResult ();
904+ }
905+
906+ // TODO: Name will be a compound name if it was written explicitly as
907+ // one, but we should also try to propagate labels into this.
908+ DeclNameLoc nameLoc = UDRE->getNameLoc ();
909+
910+ Identifier simpleName = Name.getBaseIdentifier ();
911+ const char *buffer = simpleName.get ();
912+ llvm::SmallString<64 > expectedIdentifier;
913+ bool isConfused = false ;
914+ uint32_t codepoint;
915+ uint32_t firstConfusableCodepoint = 0 ;
916+ int totalCodepoints = 0 ;
917+ int offset = 0 ;
918+ while ((codepoint = validateUTF8CharacterAndAdvance (
919+ buffer, buffer + strlen (buffer))) != ~0U ) {
920+ int length = (buffer - simpleName.get ()) - offset;
921+ if (auto expectedCodepoint =
922+ confusable::tryConvertConfusableCharacterToASCII (codepoint)) {
923+ if (firstConfusableCodepoint == 0 ) {
924+ firstConfusableCodepoint = codepoint;
925+ }
926+ isConfused = true ;
927+ expectedIdentifier += expectedCodepoint;
928+ } else {
929+ expectedIdentifier += (char )codepoint;
930+ }
931+
932+ totalCodepoints++;
933+
934+ offset += length;
935+ }
936+
937+ auto emitBasicError = [&] {
938+ if (Name.isSimpleName (Context.Id_self )) {
939+ // `self` gets diagnosed with a different error when it can't be found.
940+ Context.Diags .diagnose (Loc, diag::cannot_find_self_in_scope)
941+ .highlight (UDRE->getSourceRange ());
942+ } else {
943+ Context.Diags
944+ .diagnose (Loc, diag::cannot_find_in_scope, Name, Name.isOperator ())
945+ .highlight (UDRE->getSourceRange ());
946+ }
947+
948+ if (!Context.LangOpts .DisableExperimentalClangImporterDiagnostics ) {
949+ Context.getClangModuleLoader ()->diagnoseTopLevelValue (Name.getFullName ());
950+ }
951+ };
952+
953+ if (!isConfused) {
954+ if (Name.isSimpleName (Context.Id_Self )) {
955+ if (DeclContext *typeContext = DC->getInnermostTypeContext ()) {
956+ Type SelfType = typeContext->getSelfInterfaceType ();
957+
958+ if (typeContext->getSelfClassDecl () &&
959+ !typeContext->getSelfClassDecl ()->isForeignReferenceType ())
960+ SelfType = DynamicSelfType::get (SelfType, Context);
961+ return new (Context)
962+ TypeExpr (new (Context) SelfTypeRepr (SelfType, Loc));
963+ }
964+ }
965+
966+ TypoCorrectionResults corrections (Name, nameLoc);
967+
968+ // FIXME: Don't perform typo correction inside macro arguments, because it
969+ // will invoke synthesizing declarations in this scope, which will attempt
970+ // to expand this macro which leads to circular reference errors.
971+ if (!namelookup::isInMacroArgument (DC->getParentSourceFile (),
972+ UDRE->getLoc ())) {
973+ TypeChecker::performTypoCorrection (DC, UDRE->getRefKind (), Type (),
974+ lookupOptions, corrections);
975+ }
976+
977+ if (auto typo = corrections.claimUniqueCorrection ()) {
978+ auto diag = Context.Diags .diagnose (
979+ Loc, diag::cannot_find_in_scope_corrected, Name, Name.isOperator (),
980+ typo->CorrectedName .getBaseIdentifier ().str ());
981+ diag.highlight (UDRE->getSourceRange ());
982+ typo->addFixits (diag);
983+ } else {
984+ emitBasicError ();
985+ }
986+
987+ corrections.noteAllCandidates ();
988+ } else {
989+ emitBasicError ();
990+
991+ if (totalCodepoints == 1 ) {
992+ auto charNames = confusable::getConfusableAndBaseCodepointNames (
993+ firstConfusableCodepoint);
994+ Context.Diags
995+ .diagnose (Loc, diag::single_confusable_character,
996+ UDRE->getName ().isOperator (), simpleName.str (),
997+ charNames.first , expectedIdentifier, charNames.second )
998+ .fixItReplace (Loc, expectedIdentifier);
999+ } else {
1000+ Context.Diags
1001+ .diagnose (Loc, diag::confusable_character,
1002+ UDRE->getName ().isOperator (), simpleName.str (),
1003+ expectedIdentifier)
1004+ .fixItReplace (Loc, expectedIdentifier);
1005+ }
1006+ }
1007+
1008+ // TODO: consider recovering from here. We may want some way to suppress
1009+ // downstream diagnostics, though.
1010+ return errorResult ();
1011+ }
1012+
9861013// / If an expression references 'self.init' or 'super.init' in an
9871014// / initializer context, returns the implicit 'self' decl of the constructor.
9881015// / Otherwise, return nil.
0 commit comments