On 15 December 2014 at 18:12, Kaelyn Takata <[email protected]> wrote:
>
> In general this patch looks good. And it is probably time to kill the
> cache anyway now that so much of the typo correction bypasses it anyway
> (correction callbacks that implement a meaningful ValidateCandidate, and
> the delayed typo correction for the most part). A few things that should be
> cleaned up though:
>
> 1) The declaration of EmptyTypoCorrection
> in Sema::makeTypoCorrectionConsumer is unused,
>
> 2) The IsUnqualifiedLookup can be dropped from Sema::FailedCorrection now
> that it is unused within the function,
>
> 3) The EmptyTypoCorrection and ValidatingCallback variables
> in Sema::CorrectTypo can be dropped now that the third argument to
> Sema::FailedCorrection is unused, and
>
> 4) IsUnqualifiedLookup can be made a local variable
> within Sema::makeTypoCorrectionConsumer instead of a out-parameter and the
> corresponding variables in CorrectTypo and CorrectTypoDelayed can be
> removed, now that CorrectTypo doesn't need to know whether the lookup is
> qualified or not (which was simply passed along to various calls to
> FailedCorrection).
>

Done.


> However, as this patch is already fairly large (removing the cache, adding
> the new flag, and making use of it to reunify the two main typo correction
> test files) I'm fine with 2-4 being done in a separate cleanup commit.
>

I wrote the code to remove the cache first then the flag as an add on
afterwards. After hitting send I realized that I could split them apart and
land the new flag first. Let me know if you need me to do that.

The only concern I have with this patch is actually incidental to it:
> in test/CXX/class.access/class.friend/p11.cpp that the notes from the newly
> exposed suggestions are wrong--they are pointing to previous friend
> declarations (which had also been typo-corrected) instead of to the actual
> declarations of ::test2::foo and ::test2::bar. I suspect this is a
> relatively simple fix, probably a matter using the the
> primary/canonical/first delcaration instead of simply the most recent one
> for the NamedDecl descendants that are also Redeclarable (such as
> FunctionDecl and RecordDecl), though it is also an important one from a QoI
> perspective as that test demonstrates the "XYZ declared here" pointing to
> incorrect and potentially confusing locations.
>

Yes! That is certainly a bug, I think it's a bug in name lookup actually.
That's a problem for another day.

I tried adding getCanonicalDecl(), but it breaks other cases. If the first
declaration is a friend decl, then that one is now canonical and we will
put the note on the friend decl instead of on the non-friend decl after it.
For example:

error: 'note' diagnostics expected but not seen:
  File test/CXX/class.access/class.friend/p1.cpp Line 39: 'S2' declared here
  File test/CXX/class.access/class.friend/p1.cpp Line 39: 'S2' declared here
  File test/CXX/class.access/class.friend/p1.cpp Line 40: 'g2' declared here
  File test/CXX/class.access/class.friend/p1.cpp Line 40: 'g2' declared here
error: 'note' diagnostics seen but not expected:
  File test/CXX/class.access/class.friend/p1.cpp Line 36: 'g2' declared here
  File test/CXX/class.access/class.friend/p1.cpp Line 35: 'S2' declared here
  File test/CXX/class.access/class.friend/p1.cpp Line 36: 'g2' declared here
  File test/CXX/class.access/class.friend/p1.cpp Line 35: 'S2' declared here
8 errors generated.

I spent a while looking at the innards of name lookup to see what was
wrong, and the issue is that LookupDirect returns anything that was passed
in to makeDeclVisibleInContext before looking at other decls. Passing
friend functions to makeDeclVisibleIn the outer Context is the right thing
to do, it might be an ordering issue inside LookupQualifiedName or maybe we
shouldn't stop looking just because we found one, or maybe
findAcceptableDecl ought to do some more sorting instead of just filtering
based on visibility.

Nick

On Sat, Dec 13, 2014 at 2:47 AM, Nick Lewycky <[email protected]> wrote:
>
>> This patch removes Sema::UnqualifiedTyposCorrected.
>>
>> I'm not sure this is the right thing to do. As far as I can tell this
>> cache can't be made to be correct (wouldn't we need to invalidate it every
>> time a new decl is declared?) and I'm not convinced it saves us much
>> compile time. However, I'm not confident in my understanding of the code,
>> so please do push back if it is beneficial.
>>
>> One bug it fixes is a case where the same full-expression has the two
>> typos in the same identifier, and we emit the correction at the SourceRange
>> for the first typo twice instead of once for each place it's misspelled.
>> This is because the SourceRange is on the TypoCorrection, and the cache key
>> is an IdentifierInfo. Adding the SourceRange to the cache key wouldn't make
>> much sense because we wouldn't ever re-use it. (NB, I have similar feelings
>> about TypoCorrectionFailures which I am not touching in this patch. Why
>> would we do typo correction twice at the same location?)
>>
>> Removing it improves typo correction quality and there are changes to the
>> tests (see p11.cpp, and the last two tests in typo-correction) where it
>> fired. Because the cutoff for typos is a function of this cache, I move
>> that to a flag (-fspell-checking-limit=...) and turn the limit off entirely
>> to merge typo-correction-pt2.cpp and typo-correction.cpp. Also turn it up
>> from 20 to 50 to accommodate existing tests. Without caching, we run up the
>> counter more quickly.
>>
>> Please review!
>>
>> Nick
>>
>>
>
Index: include/clang/Basic/DiagnosticOptions.def
===================================================================
--- include/clang/Basic/DiagnosticOptions.def	(revision 224291)
+++ include/clang/Basic/DiagnosticOptions.def	(working copy)
@@ -81,6 +81,8 @@
 VALUE_DIAGOPT(TemplateBacktraceLimit, 32, DefaultTemplateBacktraceLimit)
 /// Limit depth of constexpr backtrace.
 VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit)
+/// Limit number of times to perform spell checking.
+VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit)
 
 VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops.
 /// Column limit for formatting message diagnostics, or 0 if unused.
