diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td
index 3dc03fa..c79cb43 100644
--- a/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1379,7 +1379,13 @@ def err_for_range_member_begin_end_mismatch : Error<
   "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">;
 def err_for_range_begin_end_types_differ : Error<
   "'begin' and 'end' must return the same type (got %0 and %1)">;
+def err_for_range_invalid: Error<
+  "invalid range expression of type %0">;
+def note_for_range_adl_failure: Note<
+  "no viable '%select{begin|end}0' function for range of type %1">;
 def note_for_range_type : Note<"range has type %0">;
+def note_for_range_type_is_pointer : Note<
+  "range expression is of type %0; did you mean to dereference it with '*'?">;
 def note_for_range_begin_end : Note<
   "selected '%select{begin|end}0' %select{function|template }1%2 with iterator type %3">;
 
@@ -5617,4 +5623,3 @@ def err_module_private_definition : Error<
 }
 
 } // end of sema component.
-
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index f0d3213..cb2023c 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -1911,7 +1911,23 @@ public:
                                      Expr **Args, unsigned NumArgs,
                                      SourceLocation RParenLoc,
                                      Expr *ExecConfig,
-                                     bool AllowTypoCorrection=true);
+                                     bool AllowTypoCorrection=true,
+                                     bool InRangeExpr=false);
+
+  ExprResult callExprFromCandidateSet(Scope *S, Expr *Fn,
+                                     UnresolvedLookupExpr *ULE,
+                                     SourceLocation LParenLoc,
+                                     Expr **Args, unsigned NumArgs,
+                                     SourceLocation RParenLoc,
+                                     Expr *ExecConfig, bool AllowTypoCorrection,
+                                     OverloadCandidateSet *CandidateSet,
+                                     bool InRangeExpr);
+
+  bool buildOverloadedCallSet(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+                              Expr **Args, unsigned NumArgs,
+                              SourceLocation RParenLoc,
+                              OverloadCandidateSet *CandidateSet,
+                              ExprResult *Result);
 
   ExprResult CreateOverloadedUnaryOp(SourceLocation OpLoc,
                                      unsigned Opc,
diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp
index 2ead6a6..cf6e2fa 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -14,6 +14,7 @@
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/Lookup.h"
 #include "clang/Sema/Initialization.h"
+#include "clang/Sema/Overload.h"
 #include "clang/Sema/Template.h"
 #include "clang/Sema/TemplateDeduction.h"
 #include "clang/Basic/Diagnostic.h"
@@ -9685,55 +9686,29 @@ BuildRecoveryCallExpr(Sema &SemaRef, Scope *S, Expr *Fn,
                                RParenLoc);
 }
 
