Author: rsmith Date: Tue Dec 29 13:43:10 2015 New Revision: 256575 URL: http://llvm.org/viewvc/llvm-project?rev=256575&view=rev Log: Teach typo correction to properly handle mapping declarations to their underlying decls. Preserve the found declaration throughout, and only map to the underlying declaration when we want to check whether it's the right kind. This allows us to provide the right source location for the found declaration, and prepares for the possibility of underlying decls with a different name from the found decl.
Modified: cfe/trunk/include/clang/Sema/TypoCorrection.h cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaDeclCXX.cpp cfe/trunk/lib/Sema/SemaExpr.cpp cfe/trunk/lib/Sema/SemaExprCXX.cpp cfe/trunk/lib/Sema/SemaLookup.cpp cfe/trunk/lib/Sema/SemaTemplate.cpp cfe/trunk/test/SemaCXX/typo-correction.cpp Modified: cfe/trunk/include/clang/Sema/TypoCorrection.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TypoCorrection.h?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/TypoCorrection.h (original) +++ cfe/trunk/include/clang/Sema/TypoCorrection.h Tue Dec 29 13:43:10 2015 @@ -72,15 +72,15 @@ public: /// \brief Gets the DeclarationName of the typo correction DeclarationName getCorrection() const { return CorrectionName; } - IdentifierInfo* getCorrectionAsIdentifierInfo() const { + IdentifierInfo *getCorrectionAsIdentifierInfo() const { return CorrectionName.getAsIdentifierInfo(); } /// \brief Gets the NestedNameSpecifier needed to use the typo correction - NestedNameSpecifier* getCorrectionSpecifier() const { + NestedNameSpecifier *getCorrectionSpecifier() const { return CorrectionNameSpec; } - void setCorrectionSpecifier(NestedNameSpecifier* NNS) { + void setCorrectionSpecifier(NestedNameSpecifier *NNS) { CorrectionNameSpec = NNS; ForceSpecifierReplacement = (NNS != nullptr); } @@ -129,9 +129,16 @@ public: return Normalized ? NormalizeEditDistance(ED) : ED; } + /// \brief Get the correction declaration found by name lookup (before we + /// looked through using shadow declarations and the like). + NamedDecl *getFoundDecl() const { + return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr; + } + /// \brief Gets the pointer to the declaration of the typo correction NamedDecl *getCorrectionDecl() const { - return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr; + auto *D = getFoundDecl(); + return D ? D->getUnderlyingDecl() : nullptr; } template <class DeclClass> DeclClass *getCorrectionDeclAs() const { @@ -180,8 +187,7 @@ public: // Check if this TypoCorrection is a keyword by checking if the first // item in CorrectionDecls is NULL. bool isKeyword() const { - return !CorrectionDecls.empty() && - CorrectionDecls.front() == nullptr; + return !CorrectionDecls.empty() && CorrectionDecls.front() == nullptr; } // Check if this TypoCorrection is the given keyword. Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original) +++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Tue Dec 29 13:43:10 2015 @@ -607,7 +607,7 @@ bool Sema::BuildCXXNestedNameSpecifier(S diagnoseTypo(Corrected, PDiag(diag::err_undeclared_var_use_suggest) << Name); - if (NamedDecl *ND = Corrected.getCorrectionDecl()) + if (NamedDecl *ND = Corrected.getFoundDecl()) Found.addDecl(ND); Found.setLookupName(Corrected.getCorrection()); } else { Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Dec 29 13:43:10 2015 @@ -813,9 +813,8 @@ Corrected: unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; - NamedDecl *FirstDecl = Corrected.getCorrectionDecl(); - NamedDecl *UnderlyingFirstDecl - = FirstDecl? FirstDecl->getUnderlyingDecl() : nullptr; + NamedDecl *FirstDecl = Corrected.getFoundDecl(); + NamedDecl *UnderlyingFirstDecl = Corrected.getCorrectionDecl(); if (getLangOpts().CPlusPlus && NextToken.is(tok::less) && UnderlyingFirstDecl && isa<TemplateDecl>(UnderlyingFirstDecl)) { UnqualifiedDiag = diag::err_no_template_suggest; Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Dec 29 13:43:10 2015 @@ -7531,7 +7531,7 @@ static bool TryNamespaceTypoCorrection(S S.PDiag(diag::err_using_directive_suggest) << Ident, S.PDiag(diag::note_namespace_defined_here)); } - R.addDecl(Corrected.getCorrectionDecl()); + R.addDecl(Corrected.getFoundDecl()); return true; } return false; Modified: cfe/trunk/lib/Sema/SemaExpr.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExpr.cpp (original) +++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Dec 29 13:43:10 2015 @@ -1776,10 +1776,9 @@ static void emitEmptyLookupTypoDiagnosti std::string CorrectedStr = TC.getAsString(SemaRef.getLangOpts()); bool DroppedSpecifier = TC.WillReplaceSpecifier() && Typo.getAsString() == CorrectedStr; - unsigned NoteID = - (TC.getCorrectionDecl() && isa<ImplicitParamDecl>(TC.getCorrectionDecl())) - ? diag::note_implicit_param_decl - : diag::note_previous_decl; + unsigned NoteID = TC.getCorrectionDeclAs<ImplicitParamDecl>() + ? diag::note_implicit_param_decl + : diag::note_previous_decl; if (!Ctx) SemaRef.diagnoseTypo(TC, SemaRef.PDiag(DiagnosticSuggestID) << Typo, SemaRef.PDiag(NoteID)); @@ -1903,7 +1902,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXS bool AcceptableWithRecovery = false; bool AcceptableWithoutRecovery = false; - NamedDecl *ND = Corrected.getCorrectionDecl(); + NamedDecl *ND = Corrected.getFoundDecl(); if (ND) { if (Corrected.isOverloaded()) { OverloadCandidateSet OCS(R.getNameLoc(), @@ -1922,7 +1921,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXS } switch (OCS.BestViableFunction(*this, R.getNameLoc(), Best)) { case OR_Success: - ND = Best->Function; + ND = Best->FoundDecl; Corrected.setCorrectionDecl(ND); break; default: @@ -1944,15 +1943,16 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXS R.setNamingClass(Record); } - AcceptableWithRecovery = - isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND); + auto *UnderlyingND = ND->getUnderlyingDecl(); + AcceptableWithRecovery = isa<ValueDecl>(UnderlyingND) || + isa<FunctionTemplateDecl>(UnderlyingND); // FIXME: If we ended up with a typo for a type name or // Objective-C class name, we're in trouble because the parser // is in the wrong place to recover. Suggest the typo // correction, but don't make it a fix-it since we're not going // to recover well anyway. AcceptableWithoutRecovery = - isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND); + isa<TypeDecl>(UnderlyingND) || isa<ObjCInterfaceDecl>(UnderlyingND); } else { // FIXME: We found a keyword. Suggest it, but don't provide a fix-it // because we aren't able to recover. @@ -1960,8 +1960,7 @@ Sema::DiagnoseEmptyLookup(Scope *S, CXXS } if (AcceptableWithRecovery || AcceptableWithoutRecovery) { - unsigned NoteID = (Corrected.getCorrectionDecl() && - isa<ImplicitParamDecl>(Corrected.getCorrectionDecl())) + unsigned NoteID = Corrected.getCorrectionDeclAs<ImplicitParamDecl>() ? diag::note_implicit_param_decl : diag::note_previous_decl; if (SS.isEmpty()) @@ -4402,7 +4401,7 @@ static TypoCorrection TryTypoCorrectionF llvm::make_unique<FunctionCallCCC>(S, FuncName.getAsIdentifierInfo(), Args.size(), ME), Sema::CTK_ErrorRecovery)) { - if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + if (NamedDecl *ND = Corrected.getFoundDecl()) { if (Corrected.isOverloaded()) { OverloadCandidateSet OCS(NameLoc, OverloadCandidateSet::CSK_Normal); OverloadCandidateSet::iterator Best; @@ -4413,16 +4412,16 @@ static TypoCorrection TryTypoCorrectionF } switch (OCS.BestViableFunction(S, NameLoc, Best)) { case OR_Success: - ND = Best->Function; + ND = Best->FoundDecl; Corrected.setCorrectionDecl(ND); break; default: break; } } - if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { + ND = ND->getUnderlyingDecl(); + if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) return Corrected; - } } } return TypoCorrection(); Modified: cfe/trunk/lib/Sema/SemaExprCXX.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaExprCXX.cpp (original) +++ cfe/trunk/lib/Sema/SemaExprCXX.cpp Tue Dec 29 13:43:10 2015 @@ -6409,7 +6409,7 @@ static ExprResult attemptRecovery(Sema & else if (SS && !TC.WillReplaceSpecifier()) NewSS = *SS; - if (auto *ND = TC.getCorrectionDecl()) { + if (auto *ND = TC.getFoundDecl()) { R.setLookupName(ND->getDeclName()); R.addDecl(ND); if (ND->isCXXClassMember()) { @@ -6530,9 +6530,9 @@ class TransformTypos : public TreeTransf if (!E) return nullptr; if (auto *DRE = dyn_cast<DeclRefExpr>(E)) - return DRE->getDecl(); + return DRE->getFoundDecl(); if (auto *ME = dyn_cast<MemberExpr>(E)) - return ME->getMemberDecl(); + return ME->getFoundDecl(); // FIXME: Add any other expr types that could be be seen by the delayed typo // correction TreeTransform for which the corresponding TypoCorrection could // contain multiple decls. @@ -6637,7 +6637,7 @@ public: // For the first TypoExpr and an uncached TypoExpr, find the next likely // typo correction and return it. while (TypoCorrection TC = State.Consumer->getNextCorrection()) { - if (InitDecl && TC.getCorrectionDecl() == InitDecl) + if (InitDecl && TC.getFoundDecl() == InitDecl) continue; ExprResult NE = State.RecoveryHandler ? State.RecoveryHandler(SemaRef, E, TC) : Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Dec 29 13:43:10 2015 @@ -4719,7 +4719,7 @@ void TypoCorrection::addCorrectionDecl(N if (isKeyword()) CorrectionDecls.clear(); - CorrectionDecls.push_back(CDecl->getUnderlyingDecl()); + CorrectionDecls.push_back(CDecl); if (!CorrectionName) CorrectionName = CDecl->getDeclName(); @@ -4948,7 +4948,7 @@ void Sema::diagnoseTypo(const TypoCorrec // Maybe we're just missing a module import. if (Correction.requiresImport()) { - NamedDecl *Decl = Correction.getCorrectionDecl(); + NamedDecl *Decl = Correction.getFoundDecl(); assert(Decl && "import required but no declaration to import"); diagnoseMissingImport(Correction.getCorrectionRange().getBegin(), Decl, @@ -4960,7 +4960,7 @@ void Sema::diagnoseTypo(const TypoCorrec << CorrectedQuotedStr << (ErrorRecovery ? FixTypo : FixItHint()); NamedDecl *ChosenDecl = - Correction.isKeyword() ? nullptr : Correction.getCorrectionDecl(); + Correction.isKeyword() ? nullptr : Correction.getFoundDecl(); if (PrevNote.getDiagID() && ChosenDecl) Diag(ChosenDecl->getLocation(), PrevNote) << CorrectedQuotedStr << (ErrorRecovery ? FixItHint() : FixTypo); Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Dec 29 13:43:10 2015 @@ -329,8 +329,8 @@ void Sema::LookupTemplateName(LookupResu Found.getLookupNameInfo(), Found.getLookupKind(), S, &SS, std::move(FilterCCC), CTK_ErrorRecovery, LookupCtx)) { Found.setLookupName(Corrected.getCorrection()); - if (Corrected.getCorrectionDecl()) - Found.addDecl(Corrected.getCorrectionDecl()); + if (auto *ND = Corrected.getFoundDecl()) + Found.addDecl(ND); FilterAcceptableTemplateNames(Found); if (!Found.empty()) { if (LookupCtx) { Modified: cfe/trunk/test/SemaCXX/typo-correction.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/typo-correction.cpp?rev=256575&r1=256574&r2=256575&view=diff ============================================================================== --- cfe/trunk/test/SemaCXX/typo-correction.cpp (original) +++ cfe/trunk/test/SemaCXX/typo-correction.cpp Tue Dec 29 13:43:10 2015 @@ -307,14 +307,21 @@ struct A { void CreateBar(float, float); }; struct B : A { - using A::CreateFoo; + using A::CreateFoo; // expected-note {{'CreateFoo' declared here}} void CreateFoo(int, int); // expected-note {{'CreateFoo' declared here}} }; void f(B &x) { x.Createfoo(0,0); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}} + x.Createfoo(0.f,0.f); // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}} } } +namespace using_decl { + namespace somewhere { int foobar; } + using somewhere::foobar; // expected-note {{declared here}} + int k = goobar; // expected-error {{did you mean 'foobar'?}} +} + struct DataStruct {void foo();}; struct T { DataStruct data_struct; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits