Index: clang/lib/Sema/SemaLookup.cpp =================================================================== --- clang/lib/Sema/SemaLookup.cpp +++ clang/lib/Sema/SemaLookup.cpp @@ -4307,18 +4307,35 @@ if (!CList.empty() && !CList.back().isResolved()) CList.pop_back(); if (NamedDecl *NewND = Correction.getCorrectionDecl()) { - std::string CorrectionStr = Correction.getAsString(SemaRef.getLangOpts()); - for (TypoResultList::iterator RI = CList.begin(), RIEnd = CList.end(); - RI != RIEnd; ++RI) { - // If the Correction refers to a decl already in the result list, - // replace the existing result if the string representation of Correction - // comes before the current result alphabetically, then stop as there is - // nothing more to be done to add Correction to the candidate set. - if (RI->getCorrectionDecl() == NewND) { - if (CorrectionStr < RI->getAsString(SemaRef.getLangOpts())) - *RI = Correction; - return; - } + auto RI = llvm::find_if(CList, [NewND](const TypoCorrection &typoCorr) { + return typoCorr.getCorrectionDecl() == NewND; + }); + if (RI != CList.end()) { + // The Correction refers to a decl already in the list. No insertion is + // necessary and all further cases will return. + + auto IsDeprecated = [](Decl *decl) { + while (decl) { + if (decl->isDeprecated()) + return true; + decl = llvm::dyn_cast_or_null(decl->getDeclContext()); + } + return false; + }; + + // Prefer non deprecated Corrections over deprecated and only then + // sort using an alphabetical order + std::pair newKey = { + IsDeprecated(Correction.getFoundDecl()), + Correction.getAsString(SemaRef.getLangOpts())}; + + std::pair prevKey = { + IsDeprecated(RI->getFoundDecl()), + RI->getAsString(SemaRef.getLangOpts())}; + + if (newKey < prevKey) + *RI = Correction; + return; } } if (CList.empty() || Correction.isResolved()) Index: clang/test/SemaCXX/typo-correction.cpp =================================================================== --- clang/test/SemaCXX/typo-correction.cpp +++ clang/test/SemaCXX/typo-correction.cpp @@ -757,3 +757,34 @@ b = g_volatile_uchar // expected-error {{did you mean 'g_volatile_char'}} }; } + +namespace PR47272 +{ + +namespace Views { +int Take(); // expected-note{{'Views::Take' declared here}} +} + +namespace [[deprecated("use Views instead")]] View { +using Views::Take; +} + +namespace B { +int pr47272(); // expected-note{{'B::pr47272' declared here}} +} + +namespace [[deprecated]] A { +using B::pr47272; +} + +namespace [[deprecated]] C { +using B::pr47272; +} + +void function() { + int x = ::Take(); // expected-error{{no member named 'Take' in the global namespace; did you mean 'Views::Take'?}} + int y = ::pr47272(); // expected-error{{no member named 'pr47272' in the global namespace; did you mean 'B::pr47272'?}} +} +} + +