diff options
author | Kaelyn Uhrain <rikka@google.com> | 2013-07-10 17:34:22 +0000 |
---|---|---|
committer | Kaelyn Uhrain <rikka@google.com> | 2013-07-10 17:34:22 +0000 |
commit | 8ec9f5f60e322f7c96a23423bb246467a6c12dda (patch) | |
tree | 41bc9b96aa68947ca8fe389746daf05fae34021f /clang/lib/Sema/SemaDeclCXX.cpp | |
parent | fc3876118d870f6894bc512215b35b42a2c1e644 (diff) | |
download | bcm5719-llvm-8ec9f5f60e322f7c96a23423bb246467a6c12dda.tar.gz bcm5719-llvm-8ec9f5f60e322f7c96a23423bb246467a6c12dda.zip |
Offer typo suggestions for 'using' declarations.
Patch courtesy of Luke Zarko <zarko@google.com>
llvm-svn: 186019
Diffstat (limited to 'clang/lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 58 |
1 files changed, 54 insertions, 4 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e42d249542b..1c21b2cf204 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -7024,6 +7024,35 @@ void Sema::HideUsingShadowDecl(Scope *S, UsingShadowDecl *Shadow) { // be possible for this to happen, because...? } +class UsingValidatorCCC : public CorrectionCandidateCallback { +public: + UsingValidatorCCC(bool IsTypeName, bool IsInstantiation) + : IsTypeName(IsTypeName), IsInstantiation(IsInstantiation) {} + + virtual bool ValidateCandidate(const TypoCorrection &Candidate) { + if (NamedDecl *ND = Candidate.getCorrectionDecl()) { + if (isa<NamespaceDecl>(ND)) + return false; + // Completely unqualified names are invalid for a 'using' declaration. + bool droppedSpecifier = Candidate.WillReplaceSpecifier() && + !Candidate.getCorrectionSpecifier(); + if (droppedSpecifier) + return false; + else if (isa<TypeDecl>(ND)) + return IsTypeName || !IsInstantiation; + else + return !IsTypeName; + } else { + // Keywords are not valid here. + return false; + } + } + +private: + bool IsTypeName; + bool IsInstantiation; +}; + /// Builds a using declaration. /// /// \param IsInstantiation - Whether this call arises from an @@ -7133,11 +7162,32 @@ NamedDecl *Sema::BuildUsingDeclaration(Scope *S, AccessSpecifier AS, LookupQualifiedName(R, LookupContext); + // Try to correct typos if possible. if (R.empty()) { - Diag(IdentLoc, diag::err_no_member) - << NameInfo.getName() << LookupContext << SS.getRange(); - UD->setInvalidDecl(); - return UD; + UsingValidatorCCC CCC(IsTypeName, IsInstantiation); + if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(), + R.getLookupKind(), S, &SS, CCC)){ + // We reject any correction for which ND would be NULL. + NamedDecl *ND = Corrected.getCorrectionDecl(); + std::string CorrectedStr(Corrected.getAsString(getLangOpts())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOpts())); + R.setLookupName(Corrected.getCorrection()); + R.addDecl(ND); + // We reject candidates where droppedSpecifier == true, hence the + // literal '0' below. + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << NameInfo.getName() << LookupContext << 0 + << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(Corrected.getCorrectionRange(), + CorrectedStr); + Diag(ND->getLocation(), diag::note_previous_decl) + << CorrectedQuotedStr; + } else { + Diag(IdentLoc, diag::err_no_member) + << NameInfo.getName() << LookupContext << SS.getRange(); + UD->setInvalidDecl(); + return UD; + } } if (R.isAmbiguous()) { |