@@ -92,4 +94,3 @@
 #undef SEMANTIC_DIAGOPT
 #undef SEMANTIC_ENUM_DIAGOPT
 #undef SEMANTIC_VALUE_DIAGOPT
-
Index: include/clang/Basic/DiagnosticOptions.h
===================================================================
--- include/clang/Basic/DiagnosticOptions.h	(revision 224291)
+++ include/clang/Basic/DiagnosticOptions.h	(working copy)
@@ -33,7 +33,8 @@
   enum { DefaultTabStop = 8, MaxTabStop = 100,
     DefaultMacroBacktraceLimit = 6,
     DefaultTemplateBacktraceLimit = 10,
-    DefaultConstexprBacktraceLimit = 10 };
+    DefaultConstexprBacktraceLimit = 10,
+    DefaultSpellCheckingLimit = 50 };
 
   // Define simple diagnostic options (with no accessors).
 #define DIAGOPT(Name, Bits, Default) unsigned Name : Bits;
Index: include/clang/Driver/CC1Options.td
===================================================================
--- include/clang/Driver/CC1Options.td	(revision 224291)
+++ include/clang/Driver/CC1Options.td	(working copy)
@@ -279,6 +279,8 @@
   HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">;
 def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">, MetaVarName<"<N>">,
   HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">;
+def fspell_checking_limit : Separate<["-"], "fspell-checking-limit">, MetaVarName<"<N>">,
+  HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (0 = no limit).">;
 def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">,
   HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
 def verify : Flag<["-"], "verify">,
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td	(revision 224291)
+++ include/clang/Driver/Options.td	(working copy)
@@ -862,6 +862,7 @@
 def fshow_column : Flag<["-"], "fshow-column">, Group<f_Group>, Flags<[CC1Option]>;
 def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group>;
 def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>;
+def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group<f_Group>;
 def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group<f_Group>;
 def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>;
 def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>,
Index: include/clang/Sema/Sema.h
===================================================================
--- include/clang/Sema/Sema.h	(revision 224291)
+++ include/clang/Sema/Sema.h	(working copy)
@@ -2630,7 +2630,7 @@
                              std::unique_ptr<CorrectionCandidateCallback> CCC,
                              DeclContext *MemberContext, bool EnteringContext,
                              const ObjCObjectPointerType *OPT,
-                             bool ErrorRecovery, bool &IsUnqualifiedLookup);
+                             bool ErrorRecovery);
 
 public:
   const TypoExprState &getTypoExprState(TypoExpr *TE) const;
@@ -2985,10 +2985,7 @@
 
   /// \brief Record the typo correction failure and return an empty correction.
   TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc,
-                                  bool RecordFailure = true,
-                                  bool IsUnqualifiedLookup = false) {
-    if (IsUnqualifiedLookup)
-      (void)UnqualifiedTyposCorrected[Typo];
+                                  bool RecordFailure = true) {
     if (RecordFailure)
       TypoCorrectionFailures[Typo].insert(TypoLoc);
     return TypoCorrection();
@@ -6685,17 +6682,6 @@
   /// \brief The number of typos corrected by CorrectTypo.
   unsigned TyposCorrected;
 
-  typedef llvm::DenseMap<IdentifierInfo *, TypoCorrection>
-    UnqualifiedTyposCorrectedMap;
-
-  /// \brief A cache containing the results of typo correction for unqualified
-  /// name lookup.
-  ///
-  /// The string is the string that we corrected to (which may be empty, if
-  /// there was no correction), while the boolean will be true when the
-  /// string represents a keyword.
-  UnqualifiedTyposCorrectedMap UnqualifiedTyposCorrected;
-
   typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet;
   typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations;
 
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp	(revision 224291)
+++ lib/Driver/Tools.cpp	(working copy)
@@ -3546,6 +3546,11 @@
     CmdArgs.push_back(A->getValue());
   }
 
+  if (Arg *A = Args.getLastArg(options::OPT_fspell_checking_limit_EQ)) {
+    CmdArgs.push_back("-fspell-checking-limit");
+    CmdArgs.push_back(A->getValue());
+  }
+
   // Pass -fmessage-length=.
   CmdArgs.push_back("-fmessage-length");
   if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) {
@@ -8306,4 +8311,3 @@
 
   C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs));
 }
-
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp	(revision 224291)
+++ lib/Frontend/CompilerInvocation.cpp	(working copy)
@@ -707,6 +707,9 @@
   Opts.ConstexprBacktraceLimit = getLastArgIntValue(
       Args, OPT_fconstexpr_backtrace_limit,
       DiagnosticOptions::DefaultConstexprBacktraceLimit, Diags);
+  Opts.SpellCheckingLimit = getLastArgIntValue(
+      Args, OPT_fspell_checking_limit,
+      DiagnosticOptions::DefaultSpellCheckingLimit, Diags);
   Opts.TabStop = getLastArgIntValue(Args, OPT_ftabstop,
                                     DiagnosticOptions::DefaultTabStop, Diags);
   if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
Index: lib/Sema/SemaLookup.cpp
===================================================================
--- lib/Sema/SemaLookup.cpp	(revision 224291)
+++ lib/Sema/SemaLookup.cpp	(working copy)
@@ -4023,8 +4023,7 @@
     Scope *S, CXXScopeSpec *SS,
     std::unique_ptr<CorrectionCandidateCallback> CCC,
     DeclContext *MemberContext, bool EnteringContext,
