@@ -518,11 +518,12 @@ diagnoseUnqualifiedInit(UnresolvedDeclRefExpr *initExpr, DeclContext *dc,
518
518
initExpr->getNameLoc (), /* implicit=*/ true );
519
519
}
520
520
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) {
526
527
auto &Context = DC->getASTContext ();
527
528
DeclNameRef Name = UDRE->getName ();
528
529
SourceLoc Loc = UDRE->getLoc ();
@@ -562,14 +563,6 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
562
563
LookupName = DeclNameRef (lookupName);
563
564
}
564
565
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
-
573
566
LookupResult Lookup;
574
567
575
568
bool AllDeclRefs = true ;
@@ -628,17 +621,8 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
628
621
}
629
622
630
623
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.
642
626
NameLookupOptions relookupOptions = lookupOptions;
643
627
relookupOptions |= NameLookupFlags::IgnoreAccessControl;
644
628
auto inaccessibleResults =
@@ -663,117 +647,8 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
663
647
return errorResult ();
664
648
}
665
649
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 ;
777
652
}
778
653
779
654
// FIXME: Need to refactor the way we build an AST node from a lookup result!
@@ -892,8 +767,9 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
892
767
UDRE->getNameLoc ().getStartLoc ());
893
768
}
894
769
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 ());
897
773
}
898
774
899
775
ResultValues.clear ();
@@ -983,6 +859,157 @@ Expr *TypeChecker::resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
983
859
return errorResult ();
984
860
}
985
861
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
+
986
1013
// / If an expression references 'self.init' or 'super.init' in an
987
1014
// / initializer context, returns the implicit 'self' decl of the constructor.
988
1015
// / Otherwise, return nil.
0 commit comments