-/// ResolveOverloadedCallFn - Given the call expression that calls Fn
-/// (which eventually refers to the declaration Func) and the call
-/// arguments Args/NumArgs, attempt to resolve the function call down
-/// to a specific function. If overload resolution succeeds, returns
-/// the function declaration produced by overload
-/// resolution. Otherwise, emits diagnostics, deletes all of the
-/// arguments and Fn, and returns NULL.
-ExprResult
-Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
-                              SourceLocation LParenLoc,
+// Constructs and populates an OverloadedCandidateSet from the given function.
+// Returns true when an the ExprResult output parameter has been set.
+bool Sema::buildOverloadedCallSet(Scope *S, Expr *Fn,
+                                  UnresolvedLookupExpr *ULE,
                               Expr **Args, unsigned NumArgs,
                               SourceLocation RParenLoc,
-                              Expr *ExecConfig,
-                              bool AllowTypoCorrection) {
-#ifndef NDEBUG
-  if (ULE->requiresADL()) {
-    // To do ADL, we must have found an unqualified name.
-    assert(!ULE->getQualifier() && "qualified name with ADL");
-
-    // We don't perform ADL for implicit declarations of builtins.
-    // Verify that this was correctly set up.
-    FunctionDecl *F;
-    if (ULE->decls_begin() + 1 == ULE->decls_end() &&
-        (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
-        F->getBuiltinID() && F->isImplicit())
-      llvm_unreachable("performing ADL for builtin");
-
-    // We don't perform ADL in C.
-    assert(getLangOpts().CPlusPlus && "ADL enabled in C");
-  } else
-    assert(!ULE->isStdAssociatedNamespace() &&
-           "std is associated namespace but not doing ADL");
-#endif
-
+                                  OverloadCandidateSet *CandidateSet,
+                                  ExprResult *Result) {
   UnbridgedCastsSet UnbridgedCasts;
-  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts))
-    return ExprError();
-
-  OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+  if (checkArgPlaceholdersForOverload(*this, Args, NumArgs, UnbridgedCasts)) {
+    *Result = ExprError();
+    return true;
+  }
 
   // Add the functions denoted by the callee to the set of candidate
   // functions, including those from argument-dependent lookup.
   AddOverloadedCallCandidates(ULE, llvm::makeArrayRef(Args, NumArgs),
-                              CandidateSet);
+                              *CandidateSet);
 
   // If we found nothing, try to recover.
   // BuildRecoveryCallExpr diagnoses the error itself, so we just bail
   // out if it fails.
-  if (CandidateSet.empty()) {
+  if (CandidateSet->empty()) {
     // In Microsoft mode, if we are inside a template class member function then
     // create a type dependent CallExpr. The goal is to postpone name lookup
     // to instantiation time to be able to search into type dependent base
@@ -9744,32 +9719,49 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
                                           Context.DependentTy, VK_RValue,
                                           RParenLoc);
       CE->setTypeDependent(true);
-      return Owned(CE);
+      *Result = Owned(CE);
+      return true;
     }
-    return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc,
-                                 llvm::MutableArrayRef<Expr *>(Args, NumArgs),
-                                 RParenLoc, /*EmptyLookup=*/true,
-                                 AllowTypoCorrection);
+    return false;
   }
 
   UnbridgedCasts.restore();