-    const ObjCObjectPointerType *OPT, bool ErrorRecovery,
-    bool &IsUnqualifiedLookup) {
+    const ObjCObjectPointerType *OPT, bool ErrorRecovery) {
 
   if (Diags.hasFatalErrorOccurred() || !getLangOpts().SpellChecking ||
       DisableTypoCorrection)
@@ -4068,6 +4067,14 @@
   if (getLangOpts().AltiVec && Typo->isStr("vector"))
     return nullptr;
 
+  // Provide a stop gap for files that are just seriously broken.  Trying
+  // to correct all typos can turn into a HUGE performance penalty, causing
+  // some files to take minutes to get rejected by the parser.
+  unsigned Limit = getDiagnostics().getDiagnosticOptions().SpellCheckingLimit;
+  if (Limit && TyposCorrected >= Limit)
+    return nullptr;
+  ++TyposCorrected;
+
   // If we're handling a missing symbol error, using modules, and the
   // special search all modules option is used, look for a missing import.
   if (ErrorRecovery && getLangOpts().Modules &&
@@ -4082,13 +4089,8 @@
       *this, TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
       EnteringContext);
 
-  // If a callback object considers an empty typo correction candidate to be
-  // viable, assume it does not do any actual validation of the candidates.
-  TypoCorrection EmptyCorrection;
-  bool ValidatingCallback = !isCandidateViable(CCCRef, EmptyCorrection);
-
   // Perform name lookup to find visible, similarly-named entities.
-  IsUnqualifiedLookup = false;
+  bool IsUnqualifiedLookup = false;
   DeclContext *QualifiedDC = MemberContext;
   if (MemberContext) {
     LookupVisibleDecls(MemberContext, LookupKind, *Consumer);
@@ -4103,46 +4105,9 @@
     if (!QualifiedDC)
       return nullptr;
 
-    // Provide a stop gap for files that are just seriously broken.  Trying
-    // to correct all typos can turn into a HUGE performance penalty, causing
-    // some files to take minutes to get rejected by the parser.
-    if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
-      return nullptr;
-    ++TyposCorrected;
-
     LookupVisibleDecls(QualifiedDC, LookupKind, *Consumer);
   } else {
     IsUnqualifiedLookup = true;
-    UnqualifiedTyposCorrectedMap::iterator Cached
-      = UnqualifiedTyposCorrected.find(Typo);
-    if (Cached != UnqualifiedTyposCorrected.end()) {
-      // Add the cached value, unless it's a keyword or fails validation. In the
-      // keyword case, we'll end up adding the keyword below.
-      if (Cached->second) {
-        if (!Cached->second.isKeyword() &&
-            isCandidateViable(CCCRef, Cached->second)) {
-          // Do not use correction that is unaccessible in the given scope.
-          NamedDecl *CorrectionDecl = Cached->second.getCorrectionDecl();
-          DeclarationNameInfo NameInfo(CorrectionDecl->getDeclName(),
-                                       CorrectionDecl->getLocation());
-          LookupResult R(*this, NameInfo, LookupOrdinaryName);
-          if (LookupName(R, S))
-            Consumer->addCorrection(Cached->second);
-        }
-      } else {
-        // Only honor no-correction cache hits when a callback that will validate
-        // correction candidates is not being used.
-        if (!ValidatingCallback)
-          return nullptr;
-      }
-    }
-    if (Cached == UnqualifiedTyposCorrected.end()) {
-      // Provide a stop gap for files that are just seriously broken.  Trying
-      // to correct all typos can turn into a HUGE performance penalty, causing
-      // some files to take minutes to get rejected by the parser.
-      if (TyposCorrected + UnqualifiedTyposCorrected.size() >= 20)
-        return nullptr;
-    }
   }
 
   // Determine whether we are going to search in the various namespaces for
@@ -4249,14 +4214,10 @@
   // for CTC_Unknown but not for CTC_ObjCMessageReceiver.
   bool ObjCMessageReceiver = CCC->WantObjCSuper && !CCC->WantRemainingKeywords;
 
-  TypoCorrection EmptyCorrection;
-  bool ValidatingCallback = !isCandidateViable(*CCC, EmptyCorrection);
-
   IdentifierInfo *Typo = TypoName.getName().getAsIdentifierInfo();
-  bool IsUnqualifiedLookup = false;
   auto Consumer = makeTypoCorrectionConsumer(
       TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
-      EnteringContext, OPT, Mode == CTK_ErrorRecovery, IsUnqualifiedLookup);
+      EnteringContext, OPT, Mode == CTK_ErrorRecovery);
 
   if (!Consumer)
     return TypoCorrection();
@@ -4263,8 +4224,7 @@
 
   // If we haven't found anything, we're done.
   if (Consumer->empty())
-    return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
-                            IsUnqualifiedLookup);
+    return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
 
   // Make sure the best edit distance (prior to adding any namespace qualifiers)
   // is not more that about a third of the length of the typo's identifier.
@@ -4271,8 +4231,7 @@
   unsigned ED = Consumer->getBestEditDistance(true);
   unsigned TypoLen = Typo->getName().size();
   if (ED > 0 && TypoLen / ED < 3)
-    return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
-                            IsUnqualifiedLookup);
+    return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
 
   TypoCorrection BestTC = Consumer->getNextCorrection();
   TypoCorrection SecondBestTC = Consumer->getNextCorrection();
@@ -4285,8 +4244,7 @@
     // If this was an unqualified lookup and we believe the callback
     // object wouldn't have filtered out possible corrections, note
     // that no correction was found.
-    return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
-                            IsUnqualifiedLookup && !ValidatingCallback);
+    return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
   }
 
   // If only a single name remains, return that result.
@@ -4299,10 +4257,6 @@
     if (ED == 0 && Result.isKeyword())
       return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
 
-    // Record the correction for unqualified lookup.
-    if (IsUnqualifiedLookup)
-      UnqualifiedTyposCorrected[Typo] = Result;
-
     TypoCorrection TC = Result;
     TC.setCorrectionRange(SS, TypoName);
     checkCorrectionVisibility(*this, TC);
@@ -4323,10 +4277,6 @@
         BestTC.getCorrection().getAsString() != "super")
       return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
 
-    // Record the correction for unqualified lookup.
-    if (IsUnqualifiedLookup)
-      UnqualifiedTyposCorrected[Typo] = BestTC;
-
     BestTC.setCorrectionRange(SS, TypoName);
     return BestTC;
   }
@@ -4334,8 +4284,7 @@
   // Record the failure's location if needed and return an empty correction. If
   // this was an unqualified lookup and we believe the callback object did not
   // filter out possible corrections, also cache the failure for the typo.
