diff options
author | Douglas Gregor <dgregor@apple.com> | 2011-06-28 16:20:02 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2011-06-28 16:20:02 +0000 |
commit | d8bba9c15230d2b1b3893e272106aa79efc50251 (patch) | |
tree | 3528328b9ce5acfffb481a74dc3da8f157bf7ca7 /lib/Sema | |
parent | 020540b7402f6fed6e314d50018543ea08a06b2b (diff) |
Add support for C++ namespace-aware typo correction, e.g., correcting
vector<int>
to
std::vector<int>
Patch by Kaelyn Uhrain, with minor tweaks + PCH support from me. Fixes
PR5776/<rdar://problem/8652971>.
Thanks Kaelyn!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@134007 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r-- | lib/Sema/Sema.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaCXXScopeSpec.cpp | 31 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 78 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 111 | ||||
-rw-r--r-- | lib/Sema/SemaDeclObjC.cpp | 33 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 41 | ||||
-rw-r--r-- | lib/Sema/SemaExprMember.cpp | 38 | ||||
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 28 | ||||
-rw-r--r-- | lib/Sema/SemaInit.cpp | 20 | ||||
-rw-r--r-- | lib/Sema/SemaLookup.cpp | 851 | ||||
-rw-r--r-- | lib/Sema/SemaTemplate.cpp | 25 | ||||
-rw-r--r-- | lib/Sema/SemaTemplateVariadic.cpp | 16 |
12 files changed, 773 insertions, 505 deletions
diff --git a/lib/Sema/Sema.cpp b/lib/Sema/Sema.cpp index 7d22031ecb..9550f9aad2 100644 --- a/lib/Sema/Sema.cpp +++ b/lib/Sema/Sema.cpp @@ -154,6 +154,8 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, ASTConsumer &consumer, AnalysisWarnings(*this) { TUScope = 0; + LoadedExternalKnownNamespaces = false; + if (getLangOptions().CPlusPlus) FieldCollector.reset(new CXXFieldCollector()); @@ -778,6 +780,10 @@ ExternalSemaSource::ReadMethodPool(Selector Sel) { return std::pair<ObjCMethodList, ObjCMethodList>(); } +void ExternalSemaSource::ReadKnownNamespaces( + llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces) { +} + void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const { SourceLocation Loc = this->Loc; if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation(); diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 61d9e93f2f..e54857196a 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -464,26 +464,29 @@ bool Sema::BuildCXXNestedNameSpecifier(Scope *S, // We haven't found anything, and we're not recovering from a // different kind of error, so look for typos. DeclarationName Name = Found.getLookupName(); - if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext, - CTC_NoKeywords) && - Found.isSingleResult() && - isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) { + TypoCorrection Corrected; + Found.clear(); + if ((Corrected = CorrectTypo(Found.getLookupNameInfo(), + Found.getLookupKind(), S, &SS, LookupCtx, + EnteringContext, CTC_NoKeywords)) && + isAcceptableNestedNameSpecifier(Corrected.getCorrectionDecl())) { + std::string CorrectedStr(Corrected.getAsString(getLangOptions())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); if (LookupCtx) Diag(Found.getNameLoc(), diag::err_no_member_suggest) - << Name << LookupCtx << Found.getLookupName() << SS.getRange() - << FixItHint::CreateReplacement(Found.getNameLoc(), - Found.getLookupName().getAsString()); + << Name << LookupCtx << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); else Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest) - << Name << Found.getLookupName() - << FixItHint::CreateReplacement(Found.getNameLoc(), - Found.getLookupName().getAsString()); + << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr); - if (NamedDecl *ND = Found.getAsSingle<NamedDecl>()) - Diag(ND->getLocation(), diag::note_previous_decl) - << ND->getDeclName(); + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { + Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr; + Found.addDecl(ND); + } + Found.setLookupName(Corrected.getCorrection()); } else { - Found.clear(); Found.setLookupName(&Identifier); } } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index efb06f6687..2779faeb15 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -287,41 +287,42 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, // There may have been a typo in the name of the type. Look up typo // results, in case we have something that we can suggest. - LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName, - NotForRedeclaration); + if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc), + LookupOrdinaryName, S, SS, NULL, + false, CTC_Type)) { + std::string CorrectedStr(Corrected.getAsString(getLangOptions())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); - if (DeclarationName Corrected = CorrectTypo(Lookup, S, SS, 0, 0, CTC_Type)) { - if (NamedDecl *Result = Lookup.getAsSingle<NamedDecl>()) { + if (Corrected.isKeyword()) { + // We corrected to a keyword. + // FIXME: Actually recover with the keyword we suggest, and emit a fix-it. + Diag(IILoc, diag::err_unknown_typename_suggest) + << &II << CorrectedQuotedStr; + return true; + } else { + NamedDecl *Result = Corrected.getCorrectionDecl(); if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) && !Result->isInvalidDecl()) { // We found a similarly-named type or interface; suggest that. if (!SS || !SS->isSet()) Diag(IILoc, diag::err_unknown_typename_suggest) - << &II << Lookup.getLookupName() - << FixItHint::CreateReplacement(SourceRange(IILoc), - Result->getNameAsString()); + << &II << CorrectedQuotedStr + << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); else if (DeclContext *DC = computeDeclContext(*SS, false)) Diag(IILoc, diag::err_unknown_nested_typename_suggest) - << &II << DC << Lookup.getLookupName() << SS->getRange() - << FixItHint::CreateReplacement(SourceRange(IILoc), - Result->getNameAsString()); + << &II << DC << CorrectedQuotedStr << SS->getRange() + << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr); else llvm_unreachable("could not have corrected a typo here"); Diag(Result->getLocation(), diag::note_previous_decl) - << Result->getDeclName(); + << CorrectedQuotedStr; SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS, false, false, ParsedType(), /*NonTrivialTypeSourceInfo=*/true); return true; } - } else if (Lookup.empty()) { - // We corrected to a keyword. - // FIXME: Actually recover with the keyword we suggest, and emit a fix-it. - Diag(IILoc, diag::err_unknown_typename_suggest) - << &II << Corrected; - return true; } } @@ -509,11 +510,14 @@ Corrected: // Perform typo correction to determine if there is another name that is // close to this name. if (!SecondTry) { - if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) { + if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), + Result.getLookupKind(), S, &SS)) { unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest; unsigned QualifiedDiag = diag::err_no_member_suggest; + std::string CorrectedStr(Corrected.getAsString(getLangOptions())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); - NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin(); + NamedDecl *FirstDecl = Corrected.getCorrectionDecl(); NamedDecl *UnderlyingFirstDecl = FirstDecl? FirstDecl->getUnderlyingDecl() : 0; if (getLangOptions().CPlusPlus && NextToken.is(tok::less) && @@ -528,25 +532,34 @@ Corrected: QualifiedDiag = diag::err_unknown_nested_typename_suggest; } + if (Corrected.getCorrectionSpecifier()) + SS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), SourceRange(NameLoc)); + if (SS.isEmpty()) Diag(NameLoc, UnqualifiedDiag) - << Name << Corrected - << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(NameLoc, CorrectedStr); else Diag(NameLoc, QualifiedDiag) - << Name << computeDeclContext(SS, false) << Corrected + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString()); + << FixItHint::CreateReplacement(NameLoc, CorrectedStr); // Update the name, so that the caller has the new name. - Name = Corrected.getAsIdentifierInfo(); + Name = Corrected.getCorrectionAsIdentifierInfo(); + // Also update the LookupResult... + // FIXME: This should probably go away at some point + Result.clear(); + Result.setLookupName(Corrected.getCorrection()); + if (FirstDecl) Result.addDecl(FirstDecl); + // Typo correction corrected to a keyword. - if (Result.empty()) - return Corrected.getAsIdentifierInfo(); + if (Corrected.isKeyword()) + return Corrected.getCorrectionAsIdentifierInfo(); Diag(FirstDecl->getLocation(), diag::note_previous_decl) - << FirstDecl->getDeclName(); + << CorrectedQuotedStr; // If we found an Objective-C instance variable, let // LookupInObjCMethod build the appropriate expression to @@ -1137,17 +1150,18 @@ void Sema::ActOnPopScope(SourceLocation Loc, Scope *S) { /// class could not be found. ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, SourceLocation IdLoc, - bool TypoCorrection) { + bool DoTypoCorrection) { // The third "scope" argument is 0 since we aren't enabling lazy built-in // creation from this context. NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName); - if (!IDecl && TypoCorrection) { + if (!IDecl && DoTypoCorrection) { // Perform typo correction at the given location, but only if we // find an Objective-C class name. - LookupResult R(*this, Id, IdLoc, LookupOrdinaryName); - if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && - (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { + TypoCorrection C; + if ((C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName, + TUScope, NULL, NULL, false, CTC_NoKeywords)) && + (IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>())) { Diag(IdLoc, diag::err_undef_interface_suggest) << Id << IDecl->getDeclName() << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString()); diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index c0d34da922..ac51138b91 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1426,25 +1426,27 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, } // If no results were found, try to correct typos. + TypoCorrection Corr; if (R.empty() && BaseType.isNull() && - CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) && - R.isSingleResult()) { - if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) { + (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS, + ClassDecl, false, CTC_NoKeywords))) { + std::string CorrectedStr(Corr.getAsString(getLangOptions())); + std::string CorrectedQuotedStr(Corr.getQuoted(getLangOptions())); + if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) { if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) { // We have found a non-static data member with a similar // name to what was typed; complain and initialize that // member. Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) - << MemberOrBase << true << R.getLookupName() - << FixItHint::CreateReplacement(R.getNameLoc(), - R.getLookupName().getAsString()); + << MemberOrBase << true << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); Diag(Member->getLocation(), diag::note_previous_decl) - << Member->getDeclName(); + << CorrectedQuotedStr; return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, LParenLoc, RParenLoc); } - } else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) { + } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) { const CXXBaseSpecifier *DirectBaseSpec; const CXXBaseSpecifier *VirtualBaseSpec; if (FindBaseInitializer(*this, ClassDecl, @@ -1454,9 +1456,8 @@ Sema::ActOnMemInitializer(Decl *ConstructorD, // similar name to what was typed; complain and initialize // that base class. Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest) - << MemberOrBase << false << R.getLookupName() - << FixItHint::CreateReplacement(R.getNameLoc(), - R.getLookupName().getAsString()); + << MemberOrBase << false << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec : VirtualBaseSpec; @@ -4706,6 +4707,13 @@ Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope, // Make our StdNamespace cache point at the first real definition of the // "std" namespace. StdNamespace = Namespc; + + // Add this instance of "std" to the set of known namespaces + KnownNamespaces[Namespc] = false; + } else if (!Namespc->isInline()) { + // Since this is an "original" namespace, add it to the known set of + // namespaces if it is not an inline namespace. + KnownNamespaces[Namespc] = false; } PushOnScopeChains(Namespc, DeclRegionScope); @@ -4841,6 +4849,39 @@ static bool IsUsingDirectiveInToplevelContext(DeclContext *CurContext) { } } +static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc, + CXXScopeSpec &SS, + SourceLocation IdentLoc, + IdentifierInfo *Ident) { + R.clear(); + if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(), + R.getLookupKind(), Sc, &SS, NULL, + false, S.CTC_NoKeywords, NULL)) { + if (Corrected.getCorrectionDeclAs<NamespaceDecl>() || + Corrected.getCorrectionDeclAs<NamespaceAliasDecl>()) { + std::string CorrectedStr(Corrected.getAsString(S.getLangOptions())); + std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions())); + if (DeclContext *DC = S.computeDeclContext(SS, false)) + S.Diag(IdentLoc, diag::err_using_directive_member_suggest) + << Ident << DC << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + else + S.Diag(IdentLoc, diag::err_using_directive_suggest) + << Ident << CorrectedQuotedStr + << FixItHint::CreateReplacement(IdentLoc, CorrectedStr); + + S.Diag(Corrected.getCorrectionDecl()->getLocation(), + diag::note_namespace_defined_here) << CorrectedQuotedStr; + + Ident = Corrected.getCorrectionAsIdentifierInfo(); + R.addDecl(Corrected.getCorrectionDecl()); + return true; + } + R.setLookupName(Ident); + } + return false; +} + Decl *Sema::ActOnUsingDirective(Scope *S, SourceLocation UsingLoc, SourceLocation NamespcLoc, @@ -4869,6 +4910,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, return 0; if (R.empty()) { + R.clear(); // Allow "using namespace std;" or "using namespace ::std;" even if // "std" hasn't been defined yet, for GCC compatibility. if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) && @@ -4878,27 +4920,7 @@ Decl *Sema::ActOnUsingDirective(Scope *S, R.resolveKind(); } // Otherwise, attempt typo correction. - else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, - CTC_NoKeywords, 0)) { - if (R.getAsSingle<NamespaceDecl>() || - R.getAsSingle<NamespaceAliasDecl>()) { - if (DeclContext *DC = computeDeclContext(SS, false)) - Diag(IdentLoc, diag::err_using_directive_member_suggest) - << NamespcName << DC << Corrected << SS.getRange() - << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); - else - Diag(IdentLoc, diag::err_using_directive_suggest) - << NamespcName << Corrected - << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); - Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here) - << Corrected; - - NamespcName = Corrected.getAsIdentifierInfo(); - } else { - R.clear(); - R.setLookupName(NamespcName); - } - } + else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName); } if (!R.empty()) { @@ -5816,30 +5838,7 @@ Decl *Sema::ActOnNamespaceAliasDef(Scope *S, return 0; if (R.empty()) { - if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, - CTC_NoKeywords, 0)) { - if (R.getAsSingle<NamespaceDecl>() || - R.getAsSingle<NamespaceAliasDecl>()) { - if (DeclContext *DC = computeDeclContext(SS, false)) - Diag(IdentLoc, diag::err_using_directive_member_suggest) - << Ident << DC << Corrected << SS.getRange() - << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); - else - Diag(IdentLoc, diag::err_using_directive_suggest) - << Ident << Corrected - << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); - - Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here) - << Corrected; - - Ident = Corrected.getAsIdentifierInfo(); - } else { - R.clear(); - R.setLookupName(Ident); - } - } - - if (R.empty()) { + if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) { Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange(); return 0; } diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index a3f53ec234..a9f4f95c20 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -442,9 +442,10 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, if (!PrevDecl) { // Try to correct for a typo in the superclass name. - LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName); - if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && - (PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) { + TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope, + NULL, NULL, false, CTC_NoKeywords); + if ((PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) { Diag(SuperLoc, diag::err_undef_superclass_suggest) << SuperName << ClassName << PrevDecl->getDeclName(); Diag(PrevDecl->getLocation(), diag::note_previous_decl) @@ -655,12 +656,12 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first, ProtocolId[i].second); if (!PDecl) { - LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second, - LookupObjCProtocolName); - if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && - (PDecl = R.getAsSingle<ObjCProtocolDecl>())) { + TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second), + LookupObjCProtocolName, TUScope, NULL, NULL, false, CTC_NoKeywords); + if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) { Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) - << ProtocolId[i].first << R.getLookupName(); + << ProtocolId[i].first << Corrected.getCorrection(); Diag(PDecl->getLocation(), diag::note_previous_decl) << PDecl->getDeclName(); } @@ -897,20 +898,20 @@ Decl *Sema::ActOnStartClassImplementation( } else { // We did not find anything with the name ClassName; try to correct for // typos in the class name. - LookupResult R(*this, ClassName, ClassLoc, LookupOrdinaryName); - if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) && - (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) { + TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope, + NULL, NULL, false, CTC_NoKeywords); + if ((IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) { // Suggest the (potentially) correct interface name. However, put the // fix-it hint itself in a separate note, since changing the name in // the warning would make the fix-it change semantics.However, don't // provide a code-modification hint or use the typo name for recovery, // because this is just a warning. The program may actually be correct. + DeclarationName CorrectedName = Corrected.getCorrection(); Diag(ClassLoc, diag::warn_undef_interface_suggest) - << ClassName << R.getLookupName(); - Diag(IDecl->getLocation(), diag::note_previous_decl) - << R.getLookupName() - << FixItHint::CreateReplacement(ClassLoc, - R.getLookupName().getAsString()); + << ClassName << CorrectedName; + Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName + << FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString()); IDecl = 0; } else { Diag(ClassLoc, diag::warn_undef_interface) << ClassName; diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3423d71af4..b99076005b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -1397,39 +1397,44 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, } // We didn't find anything, so try to correct for a typo. - DeclarationName Corrected; - if (S && (Corrected = CorrectTypo(R, S, &SS, 0, false, CTC))) { - if (!R.empty()) { - if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) { + TypoCorrection Corrected; + if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), + S, &SS, NULL, false, CTC))) { + std::string CorrectedStr(Corrected.getAsString(getLangOptions())); + std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions())); + R.setLookupName(Corrected.getCorrection()); + + if (!Corrected.isKeyword()) { + NamedDecl *ND = Corrected.getCorrectionDecl(); + R.addDecl(ND); + if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) { if (SS.isEmpty()) - Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName() - << FixItHint::CreateReplacement(R.getNameLoc(), - R.getLookupName().getAsString()); + Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); else Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << computeDeclContext(SS, false) << R.getLookupName() + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr << SS.getRange() - << FixItHint::CreateReplacement(R.getNameLoc(), - R.getLookupName().getAsString()); - if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + if (ND) Diag(ND->getLocation(), diag::note_previous_decl) - << ND->getDeclName(); + << CorrectedQuotedStr; // Tell the callee to try to recover. return false; } - if (isa<TypeDecl>(*R.begin()) || isa<ObjCInterfaceDecl>(*R.begin())) { + if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) { // 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. if (SS.isEmpty()) - Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName(); + Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr; else Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << computeDeclContext(SS, false) << R.getLookupName() + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr << SS.getRange(); // Don't try to recover; it won't work. @@ -1439,15 +1444,15 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, // FIXME: We found a keyword. Suggest it, but don't provide a fix-it // because we aren't able to recover. if (SS.isEmpty()) - Diag(R.getNameLoc(), diagnostic_suggest) << Name << Corrected; + Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr; else Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << computeDeclContext(SS, false) << Corrected + << Name << computeDeclContext(SS, false) << CorrectedQuotedStr << SS.getRange(); return true; } - R.clear(); } + R.clear(); // Emit a special diagnostic for failed member lookups. // FIXME: computing the declaration context might fail here (?) diff --git a/lib/Sema/SemaExprMember.cpp b/lib/Sema/SemaExprMember.cpp index 9509768205..2488dc8849 100644 --- a/lib/Sema/SemaExprMember.cpp +++ b/lib/Sema/SemaExprMember.cpp @@ -555,20 +555,24 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, // 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, false, Sema::CTC_MemberLookup) && - !R.empty() && - (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) { + TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(), + R.getLookupKind(), NULL, + &SS, DC, false, + Sema::CTC_MemberLookup); + NamedDecl *ND = Corrected.getCorrectionDecl(); + R.clear(); + if (ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) { + std::string CorrectedStr( + Corrected.getAsString(SemaRef.getLangOptions())); + std::string CorrectedQuotedStr( + Corrected.getQuoted(SemaRef.getLangOptions())); + R.setLookupName(Corrected.getCorrection()); + R.addDecl(ND); SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << DC << R.getLookupName() << SS.getRange() - << FixItHint::CreateReplacement(R.getNameLoc(), - R.getLookupName().getAsString()); - if (NamedDecl *ND = R.getAsSingle<NamedDecl>()) - SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) - << ND->getDeclName(); - return false; - } else { - R.clear(); - R.setLookupName(Name); + << Name << DC << CorrectedQuotedStr << SS.getRange() + << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr); + SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); } return false; @@ -1068,10 +1072,10 @@ Sema::LookupMemberExpr(LookupResult &R, ExprResult &BaseExpr, // Attempt to correct for typos in ivar names. LookupResult Res(*this, R.getLookupName(), R.getNameLoc(), LookupMemberName); - if (CorrectTypo(Res, 0, 0, IDecl, false, - IsArrow ? CTC_ObjCIvarLookup - : CTC_ObjCPropertyLookup) && - (IV = Res.getAsSingle<ObjCIvarDecl>())) { + TypoCorrection Corrected = CorrectTypo( + R.getLookupNameInfo(), LookupMemberName, NULL, NULL, IDecl, false, + IsArrow ? CTC_ObjCIvarLookup : CTC_ObjCPropertyLookup); + if ((IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>())) { Diag(R.getNameLoc(), diag::err_typecheck_member_reference_ivar_suggest) << IDecl->getDeclName() << MemberName << IV->getDeclName() diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 80d3a7451d..c02b634547 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -663,14 +663,15 @@ HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, } // Attempt to correct for typos in property names. - LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName); - if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) && - Res.getAsSingle<ObjCPropertyDecl>()) { - DeclarationName TypoResult = Res.getLookupName(); + TypoCorrection Corrected = CorrectTypo( + DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL, + NULL, IFace, false, CTC_NoKeywords, OPT); + if (ObjCPropertyDecl *Property = + Corrected.getCorrectionDeclAs<ObjCPropertyDecl>()) { + DeclarationName TypoResult = Corrected.getCorrection(); Diag(MemberLoc, diag::err_property_not_found_suggest) << MemberName << QualType(OPT, 0) << TypoResult << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString()); - ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>(); Diag(Property->getLocation(), diag::note_previous_decl) << Property->getDeclName(); return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc, @@ -898,29 +899,30 @@ Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S, Method->getClassInterface()->getSuperClass()) CTC = CTC_ObjCMessageReceiver; - if (DeclarationName Corrected = CorrectTypo(Result, S, 0, 0, false, CTC)) { - if (Result.isSingleResult()) { + if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(), + Result.getLookupKind(), S, NULL, + NULL, false, CTC)) { + if (NamedDecl *ND = Corrected.getCorrectionDecl()) { // If we found a declaration, correct when it refers to an Objective-C // class. - NamedDecl *ND = Result.getFoundDecl(); if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) { Diag(NameLoc, diag::err_unknown_receiver_suggest) - << Name << Result.getLookupName() + << Name << Corrected.getCorrection() << FixItHint::CreateReplacement(SourceRange(NameLoc), ND->getNameAsString()); Diag(ND->getLocation(), diag::note_previous_decl) - << Corrected; + << Corrected.getCorrection(); QualType T = Context.getObjCInterfaceType(Class); TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc); ReceiverType = CreateParsedType(T, TSInfo); return ObjCClassMessage; } - } else if (Result.empty() && Corrected.getAsIdentifierInfo() && - Corrected.getAsIdentifierInfo()->isStr("super")) { + } else if (Corrected.isKeyword() && + Corrected.getCorrectionAsIdentifierInfo()->isStr("super")) { // If we've found the keyword "super", this is a send to super. Diag(NameLoc, diag::err_unknown_receiver_suggest) - << Name << Corrected + << Name << Corrected.getCorrection() << FixItHint::CreateReplacement(SourceRange(NameLoc), "super"); return ObjCSuperMessage; } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 16ba2a2910..da20e0e8fd 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1443,19 +1443,23 @@ InitListChecker::CheckDesignatedInitializer(const InitializedEntity &Entity, // was a typo for another field name. LookupResult R(SemaRef, FieldName, D->getFieldLoc(), Sema::LookupMemberName); - if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false, - Sema::CTC_NoKeywords) && - (ReplacementField = R.getAsSingle<FieldDecl>()) && + TypoCorrection Corrected = SemaRef.CorrectTypo( + DeclarationNameInfo(FieldName, D->getFieldLoc()), + Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL, + RT->getDecl(), false, Sema::CTC_NoKeywords); + if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) && ReplacementField->getDeclContext()->getRedeclContext() ->Equals(RT->getDecl())) { + std::string CorrectedStr( + Corrected.getAsString(SemaRef.getLangOptions())); + std::string CorrectedQuotedStr( + Corrected.getQuoted(SemaRef.getLangOptions())); SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown_suggest) - << FieldName << CurrentObjectType << R.getLookupName() - << FixItHint::CreateReplacement(D->getFieldLoc(), - R.getLookupName().getAsString()); + << FieldName << CurrentObjectType << CorrectedQuotedStr + << FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr); SemaR |