<html><head></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">This was a real problem that I fixed in r134009.<div><br></div><div><span class="Apple-tab-span" style="white-space:pre"> </span>- Doug</div><div><br><div><div>On Jun 28, 2011, at 1:03 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; ">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><a href="http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits">http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits</a><br></blockquote></div><br></div></div></blockquote></div><br></div></body></html>