<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Please disregard. Looks as if an overlapping failure is causing the problem.<div><br><div><div>On Jun 28, 2011, at 12:36 PM, Chad Rosier wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">Doug,<div>I believe this is causing a make failure due to:</div><div><span class="Apple-style-span" style="font-family: Times; "><pre style="font-family: 'Courier New', courier, monotype; "><span class="stdout" style="font-family: 'Courier New', courier, monotype; color: black; ">llvm[4]: Compiling ASTLocation.cpp for Release+Asserts build
</span><span class="stderr" style="font-family: 'Courier New', courier, monotype; color: red; ">/usr/include/c++/4.2.1/bits/stl_map.h: In member function '_Tp& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](const _Key&) [with _Key = unsigned int, _Tp = llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator>, _Compare = std::less<unsigned int>, _Alloc = std::allocator<std::pair<const unsigned int, llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator> > >]':
/lib/Sema/SemaLookup.cpp:3170: instantiated from here
/usr/include/c++/4.2.1/bits/stl_map.h:350: error: no matching function for call to 'llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator>::StringMap(llvm::StringMap<clang::TypoCorrection, llvm::BumpPtrAllocator>)'</span></pre></span><div>Please take a look.</div></div><div><br></div><div>Chad</div><div><br><div><div>On Jun 28, 2011, at 9:20 AM, Douglas Gregor wrote:</div><br class="Apple-interchange-newline"><blockquote type="cite"><div>Author: dgregor<br>Date: Tue Jun 28 11:20:02 2011<br>New Revision: 134007<br><br>URL: <a href="http://llvm.org/viewvc/llvm-project?rev=134007&view=rev">http://llvm.org/viewvc/llvm-project?rev=134007&view=rev</a><br>Log:<br>Add support for C++ namespace-aware typo correction, e.g., correcting<br><br> vector<int><br><br>to<br><br> std::vector<int><br><br>Patch by Kaelyn Uhrain, with minor tweaks + PCH support from me. Fixes<br>PR5776/<<a href="rdar://problem/8652971">rdar://problem/8652971</a>>.<br><br>Thanks Kaelyn!<br><br>Added:<br> cfe/trunk/include/clang/Sema/TypoCorrection.h (with props)<br> cfe/trunk/test/PCH/Inputs/typo.hpp (with props)<br> cfe/trunk/test/PCH/typo.cpp (with props)<br> cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp (with props)<br>Modified:<br> cfe/trunk/include/clang/Sema/ExternalSemaSource.h<br> cfe/trunk/include/clang/Sema/Sema.h<br> cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br> cfe/trunk/include/clang/Serialization/ASTReader.h<br> cfe/trunk/lib/Sema/Sema.cpp<br> cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp<br> cfe/trunk/lib/Sema/SemaDecl.cpp<br> cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br> cfe/trunk/lib/Sema/SemaDeclObjC.cpp<br> cfe/trunk/lib/Sema/SemaExpr.cpp<br> cfe/trunk/lib/Sema/SemaExprMember.cpp<br> cfe/trunk/lib/Sema/SemaExprObjC.cpp<br> cfe/trunk/lib/Sema/SemaInit.cpp<br> cfe/trunk/lib/Sema/SemaLookup.cpp<br> cfe/trunk/lib/Sema/SemaTemplate.cpp<br> cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp<br> cfe/trunk/lib/Serialization/ASTReader.cpp<br> cfe/trunk/lib/Serialization/ASTWriter.cpp<br> cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp<br> cfe/trunk/test/FixIt/typo.cpp<br> cfe/trunk/test/SemaObjC/ivar-ref-misuse.m<br><br>Modified: cfe/trunk/include/clang/Sema/ExternalSemaSource.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ExternalSemaSource.h?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/ExternalSemaSource.h?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Sema/ExternalSemaSource.h (original)<br>+++ cfe/trunk/include/clang/Sema/ExternalSemaSource.h Tue Jun 28 11:20:02 2011<br>@@ -49,6 +49,11 @@<br> /// instance and factory methods, respectively, with this selector.<br> virtual std::pair<ObjCMethodList,ObjCMethodList> ReadMethodPool(Selector Sel);<br><br>+ /// \brief Load the set of namespaces that are known to the external source,<br>+ /// which will be used during typo correction.<br>+ virtual void ReadKnownNamespaces(<br>+ llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces);<br>+ <br> /// \brief Do last resort, unqualified lookup on a LookupResult that<br> /// Sema cannot find.<br> ///<br><br>Modified: cfe/trunk/include/clang/Sema/Sema.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Sema/Sema.h (original)<br>+++ cfe/trunk/include/clang/Sema/Sema.h Tue Jun 28 11:20:02 2011<br>@@ -21,6 +21,7 @@<br> #include "clang/Sema/ObjCMethodList.h"<br> #include "clang/Sema/DeclSpec.h"<br> #include "clang/Sema/LocInfoType.h"<br>+#include "clang/Sema/TypoCorrection.h"<br> #include "clang/AST/Expr.h"<br> #include "clang/AST/DeclarationName.h"<br> #include "clang/AST/ExternalASTSource.h"<br>@@ -46,6 +47,8 @@<br> class ASTConsumer;<br> class ASTContext;<br> class ASTMutationListener;<br>+ class ASTReader;<br>+ class ASTWriter;<br> class ArrayType;<br> class AttributeList;<br> class BlockDecl;<br>@@ -1623,6 +1626,16 @@<br> bool ConstThis,<br> bool VolatileThis);<br><br>+ // \brief The set of known/encountered (unique, canonicalized) NamespaceDecls.<br>+ //<br>+ // The boolean value will be true to indicate that the namespace was loaded<br>+ // from an AST/PCH file, or false otherwise.<br>+ llvm::DenseMap<NamespaceDecl*, bool> KnownNamespaces;<br>+<br>+ /// \brief Whether we have already loaded known namespaces from an extenal<br>+ /// source.<br>+ bool LoadedExternalKnownNamespaces;<br>+ <br> public:<br> /// \brief Look up a name, looking for a single declaration. Return<br> /// null if the results were absent, ambiguous, or overloaded.<br>@@ -1699,11 +1712,13 @@<br> CTC_ObjCMessageReceiver<br> };<br><br>- DeclarationName CorrectTypo(LookupResult &R, Scope *S, CXXScopeSpec *SS,<br>- DeclContext *MemberContext = 0,<br>- bool EnteringContext = false,<br>- CorrectTypoContext CTC = CTC_Unknown,<br>- const ObjCObjectPointerType *OPT = 0);<br>+ TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo,<br>+ Sema::LookupNameKind LookupKind,<br>+ Scope *S, CXXScopeSpec *SS,<br>+ DeclContext *MemberContext = NULL,<br>+ bool EnteringContext = false,<br>+ CorrectTypoContext CTC = CTC_Unknown,<br>+ const ObjCObjectPointerType *OPT = NULL);<br><br> void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,<br> AssociatedNamespaceSet &AssociatedNamespaces,<br>@@ -4721,7 +4736,7 @@<br> /// \brief The number of typos corrected by CorrectTypo.<br> unsigned TyposCorrected;<br><br>- typedef llvm::DenseMap<IdentifierInfo *, std::pair<llvm::StringRef, bool> ><br>+ typedef llvm::DenseMap<IdentifierInfo *, TypoCorrection><br> UnqualifiedTyposCorrectedMap;<br><br> /// \brief A cache containing the results of typo correction for unqualified<br>@@ -5918,6 +5933,8 @@<br> protected:<br> friend class Parser;<br> friend class InitializationSequence; <br>+ friend class ASTReader;<br>+ friend class ASTWriter;<br><br> public:<br> /// \brief Retrieve the parser's current scope.<br><br>Added: cfe/trunk/include/clang/Sema/TypoCorrection.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TypoCorrection.h?rev=134007&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/TypoCorrection.h?rev=134007&view=auto</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Sema/TypoCorrection.h (added)<br>+++ cfe/trunk/include/clang/Sema/TypoCorrection.h Tue Jun 28 11:20:02 2011<br>@@ -0,0 +1,105 @@<br>+//===--- TypoCorrection.h - Class for typo correction results ---*- C++ -*-===//<br>+//<br>+// The LLVM Compiler Infrastructure<br>+//<br>+// This file is distributed under the University of Illinois Open Source<br>+// License. See LICENSE.TXT for details.<br>+//<br>+//===----------------------------------------------------------------------===//<br>+//<br>+// This file defines the TypoCorrection class, which stores the results of<br>+// Sema's typo correction (Sema::CorrectTypo).<br>+//<br>+//===----------------------------------------------------------------------===//<br>+<br>+#ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H<br>+#define LLVM_CLANG_SEMA_TYPOCORRECTION_H<br>+<br>+#include "clang/AST/DeclCXX.h"<br>+<br>+namespace clang {<br>+<br>+/// @brief Simple class containing the result of Sema::CorrectTypo<br>+class TypoCorrection {<br>+public:<br>+ TypoCorrection(const DeclarationName &Name, NamedDecl *NameDecl,<br>+ NestedNameSpecifier *NNS=NULL, unsigned distance=0)<br>+ : CorrectionName(Name),<br>+ CorrectionNameSpec(NNS),<br>+ CorrectionDecl(NameDecl),<br>+ EditDistance(distance) {}<br>+<br>+ TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS=NULL,<br>+ unsigned distance=0)<br>+ : CorrectionName(Name->getDeclName()),<br>+ CorrectionNameSpec(NNS),<br>+ CorrectionDecl(Name),<br>+ EditDistance(distance) {}<br>+<br>+ TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS=NULL,<br>+ unsigned distance=0)<br>+ : CorrectionName(Name),<br>+ CorrectionNameSpec(NNS),<br>+ CorrectionDecl(NULL),<br>+ EditDistance(distance) {}<br>+<br>+ TypoCorrection()<br>+ : CorrectionName(), CorrectionNameSpec(NULL), CorrectionDecl(NULL),<br>+ EditDistance(0) {}<br>+<br>+ /// \brief Gets the DeclarationName of the typo correction<br>+ DeclarationName getCorrection() const { return CorrectionName; }<br>+ IdentifierInfo* getCorrectionAsIdentifierInfo() const {<br>+ return CorrectionName.getAsIdentifierInfo();<br>+ }<br>+<br>+ /// \brief Gets the NestedNameSpecifier needed to use the typo correction<br>+ NestedNameSpecifier* getCorrectionSpecifier() const {<br>+ return CorrectionNameSpec;<br>+ }<br>+ void setCorrectionSpecifier(NestedNameSpecifier* NNS) {<br>+ CorrectionNameSpec = NNS;<br>+ }<br>+<br>+ /// \brief Gets the "edit distance" of the typo correction from the typo<br>+ unsigned getEditDistance() const { return EditDistance; }<br>+<br>+ /// \brief Gets the pointer to the declaration of the typo correction<br>+ NamedDecl* getCorrectionDecl() const {<br>+ return isKeyword() ? NULL : CorrectionDecl;<br>+ }<br>+ template <class DeclClass><br>+ DeclClass *getCorrectionDeclAs() const {<br>+ return dyn_cast_or_null<DeclClass>(getCorrectionDecl());<br>+ }<br>+ <br>+ void setCorrectionDecl(NamedDecl *CDecl) {<br>+ CorrectionDecl = CDecl;<br>+ if (!CorrectionName)<br>+ CorrectionName = CDecl->getDeclName();<br>+ }<br>+<br>+ std::string getAsString(const LangOptions &LO) const;<br>+ std::string getQuoted(const LangOptions &LO) const {<br>+ return "'" + getAsString(LO) + "'";<br>+ }<br>+<br>+ operator bool() const { return bool(CorrectionName); }<br>+<br>+ static inline NamedDecl *KeywordDecl() { return (NamedDecl*)-1; }<br>+ bool isKeyword() const { return CorrectionDecl == KeywordDecl(); }<br>+<br>+ // Returns true if the correction either is a keyword or has a known decl.<br>+ bool isResolved() const { return CorrectionDecl != NULL; }<br>+<br>+private:<br>+ // Results.<br>+ DeclarationName CorrectionName;<br>+ NestedNameSpecifier *CorrectionNameSpec;<br>+ NamedDecl *CorrectionDecl;<br>+ unsigned EditDistance;<br>+};<br>+<br>+}<br>+<br>+#endif<br><br>Propchange: cfe/trunk/include/clang/Sema/TypoCorrection.h<br>------------------------------------------------------------------------------<br> svn:eol-style = native<br><br>Propchange: cfe/trunk/include/clang/Sema/TypoCorrection.h<br>------------------------------------------------------------------------------<br> svn:keywords = Id<br><br>Propchange: cfe/trunk/include/clang/Sema/TypoCorrection.h<br>------------------------------------------------------------------------------<br> svn:mime-type = text/plain<br><br>Modified: cfe/trunk/include/clang/Serialization/ASTBitCodes.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTBitCodes.h?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Serialization/ASTBitCodes.h (original)<br>+++ cfe/trunk/include/clang/Serialization/ASTBitCodes.h Tue Jun 28 11:20:02 2011<br>@@ -371,7 +371,11 @@<br><br> /// \brief Record code for the table of offsets into the block<br> /// of file source-location information.<br>- FILE_SOURCE_LOCATION_OFFSETS = 45<br>+ FILE_SOURCE_LOCATION_OFFSETS = 45,<br>+ <br>+ /// \brief Record code for the set of known namespaces, which are used<br>+ /// for typo correction.<br>+ KNOWN_NAMESPACES = 46<br><br> };<br><br><br>Modified: cfe/trunk/include/clang/Serialization/ASTReader.h<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)<br>+++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Jun 28 11:20:02 2011<br>@@ -625,6 +625,9 @@<br> /// \brief The OpenCL extension settings.<br> llvm::SmallVector<uint64_t, 1> OpenCLExtensions;<br><br>+ /// \brief A list of the namespaces we've seen.<br>+ llvm::SmallVector<uint64_t, 4> KnownNamespaces;<br>+<br> //@}<br><br> /// \brief Diagnostic IDs and their mappings that the user changed.<br>@@ -1125,6 +1128,11 @@<br> virtual std::pair<ObjCMethodList, ObjCMethodList><br> ReadMethodPool(Selector Sel);<br><br>+ /// \brief Load the set of namespaces that are known to the external source,<br>+ /// which will be used during typo correction.<br>+ virtual void ReadKnownNamespaces(<br>+ llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces);<br>+<br> /// \brief Load a selector from disk, registering its ID if it exists.<br> void LoadSelector(Selector Sel);<br><br><br>Modified: cfe/trunk/lib/Sema/Sema.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/Sema.cpp (original)<br>+++ cfe/trunk/lib/Sema/Sema.cpp Tue Jun 28 11:20:02 2011<br>@@ -154,6 +154,8 @@<br> AnalysisWarnings(*this)<br> {<br> TUScope = 0;<br>+ LoadedExternalKnownNamespaces = false;<br>+ <br> if (getLangOptions().CPlusPlus)<br> FieldCollector.reset(new CXXFieldCollector());<br><br>@@ -778,6 +780,10 @@<br> return std::pair<ObjCMethodList, ObjCMethodList>();<br> }<br><br>+void ExternalSemaSource::ReadKnownNamespaces(<br>+ llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces) { <br>+}<br>+<br> void PrettyDeclStackTraceEntry::print(llvm::raw_ostream &OS) const {<br> SourceLocation Loc = this->Loc;<br> if (!Loc.isValid() && TheDecl) Loc = TheDecl->getLocation();<br><br>Modified: cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaCXXScopeSpec.cpp Tue Jun 28 11:20:02 2011<br>@@ -464,26 +464,29 @@<br> // We haven't found anything, and we're not recovering from a<br> // different kind of error, so look for typos.<br> DeclarationName Name = Found.getLookupName();<br>- if (CorrectTypo(Found, S, &SS, LookupCtx, EnteringContext, <br>- CTC_NoKeywords) &&<br>- Found.isSingleResult() &&<br>- isAcceptableNestedNameSpecifier(Found.getAsSingle<NamedDecl>())) {<br>+ TypoCorrection Corrected;<br>+ Found.clear();<br>+ if ((Corrected = CorrectTypo(Found.getLookupNameInfo(),<br>+ Found.getLookupKind(), S, &SS, LookupCtx,<br>+ EnteringContext, CTC_NoKeywords)) &&<br>+ isAcceptableNestedNameSpecifier(Corrected.getCorrectionDecl())) {<br>+ std::string CorrectedStr(Corrected.getAsString(getLangOptions()));<br>+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));<br> if (LookupCtx)<br> Diag(Found.getNameLoc(), diag::err_no_member_suggest)<br>- << Name << LookupCtx << Found.getLookupName() << SS.getRange()<br>- << FixItHint::CreateReplacement(Found.getNameLoc(),<br>- Found.getLookupName().getAsString());<br>+ << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()<br>+ << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);<br> else<br> Diag(Found.getNameLoc(), diag::err_undeclared_var_use_suggest)<br>- << Name << Found.getLookupName()<br>- << FixItHint::CreateReplacement(Found.getNameLoc(),<br>- Found.getLookupName().getAsString());<br>+ << Name << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);<br><br>- if (NamedDecl *ND = Found.getAsSingle<NamedDecl>())<br>- Diag(ND->getLocation(), diag::note_previous_decl)<br>- << ND->getDeclName();<br>+ if (NamedDecl *ND = Corrected.getCorrectionDecl()) {<br>+ Diag(ND->getLocation(), diag::note_previous_decl) << CorrectedQuotedStr;<br>+ Found.addDecl(ND);<br>+ }<br>+ Found.setLookupName(Corrected.getCorrection());<br> } else {<br>- Found.clear();<br> Found.setLookupName(&Identifier);<br> }<br> }<br><br>Modified: cfe/trunk/lib/Sema/SemaDecl.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaDecl.cpp Tue Jun 28 11:20:02 2011<br>@@ -287,41 +287,42 @@<br><br> // There may have been a typo in the name of the type. Look up typo<br> // results, in case we have something that we can suggest.<br>- LookupResult Lookup(*this, &II, IILoc, LookupOrdinaryName, <br>- NotForRedeclaration);<br>+ if (TypoCorrection Corrected = CorrectTypo(DeclarationNameInfo(&II, IILoc),<br>+ LookupOrdinaryName, S, SS, NULL,<br>+ false, CTC_Type)) {<br>+ std::string CorrectedStr(Corrected.getAsString(getLangOptions()));<br>+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));<br><br>- if (DeclarationName Corrected = CorrectTypo(Lookup, S, SS, 0, 0, CTC_Type)) {<br>- if (NamedDecl *Result = Lookup.getAsSingle<NamedDecl>()) {<br>+ if (Corrected.isKeyword()) {<br>+ // We corrected to a keyword.<br>+ // FIXME: Actually recover with the keyword we suggest, and emit a fix-it.<br>+ Diag(IILoc, diag::err_unknown_typename_suggest)<br>+ << &II << CorrectedQuotedStr;<br>+ return true; <br>+ } else {<br>+ NamedDecl *Result = Corrected.getCorrectionDecl();<br> if ((isa<TypeDecl>(Result) || isa<ObjCInterfaceDecl>(Result)) &&<br> !Result->isInvalidDecl()) {<br> // We found a similarly-named type or interface; suggest that.<br> if (!SS || !SS->isSet())<br> Diag(IILoc, diag::err_unknown_typename_suggest)<br>- << &II << Lookup.getLookupName()<br>- << FixItHint::CreateReplacement(SourceRange(IILoc),<br>- Result->getNameAsString());<br>+ << &II << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);<br> else if (DeclContext *DC = computeDeclContext(*SS, false))<br> Diag(IILoc, diag::err_unknown_nested_typename_suggest) <br>- << &II << DC << Lookup.getLookupName() << SS->getRange()<br>- << FixItHint::CreateReplacement(SourceRange(IILoc),<br>- Result->getNameAsString());<br>+ << &II << DC << CorrectedQuotedStr << SS->getRange()<br>+ << FixItHint::CreateReplacement(SourceRange(IILoc), CorrectedStr);<br> else<br> llvm_unreachable("could not have corrected a typo here");<br><br> Diag(Result->getLocation(), diag::note_previous_decl)<br>- << Result->getDeclName();<br>+ << CorrectedQuotedStr;<br><br> SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS,<br> false, false, ParsedType(),<br> /*NonTrivialTypeSourceInfo=*/true);<br> return true;<br> }<br>- } else if (Lookup.empty()) {<br>- // We corrected to a keyword.<br>- // FIXME: Actually recover with the keyword we suggest, and emit a fix-it.<br>- Diag(IILoc, diag::err_unknown_typename_suggest)<br>- << &II << Corrected;<br>- return true; <br> }<br> }<br><br>@@ -509,11 +510,14 @@<br> // Perform typo correction to determine if there is another name that is<br> // close to this name.<br> if (!SecondTry) {<br>- if (DeclarationName Corrected = CorrectTypo(Result, S, &SS)) {<br>+ if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),<br>+ Result.getLookupKind(), S, &SS)) {<br> unsigned UnqualifiedDiag = diag::err_undeclared_var_use_suggest;<br> unsigned QualifiedDiag = diag::err_no_member_suggest;<br>+ std::string CorrectedStr(Corrected.getAsString(getLangOptions()));<br>+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));<br><br>- NamedDecl *FirstDecl = Result.empty()? 0 : *Result.begin();<br>+ NamedDecl *FirstDecl = Corrected.getCorrectionDecl();<br> NamedDecl *UnderlyingFirstDecl<br> = FirstDecl? FirstDecl->getUnderlyingDecl() : 0;<br> if (getLangOptions().CPlusPlus && <a href="http://NextToken.is/">NextToken.is</a>(tok::less) &&<br>@@ -528,25 +532,34 @@<br> QualifiedDiag = diag::err_unknown_nested_typename_suggest;<br> }<br><br>+ if (Corrected.getCorrectionSpecifier())<br>+ SS.MakeTrivial(Context, Corrected.getCorrectionSpecifier(), SourceRange(NameLoc));<br>+<br> if (SS.isEmpty())<br> Diag(NameLoc, UnqualifiedDiag)<br>- << Name << Corrected<br>- << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString());<br>+ << Name << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(NameLoc, CorrectedStr);<br> else<br> Diag(NameLoc, QualifiedDiag)<br>- << Name << computeDeclContext(SS, false) << Corrected<br>+ << Name << computeDeclContext(SS, false) << CorrectedQuotedStr<br> << SS.getRange()<br>- << FixItHint::CreateReplacement(NameLoc, Corrected.getAsString());<br>+ << FixItHint::CreateReplacement(NameLoc, CorrectedStr);<br><br> // Update the name, so that the caller has the new name.<br>- Name = Corrected.getAsIdentifierInfo();<br>+ Name = Corrected.getCorrectionAsIdentifierInfo();<br><br>+ // Also update the LookupResult...<br>+ // FIXME: This should probably go away at some point<br>+ Result.clear();<br>+ Result.setLookupName(Corrected.getCorrection());<br>+ if (FirstDecl) Result.addDecl(FirstDecl);<br>+<br> // Typo correction corrected to a keyword.<br>- if (Result.empty())<br>- return Corrected.getAsIdentifierInfo();<br>+ if (Corrected.isKeyword())<br>+ return Corrected.getCorrectionAsIdentifierInfo();<br><br> Diag(FirstDecl->getLocation(), diag::note_previous_decl)<br>- << FirstDecl->getDeclName();<br>+ << CorrectedQuotedStr;<br><br> // If we found an Objective-C instance variable, let<br> // LookupInObjCMethod build the appropriate expression to<br>@@ -1137,17 +1150,18 @@<br> /// class could not be found.<br> ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id,<br> SourceLocation IdLoc,<br>- bool TypoCorrection) {<br>+ bool DoTypoCorrection) {<br> // The third "scope" argument is 0 since we aren't enabling lazy built-in<br> // creation from this context.<br> NamedDecl *IDecl = LookupSingleName(TUScope, Id, IdLoc, LookupOrdinaryName);<br><br>- if (!IDecl && TypoCorrection) {<br>+ if (!IDecl && DoTypoCorrection) {<br> // Perform typo correction at the given location, but only if we<br> // find an Objective-C class name.<br>- LookupResult R(*this, Id, IdLoc, LookupOrdinaryName);<br>- if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&<br>- (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {<br>+ TypoCorrection C;<br>+ if ((C = CorrectTypo(DeclarationNameInfo(Id, IdLoc), LookupOrdinaryName,<br>+ TUScope, NULL, NULL, false, CTC_NoKeywords)) &&<br>+ (IDecl = C.getCorrectionDeclAs<ObjCInterfaceDecl>())) {<br> Diag(IdLoc, diag::err_undef_interface_suggest)<br> << Id << IDecl->getDeclName() <br> << FixItHint::CreateReplacement(IdLoc, IDecl->getNameAsString());<br><br>Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jun 28 11:20:02 2011<br>@@ -1426,25 +1426,27 @@<br> }<br><br> // If no results were found, try to correct typos.<br>+ TypoCorrection Corr;<br> if (R.empty() && BaseType.isNull() &&<br>- CorrectTypo(R, S, &SS, ClassDecl, 0, CTC_NoKeywords) && <br>- R.isSingleResult()) {<br>- if (FieldDecl *Member = R.getAsSingle<FieldDecl>()) {<br>+ (Corr = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(), S, &SS,<br>+ ClassDecl, false, CTC_NoKeywords))) {<br>+ std::string CorrectedStr(Corr.getAsString(getLangOptions()));<br>+ std::string CorrectedQuotedStr(Corr.getQuoted(getLangOptions()));<br>+ if (FieldDecl *Member = Corr.getCorrectionDeclAs<FieldDecl>()) {<br> if (Member->getDeclContext()->getRedeclContext()->Equals(ClassDecl)) {<br> // We have found a non-static data member with a similar<br> // name to what was typed; complain and initialize that<br> // member.<br> Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)<br>- << MemberOrBase << true << R.getLookupName()<br>- << FixItHint::CreateReplacement(R.getNameLoc(),<br>- R.getLookupName().getAsString());<br>+ << MemberOrBase << true << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);<br> Diag(Member->getLocation(), diag::note_previous_decl)<br>- << Member->getDeclName();<br>+ << CorrectedQuotedStr;<br><br> return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc,<br> LParenLoc, RParenLoc);<br> }<br>- } else if (TypeDecl *Type = R.getAsSingle<TypeDecl>()) {<br>+ } else if (TypeDecl *Type = Corr.getCorrectionDeclAs<TypeDecl>()) {<br> const CXXBaseSpecifier *DirectBaseSpec;<br> const CXXBaseSpecifier *VirtualBaseSpec;<br> if (FindBaseInitializer(*this, ClassDecl, <br>@@ -1454,9 +1456,8 @@<br> // similar name to what was typed; complain and initialize<br> // that base class.<br> Diag(R.getNameLoc(), diag::err_mem_init_not_member_or_class_suggest)<br>- << MemberOrBase << false << R.getLookupName()<br>- << FixItHint::CreateReplacement(R.getNameLoc(),<br>- R.getLookupName().getAsString());<br>+ << MemberOrBase << false << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);<br><br> const CXXBaseSpecifier *BaseSpec = DirectBaseSpec? DirectBaseSpec <br> : VirtualBaseSpec;<br>@@ -4706,6 +4707,13 @@<br> // Make our StdNamespace cache point at the first real definition of the<br> // "std" namespace.<br> StdNamespace = Namespc;<br>+<br>+ // Add this instance of "std" to the set of known namespaces<br>+ KnownNamespaces[Namespc] = false;<br>+ } else if (!Namespc->isInline()) {<br>+ // Since this is an "original" namespace, add it to the known set of<br>+ // namespaces if it is not an inline namespace.<br>+ KnownNamespaces[Namespc] = false;<br> }<br><br> PushOnScopeChains(Namespc, DeclRegionScope);<br>@@ -4841,6 +4849,39 @@<br> }<br> }<br><br>+static bool TryNamespaceTypoCorrection(Sema &S, LookupResult &R, Scope *Sc,<br>+ CXXScopeSpec &SS,<br>+ SourceLocation IdentLoc,<br>+ IdentifierInfo *Ident) {<br>+ R.clear();<br>+ if (TypoCorrection Corrected = S.CorrectTypo(R.getLookupNameInfo(),<br>+ R.getLookupKind(), Sc, &SS, NULL,<br>+ false, S.CTC_NoKeywords, NULL)) {<br>+ if (Corrected.getCorrectionDeclAs<NamespaceDecl>() ||<br>+ Corrected.getCorrectionDeclAs<NamespaceAliasDecl>()) {<br>+ std::string CorrectedStr(Corrected.getAsString(S.getLangOptions()));<br>+ std::string CorrectedQuotedStr(Corrected.getQuoted(S.getLangOptions()));<br>+ if (DeclContext *DC = S.computeDeclContext(SS, false))<br>+ S.Diag(IdentLoc, diag::err_using_directive_member_suggest)<br>+ << Ident << DC << CorrectedQuotedStr << SS.getRange()<br>+ << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);<br>+ else<br>+ S.Diag(IdentLoc, diag::err_using_directive_suggest)<br>+ << Ident << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(IdentLoc, CorrectedStr);<br>+<br>+ S.Diag(Corrected.getCorrectionDecl()->getLocation(),<br>+ diag::note_namespace_defined_here) << CorrectedQuotedStr;<br>+<br>+ Ident = Corrected.getCorrectionAsIdentifierInfo();<br>+ R.addDecl(Corrected.getCorrectionDecl());<br>+ return true;<br>+ }<br>+ R.setLookupName(Ident);<br>+ }<br>+ return false;<br>+}<br>+<br> Decl *Sema::ActOnUsingDirective(Scope *S,<br> SourceLocation UsingLoc,<br> SourceLocation NamespcLoc,<br>@@ -4869,6 +4910,7 @@<br> return 0;<br><br> if (R.empty()) {<br>+ R.clear();<br> // Allow "using namespace std;" or "using namespace ::std;" even if <br> // "std" hasn't been defined yet, for GCC compatibility.<br> if ((!Qualifier || Qualifier->getKind() == NestedNameSpecifier::Global) &&<br>@@ -4878,27 +4920,7 @@<br> R.resolveKind();<br> } <br> // Otherwise, attempt typo correction.<br>- else if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, <br>- CTC_NoKeywords, 0)) {<br>- if (R.getAsSingle<NamespaceDecl>() || <br>- R.getAsSingle<NamespaceAliasDecl>()) {<br>- if (DeclContext *DC = computeDeclContext(SS, false))<br>- Diag(IdentLoc, diag::err_using_directive_member_suggest)<br>- << NamespcName << DC << Corrected << SS.getRange()<br>- << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); <br>- else<br>- Diag(IdentLoc, diag::err_using_directive_suggest)<br>- << NamespcName << Corrected<br>- << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());<br>- Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)<br>- << Corrected;<br>- <br>- NamespcName = Corrected.getAsIdentifierInfo();<br>- } else {<br>- R.clear();<br>- R.setLookupName(NamespcName);<br>- }<br>- }<br>+ else TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, NamespcName);<br> }<br><br> if (!R.empty()) {<br>@@ -5816,30 +5838,7 @@<br> return 0;<br><br> if (R.empty()) {<br>- if (DeclarationName Corrected = CorrectTypo(R, S, &SS, 0, false, <br>- CTC_NoKeywords, 0)) {<br>- if (R.getAsSingle<NamespaceDecl>() || <br>- R.getAsSingle<NamespaceAliasDecl>()) {<br>- if (DeclContext *DC = computeDeclContext(SS, false))<br>- Diag(IdentLoc, diag::err_using_directive_member_suggest)<br>- << Ident << DC << Corrected << SS.getRange()<br>- << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString()); <br>- else<br>- Diag(IdentLoc, diag::err_using_directive_suggest)<br>- << Ident << Corrected<br>- << FixItHint::CreateReplacement(IdentLoc, Corrected.getAsString());<br>- <br>- Diag(R.getFoundDecl()->getLocation(), diag::note_namespace_defined_here)<br>- << Corrected;<br>- <br>- Ident = Corrected.getAsIdentifierInfo();<br>- } else {<br>- R.clear();<br>- R.setLookupName(Ident);<br>- }<br>- }<br>- <br>- if (R.empty()) {<br>+ if (!TryNamespaceTypoCorrection(*this, R, S, SS, IdentLoc, Ident)) {<br> Diag(NamespaceLoc, diag::err_expected_namespace_name) << SS.getRange();<br> return 0;<br> }<br><br>Modified: cfe/trunk/lib/Sema/SemaDeclObjC.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclObjC.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaDeclObjC.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaDeclObjC.cpp Tue Jun 28 11:20:02 2011<br>@@ -442,9 +442,10 @@<br><br> if (!PrevDecl) {<br> // Try to correct for a typo in the superclass name.<br>- LookupResult R(*this, SuperName, SuperLoc, LookupOrdinaryName);<br>- if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&<br>- (PrevDecl = R.getAsSingle<ObjCInterfaceDecl>())) {<br>+ TypoCorrection Corrected = CorrectTypo(<br>+ DeclarationNameInfo(SuperName, SuperLoc), LookupOrdinaryName, TUScope,<br>+ NULL, NULL, false, CTC_NoKeywords);<br>+ if ((PrevDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {<br> Diag(SuperLoc, diag::err_undef_superclass_suggest)<br> << SuperName << ClassName << PrevDecl->getDeclName();<br> Diag(PrevDecl->getLocation(), diag::note_previous_decl)<br>@@ -655,12 +656,12 @@<br> ObjCProtocolDecl *PDecl = LookupProtocol(ProtocolId[i].first,<br> ProtocolId[i].second);<br> if (!PDecl) {<br>- LookupResult R(*this, ProtocolId[i].first, ProtocolId[i].second,<br>- LookupObjCProtocolName);<br>- if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&<br>- (PDecl = R.getAsSingle<ObjCProtocolDecl>())) {<br>+ TypoCorrection Corrected = CorrectTypo(<br>+ DeclarationNameInfo(ProtocolId[i].first, ProtocolId[i].second),<br>+ LookupObjCProtocolName, TUScope, NULL, NULL, false, CTC_NoKeywords);<br>+ if ((PDecl = Corrected.getCorrectionDeclAs<ObjCProtocolDecl>())) {<br> Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest)<br>- << ProtocolId[i].first << R.getLookupName();<br>+ << ProtocolId[i].first << Corrected.getCorrection();<br> Diag(PDecl->getLocation(), diag::note_previous_decl)<br> << PDecl->getDeclName();<br> }<br>@@ -897,20 +898,20 @@<br> } else {<br> // We did not find anything with the name ClassName; try to correct for <br> // typos in the class name.<br>- LookupResult R(*this, ClassName, ClassLoc, LookupOrdinaryName);<br>- if (CorrectTypo(R, TUScope, 0, 0, false, CTC_NoKeywords) &&<br>- (IDecl = R.getAsSingle<ObjCInterfaceDecl>())) {<br>+ TypoCorrection Corrected = CorrectTypo(<br>+ DeclarationNameInfo(ClassName, ClassLoc), LookupOrdinaryName, TUScope,<br>+ NULL, NULL, false, CTC_NoKeywords);<br>+ if ((IDecl = Corrected.getCorrectionDeclAs<ObjCInterfaceDecl>())) {<br> // Suggest the (potentially) correct interface name. However, put the<br> // fix-it hint itself in a separate note, since changing the name in <br> // the warning would make the fix-it change semantics.However, don't<br> // provide a code-modification hint or use the typo name for recovery,<br> // because this is just a warning. The program may actually be correct.<br>+ DeclarationName CorrectedName = Corrected.getCorrection();<br> Diag(ClassLoc, diag::warn_undef_interface_suggest)<br>- << ClassName << R.getLookupName();<br>- Diag(IDecl->getLocation(), diag::note_previous_decl)<br>- << R.getLookupName()<br>- << FixItHint::CreateReplacement(ClassLoc,<br>- R.getLookupName().getAsString());<br>+ << ClassName << CorrectedName;<br>+ Diag(IDecl->getLocation(), diag::note_previous_decl) << CorrectedName<br>+ << FixItHint::CreateReplacement(ClassLoc, CorrectedName.getAsString());<br> IDecl = 0;<br> } else {<br> Diag(ClassLoc, diag::warn_undef_interface) << ClassName;<br><br>Modified: cfe/trunk/lib/Sema/SemaExpr.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaExpr.cpp Tue Jun 28 11:20:02 2011<br>@@ -1397,39 +1397,44 @@<br> }<br><br> // We didn't find anything, so try to correct for a typo.<br>- DeclarationName Corrected;<br>- if (S && (Corrected = CorrectTypo(R, S, &SS, 0, false, CTC))) {<br>- if (!R.empty()) {<br>- if (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin())) {<br>+ TypoCorrection Corrected;<br>+ if (S && (Corrected = CorrectTypo(R.getLookupNameInfo(), R.getLookupKind(),<br>+ S, &SS, NULL, false, CTC))) {<br>+ std::string CorrectedStr(Corrected.getAsString(getLangOptions()));<br>+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));<br>+ R.setLookupName(Corrected.getCorrection());<br>+<br>+ if (!Corrected.isKeyword()) {<br>+ NamedDecl *ND = Corrected.getCorrectionDecl();<br>+ R.addDecl(ND);<br>+ if (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND)) {<br> if (SS.isEmpty())<br>- Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName()<br>- << FixItHint::CreateReplacement(R.getNameLoc(),<br>- R.getLookupName().getAsString());<br>+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);<br> else<br> Diag(R.getNameLoc(), diag::err_no_member_suggest)<br>- << Name << computeDeclContext(SS, false) << R.getLookupName()<br>+ << Name << computeDeclContext(SS, false) << CorrectedQuotedStr<br> << SS.getRange()<br>- << FixItHint::CreateReplacement(R.getNameLoc(),<br>- R.getLookupName().getAsString());<br>- if (NamedDecl *ND = R.getAsSingle<NamedDecl>())<br>+ << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);<br>+ if (ND)<br> Diag(ND->getLocation(), diag::note_previous_decl)<br>- << ND->getDeclName();<br>+ << CorrectedQuotedStr;<br><br> // Tell the callee to try to recover.<br> return false;<br> }<br><br>- if (isa<TypeDecl>(*R.begin()) || isa<ObjCInterfaceDecl>(*R.begin())) {<br>+ if (isa<TypeDecl>(ND) || isa<ObjCInterfaceDecl>(ND)) {<br> // FIXME: If we ended up with a typo for a type name or<br> // Objective-C class name, we're in trouble because the parser<br> // is in the wrong place to recover. Suggest the typo<br> // correction, but don't make it a fix-it since we're not going<br> // to recover well anyway.<br> if (SS.isEmpty())<br>- Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName();<br>+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;<br> else<br> Diag(R.getNameLoc(), diag::err_no_member_suggest)<br>- << Name << computeDeclContext(SS, false) << R.getLookupName()<br>+ << Name << computeDeclContext(SS, false) << CorrectedQuotedStr<br> << SS.getRange();<br><br> // Don't try to recover; it won't work.<br>@@ -1439,15 +1444,15 @@<br> // FIXME: We found a keyword. Suggest it, but don't provide a fix-it<br> // because we aren't able to recover.<br> if (SS.isEmpty())<br>- Diag(R.getNameLoc(), diagnostic_suggest) << Name << Corrected;<br>+ Diag(R.getNameLoc(), diagnostic_suggest) << Name << CorrectedQuotedStr;<br> else<br> Diag(R.getNameLoc(), diag::err_no_member_suggest)<br>- << Name << computeDeclContext(SS, false) << Corrected<br>+ << Name << computeDeclContext(SS, false) << CorrectedQuotedStr<br> << SS.getRange();<br> return true;<br> }<br>- R.clear();<br> }<br>+ R.clear();<br><br> // Emit a special diagnostic for failed member lookups.<br> // FIXME: computing the declaration context might fail here (?)<br><br>Modified: cfe/trunk/lib/Sema/SemaExprMember.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprMember.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaExprMember.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaExprMember.cpp Tue Jun 28 11:20:02 2011<br>@@ -555,20 +555,24 @@<br> // We didn't find anything with the given name, so try to correct<br> // for typos.<br> DeclarationName Name = R.getLookupName();<br>- if (SemaRef.CorrectTypo(R, 0, &SS, DC, false, Sema::CTC_MemberLookup) &&<br>- !R.empty() &&<br>- (isa<ValueDecl>(*R.begin()) || isa<FunctionTemplateDecl>(*R.begin()))) {<br>+ TypoCorrection Corrected = SemaRef.CorrectTypo(R.getLookupNameInfo(),<br>+ R.getLookupKind(), NULL,<br>+ &SS, DC, false,<br>+ Sema::CTC_MemberLookup);<br>+ NamedDecl *ND = Corrected.getCorrectionDecl();<br>+ R.clear();<br>+ if (ND && (isa<ValueDecl>(ND) || isa<FunctionTemplateDecl>(ND))) {<br>+ std::string CorrectedStr(<br>+ Corrected.getAsString(SemaRef.getLangOptions()));<br>+ std::string CorrectedQuotedStr(<br>+ Corrected.getQuoted(SemaRef.getLangOptions()));<br>+ R.setLookupName(Corrected.getCorrection());<br>+ R.addDecl(ND);<br> SemaRef.Diag(R.getNameLoc(), diag::err_no_member_suggest)<br>- << Name << DC << R.getLookupName() << SS.getRange()<br>- << FixItHint::CreateReplacement(R.getNameLoc(),<br>- R.getLookupName().getAsString());<br>- if (NamedDecl *ND = R.getAsSingle<NamedDecl>())<br>- SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)<br>- << ND->getDeclName();<br>- return false;<br>- } else {<br>- R.clear();<br>- R.setLookupName(Name);<br>+ << Name << DC << CorrectedQuotedStr << SS.getRange()<br>+ << FixItHint::CreateReplacement(R.getNameLoc(), CorrectedStr);<br>+ SemaRef.Diag(ND->getLocation(), diag::note_previous_decl)<br>+ << ND->getDeclName();<br> }<br><br> return false;<br>@@ -1068,10 +1072,10 @@<br> // Attempt to correct for typos in ivar names.<br> LookupResult Res(*this, R.getLookupName(), R.getNameLoc(),<br> LookupMemberName);<br>- if (CorrectTypo(Res, 0, 0, IDecl, false, <br>- IsArrow ? CTC_ObjCIvarLookup<br>- : CTC_ObjCPropertyLookup) &&<br>- (IV = Res.getAsSingle<ObjCIvarDecl>())) {<br>+ TypoCorrection Corrected = CorrectTypo(<br>+ R.getLookupNameInfo(), LookupMemberName, NULL, NULL, IDecl, false,<br>+ IsArrow ? CTC_ObjCIvarLookup : CTC_ObjCPropertyLookup);<br>+ if ((IV = Corrected.getCorrectionDeclAs<ObjCIvarDecl>())) {<br> Diag(R.getNameLoc(),<br> diag::err_typecheck_member_reference_ivar_suggest)<br> << IDecl->getDeclName() << MemberName << IV->getDeclName()<br><br>Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Jun 28 11:20:02 2011<br>@@ -663,14 +663,15 @@<br> }<br><br> // Attempt to correct for typos in property names.<br>- LookupResult Res(*this, MemberName, MemberLoc, LookupOrdinaryName);<br>- if (CorrectTypo(Res, 0, 0, IFace, false, CTC_NoKeywords, OPT) &&<br>- Res.getAsSingle<ObjCPropertyDecl>()) {<br>- DeclarationName TypoResult = Res.getLookupName();<br>+ TypoCorrection Corrected = CorrectTypo(<br>+ DeclarationNameInfo(MemberName, MemberLoc), LookupOrdinaryName, NULL,<br>+ NULL, IFace, false, CTC_NoKeywords, OPT);<br>+ if (ObjCPropertyDecl *Property =<br>+ Corrected.getCorrectionDeclAs<ObjCPropertyDecl>()) {<br>+ DeclarationName TypoResult = Corrected.getCorrection();<br> Diag(MemberLoc, diag::err_property_not_found_suggest)<br> << MemberName << QualType(OPT, 0) << TypoResult<br> << FixItHint::CreateReplacement(MemberLoc, TypoResult.getAsString());<br>- ObjCPropertyDecl *Property = Res.getAsSingle<ObjCPropertyDecl>();<br> Diag(Property->getLocation(), diag::note_previous_decl)<br> << Property->getDeclName();<br> return HandleExprPropertyRefExpr(OPT, BaseExpr, OpLoc,<br>@@ -898,29 +899,30 @@<br> Method->getClassInterface()->getSuperClass())<br> CTC = CTC_ObjCMessageReceiver;<br><br>- if (DeclarationName Corrected = CorrectTypo(Result, S, 0, 0, false, CTC)) {<br>- if (Result.isSingleResult()) {<br>+ if (TypoCorrection Corrected = CorrectTypo(Result.getLookupNameInfo(),<br>+ Result.getLookupKind(), S, NULL,<br>+ NULL, false, CTC)) {<br>+ if (NamedDecl *ND = Corrected.getCorrectionDecl()) {<br> // If we found a declaration, correct when it refers to an Objective-C<br> // class.<br>- NamedDecl *ND = Result.getFoundDecl();<br> if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(ND)) {<br> Diag(NameLoc, diag::err_unknown_receiver_suggest)<br>- << Name << Result.getLookupName()<br>+ << Name << Corrected.getCorrection()<br> << FixItHint::CreateReplacement(SourceRange(NameLoc),<br> ND->getNameAsString());<br> Diag(ND->getLocation(), diag::note_previous_decl)<br>- << Corrected;<br>+ << Corrected.getCorrection();<br><br> QualType T = Context.getObjCInterfaceType(Class);<br> TypeSourceInfo *TSInfo = Context.getTrivialTypeSourceInfo(T, NameLoc);<br> ReceiverType = CreateParsedType(T, TSInfo);<br> return ObjCClassMessage;<br> }<br>- } else if (Result.empty() && Corrected.getAsIdentifierInfo() &&<br>- Corrected.getAsIdentifierInfo()->isStr("super")) {<br>+ } else if (Corrected.isKeyword() &&<br>+ Corrected.getCorrectionAsIdentifierInfo()->isStr("super")) {<br> // If we've found the keyword "super", this is a send to super.<br> Diag(NameLoc, diag::err_unknown_receiver_suggest)<br>- << Name << Corrected<br>+ << Name << Corrected.getCorrection()<br> << FixItHint::CreateReplacement(SourceRange(NameLoc), "super");<br> return ObjCSuperMessage;<br> }<br><br>Modified: cfe/trunk/lib/Sema/SemaInit.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaInit.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Jun 28 11:20:02 2011<br>@@ -1443,19 +1443,23 @@<br> // was a typo for another field name.<br> LookupResult R(SemaRef, FieldName, D->getFieldLoc(),<br> Sema::LookupMemberName);<br>- if (SemaRef.CorrectTypo(R, /*Scope=*/0, /*SS=*/0, RT->getDecl(), false,<br>- Sema::CTC_NoKeywords) &&<br>- (ReplacementField = R.getAsSingle<FieldDecl>()) &&<br>+ TypoCorrection Corrected = SemaRef.CorrectTypo(<br>+ DeclarationNameInfo(FieldName, D->getFieldLoc()),<br>+ Sema::LookupMemberName, /*Scope=*/NULL, /*SS=*/NULL,<br>+ RT->getDecl(), false, Sema::CTC_NoKeywords);<br>+ if ((ReplacementField = Corrected.getCorrectionDeclAs<FieldDecl>()) &&<br> ReplacementField->getDeclContext()->getRedeclContext()<br> ->Equals(RT->getDecl())) {<br>+ std::string CorrectedStr(<br>+ Corrected.getAsString(SemaRef.getLangOptions()));<br>+ std::string CorrectedQuotedStr(<br>+ Corrected.getQuoted(SemaRef.getLangOptions()));<br> SemaRef.Diag(D->getFieldLoc(),<br> diag::err_field_designator_unknown_suggest)<br>- << FieldName << CurrentObjectType << R.getLookupName()<br>- << FixItHint::CreateReplacement(D->getFieldLoc(),<br>- R.getLookupName().getAsString());<br>+ << FieldName << CurrentObjectType << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(D->getFieldLoc(), CorrectedStr);<br> SemaRef.Diag(ReplacementField->getLocation(),<br>- diag::note_previous_decl)<br>- << ReplacementField->getDeclName();<br>+ diag::note_previous_decl) << CorrectedQuotedStr;<br> } else {<br> SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown)<br> << FieldName << CurrentObjectType;<br><br>Modified: cfe/trunk/lib/Sema/SemaLookup.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaLookup.cpp Tue Jun 28 11:20:02 2011<br>@@ -20,6 +20,7 @@<br> #include "clang/Sema/ScopeInfo.h"<br> #include "clang/Sema/TemplateDeduction.h"<br> #include "clang/Sema/ExternalSemaSource.h"<br>+#include "clang/Sema/TypoCorrection.h"<br> #include "clang/AST/ASTContext.h"<br> #include "clang/AST/CXXInheritance.h"<br> #include "clang/AST/Decl.h"<br>@@ -42,6 +43,7 @@<br> #include <iterator><br> #include <utility><br> #include <algorithm><br>+#include <map><br><br> using namespace clang;<br> using namespace sema;<br>@@ -3041,6 +3043,12 @@<br> //===----------------------------------------------------------------------===//<br><br> namespace {<br>+<br>+typedef llvm::StringMap<TypoCorrection, llvm::BumpPtrAllocator> TypoResultsMap;<br>+typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap;<br>+<br>+static const unsigned MaxTypoDistanceResultSets = 5;<br>+<br> class TypoCorrectionConsumer : public VisibleDeclConsumer {<br> /// \brief The name written that is a typo in the source.<br> llvm::StringRef Typo;<br>@@ -3048,33 +3056,47 @@<br> /// \brief The results found that have the smallest edit distance<br> /// found (so far) with the typo name.<br> ///<br>- /// The boolean value indicates whether there is a keyword with this name.<br>- llvm::StringMap<bool, llvm::BumpPtrAllocator> BestResults;<br>+ /// The pointer value being set to the current DeclContext indicates<br>+ /// whether there is a keyword with this name.<br>+ TypoEditDistanceMap BestResults;<br><br>- /// \brief The best edit distance found so far.<br>- unsigned BestEditDistance;<br>+ /// \brief The worst of the best N edit distances found so far.<br>+ unsigned MaxEditDistance;<br>+<br>+ Sema &SemaRef;<br><br> public:<br>- explicit TypoCorrectionConsumer(IdentifierInfo *Typo)<br>+ explicit TypoCorrectionConsumer(Sema &SemaRef, IdentifierInfo *Typo)<br> : Typo(Typo->getName()),<br>- BestEditDistance((std::numeric_limits<unsigned>::max)()) { }<br>+ MaxEditDistance((std::numeric_limits<unsigned>::max)()),<br>+ SemaRef(SemaRef) { }<br><br> virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);<br> void FoundName(llvm::StringRef Name);<br>- void addKeywordResult(ASTContext &Context, llvm::StringRef Keyword);<br>-<br>- typedef llvm::StringMap<bool, llvm::BumpPtrAllocator>::iterator iterator;<br>- iterator begin() { return BestResults.begin(); }<br>- iterator end() { return BestResults.end(); }<br>- void erase(iterator I) { BestResults.erase(I); }<br>+ void addKeywordResult(llvm::StringRef Keyword);<br>+ void addName(llvm::StringRef Name, NamedDecl *ND, unsigned Distance,<br>+ NestedNameSpecifier *NNS=NULL);<br>+ void addCorrection(TypoCorrection Correction);<br>+<br>+ typedef TypoResultsMap::iterator result_iterator;<br>+ typedef TypoEditDistanceMap::iterator distance_iterator;<br>+ distance_iterator begin() { return BestResults.begin(); }<br>+ distance_iterator end() { return BestResults.end(); }<br>+ void erase(distance_iterator I) { BestResults.erase(I); }<br> unsigned size() const { return BestResults.size(); }<br> bool empty() const { return BestResults.empty(); }<br><br>- bool &operator[](llvm::StringRef Name) {<br>- return BestResults[Name];<br>+ TypoCorrection &operator[](llvm::StringRef Name) {<br>+ return BestResults.begin()->second[Name];<br> }<br><br>- unsigned getBestEditDistance() const { return BestEditDistance; }<br>+ unsigned getMaxEditDistance() const {<br>+ return MaxEditDistance;<br>+ }<br>+<br>+ unsigned getBestEditDistance() {<br>+ return (BestResults.empty()) ? MaxEditDistance : BestResults.begin()->first;<br>+ }<br> };<br><br> }<br>@@ -3099,55 +3121,164 @@<br> // Use a simple length-based heuristic to determine the minimum possible<br> // edit distance. If the minimum isn't good enough, bail out early.<br> unsigned MinED = abs((int)Name.size() - (int)Typo.size());<br>- if (MinED > BestEditDistance || (MinED && Typo.size() / MinED < 3))<br>+ if (MinED > MaxEditDistance || (MinED && Typo.size() / MinED < 3))<br> return;<br><br> // Compute an upper bound on the allowable edit distance, so that the<br> // edit-distance algorithm can short-circuit.<br> unsigned UpperBound =<br>- std::min(unsigned((Typo.size() + 2) / 3), BestEditDistance);<br>+ std::min(unsigned((Typo.size() + 2) / 3), MaxEditDistance);<br><br> // Compute the edit distance between the typo and the name of this<br> // entity. If this edit distance is not worse than the best edit<br> // distance we've seen so far, add it to the list of results.<br> unsigned ED = Typo.edit_distance(Name, true, UpperBound);<br>- if (ED == 0)<br>- return;<br><br>- if (ED < BestEditDistance) {<br>- // This result is better than any we've seen before; clear out<br>- // the previous results.<br>- BestResults.clear();<br>- BestEditDistance = ED;<br>- } else if (ED > BestEditDistance) {<br>+ if (ED > MaxEditDistance) {<br> // This result is worse than the best results we've seen so far;<br> // ignore it.<br> return;<br> }<br><br>- // Add this name to the list of results. By not assigning a value, we<br>- // keep the current value if we've seen this name before (either as a<br>- // keyword or as a declaration), or get the default value (not a keyword)<br>- // if we haven't seen it before.<br>- (void)BestResults[Name];<br>+ addName(Name, NULL, ED);<br> }<br><br>-void TypoCorrectionConsumer::addKeywordResult(ASTContext &Context,<br>- llvm::StringRef Keyword) {<br>+void TypoCorrectionConsumer::addKeywordResult(llvm::StringRef Keyword) {<br> // Compute the edit distance between the typo and this keyword.<br> // If this edit distance is not worse than the best edit<br> // distance we've seen so far, add it to the list of results.<br> unsigned ED = Typo.edit_distance(Keyword);<br>- if (ED < BestEditDistance) {<br>- BestResults.clear();<br>- BestEditDistance = ED;<br>- } else if (ED > BestEditDistance) {<br>+ if (ED > MaxEditDistance) {<br> // This result is worse than the best results we've seen so far;<br> // ignore it.<br> return;<br> }<br><br>- BestResults[Keyword] = true;<br>+ addName(Keyword, TypoCorrection::KeywordDecl(), ED);<br>+}<br>+<br>+void TypoCorrectionConsumer::addName(llvm::StringRef Name,<br>+ NamedDecl *ND,<br>+ unsigned Distance,<br>+ NestedNameSpecifier *NNS) {<br>+ addCorrection(TypoCorrection(&SemaRef.Context.Idents.get(Name),<br>+ ND, NNS, Distance));<br>+}<br>+<br>+void TypoCorrectionConsumer::addCorrection(TypoCorrection Correction) {<br>+ llvm::StringRef Name = Correction.getCorrectionAsIdentifierInfo()->getName();<br>+ BestResults[Correction.getEditDistance()][Name] = Correction;<br>+<br>+ while (BestResults.size() > MaxTypoDistanceResultSets) {<br>+ BestResults.erase(--BestResults.end());<br>+ }<br>+}<br>+<br>+namespace {<br>+<br>+class SpecifierInfo {<br>+ public:<br>+ DeclContext* DeclCtx;<br>+ NestedNameSpecifier* NameSpecifier;<br>+ unsigned EditDistance;<br>+<br>+ SpecifierInfo(DeclContext *Ctx, NestedNameSpecifier *NNS, unsigned ED)<br>+ : DeclCtx(Ctx), NameSpecifier(NNS), EditDistance(ED) {}<br>+};<br>+<br>+typedef llvm::SmallVector<DeclContext*, 4> DeclContextList;<br>+typedef llvm::SmallVector<SpecifierInfo, 16> SpecifierInfoList;<br>+<br>+class NamespaceSpecifierSet {<br>+ ASTContext &Context;<br>+ DeclContextList CurContextChain;<br>+ bool isSorted;<br>+<br>+ SpecifierInfoList Specifiers;<br>+ llvm::SmallSetVector<unsigned, 4> Distances;<br>+ llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap;<br>+<br>+ /// \brief Helper for building the list of DeclContexts between the current<br>+ /// context and the top of the translation unit<br>+ static DeclContextList BuildContextChain(DeclContext *Start);<br>+<br>+ void SortNamespaces();<br>+<br>+ public:<br>+ explicit NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext)<br>+ : Context(Context), CurContextChain(BuildContextChain(CurContext)) {}<br>+<br>+ /// \brief Add the namespace to the set, computing the corresponding<br>+ /// NestedNameSpecifier and its distance in the process.<br>+ void AddNamespace(NamespaceDecl *ND);<br>+<br>+ typedef SpecifierInfoList::iterator iterator;<br>+ iterator begin() {<br>+ if (!isSorted) SortNamespaces();<br>+ return Specifiers.begin();<br>+ }<br>+ iterator end() { return Specifiers.end(); }<br>+};<br>+<br>+}<br>+<br>+DeclContextList NamespaceSpecifierSet::BuildContextChain(DeclContext *Start) {<br>+ DeclContextList Chain;<br>+ for (DeclContext *DC = Start->getPrimaryContext(); DC != NULL;<br>+ DC = DC->getLookupParent()) {<br>+ NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(DC);<br>+ if (!DC->isInlineNamespace() && !DC->isTransparentContext() &&<br>+ !(ND && ND->isAnonymousNamespace()))<br>+ Chain.push_back(DC->getPrimaryContext());<br>+ }<br>+ return Chain;<br>+}<br>+<br>+void NamespaceSpecifierSet::SortNamespaces() {<br>+ llvm::SmallVector<unsigned, 4> sortedDistances;<br>+ sortedDistances.append(Distances.begin(), Distances.end());<br>+<br>+ if (sortedDistances.size() > 1)<br>+ std::sort(sortedDistances.begin(), sortedDistances.end());<br>+<br>+ Specifiers.clear();<br>+ for (llvm::SmallVector<unsigned, 4>::iterator DI = sortedDistances.begin(),<br>+ DIEnd = sortedDistances.end();<br>+ DI != DIEnd; ++DI) {<br>+ SpecifierInfoList &SpecList = DistanceMap[*DI];<br>+ Specifiers.append(SpecList.begin(), SpecList.end());<br>+ }<br>+<br>+ isSorted = true;<br>+}<br>+<br>+void NamespaceSpecifierSet::AddNamespace(NamespaceDecl *ND) {<br>+ DeclContext *Ctx = dyn_cast<DeclContext>(ND);<br>+ NestedNameSpecifier *NNS = NULL;<br>+ unsigned NumSpecifiers = 0;<br>+ DeclContextList NamespaceDeclChain(BuildContextChain(Ctx));<br>+<br>+ // Eliminate common elements from the two DeclContext chains<br>+ for (DeclContextList::reverse_iterator C = CurContextChain.rbegin(),<br>+ CEnd = CurContextChain.rend();<br>+ C != CEnd && NamespaceDeclChain.back() == *C; ++C) {<br>+ NamespaceDeclChain.pop_back();<br>+ }<br>+<br>+ // Build the NestedNameSpecifier from what is left of the NamespaceDeclChain<br>+ for (DeclContextList::reverse_iterator C = NamespaceDeclChain.rbegin(),<br>+ CEnd = NamespaceDeclChain.rend();<br>+ C != CEnd; ++C) {<br>+ NamespaceDecl *ND = dyn_cast_or_null<NamespaceDecl>(*C);<br>+ if (ND) {<br>+ NNS = NestedNameSpecifier::Create(Context, NNS, ND);<br>+ ++NumSpecifiers;<br>+ }<br>+ }<br>+<br>+ isSorted = false;<br>+ Distances.insert(NumSpecifiers);<br>+ DistanceMap[NumSpecifiers].push_back(SpecifierInfo(Ctx, NNS, NumSpecifiers));<br> }<br><br> /// \brief Perform name lookup for a possible result for typo correction.<br>@@ -3201,177 +3332,60 @@<br> }<br> }<br><br>-/// \brief Try to "correct" a typo in the source code by finding<br>-/// visible declarations whose names are similar to the name that was<br>-/// present in the source code.<br>-///<br>-/// \param Res the \c LookupResult structure that contains the name<br>-/// that was present in the source code along with the name-lookup<br>-/// criteria used to search for the name. On success, this structure<br>-/// will contain the results of name lookup.<br>-///<br>-/// \param S the scope in which name lookup occurs.<br>-///<br>-/// \param SS the nested-name-specifier that precedes the name we're<br>-/// looking for, if present.<br>-///<br>-/// \param MemberContext if non-NULL, the context in which to look for<br>-/// a member access expression.<br>-///<br>-/// \param EnteringContext whether we're entering the context described by<br>-/// the nested-name-specifier SS.<br>-///<br>-/// \param CTC The context in which typo correction occurs, which impacts the<br>-/// set of keywords permitted.<br>-///<br>-/// \param OPT when non-NULL, the search for visible declarations will<br>-/// also walk the protocols in the qualified interfaces of \p OPT.<br>-///<br>-/// \returns the corrected name if the typo was corrected, otherwise returns an<br>-/// empty \c DeclarationName. When a typo was corrected, the result structure<br>-/// may contain the results of name lookup for the correct name or it may be<br>-/// empty.<br>-DeclarationName Sema::CorrectTypo(LookupResult &Res, Scope *S, CXXScopeSpec *SS,<br>- DeclContext *MemberContext,<br>- bool EnteringContext,<br>- CorrectTypoContext CTC,<br>- const ObjCObjectPointerType *OPT) {<br>- if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)<br>- return DeclarationName();<br>-<br>- // We only attempt to correct typos for identifiers.<br>- IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();<br>- if (!Typo)<br>- return DeclarationName();<br>-<br>- // If the scope specifier itself was invalid, don't try to correct<br>- // typos.<br>- if (SS && SS->isInvalid())<br>- return DeclarationName();<br>-<br>- // Never try to correct typos during template deduction or<br>- // instantiation.<br>- if (!ActiveTemplateInstantiations.empty())<br>- return DeclarationName();<br>-<br>- TypoCorrectionConsumer Consumer(Typo);<br>-<br>- // Perform name lookup to find visible, similarly-named entities.<br>- bool IsUnqualifiedLookup = false;<br>- if (MemberContext) {<br>- LookupVisibleDecls(MemberContext, Res.getLookupKind(), Consumer);<br>-<br>- // Look in qualified interfaces.<br>- if (OPT) {<br>- for (ObjCObjectPointerType::qual_iterator<br>- I = OPT->qual_begin(), E = OPT->qual_end();<br>- I != E; ++I)<br>- LookupVisibleDecls(*I, Res.getLookupKind(), Consumer);<br>- }<br>- } else if (SS && SS->isSet()) {<br>- DeclContext *DC = computeDeclContext(*SS, EnteringContext);<br>- if (!DC)<br>- return DeclarationName();<br>-<br>- // Provide a stop gap for files that are just seriously broken. Trying<br>- // to correct all typos can turn into a HUGE performance penalty, causing<br>- // some files to take minutes to get rejected by the parser.<br>- if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)<br>- return DeclarationName();<br>- ++TyposCorrected;<br>-<br>- LookupVisibleDecls(DC, Res.getLookupKind(), Consumer);<br>- } else {<br>- IsUnqualifiedLookup = true;<br>- UnqualifiedTyposCorrectedMap::iterator Cached<br>- = UnqualifiedTyposCorrected.find(Typo);<br>- if (Cached == UnqualifiedTyposCorrected.end()) {<br>- // Provide a stop gap for files that are just seriously broken. Trying<br>- // to correct all typos can turn into a HUGE performance penalty, causing<br>- // some files to take minutes to get rejected by the parser.<br>- if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)<br>- return DeclarationName();<br>-<br>- // For unqualified lookup, look through all of the names that we have<br>- // seen in this translation unit.<br>- for (IdentifierTable::iterator I = Context.Idents.begin(),<br>- IEnd = Context.Idents.end();<br>- I != IEnd; ++I)<br>- Consumer.FoundName(I->getKey());<br>-<br>- // Walk through identifiers in external identifier sources.<br>- if (IdentifierInfoLookup *External<br>- = Context.Idents.getExternalIdentifierLookup()) {<br>- llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());<br>- do {<br>- llvm::StringRef Name = Iter->Next();<br>- if (Name.empty())<br>- break;<br>-<br>- Consumer.FoundName(Name);<br>- } while (true);<br>- }<br>- } else {<br>- // Use the cached value, unless it's a keyword. In the keyword case, we'll<br>- // end up adding the keyword below.<br>- if (Cached->second.first.empty())<br>- return DeclarationName();<br>-<br>- if (!Cached->second.second)<br>- Consumer.FoundName(Cached->second.first);<br>- }<br>- }<br>-<br>+/// \brief Add keywords to the consumer as possible typo corrections.<br>+static void AddKeywordsToConsumer(Sema &SemaRef,<br>+ TypoCorrectionConsumer &Consumer,<br>+ Scope *S, Sema::CorrectTypoContext CTC) {<br> // Add context-dependent keywords.<br> bool WantTypeSpecifiers = false;<br> bool WantExpressionKeywords = false;<br> bool WantCXXNamedCasts = false;<br> bool WantRemainingKeywords = false;<br> switch (CTC) {<br>- case CTC_Unknown:<br>+ case Sema::CTC_Unknown:<br> WantTypeSpecifiers = true;<br> WantExpressionKeywords = true;<br> WantCXXNamedCasts = true;<br> WantRemainingKeywords = true;<br><br>- if (ObjCMethodDecl *Method = getCurMethodDecl())<br>+ if (ObjCMethodDecl *Method = SemaRef.getCurMethodDecl())<br> if (Method->getClassInterface() &&<br> Method->getClassInterface()->getSuperClass())<br>- Consumer.addKeywordResult(Context, "super");<br>+ Consumer.addKeywordResult("super");<br><br> break;<br><br>- case CTC_NoKeywords:<br>+ case Sema::CTC_NoKeywords:<br> break;<br><br>- case CTC_Type:<br>+ case Sema::CTC_Type:<br> WantTypeSpecifiers = true;<br> break;<br><br>- case CTC_ObjCMessageReceiver:<br>- Consumer.addKeywordResult(Context, "super");<br>+ case Sema::CTC_ObjCMessageReceiver:<br>+ Consumer.addKeywordResult("super");<br> // Fall through to handle message receivers like expressions.<br><br>- case CTC_Expression:<br>- if (getLangOptions().CPlusPlus)<br>+ case Sema::CTC_Expression:<br>+ if (SemaRef.getLangOptions().CPlusPlus)<br> WantTypeSpecifiers = true;<br> WantExpressionKeywords = true;<br> // Fall through to get C++ named casts.<br><br>- case CTC_CXXCasts:<br>+ case Sema::CTC_CXXCasts:<br> WantCXXNamedCasts = true;<br> break;<br><br>- case CTC_ObjCPropertyLookup:<br>+ case Sema::CTC_ObjCPropertyLookup:<br> // FIXME: Add "isa"?<br> break;<br><br>- case CTC_MemberLookup:<br>- if (getLangOptions().CPlusPlus)<br>- Consumer.addKeywordResult(Context, "template");<br>+ case Sema::CTC_MemberLookup:<br>+ if (SemaRef.getLangOptions().CPlusPlus)<br>+ Consumer.addKeywordResult("template");<br> break;<br><br>- case CTC_ObjCIvarLookup:<br>+ case Sema::CTC_ObjCIvarLookup:<br> break;<br> }<br><br>@@ -3387,240 +3401,449 @@<br><br> const unsigned NumCTypeSpecs = sizeof(CTypeSpecs) / sizeof(CTypeSpecs[0]);<br> for (unsigned I = 0; I != NumCTypeSpecs; ++I)<br>- Consumer.addKeywordResult(Context, CTypeSpecs[I]);<br>+ Consumer.addKeywordResult(CTypeSpecs[I]);<br><br>- if (getLangOptions().C99)<br>- Consumer.addKeywordResult(Context, "restrict");<br>- if (getLangOptions().Bool || getLangOptions().CPlusPlus)<br>- Consumer.addKeywordResult(Context, "bool");<br>+ if (SemaRef.getLangOptions().C99)<br>+ Consumer.addKeywordResult("restrict");<br>+ if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus)<br>+ Consumer.addKeywordResult("bool");<br><br>- if (getLangOptions().CPlusPlus) {<br>- Consumer.addKeywordResult(Context, "class");<br>- Consumer.addKeywordResult(Context, "typename");<br>- Consumer.addKeywordResult(Context, "wchar_t");<br>+ if (SemaRef.getLangOptions().CPlusPlus) {<br>+ Consumer.addKeywordResult("class");<br>+ Consumer.addKeywordResult("typename");<br>+ Consumer.addKeywordResult("wchar_t");<br><br>- if (getLangOptions().CPlusPlus0x) {<br>- Consumer.addKeywordResult(Context, "char16_t");<br>- Consumer.addKeywordResult(Context, "char32_t");<br>- Consumer.addKeywordResult(Context, "constexpr");<br>- Consumer.addKeywordResult(Context, "decltype");<br>- Consumer.addKeywordResult(Context, "thread_local");<br>+ if (SemaRef.getLangOptions().CPlusPlus0x) {<br>+ Consumer.addKeywordResult("char16_t");<br>+ Consumer.addKeywordResult("char32_t");<br>+ Consumer.addKeywordResult("constexpr");<br>+ Consumer.addKeywordResult("decltype");<br>+ Consumer.addKeywordResult("thread_local");<br> }<br> }<br><br>- if (getLangOptions().GNUMode)<br>- Consumer.addKeywordResult(Context, "typeof");<br>+ if (SemaRef.getLangOptions().GNUMode)<br>+ Consumer.addKeywordResult("typeof");<br> }<br><br>- if (WantCXXNamedCasts && getLangOptions().CPlusPlus) {<br>- Consumer.addKeywordResult(Context, "const_cast");<br>- Consumer.addKeywordResult(Context, "dynamic_cast");<br>- Consumer.addKeywordResult(Context, "reinterpret_cast");<br>- Consumer.addKeywordResult(Context, "static_cast");<br>+ if (WantCXXNamedCasts && SemaRef.getLangOptions().CPlusPlus) {<br>+ Consumer.addKeywordResult("const_cast");<br>+ Consumer.addKeywordResult("dynamic_cast");<br>+ Consumer.addKeywordResult("reinterpret_cast");<br>+ Consumer.addKeywordResult("static_cast");<br> }<br><br> if (WantExpressionKeywords) {<br>- Consumer.addKeywordResult(Context, "sizeof");<br>- if (getLangOptions().Bool || getLangOptions().CPlusPlus) {<br>- Consumer.addKeywordResult(Context, "false");<br>- Consumer.addKeywordResult(Context, "true");<br>+ Consumer.addKeywordResult("sizeof");<br>+ if (SemaRef.getLangOptions().Bool || SemaRef.getLangOptions().CPlusPlus) {<br>+ Consumer.addKeywordResult("false");<br>+ Consumer.addKeywordResult("true");<br> }<br><br>- if (getLangOptions().CPlusPlus) {<br>+ if (SemaRef.getLangOptions().CPlusPlus) {<br> const char *CXXExprs[] = {<br> "delete", "new", "operator", "throw", "typeid"<br> };<br> const unsigned NumCXXExprs = sizeof(CXXExprs) / sizeof(CXXExprs[0]);<br> for (unsigned I = 0; I != NumCXXExprs; ++I)<br>- Consumer.addKeywordResult(Context, CXXExprs[I]);<br>+ Consumer.addKeywordResult(CXXExprs[I]);<br><br>- if (isa<CXXMethodDecl>(CurContext) &&<br>- cast<CXXMethodDecl>(CurContext)->isInstance())<br>- Consumer.addKeywordResult(Context, "this");<br>-<br>- if (getLangOptions().CPlusPlus0x) {<br>- Consumer.addKeywordResult(Context, "alignof");<br>- Consumer.addKeywordResult(Context, "nullptr");<br>+ if (isa<CXXMethodDecl>(SemaRef.CurContext) &&<br>+ cast<CXXMethodDecl>(SemaRef.CurContext)->isInstance())<br>+ Consumer.addKeywordResult("this");<br>+<br>+ if (SemaRef.getLangOptions().CPlusPlus0x) {<br>+ Consumer.addKeywordResult("alignof");<br>+ Consumer.addKeywordResult("nullptr");<br> }<br> }<br> }<br><br> if (WantRemainingKeywords) {<br>- if (getCurFunctionOrMethodDecl() || getCurBlock()) {<br>+ if (SemaRef.getCurFunctionOrMethodDecl() || SemaRef.getCurBlock()) {<br> // Statements.<br> const char *CStmts[] = {<br> "do", "else", "for", "goto", "if", "return", "switch", "while" };<br> const unsigned NumCStmts = sizeof(CStmts) / sizeof(CStmts[0]);<br> for (unsigned I = 0; I != NumCStmts; ++I)<br>- Consumer.addKeywordResult(Context, CStmts[I]);<br>+ Consumer.addKeywordResult(CStmts[I]);<br><br>- if (getLangOptions().CPlusPlus) {<br>- Consumer.addKeywordResult(Context, "catch");<br>- Consumer.addKeywordResult(Context, "try");<br>+ if (SemaRef.getLangOptions().CPlusPlus) {<br>+ Consumer.addKeywordResult("catch");<br>+ Consumer.addKeywordResult("try");<br> }<br><br> if (S && S->getBreakParent())<br>- Consumer.addKeywordResult(Context, "break");<br>+ Consumer.addKeywordResult("break");<br><br> if (S && S->getContinueParent())<br>- Consumer.addKeywordResult(Context, "continue");<br>+ Consumer.addKeywordResult("continue");<br><br>- if (!getCurFunction()->SwitchStack.empty()) {<br>- Consumer.addKeywordResult(Context, "case");<br>- Consumer.addKeywordResult(Context, "default");<br>+ if (!SemaRef.getCurFunction()->SwitchStack.empty()) {<br>+ Consumer.addKeywordResult("case");<br>+ Consumer.addKeywordResult("default");<br> }<br> } else {<br>- if (getLangOptions().CPlusPlus) {<br>- Consumer.addKeywordResult(Context, "namespace");<br>- Consumer.addKeywordResult(Context, "template");<br>+ if (SemaRef.getLangOptions().CPlusPlus) {<br>+ Consumer.addKeywordResult("namespace");<br>+ Consumer.addKeywordResult("template");<br> }<br><br> if (S && S->isClassScope()) {<br>- Consumer.addKeywordResult(Context, "explicit");<br>- Consumer.addKeywordResult(Context, "friend");<br>- Consumer.addKeywordResult(Context, "mutable");<br>- Consumer.addKeywordResult(Context, "private");<br>- Consumer.addKeywordResult(Context, "protected");<br>- Consumer.addKeywordResult(Context, "public");<br>- Consumer.addKeywordResult(Context, "virtual");<br>+ Consumer.addKeywordResult("explicit");<br>+ Consumer.addKeywordResult("friend");<br>+ Consumer.addKeywordResult("mutable");<br>+ Consumer.addKeywordResult("private");<br>+ Consumer.addKeywordResult("protected");<br>+ Consumer.addKeywordResult("public");<br>+ Consumer.addKeywordResult("virtual");<br> }<br> }<br><br>- if (getLangOptions().CPlusPlus) {<br>- Consumer.addKeywordResult(Context, "using");<br>+ if (SemaRef.getLangOptions().CPlusPlus) {<br>+ Consumer.addKeywordResult("using");<br>+<br>+ if (SemaRef.getLangOptions().CPlusPlus0x)<br>+ Consumer.addKeywordResult("static_assert");<br>+ }<br>+ }<br>+}<br>+<br>+/// \brief Try to "correct" a typo in the source code by finding<br>+/// visible declarations whose names are similar to the name that was<br>+/// present in the source code.<br>+///<br>+/// \param TypoName the \c DeclarationNameInfo structure that contains<br>+/// the name that was present in the source code along with its location.<br>+///<br>+/// \param LookupKind the name-lookup criteria used to search for the name.<br>+///<br>+/// \param S the scope in which name lookup occurs.<br>+///<br>+/// \param SS the nested-name-specifier that precedes the name we're<br>+/// looking for, if present.<br>+///<br>+/// \param MemberContext if non-NULL, the context in which to look for<br>+/// a member access expression.<br>+///<br>+/// \param EnteringContext whether we're entering the context described by<br>+/// the nested-name-specifier SS.<br>+///<br>+/// \param CTC The context in which typo correction occurs, which impacts the<br>+/// set of keywords permitted.<br>+///<br>+/// \param OPT when non-NULL, the search for visible declarations will<br>+/// also walk the protocols in the qualified interfaces of \p OPT.<br>+///<br>+/// \returns a \c TypoCorrection containing the corrected name if the typo<br>+/// along with information such as the \c NamedDecl where the corrected name<br>+/// was declared, and any additional \c NestedNameSpecifier needed to access<br>+/// it (C++ only). The \c TypoCorrection is empty if there is no correction.<br>+TypoCorrection Sema::CorrectTypo(const DeclarationNameInfo &TypoName,<br>+ Sema::LookupNameKind LookupKind,<br>+ Scope *S, CXXScopeSpec *SS,<br>+ DeclContext *MemberContext,<br>+ bool EnteringContext,<br>+ CorrectTypoContext CTC,<br>+ const ObjCObjectPointerType *OPT) {<br>+ if (Diags.hasFatalErrorOccurred() || !getLangOptions().SpellChecking)<br>+ return TypoCorrection();<br>+<br>+ // We only attempt to correct typos for identifiers.<br>+ IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();<br>+ if (!Typo)<br>+ return TypoCorrection();<br><br>- if (getLangOptions().CPlusPlus0x)<br>- Consumer.addKeywordResult(Context, "static_assert");<br>+ // If the scope specifier itself was invalid, don't try to correct<br>+ // typos.<br>+ if (SS && SS->isInvalid())<br>+ return TypoCorrection();<br>+<br>+ // Never try to correct typos during template deduction or<br>+ // instantiation.<br>+ if (!ActiveTemplateInstantiations.empty())<br>+ return TypoCorrection();<br>+<br>+ NamespaceSpecifierSet Namespaces(Context, CurContext);<br>+<br>+ TypoCorrectionConsumer Consumer(*this, Typo);<br>+<br>+ // Perform name lookup to find visible, similarly-named entities.<br>+ bool IsUnqualifiedLookup = false;<br>+ if (MemberContext) {<br>+ LookupVisibleDecls(MemberContext, LookupKind, Consumer);<br>+<br>+ // Look in qualified interfaces.<br>+ if (OPT) {<br>+ for (ObjCObjectPointerType::qual_iterator<br>+ I = OPT->qual_begin(), E = OPT->qual_end();<br>+ I != E; ++I)<br>+ LookupVisibleDecls(*I, LookupKind, Consumer);<br>+ }<br>+ } else if (SS && SS->isSet()) {<br>+ DeclContext *DC = computeDeclContext(*SS, EnteringContext);<br>+ if (!DC)<br>+ return TypoCorrection();<br>+<br>+ // Provide a stop gap for files that are just seriously broken. Trying<br>+ // to correct all typos can turn into a HUGE performance penalty, causing<br>+ // some files to take minutes to get rejected by the parser.<br>+ if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)<br>+ return TypoCorrection();<br>+ ++TyposCorrected;<br>+<br>+ LookupVisibleDecls(DC, LookupKind, Consumer);<br>+ } else {<br>+ IsUnqualifiedLookup = true;<br>+ UnqualifiedTyposCorrectedMap::iterator Cached<br>+ = UnqualifiedTyposCorrected.find(Typo);<br>+ if (Cached == UnqualifiedTyposCorrected.end()) {<br>+ // Provide a stop gap for files that are just seriously broken. Trying<br>+ // to correct all typos can turn into a HUGE performance penalty, causing<br>+ // some files to take minutes to get rejected by the parser.<br>+ if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)<br>+ return TypoCorrection();<br>+<br>+ // For unqualified lookup, look through all of the names that we have<br>+ // seen in this translation unit.<br>+ for (IdentifierTable::iterator I = Context.Idents.begin(),<br>+ IEnd = Context.Idents.end();<br>+ I != IEnd; ++I)<br>+ Consumer.FoundName(I->getKey());<br>+<br>+ // Walk through identifiers in external identifier sources.<br>+ if (IdentifierInfoLookup *External<br>+ = Context.Idents.getExternalIdentifierLookup()) {<br>+ llvm::OwningPtr<IdentifierIterator> Iter(External->getIdentifiers());<br>+ do {<br>+ llvm::StringRef Name = Iter->Next();<br>+ if (Name.empty())<br>+ break;<br>+<br>+ Consumer.FoundName(Name);<br>+ } while (true);<br>+ }<br>+ } else {<br>+ // Use the cached value, unless it's a keyword. In the keyword case, we'll<br>+ // end up adding the keyword below.<br>+ if (!Cached->second)<br>+ return TypoCorrection();<br>+<br>+ if (!Cached->second.isKeyword())<br>+ Consumer.addCorrection(Cached->second);<br> }<br> }<br><br>+ AddKeywordsToConsumer(*this, Consumer, S, CTC);<br>+<br> // If we haven't found anything, we're done.<br> if (Consumer.empty()) {<br> // If this was an unqualified lookup, note that no correction was found.<br> if (IsUnqualifiedLookup)<br> (void)UnqualifiedTyposCorrected[Typo];<br><br>- return DeclarationName();<br>+ return TypoCorrection();<br> }<br><br> // Make sure that the user typed at least 3 characters for each correction<br> // made. Otherwise, we don't even both looking at the results.<br>-<br>- // We also suppress exact matches; those should be handled by a<br>- // different mechanism (e.g., one that introduces qualification in<br>- // C++).<br> unsigned ED = Consumer.getBestEditDistance();<br> if (ED > 0 && Typo->getName().size() / ED < 3) {<br> // If this was an unqualified lookup, note that no correction was found.<br> if (IsUnqualifiedLookup)<br> (void)UnqualifiedTyposCorrected[Typo];<br><br>- return DeclarationName();<br>+ return TypoCorrection();<br>+ }<br>+<br>+ // Build the NestedNameSpecifiers for the KnownNamespaces<br>+ if (getLangOptions().CPlusPlus) {<br>+ // Load any externally-known namespaces.<br>+ if (ExternalSource && !LoadedExternalKnownNamespaces) {<br>+ llvm::SmallVector<NamespaceDecl *, 4> ExternalKnownNamespaces;<br>+ LoadedExternalKnownNamespaces = true;<br>+ ExternalSource->ReadKnownNamespaces(ExternalKnownNamespaces);<br>+ for (unsigned I = 0, N = ExternalKnownNamespaces.size(); I != N; ++I)<br>+ KnownNamespaces[ExternalKnownNamespaces[I]] = true;<br>+ }<br>+ <br>+ for (llvm::DenseMap<NamespaceDecl*, bool>::iterator <br>+ KNI = KnownNamespaces.begin(),<br>+ KNIEnd = KnownNamespaces.end();<br>+ KNI != KNIEnd; ++KNI)<br>+ Namespaces.AddNamespace(KNI->first);<br> }<br><br> // Weed out any names that could not be found by name lookup.<br>- bool LastLookupWasAccepted = false;<br>- for (TypoCorrectionConsumer::iterator I = Consumer.begin(),<br>- IEnd = Consumer.end();<br>- I != IEnd; /* Increment in loop. */) {<br>- // Keywords are always found.<br>- if (I->second) {<br>- ++I;<br>- continue;<br>+ llvm::SmallPtrSet<IdentifierInfo*, 16> QualifiedResults;<br>+ LookupResult TmpRes(*this, TypoName, LookupKind);<br>+ TmpRes.suppressDiagnostics();<br>+ while (!Consumer.empty()) {<br>+ TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();<br>+ unsigned ED = DI->first;<br>+ for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),<br>+ IEnd = DI->second.end();<br>+ I != IEnd; /* Increment in loop. */) {<br>+ // If the item already has been looked up or is a keyword, keep it<br>+ if (I->second.isResolved()) {<br>+ ++I;<br>+ continue;<br>+ }<br>+<br>+ // Perform name lookup on this name.<br>+ IdentifierInfo *Name = I->second.getCorrectionAsIdentifierInfo();<br>+ LookupPotentialTypoResult(*this, TmpRes, Name, S, SS, MemberContext,<br>+ EnteringContext, CTC);<br>+<br>+ switch (TmpRes.getResultKind()) {<br>+ case LookupResult::NotFound:<br>+ case LookupResult::NotFoundInCurrentInstantiation:<br>+ QualifiedResults.insert(Name);<br>+ // We didn't find this name in our scope, or didn't like what we found;<br>+ // ignore it.<br>+ {<br>+ TypoCorrectionConsumer::result_iterator Next = I;<br>+ ++Next;<br>+ DI->second.erase(I);<br>+ I = Next;<br>+ }<br>+ break;<br>+<br>+ case LookupResult::Ambiguous:<br>+ // We don't deal with ambiguities.<br>+ return TypoCorrection();<br>+<br>+ case LookupResult::Found:<br>+ case LookupResult::FoundOverloaded:<br>+ case LookupResult::FoundUnresolvedValue:<br>+ I->second.setCorrectionDecl(TmpRes.getAsSingle<NamedDecl>());<br>+ ++I;<br>+ break;<br>+ }<br> }<br><br>- // Perform name lookup on this name.<br>- IdentifierInfo *Name = &Context.Idents.get(I->getKey());<br>- LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext,<br>- EnteringContext, CTC);<br>-<br>- switch (Res.getResultKind()) {<br>- case LookupResult::NotFound:<br>- case LookupResult::NotFoundInCurrentInstantiation:<br>- case LookupResult::Ambiguous:<br>- // We didn't find this name in our scope, or didn't like what we found;<br>- // ignore it.<br>- Res.suppressDiagnostics();<br>- {<br>- TypoCorrectionConsumer::iterator Next = I;<br>- ++Next;<br>- Consumer.erase(I);<br>- I = Next;<br>- }<br>- LastLookupWasAccepted = false;<br>- break;<br>-<br>- case LookupResult::Found:<br>- case LookupResult::FoundOverloaded:<br>- case LookupResult::FoundUnresolvedValue:<br>- ++I;<br>- LastLookupWasAccepted = true;<br>+ if (DI->second.empty())<br>+ Consumer.erase(DI);<br>+ else if (!getLangOptions().CPlusPlus || QualifiedResults.empty() || !ED)<br>+ // If there are results in the closest possible bucket, stop<br> break;<br>+<br>+ // Only perform the qualified lookups for C++<br>+ if (getLangOptions().CPlusPlus) {<br>+ TmpRes.suppressDiagnostics();<br>+ for (llvm::SmallPtrSet<IdentifierInfo*,<br>+ 16>::iterator QRI = QualifiedResults.begin(),<br>+ QRIEnd = QualifiedResults.end();<br>+ QRI != QRIEnd; ++QRI) {<br>+ for (NamespaceSpecifierSet::iterator NI = Namespaces.begin(),<br>+ NIEnd = Namespaces.end();<br>+ NI != NIEnd; ++NI) {<br>+ DeclContext *Ctx = NI->DeclCtx;<br>+ unsigned QualifiedED = ED + NI->EditDistance;<br>+<br>+ // Stop searching once the namespaces are too far away to create<br>+ // acceptable corrections for this identifier (since the namespaces<br>+ // are sorted in ascending order by edit distance)<br>+ if (QualifiedED > Consumer.getMaxEditDistance()) break;<br>+<br>+ TmpRes.clear();<br>+ TmpRes.setLookupName(*QRI);<br>+ if (!LookupQualifiedName(TmpRes, Ctx)) continue;<br>+<br>+ switch (TmpRes.getResultKind()) {<br>+ case LookupResult::Found:<br>+ case LookupResult::FoundOverloaded:<br>+ case LookupResult::FoundUnresolvedValue:<br>+ Consumer.addName((*QRI)->getName(), TmpRes.getAsSingle<NamedDecl>(),<br>+ QualifiedED, NI->NameSpecifier);<br>+ break;<br>+ case LookupResult::NotFound:<br>+ case LookupResult::NotFoundInCurrentInstantiation:<br>+ case LookupResult::Ambiguous:<br>+ break;<br>+ }<br>+ }<br>+ }<br> }<br><br>- if (Res.isAmbiguous()) {<br>- // We don't deal with ambiguities.<br>- Res.suppressDiagnostics();<br>- Res.clear();<br>- return DeclarationName();<br>+ QualifiedResults.clear();<br>+ }<br>+<br>+ // No corrections remain...<br>+ if (Consumer.empty()) return TypoCorrection();<br>+<br>+ TypoResultsMap &BestResults = Consumer.begin()->second;<br>+ ED = Consumer.begin()->first;<br>+<br>+ if (ED > 0 && Typo->getName().size() / ED < 3) {<br>+ // If this was an unqualified lookup, note that no correction was found.<br>+ if (IsUnqualifiedLookup)<br>+ (void)UnqualifiedTyposCorrected[Typo];<br>+<br>+ return TypoCorrection();<br>+ }<br>+<br>+ // If we have multiple possible corrections, eliminate the ones where we<br>+ // added namespace qualifiers to try to resolve the ambiguity (and to favor<br>+ // corrections without additional namespace qualifiers)<br>+ if (getLangOptions().CPlusPlus && BestResults.size() > 1) {<br>+ TypoCorrectionConsumer::distance_iterator DI = Consumer.begin();<br>+ for (TypoCorrectionConsumer::result_iterator I = DI->second.begin(),<br>+ IEnd = DI->second.end();<br>+ I != IEnd; /* Increment in loop. */) {<br>+ if (I->second.getCorrectionSpecifier() != NULL) {<br>+ TypoCorrectionConsumer::result_iterator Cur = I;<br>+ ++I;<br>+ DI->second.erase(Cur);<br>+ } else ++I;<br> }<br> }<br><br> // If only a single name remains, return that result.<br>- if (Consumer.size() == 1) {<br>- IdentifierInfo *Name = &Context.Idents.get(Consumer.begin()->getKey());<br>- if (Consumer.begin()->second) {<br>- Res.suppressDiagnostics();<br>- Res.clear();<br>-<br>- // Don't correct to a keyword that's the same as the typo; the keyword<br>- // wasn't actually in scope.<br>- if (ED == 0) {<br>- Res.setLookupName(Typo);<br>- return DeclarationName();<br>- }<br>+ if (BestResults.size() == 1) {<br>+ const llvm::StringMapEntry<TypoCorrection> &Correction = *(BestResults.begin());<br>+ const TypoCorrection &Result = Correction.second;<br><br>- } else if (!LastLookupWasAccepted) {<br>- // Perform name lookup on this name.<br>- LookupPotentialTypoResult(*this, Res, Name, S, SS, MemberContext,<br>- EnteringContext, CTC);<br>- }<br>+ // Don't correct to a keyword that's the same as the typo; the keyword<br>+ // wasn't actually in scope.<br>+ if (ED == 0 && Result.isKeyword()) return TypoCorrection();<br><br>+ assert(Result.isResolved() && "correction has not been looked up");<br> // Record the correction for unqualified lookup.<br> if (IsUnqualifiedLookup)<br>- UnqualifiedTyposCorrected[Typo]<br>- = std::make_pair(Name->getName(), Consumer.begin()->second);<br>+ UnqualifiedTyposCorrected[Typo] = Result;<br><br>- return &Context.Idents.get(Consumer.begin()->getKey());<br>+ return Result;<br> }<br>- else if (Consumer.size() > 1 && CTC == CTC_ObjCMessageReceiver<br>- && Consumer["super"]) {<br>- // Prefix 'super' when we're completing in a message-receiver<br>+ else if (BestResults.size() > 1 && CTC == CTC_ObjCMessageReceiver<br>+ && BestResults["super"].isKeyword()) {<br>+ // Prefer 'super' when we're completing in a message-receiver<br> // context.<br>- Res.suppressDiagnostics();<br>- Res.clear();<br><br> // Don't correct to a keyword that's the same as the typo; the keyword<br> // wasn't actually in scope.<br>- if (ED == 0) {<br>- Res.setLookupName(Typo);<br>- return DeclarationName();<br>- }<br>+ if (ED == 0) return TypoCorrection();<br><br> // Record the correction for unqualified lookup.<br> if (IsUnqualifiedLookup)<br>- UnqualifiedTyposCorrected[Typo]<br>- = std::make_pair("super", Consumer.begin()->second);<br>+ UnqualifiedTyposCorrected[Typo] = BestResults["super"];<br><br>- return &Context.Idents.get("super");<br>+ return BestResults["super"];<br> }<br><br>- Res.suppressDiagnostics();<br>- Res.setLookupName(Typo);<br>- Res.clear();<br>- // Record the correction for unqualified lookup.<br> if (IsUnqualifiedLookup)<br> (void)UnqualifiedTyposCorrected[Typo];<br><br>- return DeclarationName();<br>+ return TypoCorrection();<br>+}<br>+<br>+std::string TypoCorrection::getAsString(const LangOptions &LO) const {<br>+ if (CorrectionNameSpec) {<br>+ std::string tmpBuffer;<br>+ llvm::raw_string_ostream PrefixOStream(tmpBuffer);<br>+ CorrectionNameSpec->print(PrefixOStream, PrintingPolicy(LO));<br>+ return PrefixOStream.str() + CorrectionName.getAsString();<br>+ }<br>+<br>+ return CorrectionName.getAsString();<br> }<br><br>Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Tue Jun 28 11:20:02 2011<br>@@ -294,26 +294,31 @@<br> if (Found.empty() && !isDependent) {<br> // If we did not find any names, attempt to correct any typos.<br> DeclarationName Name = Found.getLookupName();<br>- if (DeclarationName Corrected = CorrectTypo(Found, S, &SS, LookupCtx,<br>- false, CTC_CXXCasts)) {<br>+ Found.clear();<br>+ if (TypoCorrection Corrected = CorrectTypo(Found.getLookupNameInfo(),<br>+ Found.getLookupKind(), S, &SS,<br>+ LookupCtx, false,<br>+ CTC_CXXCasts)) {<br>+ Found.setLookupName(Corrected.getCorrection());<br>+ if (Corrected.getCorrectionDecl())<br>+ Found.addDecl(Corrected.getCorrectionDecl());<br> FilterAcceptableTemplateNames(Found);<br> if (!Found.empty()) {<br>+ std::string CorrectedStr(Corrected.getAsString(getLangOptions()));<br>+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));<br> if (LookupCtx)<br> Diag(Found.getNameLoc(), diag::err_no_member_template_suggest)<br>- << Name << LookupCtx << Found.getLookupName() << SS.getRange()<br>- << FixItHint::CreateReplacement(Found.getNameLoc(),<br>- Found.getLookupName().getAsString());<br>+ << Name << LookupCtx << CorrectedQuotedStr << SS.getRange()<br>+ << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);<br> else<br> Diag(Found.getNameLoc(), diag::err_no_template_suggest)<br>- << Name << Found.getLookupName()<br>- << FixItHint::CreateReplacement(Found.getNameLoc(),<br>- Found.getLookupName().getAsString());<br>+ << Name << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(Found.getNameLoc(), CorrectedStr);<br> if (TemplateDecl *Template = Found.getAsSingle<TemplateDecl>())<br> Diag(Template->getLocation(), diag::note_previous_decl)<br>- << Template->getDeclName();<br>+ << CorrectedQuotedStr;<br> }<br> } else {<br>- Found.clear();<br> Found.setLookupName(Name);<br> }<br> }<br><br>Modified: cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp (original)<br>+++ cfe/trunk/lib/Sema/SemaTemplateVariadic.cpp Tue Jun 28 11:20:02 2011<br>@@ -716,17 +716,19 @@<br><br> case LookupResult::NotFound:<br> case LookupResult::NotFoundInCurrentInstantiation:<br>- if (DeclarationName CorrectedName = CorrectTypo(R, S, 0, 0, false, <br>- CTC_NoKeywords)) {<br>- if (NamedDecl *CorrectedResult = R.getAsSingle<NamedDecl>())<br>+ if (TypoCorrection Corrected = CorrectTypo(R.getLookupNameInfo(),<br>+ R.getLookupKind(), S, 0, 0,<br>+ false, CTC_NoKeywords)) {<br>+ if (NamedDecl *CorrectedResult = Corrected.getCorrectionDecl())<br> if (CorrectedResult->isParameterPack()) {<br>+ std::string CorrectedQuotedStr(Corrected.getQuoted(getLangOptions()));<br> ParameterPack = CorrectedResult;<br> Diag(NameLoc, diag::err_sizeof_pack_no_pack_name_suggest)<br>- << &Name << CorrectedName<br>- << FixItHint::CreateReplacement(NameLoc, <br>- CorrectedName.getAsString());<br>+ << &Name << CorrectedQuotedStr<br>+ << FixItHint::CreateReplacement(<br>+ NameLoc, Corrected.getAsString(getLangOptions()));<br> Diag(ParameterPack->getLocation(), diag::note_parameter_pack_here)<br>- << CorrectedName;<br>+ << CorrectedQuotedStr;<br> }<br> }<br><br><br>Modified: cfe/trunk/lib/Serialization/ASTReader.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)<br>+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Jun 28 11:20:02 2011<br>@@ -2369,6 +2369,15 @@<br> TentativeDefinitions.insert(TentativeDefinitions.end(),<br> Record.begin(), Record.end());<br> break;<br>+ <br>+ case KNOWN_NAMESPACES:<br>+ // Optimization for the first block.<br>+ if (KnownNamespaces.empty())<br>+ KnownNamespaces.swap(Record);<br>+ else<br>+ KnownNamespaces.insert(KnownNamespaces.end(), <br>+ Record.begin(), Record.end());<br>+ break;<br> }<br> First = false;<br> }<br>@@ -4452,6 +4461,17 @@<br> return std::pair<ObjCMethodList, ObjCMethodList>();<br> }<br><br>+void ASTReader::ReadKnownNamespaces(<br>+ llvm::SmallVectorImpl<NamespaceDecl *> &Namespaces) {<br>+ Namespaces.clear();<br>+ <br>+ for (unsigned I = 0, N = KnownNamespaces.size(); I != N; ++I) {<br>+ if (NamespaceDecl *Namespace <br>+ = dyn_cast_or_null<NamespaceDecl>(GetDecl(KnownNamespaces[I])))<br>+ Namespaces.push_back(Namespace);<br>+ }<br>+}<br>+<br> void ASTReader::LoadSelector(Selector Sel) {<br> // It would be complicated to avoid reading the methods anyway. So don't.<br> ReadMethodPool(Sel);<br><br>Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)<br>+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Jun 28 11:20:02 2011<br>@@ -781,6 +781,8 @@<br> RECORD(FP_PRAGMA_OPTIONS);<br> RECORD(OPENCL_EXTENSIONS);<br> RECORD(DELEGATING_CTORS);<br>+ RECORD(FILE_SOURCE_LOCATION_OFFSETS);<br>+ RECORD(KNOWN_NAMESPACES);<br><br> // SourceManager Block.<br> BLOCK(SOURCE_MANAGER_BLOCK);<br>@@ -2845,6 +2847,16 @@<br> AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs);<br> }<br><br>+ // Build a record containing all of the known namespaces.<br>+ RecordData KnownNamespaces;<br>+ for (llvm::DenseMap<NamespaceDecl*, bool>::iterator <br>+ I = SemaRef.KnownNamespaces.begin(),<br>+ IEnd = SemaRef.KnownNamespaces.end();<br>+ I != IEnd; ++I) {<br>+ if (!I->second)<br>+ AddDeclRef(I->first, KnownNamespaces);<br>+ }<br>+ <br> // Write the remaining AST contents.<br> RecordData Record;<br> Stream.EnterSubblock(AST_BLOCK_ID, 5);<br>@@ -2954,6 +2966,10 @@<br> if (!DelegatingCtorDecls.empty())<br> Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls);<br><br>+ // Write the known namespaces.<br>+ if (!KnownNamespaces.empty())<br>+ Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces);<br>+ <br> // Some simple statistics<br> Record.clear();<br> Record.push_back(NumStatements);<br><br>Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp (original)<br>+++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.argdep/p4.cpp Tue Jun 28 11:20:02 2011<br>@@ -19,8 +19,9 @@<br> }<br><br> namespace C {<br>- class C {};<br>- void func(C);<br>+ class C {}; // expected-note {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'B::B' to 'const C::C &' for 1st argument}}<br>+ void func(C); // expected-note {{'C::func' declared here}} \<br>+ // expected-note {{passing argument to parameter here}}<br> C operator+(C,C);<br> D::D operator+(D::D,D::D);<br> }<br>@@ -32,7 +33,13 @@<br> namespace Test {<br> void test() {<br> func(A::A());<br>- func(B::B()); // expected-error {{use of undeclared identifier 'func'}}<br>+ // FIXME: namespace-aware typo correction causes an extra, misleading<br>+ // message in this case; some form of backtracking, diagnostic message<br>+ // delaying, or argument checking before emitting diagnostics is needed to<br>+ // avoid accepting and printing out a typo correction that proves to be<br>+ // incorrect once argument-dependent lookup resolution has occurred.<br>+ func(B::B()); // expected-error {{use of undeclared identifier 'func'; did you mean 'C::func'?}} \<br>+ // expected-error {{no viable conversion from 'B::B' to 'C::C'}}<br> func(C::C());<br> A::A() + A::A();<br> B::B() + B::B();<br><br>Modified: cfe/trunk/test/FixIt/typo.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.cpp?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.cpp?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/FixIt/typo.cpp (original)<br>+++ cfe/trunk/test/FixIt/typo.cpp Tue Jun 28 11:20:02 2011<br>@@ -74,3 +74,9 @@<br> unsinged *ptr = 0; // expected-error{{use of undeclared identifier 'unsinged'; did you mean 'unsigned'?}}<br> return *i + *ptr + global_val; // expected-error{{use of undeclared identifier 'global_val'; did you mean 'global_value'?}}<br> }<br>+<br>+namespace nonstd {<br>+ typedef std::basic_string<char> yarn; // expected-note{{'nonstd::yarn' declared here}}<br>+}<br>+<br>+yarn str4; // expected-error{{unknown type name 'yarn'; did you mean 'nonstd::yarn'?}}<br><br>Added: cfe/trunk/test/PCH/Inputs/typo.hpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/Inputs/typo.hpp?rev=134007&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/Inputs/typo.hpp?rev=134007&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/PCH/Inputs/typo.hpp (added)<br>+++ cfe/trunk/test/PCH/Inputs/typo.hpp Tue Jun 28 11:20:02 2011<br>@@ -0,0 +1,8 @@<br>+namespace boost {<br>+ template<typename F> class function {};<br>+<br>+ namespace graph {<br>+ template<typename V, typename E> class adjacency_list { }; <br>+ };<br>+}<br>+<br><br>Propchange: cfe/trunk/test/PCH/Inputs/typo.hpp<br>------------------------------------------------------------------------------<br> svn:eol-style = native<br><br>Propchange: cfe/trunk/test/PCH/Inputs/typo.hpp<br>------------------------------------------------------------------------------<br> svn:keywords = Id<br><br>Propchange: cfe/trunk/test/PCH/Inputs/typo.hpp<br>------------------------------------------------------------------------------<br> svn:mime-type = text/plain<br><br>Added: cfe/trunk/test/PCH/typo.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/typo.cpp?rev=134007&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/typo.cpp?rev=134007&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/PCH/typo.cpp (added)<br>+++ cfe/trunk/test/PCH/typo.cpp Tue Jun 28 11:20:02 2011<br>@@ -0,0 +1,17 @@<br>+<br>+// In header: expected-note{{ 'boost::function' declared here}}<br>+<br>+<br>+// In header: expected-note{{ 'boost::graph::adjacency_list' declared here}}<br>+<br>+<br>+<br>+adjacent_list<int, int> g; // expected-error{{no template named 'adjacent_list'; did you mean 'boost::graph::adjacency_list'?}}<br>+Function<int(int)> f; // expected-error{{no template named 'Function'; did you mean 'boost::function'?}}<br>+<br>+// Without PCH<br>+// RUN: %clang_cc1 -include %S/Inputs/typo.hpp -verify %s<br>+<br>+// With PCH<br>+// RUN: %clang_cc1 -x c++-header -emit-pch -o %t %S/Inputs/typo.hpp<br>+// RUN: %clang_cc1 -include-pch %t -verify %s<br><br>Propchange: cfe/trunk/test/PCH/typo.cpp<br>------------------------------------------------------------------------------<br> svn:eol-style = native<br><br>Propchange: cfe/trunk/test/PCH/typo.cpp<br>------------------------------------------------------------------------------<br> svn:keywords = Id<br><br>Propchange: cfe/trunk/test/PCH/typo.cpp<br>------------------------------------------------------------------------------<br> svn:mime-type = text/plain<br><br>Added: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp?rev=134007&view=auto">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp?rev=134007&view=auto</a><br>==============================================================================<br>--- cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp (added)<br>+++ cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp Tue Jun 28 11:20:02 2011<br>@@ -0,0 +1,61 @@<br>+// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++0x-extensions %s<br>+<br>+namespace fizbin { class Foobar; } // expected-note{{'fizbin::Foobar' declared here}}<br>+Foobar *my_bar = new Foobar; // expected-error{{unknown type name 'Foobar'; did you mean 'fizbin::Foobar'?}} \<br>+ // expected-error{{expected a type}}<br>+<br>+namespace barstool { int toFoobar() { return 1; } } // expected-note 3 {{'barstool::toFoobar' declared here}}<br>+int Double(int x) { return x + x; }<br>+void empty() {<br>+ Double(toFoobar()); // expected-error{{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}<br>+}<br>+<br>+namespace fizbin {<br>+ namespace baztool { bool toFoobar() { return true; } } // expected-note{{'fizbin::baztool' declared here}}<br>+ namespace nested { bool moreFoobar() { return true; } } // expected-note{{'fizbin::nested::moreFoobar' declared here}}<br>+ namespace nested { bool lessFoobar() { return true; } } // expected-note{{'fizbin::nested' declared here}} \<br>+ // expected-note{{'fizbin::nested::lessFoobar' declared here}}<br>+ class dummy { // expected-note 2 {{'fizbin::dummy' declared here}}<br>+ public:<br>+ static bool moreFoobar() { return false; } // expected-note{{'moreFoobar' declared here}}<br>+ };<br>+}<br>+void Check() { // expected-note{{'Check' declared here}}<br>+ if (toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'toFoobar'; did you mean 'barstool::toFoobar'?}}<br>+ if (noFoobar()) Double(7); // expected-error{{use of undeclared identifier 'noFoobar'; did you mean 'barstool::toFoobar'?}}<br>+ if (moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'moreFoobar'; did you mean 'fizbin::nested::moreFoobar'}}<br>+ if (lessFoobar()) Double(7); // expected-error{{use of undeclared identifier 'lessFoobar'; did you mean 'fizbin::nested::lessFoobar'?}}<br>+ if (baztool::toFoobar()) Double(7); // expected-error{{use of undeclared identifier 'baztool'; did you mean 'fizbin::baztool'?}}<br>+ if (nested::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'nested'; did you mean 'fizbin::nested'?}}<br>+ if (dummy::moreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}}<br>+ if (dummy::mreFoobar()) Double(7); // expected-error{{use of undeclared identifier 'dummy'; did you mean 'fizbin::dummy'?}} \<br>+ // expected-error{{no member named 'mreFoobar' in 'fizbin::dummy'; did you mean 'moreFoobar'?}}<br>+ if (moFoobin()) Double(7); // expected-error{{use of undeclared identifier 'moFoobin'}}<br>+}<br>+<br>+void Alt() {<br>+ Cleck(); // expected-error{{{use of undeclared identifier 'Cleck'; did you mean 'Check'?}}<br>+}<br>+<br>+namespace N {<br>+ namespace inner {<br>+ class myvector { /* ... */ }; // expected-note{{'inner::myvector' declared here}}<br>+ }<br>+<br>+ void f() {<br>+ myvector v; // expected-error{{no type named 'myvector' in namespace 'N::inner'; did you mean 'inner::myvector'?}}<br>+ }<br>+}<br>+<br>+namespace realstd {<br>+ inline namespace __1 {<br>+ class mylinkedlist { /* ... */ }; // expected-note 2 {{'realstd::mylinkedlist' declared here}}<br>+ }<br>+<br>+ class linkedlist { /* ... */ };<br>+}<br>+<br>+void f() {<br>+ mylinkedlist v; // expected-error{{no type named 'mylinkedlist' in namespace 'realstd'; did you mean 'realstd::mylinkedlist'?}}<br>+ nylinkedlist w; // expected-error{{no type named 'nylinkedlist' in namespace 'realstd'; did you mean 'realstd::mylinkedlist'?}}<br>+}<br><br>Propchange: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp<br>------------------------------------------------------------------------------<br> svn:eol-style = native<br><br>Propchange: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp<br>------------------------------------------------------------------------------<br> svn:keywords = Id<br><br>Propchange: cfe/trunk/test/SemaCXX/missing-namespace-qualifier-typo-corrections.cpp<br>------------------------------------------------------------------------------<br> svn:mime-type = text/plain<br><br>Modified: cfe/trunk/test/SemaObjC/ivar-ref-misuse.m<br>URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ivar-ref-misuse.m?rev=134007&r1=134006&r2=134007&view=diff">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaObjC/ivar-ref-misuse.m?rev=134007&r1=134006&r2=134007&view=diff</a><br>==============================================================================<br>--- cfe/trunk/test/SemaObjC/ivar-ref-misuse.m (original)<br>+++ cfe/trunk/test/SemaObjC/ivar-ref-misuse.m Tue Jun 28 11:20:02 2011<br>@@ -1,6 +1,6 @@<br> // RUN: %clang_cc1 -fsyntax-only -verify %s<br><br>-@interface Sprite {<br>+@interface Sprite { // expected-note{{'Sprite' declared here}}<br> int sprite, spree;<br> int UseGlobalBar;<br> }<br>@@ -17,7 +17,8 @@<br> + (void)setFoo:(int)foo {<br> sprite = foo; // expected-error {{instance variable 'sprite' accessed in class method}}<br> spree = foo;<br>- Xsprite = foo; // expected-error {{use of undeclared identifier 'Xsprite'}} <br>+ Xsprite = foo; // expected-error {{unknown type name 'Xsprite'; did you mean 'Sprite'?}} \<br>+ // expected-error{{expected identifier or '('}}<br> UseGlobalBar = 10;<br> }<br> + (void)setSprite:(int)sprite {<br><br><br>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br></div></blockquote></div><br></div></div>_______________________________________________<br>cfe-commits mailing list<br><a href="mailto:cfe-commits@cs.uiuc.edu">cfe-commits@cs.uiuc.edu</a><br>http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits<br></blockquote></div><br></div></body></html>