-  return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure,
-                          IsUnqualifiedLookup && !ValidatingCallback);
+  return FailedCorrection(Typo, TypoName.getLoc(), RecordFailure);
 }
 
 /// \brief Try to "correct" a typo in the source code by finding
@@ -4386,13 +4335,11 @@
   assert(CCC && "CorrectTypoDelayed requires a CorrectionCandidateCallback");
 
   TypoCorrection Empty;
-  bool IsUnqualifiedLookup = false;
   auto Consumer = makeTypoCorrectionConsumer(
       TypoName, LookupKind, S, SS, std::move(CCC), MemberContext,
       EnteringContext, OPT,
       /*SearchModules=*/(Mode == CTK_ErrorRecovery) && getLangOpts().Modules &&
-          getLangOpts().ModulesSearchAll,
-      IsUnqualifiedLookup);
+          getLangOpts().ModulesSearchAll);
 
   if (!Consumer || Consumer->empty())
     return nullptr;
Index: test/CXX/class.access/class.friend/p11.cpp
===================================================================
--- test/CXX/class.access/class.friend/p11.cpp	(revision 224291)
+++ test/CXX/class.access/class.friend/p11.cpp	(working copy)
@@ -23,7 +23,7 @@
 
   void foo() { // expected-note {{'::test2::foo' declared here}}
     struct S1 {
-      friend void foo(); // expected-error {{no matching function 'foo' found in local scope; did you mean '::test2::foo'?}}
+      friend void foo(); // expected-error {{no matching function 'foo' found in local scope; did you mean '::test2::foo'?}}  expected-note{{'::test2::foo' declared here}}
     };
 
     void foo(); // expected-note {{local declaration nearly matches}}
@@ -40,17 +40,17 @@
     {
       int foo;
       struct S3 {
-        friend void foo(); // expected-error {{no matching function found in local scope}}
+        friend void foo(); // expected-error {{no matching function 'foo' found in local scope; did you mean '::test2::foo'?}}
       };
     }
 
     struct S4 {
-      friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}}
+      friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}}  expected-note 2 {{'::test2::bar' declared here}}
     };
 
     { void bar(); }
     struct S5 {
-      friend void bar(); // expected-error {{no matching function found in local scope}}
+      friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}}
     };
 
     {
@@ -68,7 +68,7 @@
       };
     };
 
