Typo correction for member access into classes/structs/unions, e.g.,

s.fnd("hello")

llvm-svn: 92345
This commit is contained in:
Douglas Gregor 2009-12-31 07:42:17 +00:00
parent 9039ff8912
commit af2bd473d2
4 changed files with 33 additions and 5 deletions

View File

@ -1209,6 +1209,7 @@ public:
VisibleDeclConsumer &Consumer);
bool CorrectTypo(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
DeclContext *MemberContext = 0,
bool EnteringContext = false);
void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,

View File

@ -932,7 +932,7 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS,
// We didn't find anything, so try to correct for a typo.
if (S && CorrectTypo(R, S, &SS) &&
(isa<ValueDecl>(*R.begin()) || isa<TemplateDecl>(*R.begin()))) {
(isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {
if (SS.isEmpty())
Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName()
<< CodeModificationHint::CreateReplacement(R.getNameLoc(),
@ -2346,6 +2346,23 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R,
// The record definition is complete, now look up the member.
SemaRef.LookupQualifiedName(R, DC);
if (!R.empty())
return false;
// We didn't find anything with the given name, so try to correct
// for typos.
DeclarationName Name = R.getLookupName();
if (SemaRef.CorrectTypo(R, 0, &SS, DC) &&
(isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {
SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)
<< Name << DC << R.getLookupName() << SS.getRange()
<< CodeModificationHint::CreateReplacement(R.getNameLoc(),
R.getLookupName().getAsString());
return false;
} else {
R.clear();
}
return false;
}

View File

@ -2134,6 +2134,9 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding) {
/// \param SS the nested-name-specifier that precedes the name we're
/// looking for, if present.
///
/// \param MemberContext if non-NULL, the context in which to look for
/// a member access expression.
///
/// \param EnteringContext whether we're entering the context described by
/// the nested-name-specifier SS.
///
@ -2141,7 +2144,7 @@ void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding) {
/// structure will contain the results of name lookup for the
/// corrected name. Otherwise, returns false.
bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
bool EnteringContext) {
DeclContext *MemberContext, bool EnteringContext) {
// We only attempt to correct typos for identifiers.
IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
if (!Typo)
@ -2158,7 +2161,9 @@ bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
return false;
TypoCorrectionConsumer Consumer(Typo);
if (SS && SS->isSet()) {
if (MemberContext)
LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer);
else if (SS && SS->isSet()) {
DeclContext *DC = computeDeclContext(*SS, EnteringContext);
if (!DC)
return false;
@ -2193,7 +2198,11 @@ bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
// success if we found something that was not ambiguous.
Res.clear();
Res.setLookupName(BestName);
LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, EnteringContext);
if (MemberContext)
LookupQualifiedName(Res, MemberContext);
else
LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false,
EnteringContext);
if (Res.isAmbiguous()) {
Res.suppressDiagnostics();

View File

@ -23,5 +23,6 @@ float area(float radius, float pi) {
}
bool test_string(std::string s) {
return s.find("hello") == std::string::pos; // expected-error{{no member named 'pos' in 'class std::basic_string<char>'; did you mean 'npos'?}}
return s.fnd("hello") // expected-error{{no member named 'fnd' in 'class std::basic_string<char>'; did you mean 'find'?}}
== std::string::pos; // expected-error{{no member named 'pos' in 'class std::basic_string<char>'; did you mean 'npos'?}}
}