+  return false;
+}
+
+// Attempts to resolve overloaded functions, given the set of candidates.
+// Returns the resolved call expression or an ExprError().
+ExprResult Sema::callExprFromCandidateSet(Scope *S, Expr *Fn,
+                                          UnresolvedLookupExpr *ULE,
+                                          SourceLocation LParenLoc,
+                                          Expr **Args, unsigned NumArgs,
+                                          SourceLocation RParenLoc,
+                                          Expr *ExecConfig,
+                                          bool AllowTypoCorrection,
+                                          OverloadCandidateSet *CandidateSet,
+                                          bool InRangeExpr) {
 
   OverloadCandidateSet::iterator Best;
-  switch (CandidateSet.BestViableFunction(*this, Fn->getLocStart(), Best)) {
+  switch (CandidateSet->BestViableFunction(*this, Fn->getLocStart(), Best)) {
   case OR_Success: {
     FunctionDecl *FDecl = Best->Function;
     MarkFunctionReferenced(Fn->getExprLoc(), FDecl);
     CheckUnresolvedLookupAccess(ULE, Best->FoundDecl);
     DiagnoseUseOfDecl(FDecl, ULE->getNameLoc());
     Fn = FixOverloadedFunctionReference(Fn, Best->FoundDecl, FDecl);
-    return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs, RParenLoc,
-                                 ExecConfig);
+      return BuildResolvedCallExpr(Fn, FDecl, LParenLoc, Args, NumArgs,
+                                   RParenLoc, ExecConfig);
   }
 
   case OR_No_Viable_Function: {
+      // In case we're in a range expression, let the range handling code take
+      // care of it.
+      if (InRangeExpr)
+        break;
     // Try to recover by looking for viable functions which the user might
     // have meant to call.
-    ExprResult Recovery = BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc,
+      ExprResult Recovery =
+          BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc,
                                   llvm::MutableArrayRef<Expr *>(Args, NumArgs),
                                                 RParenLoc,
                                                 /*EmptyLookup=*/false,
@@ -9780,7 +9772,7 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
     Diag(Fn->getLocStart(),
          diag::err_ovl_no_viable_function_in_call)
       << ULE->getName() << Fn->getSourceRange();
-    CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+      CandidateSet->NoteCandidates(*this, OCD_AllCandidates,
                                 llvm::makeArrayRef(Args, NumArgs));
     break;
   }
@@ -9788,18 +9780,17 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
   case OR_Ambiguous:
     Diag(Fn->getLocStart(), diag::err_ovl_ambiguous_call)
       << ULE->getName() << Fn->getSourceRange();
-    CandidateSet.NoteCandidates(*this, OCD_ViableCandidates,
+      CandidateSet->NoteCandidates(*this, OCD_ViableCandidates,
                                 llvm::makeArrayRef(Args, NumArgs));
     break;
 
-  case OR_Deleted:
-    {
+    case OR_Deleted: {
       Diag(Fn->getLocStart(), diag::err_ovl_deleted_call)
         << Best->Function->isDeleted()
         << ULE->getName()
         << getDeletedOrUnavailableSuffix(Best->Function)
         << Fn->getSourceRange();
-      CandidateSet.NoteCandidates(*this, OCD_AllCandidates,
+      CandidateSet->NoteCandidates(*this, OCD_AllCandidates,
                                   llvm::makeArrayRef(Args, NumArgs));
 
       // We emitted an error for the unvailable/deleted function call but keep
@@ -9815,6 +9806,59 @@ Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
   return ExprError();
 }
 
+/// ResolveOverloadedCallFn - Given the call expression that calls Fn
+/// (which eventually refers to the declaration Func) and the call
+/// arguments Args/NumArgs, attempt to resolve the function call down
+/// to a specific function. If overload resolution succeeds, returns
+/// the function declaration produced by overload
+/// resolution. Otherwise, emits diagnostics, deletes all of the
+/// arguments and Fn, and returns NULL.
+ExprResult
+Sema::BuildOverloadedCallExpr(Scope *S, Expr *Fn, UnresolvedLookupExpr *ULE,
+                              SourceLocation LParenLoc,
+                              Expr **Args, unsigned NumArgs,
+                              SourceLocation RParenLoc,
+                              Expr *ExecConfig,
+                              bool AllowTypoCorrection,
+                              bool InRangeExpr) {
+#ifndef NDEBUG
+  if (ULE->requiresADL()) {
+    // To do ADL, we must have found an unqualified name.
+    assert(!ULE->getQualifier() && "qualified name with ADL");
+
+    // We don't perform ADL for implicit declarations of builtins.
+    // Verify that this was correctly set up.
+    FunctionDecl *F;
+    if (ULE->decls_begin() + 1 == ULE->decls_end() &&
+        (F = dyn_cast<FunctionDecl>(*ULE->decls_begin())) &&
+        F->getBuiltinID() && F->isImplicit())
+      llvm_unreachable("performing ADL for builtin");
+
+    // We don't perform ADL in C.
+    assert(getLangOpts().CPlusPlus && "ADL enabled in C");
+  } else
+    assert(!ULE->isStdAssociatedNamespace() &&
+           "std is associated namespace but not doing ADL");
+#endif
+  
+  OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+  ExprResult result;
+  if (buildOverloadedCallSet(S, Fn, ULE, Args, NumArgs, LParenLoc,
+                             &CandidateSet, &result))
+    return result;
+
+  if (CandidateSet.empty())
+    return BuildRecoveryCallExpr(*this, S, Fn, ULE, LParenLoc,
+                                 llvm::MutableArrayRef<Expr *>(Args, NumArgs),
+                                 RParenLoc, /*EmptyLookup=*/true,
+                                 AllowTypoCorrection);
+
+  return callExprFromCandidateSet(S, Fn, ULE, LParenLoc,
+                                  Args, NumArgs, RParenLoc,
+                                  ExecConfig, AllowTypoCorrection,
+                                  &CandidateSet, InRangeExpr);
+}
+
 static bool IsOverloaded(const UnresolvedSetImpl &Functions) {
   return Functions.size() > 1 ||
     (Functions.size() == 1 && isa<FunctionTemplateDecl>(*Functions.begin()));
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index 20b0d2f..481ff0b 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -1572,12 +1572,45 @@ void NoteForRangeBeginEndFunction(Sema &SemaRef, Expr *E,
     << BEF << IsTemplate << Description << E->getType();
 }
 
+// If the calls to 'begin' and 'end' would fail for a c++-11 for-range
+// statement, check to see if the range provided was mistakenly a pointer to a
+// valid range statement.
+static ExprResult checkRangeForMissingIndirection(Sema &SemaRef, Expr *Range,
+                                                  SourceLocation Loc,
+                                                  SourceLocation RangeLoc) {
+  QualType RangeType = Range->getType();
+  DeclarationNameInfo BeginNameInfo(
+      &SemaRef.PP.getIdentifierTable().get("begin"), Loc);
+  DeclarationNameInfo EndNameInfo(
+      &SemaRef.PP.getIdentifierTable().get("end"), Loc);
+
+  LookupResult BeginMemberLookup(SemaRef, BeginNameInfo,
+                                 Sema::LookupMemberName);
+  LookupResult EndMemberLookup(SemaRef, EndNameInfo,
+                               Sema::LookupMemberName);
+  if (!RangeType->isPointerType())
+    return ExprError();
+
+  if (CXXRecordDecl *D =
+        RangeType->getPointeeType()->getAsCXXRecordDecl()) {
+    SemaRef.LookupQualifiedName(BeginMemberLookup, D);
+    SemaRef.LookupQualifiedName(EndMemberLookup, D);
+    if (!BeginMemberLookup.empty() && !EndMemberLookup.empty()) {
+      SemaRef.Diag(RangeLoc, diag::note_for_range_type_is_pointer)
+          << RangeLoc << RangeType
+          << FixItHint::CreateInsertion(RangeLoc, "*");
+    }
+  }
+  return ExprError();
+}
+
 /// Build a call to 'begin' or 'end' for a C++0x for-range statement. If the
 /// given LookupResult is non-empty, it is assumed to describe a member which
 /// will be invoked. Otherwise, the function will be found via argument
 /// dependent lookup.
 static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S,
                                             SourceLocation Loc,
+                                            SourceLocation RangeLoc,
                                             VarDecl *Decl,
                                             BeginEndFunction BEF,
                                             const DeclarationNameInfo &NameInfo,
@@ -1608,12 +1641,53 @@ static ExprResult BuildForRangeBeginEndCall(Sema &SemaRef, Scope *S,
                                    /*NeedsADL=*/true, /*Overloaded=*/false,
                                    FoundNames.begin(), FoundNames.end(),
                                    /*LookInStdNamespace=*/true);
-    CallExpr = SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc,
-                                               0, /*AllowTypoCorrection=*/false);
+
+    OverloadCandidateSet CandidateSet(Fn->getExprLoc());
+    SemaRef.buildOverloadedCallSet(S, Fn, Fn, &Range, 1, Loc, &CandidateSet,
+                                   &CallExpr);
+
+    OverloadCandidateSet::iterator Best;
+    if (CandidateSet.empty()) {
+      SemaRef.Diag(Range->getLocStart(), diag::err_for_range_invalid)
+          << RangeLoc << Range->getType();
+      CallExpr = ExprError();
+    } else {
+      switch (CandidateSet.BestViableFunction(SemaRef,
+                                              Fn->getLocStart(), Best)) {
+      case OR_Success:
+        CallExpr =
+            SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, 0,
+                                            /*AllowTypoCorrection=*/false,
+                                            /*InRangeExpr=*/true);
+        break;
+      case OR_No_Viable_Function:
+        SemaRef.Diag(Range->getLocStart(), diag::err_for_range_invalid)
+            << RangeLoc << Range->getType();
+        CandidateSet.NoteCandidates(SemaRef, OCD_AllCandidates,
+                                    llvm::makeArrayRef(&Range, /*NumArgs=*/1));
+        CallExpr = ExprError();
+        break;
+      case OR_Deleted:
+      case OR_Ambiguous:
+        // Here we want to defer to the diagnostics in BuildOverloadedCallExpr.
+        SemaRef.Diag(Range->getLocStart(), diag::err_for_range_invalid)
+            << RangeLoc << Range->getType();
+        CallExpr =
+            SemaRef.BuildOverloadedCallExpr(S, Fn, Fn, Loc, &Range, 1, Loc, 0,
+                                            /*AllowTypoCorrection=*/false,
+                                            /*InRangeExpr=*/true);
+        break;
+      }
+    }
+
     if (CallExpr.isInvalid()) {
-      SemaRef.Diag(Range->getLocStart(), diag::note_for_range_type)
+      CallExpr = checkRangeForMissingIndirection(SemaRef, Range, Loc,
+                                                 RangeLoc);
+      if (CallExpr.isInvalid())
+        SemaRef.Diag(Range->getLocStart(), diag::note_for_range_adl_failure)
+          << BEF
         << Range->getType();
-      return ExprError();
+      return CallExpr;
     }
   }
   if (FinishForRangeVarDecl(SemaRef, Decl, CallExpr.get(), Loc,
@@ -1803,16 +1877,18 @@ Sema::BuildCXXForRangeStmt(SourceLocation ForLoc, SourceLocation ColonLoc,
         //   end(__range), respectively, where begin and end are looked up with
         //   argument-dependent lookup (3.4.2). For the purposes of this name
         //   lookup, namespace std is an associated namespace.
+
       }
 
-      BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, BeginVar,
+      BeginExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, RangeLoc,
+                                            BeginVar,
                                             BEF_begin, BeginNameInfo,
                                             BeginMemberLookup,
                                             BeginRangeRef.get());
       if (BeginExpr.isInvalid())
         return StmtError();
 
-      EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, EndVar,
+      EndExpr = BuildForRangeBeginEndCall(*this, S, ColonLoc, RangeLoc, EndVar,
                                           BEF_end, EndNameInfo,
                                           EndMemberLookup, EndRangeRef.get());
       if (EndExpr.isInvalid())
diff --git a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index 96bb472..41dd960 100644
--- a/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -3,7 +3,8 @@
 struct pr12960 {
   int begin;
   void foo(int x) {
-    for (int& it : x) { // expected-error {{use of undeclared identifier 'begin'}} expected-note {{range has type 'int'}}
+    for (int& it : x) { //expected-error{{invalid range expression}}\
+      expected-note{{no viable 'begin' function for range of type 'int'}}
     }
   }
 };
@@ -116,9 +117,11 @@ void g() {
   struct NoEndADL {
     null_t alt_begin();
   };
-  for (auto u : NoBeginADL()) { // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type 'NoBeginADL'}}
+  for (auto u : NoBeginADL()) {// expected-error{{invalid range expression of type 'NoBeginADL'}} \
+    expected-note{{no viable 'begin' function for range of type 'NoBeginADL'}}
   }
-  for (auto u : NoEndADL()) { // expected-error {{no matching function for call to 'end'}} expected-note {{range has type 'NoEndADL'}}
+  for (auto u : NoEndADL()) { // expected-error{{invalid range expression of type 'NoEndADL'}} \
+    expected-note{{no viable 'end' function for range of type 'NoEndADL'}}
   }
 
   struct NoBegin {
@@ -156,8 +159,8 @@ void g() {
   for (int n : NoCopy()) { // ok
   }
 
-  for (int n : 42) { // expected-error {{no matching function for call to 'begin'}} \
-                        expected-note {{range has type 'int'}}
+  for (int n : 42) { // expected-error{{invalid range expression of type 'int'}} \
+    expected-note{{no viable 'begin' function for range of type 'int'}}
   }
 
   for (auto a : *also_incomplete) { // expected-error {{cannot use incomplete type 'struct Incomplete' as a range}}
@@ -179,9 +182,10 @@ template void h<A(&)[13], int>(A(&)[13]); // expected-note {{requested here}}
 
 template<typename T>
 void i(T t) {
-  for (auto u : t) { // expected-error {{no matching function for call to 'begin'}} \
+  for (auto u : t) { // expected-error {{invalid range expression of type 'A *'}} \
                         expected-error {{member function 'begin' not viable}} \
-                        expected-note {{range has type}}
+                        expected-note {{no viable 'begin' function for range of type 'A *'}} \
+                        expected-note {{range expression is of type 'A *'; did you mean to dereference it with '*'?}}
   }
 }
 template void i<A[13]>(A*); // expected-note {{requested here}}
@@ -204,7 +208,8 @@ void end(VoidBeginADL);
 void j() {
   for (auto u : NS::ADL()) {
   }
-  for (auto u : NS::NoADL()) { // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}}
+  for (auto u : NS::NoADL()) { // expected-error{{invalid range expression of type 'NS::NoADL'}}\
+    expected-note {{no viable 'begin' function for range of type 'NS::NoADL'}}
   }
   for (auto a : VoidBeginADL()) { // expected-error {{cannot use type 'void' as an iterator}}
   }
@@ -215,4 +220,3 @@ void example() {
   for (int &x : array)
     x *= 2;
 }
-
diff --git a/test/SemaCXX/for-range-no-std.cpp b/test/SemaCXX/for-range-no-std.cpp
index fa42ca4..8f3213b 100644
--- a/test/SemaCXX/for-range-no-std.cpp
+++ b/test/SemaCXX/for-range-no-std.cpp
@@ -31,10 +31,11 @@ NS::iter end(NS::NoADL);
 void f() {
   int a[] = {1, 2, 3};
   for (auto b : S()) {} // ok
-  for (auto b : T()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}}
+  for (auto b : T()) {} // expected-error {{invalid range expression of type 'T'}} expected-note {{no viable 'begin' function for range of type 'T'}}
   for (auto b : a) {} // ok
   for (int b : NS::ADL()) {} // ok
-  for (int b : NS::NoADL()) {} // expected-error {{no matching function for call to 'begin'}} expected-note {{range has type}}
+  for (int b : NS::NoADL()) {} // expected-error {{invalid range expression of type 'NS::NoADL'}} \
+  expected-note {{no viable 'begin' function for range of type 'NS::NoADL'}}
 }
 
 void PR11601() {
diff --git a/test/SemaCXX/typo-correction.cpp b/test/SemaCXX/typo-correction.cpp
index fb07ce1..5a961b6 100644
--- a/test/SemaCXX/typo-correction.cpp
+++ b/test/SemaCXX/typo-correction.cpp
@@ -155,7 +155,8 @@ void Test3() {
 struct R {};
 bool begun(R);
 void RangeTest() {
-  for (auto b : R()) {} // expected-error {{use of undeclared identifier 'begin'}} expected-note {{range has type}}
+  for (auto b : R()) {} // expected-error {{invalid range expression of type 'R'}}\
+  expected-note {{no viable 'begin' function for range of type 'R'}}
 }
 
 // PR 12019 - Avoid infinite mutual recursion in DiagnoseInvalidRedeclaration