-    void bar(); // expected-note {{'bar' declared here}}
+    void bar();  // expected-note {{'bar' declared here}}
     struct S8 {
       struct Inner {
         friend void bar();
@@ -85,7 +85,7 @@
       void quux() {}
       void foo() {
         struct Inner1 {
-          friend void bar(); // expected-error {{no matching function found in local scope}}
+          friend void bar(); // expected-error {{no matching function 'bar' found in local scope; did you mean '::test2::bar'?}}
           friend void quux(); // expected-error {{no matching function found in local scope}}
         };
 
Index: test/SemaCXX/typo-correction.cpp
===================================================================
--- test/SemaCXX/typo-correction.cpp	(revision 224291)
+++ test/SemaCXX/typo-correction.cpp	(working copy)
@@ -1,8 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
-//
-// WARNING: Do not add more typo correction test cases to this file lest you run
-// afoul the hard-coded limit (escape hatch) of 20 different typos whose
-// correction was attempted by Sema::CorrectTypo
+// RUN: %clang_cc1 -fspell-checking-limit 0 -verify -Wno-c++11-extensions %s
 
 namespace PR21817{
 int a(-rsing[2]); // expected-error {{undeclared identifier 'rsing'; did you mean 'using'?}}
@@ -102,7 +98,7 @@
 // Demonstrate a case where using only the cached value returns the wrong thing
 // when the cached value was the result of a previous callback object that only
 // accepts a subset of the current callback object.
-namespace {
+namespace cache_invalidation_test {
 using namespace unknown_type_test;
 void bar(long i);
 void before_caching_classname() {
@@ -289,13 +285,352 @@
   }
 }
 
-// This test should have one correction, followed by an error without a
-// suggestion due to exceeding the maximum number of typos for which correction
-// is attempted.
-namespace CorrectTypo_has_reached_its_limit {
-int flibberdy();  // expected-note{{'flibberdy' declared here}}
-int no_correction() {
-  return hibberdy() +  // expected-error{{use of undeclared identifier 'hibberdy'; did you mean 'flibberdy'?}}
-         gibberdy();  // expected-error-re{{use of undeclared identifier 'gibberdy'{{$}}}}
+namespace PR12951 {
+// If there are two corrections that have the same identifier and edit distance
+// and only differ by their namespaces, don't suggest either as a correction
+// since both are equally likely corrections.
+namespace foobar { struct Thing {}; }
+namespace bazquux { struct Thing {}; }
+void f() { Thing t; } // expected-error{{unknown type name 'Thing'}}
+}
+
+namespace bogus_keyword_suggestion {
+void test() {
+   status = "OK";  // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
+   return status;  // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
+ }
+}
+
+namespace PR13387 {
+struct A {
+  void CreateFoo(float, float);
+  void CreateBar(float, float);
 };
+struct B : A {
+  using A::CreateFoo;
+  void CreateFoo(int, int);  // expected-note {{'CreateFoo' declared here}}
+};
+void f(B &x) {
+  x.Createfoo(0,0);  // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}}
 }
+}
+
+struct DataStruct {void foo();};
+struct T {
+ DataStruct data_struct;
+ void f();
+};
+// should be void T::f();
+void f() {
+ data_struct->foo();  // expected-error-re{{use of undeclared identifier 'data_struct'{{$}}}}
+}
+
+namespace PR12287 {
+class zif {
+  void nab(int);
+};
+void nab();  // expected-note{{'::PR12287::nab' declared here}}
+void zif::nab(int) {
+  nab();  // expected-error{{too few arguments to function call, expected 1, have 0; did you mean '::PR12287::nab'?}}
+}
+}
+
+namespace TemplateFunction {
+template <class T>
+void A(T) { }  // expected-note {{'::TemplateFunction::A' declared here}}
+
+template <class T>
+void B(T) { }  // expected-note {{'::TemplateFunction::B' declared here}}
+
+class Foo {
+ public:
+  void A(int, int) {}
+  void B() {}
+};
+
+void test(Foo F, int num) {
+  F.A(num);  // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::A'?}}
+  F.B(num);  // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::B'?}}
+}
+}
+namespace using_suggestion_val_dropped_specifier {
+void FFF() {} // expected-note {{'::using_suggestion_val_dropped_specifier::FFF' declared here}}
+namespace N { }
+using N::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_specifier::N'; did you mean '::using_suggestion_val_dropped_specifier::FFF'?}}
+}
+
+namespace class_member_typo_corrections {
+class Outer {
+public:
+  class Inner {};  // expected-note {{'Outer::Inner' declared here}}
+  Inner MyMethod(Inner arg);
+};
+
+Inner Outer::MyMethod(Inner arg) {  // expected-error {{unknown type name 'Inner'; did you mean 'Outer::Inner'?}}
+  return Inner();
+}
+
+class Result {
+public:
+  enum ResultType {
+    ENTITY,  // expected-note {{'Result::ENTITY' declared here}}
+    PREDICATE,  // expected-note {{'Result::PREDICATE' declared here}}
+    LITERAL  // expected-note {{'Result::LITERAL' declared here}}
+  };
+
+  ResultType type();
+};
+
+void test() {
+  Result result_cell;
+  switch (result_cell.type()) {
+  case ENTITY:  // expected-error {{use of undeclared identifier 'ENTITY'; did you mean 'Result::ENTITY'?}}
+  case LITERAL:  // expected-error {{use of undeclared identifier 'LITERAL'; did you mean 'Result::LITERAL'?}}
+  case PREDICAT:  // expected-error {{use of undeclared identifier 'PREDICAT'; did you mean 'Result::PREDICATE'?}}
+    break;
+  }
+}
+
+class Figure {
+  enum ResultType {
+    SQUARE,
+    TRIANGLE,
+    CIRCLE
+  };
+
+public:
+  ResultType type();
+};
+
+void testAccess() {
+  Figure obj;
+  switch (obj.type()) {  // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}}
+  case SQUARE:  // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}}
+  case TRIANGLE:  // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}}
+  case CIRCE:  // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}}
+    break;
+  }
+}
+}
+
+long readline(const char *, char *, unsigned long);
+void assign_to_unknown_var() {
+    deadline_ = 1;  // expected-error-re {{use of undeclared identifier 'deadline_'{{$}}}}
+}
+
+namespace no_ns_before_dot {
+namespace re2 {}
+void test() {
+    req.set_check(false);  // expected-error-re {{use of undeclared identifier 'req'{{$}}}}
+}
+}
+
+namespace PR17394 {
+  class A {
+  protected:
+    long zzzzzzzzzz;
+  };
+  class B : private A {};
+  B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{}
+}
+
+namespace correct_fields_in_member_funcs {
+struct S {
+  int my_member;  // expected-note {{'my_member' declared here}}
+  void f() { my_menber = 1; }  // expected-error {{use of undeclared identifier 'my_menber'; did you mean 'my_member'?}}
+};
+}
+
+namespace PR17019 {
+  template<class F>
+  struct evil {
+    evil(F de) {  // expected-note {{'de' declared here}}
+      de_;  // expected-error {{use of undeclared identifier 'de_'; did you mean 'de'?}} \
+            // expected-warning {{expression result unused}}
+    }
+    ~evil() {
+      de_->bar()  // expected-error {{use of undeclared identifier 'de_'}}
+    }
+  };
+
+  void meow() {
+    evil<int> Q(0); // expected-note {{in instantiation of member function}}
+  }
+}
+
+namespace fix_class_name_qualifier {
+class MessageHeaders {};
+class MessageUtils {
+ public:
+  static void ParseMessageHeaders(int, int); // expected-note {{'MessageUtils::ParseMessageHeaders' declared here}}
+};
+
+void test() {
+  // No, we didn't mean to call MessageHeaders::MessageHeaders.
+  MessageHeaders::ParseMessageHeaders(5, 4); // expected-error {{no member named 'ParseMessageHeaders' in 'fix_class_name_qualifier::MessageHeaders'; did you mean 'MessageUtils::ParseMessageHeaders'?}}
+}
+}
+
+namespace PR18213 {  // expected-note {{'PR18213' declared here}}
+struct WrapperInfo {
+  int i;
+};
+
+template <typename T> struct Wrappable {
+  static WrapperInfo kWrapperInfo;
+};
+
+// Note the space before "::PR18213" is intended and needed, as it highlights
+// the actual typo, which is the leading "::".
+// TODO: Suggest removing the "::" from "::PR18213" (the right correction)
+// instead of incorrectly suggesting dropping "PR18213::WrapperInfo::".
+template <>
+PR18213::WrapperInfo ::PR18213::Wrappable<int>::kWrapperInfo = { 0 };  // expected-error {{no member named 'PR18213' in 'PR18213::WrapperInfo'; did you mean simply 'PR18213'?}} \
+                                                                       // expected-error {{C++ requires a type specifier for all declarations}}
+}
+
+namespace PR18651 {
+struct {
+  int x;
+} a, b;
+
+int y = x;  // expected-error-re {{use of undeclared identifier 'x'{{$}}}}
+}
+
+namespace PR18685 {
+template <class C, int I, int J>
+class SetVector {
+ public:
+  SetVector() {}
+};
+
+template <class C, int I>
+class SmallSetVector : public SetVector<C, I, 8> {};
+
+class foo {};
+SmallSetVector<foo*, 2> fooSet;
+}
+
+PR18685::BitVector Map;  // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}}
+
+namespace shadowed_template {
+template <typename T> class Fizbin {};  // expected-note {{'::shadowed_template::Fizbin' declared here}}
+class Baz {
+   int Fizbin();
+   // TODO: Teach the parser to recover from the typo correction instead of
+   // continuing to treat the template name as an implicit-int declaration.
+   Fizbin<int> qux;  // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \
+                     // expected-error {{expected member name or ';' after declaration specifiers}}
+};
+}
+
+namespace PR18852 {
+void func() {
+  struct foo {
+    void bar() {}
+  };
+  bar();  // expected-error-re {{use of undeclared identifier 'bar'{{$}}}}
+}
+
+class Thread {
+ public:
+  void Start();
+  static void Stop();  // expected-note {{'Thread::Stop' declared here}}
+};
+
+class Manager {
+ public:
+  void Start(int);  // expected-note {{'Start' declared here}}
+  void Stop(int);  // expected-note {{'Stop' declared here}}
+};
+
+void test(Manager *m) {
+  // Don't suggest Thread::Start as a correction just because it has the same
+  // (unqualified) name and accepts the right number of args; this is a method
+  // call on an object in an unrelated class.
+  m->Start();  // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
+  m->Stop();  // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
+  Stop();  // expected-error {{use of undeclared identifier 'Stop'; did you mean 'Thread::Stop'?}}
+}
+
+}
+
+namespace std {
+class bernoulli_distribution {
+ public:
+  double p() const;
+};
+}
+void test() {
+  // Make sure that typo correction doesn't suggest changing 'p' to
+  // 'std::bernoulli_distribution::p' as that is most likely wrong.
+  if (p)  // expected-error-re {{use of undeclared identifier 'p'{{$}}}}
+    return;
+}
+
+namespace PR19681 {
+  struct TypoA {};
+  struct TypoB {
+    void test();
+  private:
+    template<typename T> void private_memfn(T);  // expected-note{{declared here}}
+  };
+  void TypoB::test() {
+    // FIXME: should suggest 'PR19681::TypoB::private_memfn' instead of '::PR19681::TypoB::private_memfn'
+    (void)static_cast<void(TypoB::*)(int)>(&TypoA::private_memfn);  // expected-error{{no member named 'private_memfn' in 'PR19681::TypoA'; did you mean '::PR19681::TypoB::private_memfn'?}}
+  }
+}
+
+namespace testWantFunctionLikeCasts {
+  long test(bool a) {
+    if (a)
+      return struc(5.7);  // expected-error-re {{use of undeclared identifier 'struc'{{$}}}}
+    else
+      return lon(8.0);  // expected-error {{use of undeclared identifier 'lon'; did you mean 'long'?}}
+  }
+}
+
+namespace testCXXDeclarationSpecifierParsing {
+namespace test {
+  struct SomeSettings {};  // expected-note {{'test::SomeSettings' declared here}}
+}
+class Test {};
+int bar() {
+  Test::SomeSettings some_settings; // expected-error {{no type named 'SomeSettings' in 'testCXXDeclarationSpecifierParsing::Test'; did you mean 'test::SomeSettings'?}}
+}
+}
+
+namespace testNonStaticMemberHandling {
+struct Foo {
+  bool usesMetadata;  // expected-note {{'usesMetadata' declared here}}
+};
+int test(Foo f) {
+  if (UsesMetadata)  // expected-error-re {{use of undeclared identifier 'UsesMetadata'{{$}}}}
+    return 5;
+  if (f.UsesMetadata)  // expected-error {{no member named 'UsesMetadata' in 'testNonStaticMemberHandling::Foo'; did you mean 'usesMetadata'?}}
+    return 11;
+  return 0;
+}
+};
+
+namespace testMemberExprDeclarationNameInfo {
+  // The AST should only have the corrected name with no mention of 'data_'.
+  void f(int);
+  struct S {
+    int data;  // expected-note 2{{'data' declared here}}
+    void m_fn1() {
+      data_  // expected-error {{use of undeclared identifier 'data_'}}
+          [] =  // expected-error {{expected expression}}
+          f(data_);  // expected-error {{use of undeclared identifier 'data_'}}
+    }
+  };
+}
+
+namespace testArraySubscriptIndex {
+  struct S {
+    int data;  // expected-note {{'data' declared here}}
+    void m_fn1() {
+      (+)[data_];  // expected-error{{expected expression}} expected-error {{use of undeclared identifier 'data_'; did you mean 'data'}}
+    }
+  };
+}
Index: test/SemaCXX/typo-correction-pt2.cpp
===================================================================
--- test/SemaCXX/typo-correction-pt2.cpp	(revision 224291)
+++ test/SemaCXX/typo-correction-pt2.cpp	(working copy)
@@ -1,358 +0,0 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -Wno-c++11-extensions %s
-//
-// FIXME: This file is overflow from test/SemaCXX/typo-correction.cpp due to a
-// hard-coded limit of 20 different typo corrections Sema::CorrectTypo will
-// attempt within a single file (which is to avoid having very broken files take
-// minutes to finally be rejected by the parser).
-
-namespace PR12951 {
-// If there are two corrections that have the same identifier and edit distance
-// and only differ by their namespaces, don't suggest either as a correction
-// since both are equally likely corrections.
-namespace foobar { struct Thing {}; }
-namespace bazquux { struct Thing {}; }
-void f() { Thing t; } // expected-error{{unknown type name 'Thing'}}
-}
-
-namespace bogus_keyword_suggestion {
-void test() {
-   status = "OK";  // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
-   return status;  // expected-error-re {{use of undeclared identifier 'status'{{$}}}}
- }
-}
-
-namespace PR13387 {
-struct A {
-  void CreateFoo(float, float);
-  void CreateBar(float, float);
-};
-struct B : A {
-  using A::CreateFoo;
-  void CreateFoo(int, int);  // expected-note {{'CreateFoo' declared here}}
-};
-void f(B &x) {
-  x.Createfoo(0,0);  // expected-error {{no member named 'Createfoo' in 'PR13387::B'; did you mean 'CreateFoo'?}}
-}
-}
-
-struct DataStruct {void foo();};
-struct T {
- DataStruct data_struct;
- void f();
-};
-// should be void T::f();
-void f() {
- data_struct->foo();  // expected-error-re{{use of undeclared identifier 'data_struct'{{$}}}}
-}
-
-namespace PR12287 {
-class zif {
-  void nab(int);
-};
-void nab();  // expected-note{{'::PR12287::nab' declared here}}
-void zif::nab(int) {
-  nab();  // expected-error{{too few arguments to function call, expected 1, have 0; did you mean '::PR12287::nab'?}}
-}
-}
-
-namespace TemplateFunction {
-template <class T>
-void A(T) { }  // expected-note {{'::TemplateFunction::A' declared here}}
-
-template <class T>
-void B(T) { }  // expected-note {{'::TemplateFunction::B' declared here}}
-
-class Foo {
- public:
-  void A(int, int) {}
-  void B() {}
-};
-
-void test(Foo F, int num) {
-  F.A(num);  // expected-error {{too few arguments to function call, expected 2, have 1; did you mean '::TemplateFunction::A'?}}
-  F.B(num);  // expected-error {{too many arguments to function call, expected 0, have 1; did you mean '::TemplateFunction::B'?}}
-}
-}
-namespace using_suggestion_val_dropped_specifier {
-void FFF() {} // expected-note {{'::using_suggestion_val_dropped_specifier::FFF' declared here}}
-namespace N { }
-using N::FFF; // expected-error {{no member named 'FFF' in namespace 'using_suggestion_val_dropped_specifier::N'; did you mean '::using_suggestion_val_dropped_specifier::FFF'?}}
-}
-
-namespace class_member_typo_corrections {
-class Outer {
-public:
-  class Inner {};  // expected-note {{'Outer::Inner' declared here}}
-  Inner MyMethod(Inner arg);
-};
-
-Inner Outer::MyMethod(Inner arg) {  // expected-error {{unknown type name 'Inner'; did you mean 'Outer::Inner'?}}
-  return Inner();
-}
-
-class Result {
-public:
-  enum ResultType {
-    ENTITY,  // expected-note {{'Result::ENTITY' declared here}}
-    PREDICATE,  // expected-note {{'Result::PREDICATE' declared here}}
-    LITERAL  // expected-note {{'Result::LITERAL' declared here}}
-  };
-
-  ResultType type();
-};
-
-void test() {
-  Result result_cell;
-  switch (result_cell.type()) {
-  case ENTITY:  // expected-error {{use of undeclared identifier 'ENTITY'; did you mean 'Result::ENTITY'?}}
-  case LITERAL:  // expected-error {{use of undeclared identifier 'LITERAL'; did you mean 'Result::LITERAL'?}}
-  case PREDICAT:  // expected-error {{use of undeclared identifier 'PREDICAT'; did you mean 'Result::PREDICATE'?}}
-    break;
-  }
-}
-
-class Figure {
-  enum ResultType {
-    SQUARE,
-    TRIANGLE,
-    CIRCLE
-  };
-
-public:
-  ResultType type();
-};
-
-void testAccess() {
-  Figure obj;
-  switch (obj.type()) {  // expected-warning {{enumeration values 'SQUARE', 'TRIANGLE', and 'CIRCLE' not handled in switch}}
-  case SQUARE:  // expected-error-re {{use of undeclared identifier 'SQUARE'{{$}}}}
-  case TRIANGLE:  // expected-error-re {{use of undeclared identifier 'TRIANGLE'{{$}}}}
-  case CIRCE:  // expected-error-re {{use of undeclared identifier 'CIRCE'{{$}}}}
-    break;
-  }
-}
-}
-
-long readline(const char *, char *, unsigned long);
-void assign_to_unknown_var() {
-    deadline_ = 1;  // expected-error-re {{use of undeclared identifier 'deadline_'{{$}}}}
-}
-
-namespace no_ns_before_dot {
-namespace re2 {}
-void test() {
-    req.set_check(false);  // expected-error-re {{use of undeclared identifier 'req'{{$}}}}
-}
-}
-
-namespace PR17394 {
-  class A {
-  protected:
-    long zzzzzzzzzz;
-  };
-  class B : private A {};
-  B zzzzzzzzzy<>; // expected-error {{expected ';' after top level declarator}}{}
-}
-
-namespace correct_fields_in_member_funcs {
-struct S {
-  int my_member;  // expected-note {{'my_member' declared here}}
-  void f() { my_menber = 1; }  // expected-error {{use of undeclared identifier 'my_menber'; did you mean 'my_member'?}}
-};
-}
-
-namespace PR17019 {
-  template<class F>
-  struct evil {
-    evil(F de) {  // expected-note {{'de' declared here}}
-      de_;  // expected-error {{use of undeclared identifier 'de_'; did you mean 'de'?}} \
-            // expected-warning {{expression result unused}}
-    }
-    ~evil() {
-      de_->bar()  // expected-error {{use of undeclared identifier 'de_'}}
-    }
-  };
-
-  void meow() {
-    evil<int> Q(0); // expected-note {{in instantiation of member function}}
-  }
-}
-
-namespace fix_class_name_qualifier {
-class MessageHeaders {};
-class MessageUtils {
- public:
-  static void ParseMessageHeaders(int, int); // expected-note {{'MessageUtils::ParseMessageHeaders' declared here}}
-};
-
-void test() {
-  // No, we didn't mean to call MessageHeaders::MessageHeaders.
-  MessageHeaders::ParseMessageHeaders(5, 4); // expected-error {{no member named 'ParseMessageHeaders' in 'fix_class_name_qualifier::MessageHeaders'; did you mean 'MessageUtils::ParseMessageHeaders'?}}
-}
-}
-
-namespace PR18213 {  // expected-note {{'PR18213' declared here}}
-struct WrapperInfo {
-  int i;
-};
-
-template <typename T> struct Wrappable {
-  static WrapperInfo kWrapperInfo;
-};
-
-// Note the space before "::PR18213" is intended and needed, as it highlights
-// the actual typo, which is the leading "::".
-// TODO: Suggest removing the "::" from "::PR18213" (the right correction)
-// instead of incorrectly suggesting dropping "PR18213::WrapperInfo::".
-template <>
-PR18213::WrapperInfo ::PR18213::Wrappable<int>::kWrapperInfo = { 0 };  // expected-error {{no member named 'PR18213' in 'PR18213::WrapperInfo'; did you mean simply 'PR18213'?}} \
-                                                                       // expected-error {{C++ requires a type specifier for all declarations}}
-}
-
-namespace PR18651 {
-struct {
-  int x;
-} a, b;
-
-int y = x;  // expected-error-re {{use of undeclared identifier 'x'{{$}}}}
-}
-
-namespace PR18685 {
-template <class C, int I, int J>
-class SetVector {
- public:
-  SetVector() {}
-};
-
-template <class C, int I>
-class SmallSetVector : public SetVector<C, I, 8> {};
-
-class foo {};
-SmallSetVector<foo*, 2> fooSet;
-}
-
-PR18685::BitVector Map;  // expected-error-re {{no type named 'BitVector' in namespace 'PR18685'{{$}}}}
-
-namespace shadowed_template {
-template <typename T> class Fizbin {};  // expected-note {{'::shadowed_template::Fizbin' declared here}}
-class Baz {
-   int Fizbin();
-   // TODO: Teach the parser to recover from the typo correction instead of
-   // continuing to treat the template name as an implicit-int declaration.
-   Fizbin<int> qux;  // expected-error {{unknown type name 'Fizbin'; did you mean '::shadowed_template::Fizbin'?}} \
-                     // expected-error {{expected member name or ';' after declaration specifiers}}
-};
-}
-
-namespace PR18852 {
-void func() {
-  struct foo {
-    void bar() {}
-  };
-  bar();  // expected-error-re {{use of undeclared identifier 'bar'{{$}}}}
-}
-
-class Thread {
- public:
-  void Start();
-  static void Stop();  // expected-note {{'Thread::Stop' declared here}}
-};
-
-class Manager {
- public:
-  void Start(int);  // expected-note {{'Start' declared here}}
-  void Stop(int);  // expected-note {{'Stop' declared here}}
-};
-
-void test(Manager *m) {
-  // Don't suggest Thread::Start as a correction just because it has the same
-  // (unqualified) name and accepts the right number of args; this is a method
-  // call on an object in an unrelated class.
-  m->Start();  // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
-  m->Stop();  // expected-error-re {{too few arguments to function call, expected 1, have 0{{$}}}}
-  Stop();  // expected-error {{use of undeclared identifier 'Stop'; did you mean 'Thread::Stop'?}}
-}
-
-}
-
-namespace std {
-class bernoulli_distribution {
- public:
-  double p() const;
-};
-}
-void test() {
-  // Make sure that typo correction doesn't suggest changing 'p' to
-  // 'std::bernoulli_distribution::p' as that is most likely wrong.
-  if (p)  // expected-error-re {{use of undeclared identifier 'p'{{$}}}}
-    return;
-}
-
-namespace PR19681 {
-  struct TypoA {};
-  struct TypoB {
-    void test();
-  private:
-    template<typename T> void private_memfn(T);  // expected-note{{declared here}}
-  };
-  void TypoB::test() {
-    // FIXME: should suggest 'PR19681::TypoB::private_memfn' instead of '::PR19681::TypoB::private_memfn'
-    (void)static_cast<void(TypoB::*)(int)>(&TypoA::private_memfn);  // expected-error{{no member named 'private_memfn' in 'PR19681::TypoA'; did you mean '::PR19681::TypoB::private_memfn'?}}
-  }
-}
-
-namespace testWantFunctionLikeCasts {
-  long test(bool a) {
-    if (a)
-      return struc(5.7);  // expected-error-re {{use of undeclared identifier 'struc'{{$}}}}
-    else
-      return lon(8.0);  // expected-error {{use of undeclared identifier 'lon'; did you mean 'long'?}}
-  }
-}
-
-namespace testCXXDeclarationSpecifierParsing {
-namespace test {
-  struct SomeSettings {};  // expected-note {{'test::SomeSettings' declared here}}
-}
-class Test {};
-int bar() {
-  Test::SomeSettings some_settings; // expected-error {{no type named 'SomeSettings' in 'testCXXDeclarationSpecifierParsing::Test'; did you mean 'test::SomeSettings'?}}
-}
-}
-
-namespace testNonStaticMemberHandling {
-struct Foo {
-  bool usesMetadata;  // expected-note {{'usesMetadata' declared here}}
-};
-int test(Foo f) {
-  if (UsesMetadata)  // expected-error-re {{use of undeclared identifier 'UsesMetadata'{{$}}}}
-    return 5;
-  if (f.UsesMetadata)  // expected-error {{no member named 'UsesMetadata' in 'testNonStaticMemberHandling::Foo'; did you mean 'usesMetadata'?}}
-    return 11;
-  return 0;
-}
-};
-
-namespace testMemberExprDeclarationNameInfo {
-  // The AST should only have the corrected name with no mention of 'data_'.
-  // FIXME: the second typo is being printed out with the location of the first
-  // because the TypoCorrection objects contain the SourceRange but the
-  // UnqualifiedTyposCorrected cache is keyed on IdentifierInfo.
-  void f(int);
-  struct S {
-    int data;  // expected-note 2{{'data' declared here}}
-    void m_fn1() {
-      data_[] =  // expected-error 2{{use of undeclared identifier 'data_'}}  expected-error {{expected expression}}
-          f(data_);
-    }
-  };
-}
-
-namespace testArraySubscriptIndex {
-  struct S {
-    int foodata;  // expected-note {{'foodata' declared here}}
-    void m_fn1() {
-      (+)[foodata_];  // expected-error{{expected expression}} expected-error {{use of undeclared identifier 'foodata_'; did you mean 'foodata'}}
-    }
-  };
-}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to