<div dir="ltr"><div dir="ltr"><a href="http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/24083">http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/24083</a></div><div dir="ltr"><br></div><div dir="ltr"><pre style="font-family:"Courier New",courier,monotype,monospace;color:rgb(0,0,0);font-size:medium"><span class="gmail-stdout">FAIL: Clang :: CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp (1692 of 13357)
******************** TEST 'Clang :: CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp' FAILED ********************
Script:
--
: 'RUN: at line 1';   /b/sanitizer-x86_64-linux-fast/build/llvm_build_ubsan/bin/clang -cc1 -internal-isystem /b/sanitizer-x86_64-linux-fast/build/llvm_build_ubsan/lib/clang/8.0.0/include -nostdsysteminc -std=c++11 -fsyntax-only -verify /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
: 'RUN: at line 2';   /b/sanitizer-x86_64-linux-fast/build/llvm_build_ubsan/bin/clang -cc1 -internal-isystem /b/sanitizer-x86_64-linux-fast/build/llvm_build_ubsan/lib/clang/8.0.0/include -nostdsysteminc -std=c++14 -fsyntax-only -verify /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
: 'RUN: at line 3';   /b/sanitizer-x86_64-linux-fast/build/llvm_build_ubsan/bin/clang -cc1 -internal-isystem /b/sanitizer-x86_64-linux-fast/build/llvm_build_ubsan/lib/clang/8.0.0/include -nostdsysteminc -std=c++17 -fsyntax-only -verify /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
--
Exit Code: 1

Command Output (stderr):
--
/b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/Sema/Lookup.h:185:19: runtime error: load of value 32764, which is not a valid value for type 'typename std::remove_reference<AmbiguityKind &>::type' (aka 'clang::LookupResult::AmbiguityKind')
    #0 0x49b97ec in clang::LookupResult::LookupResult(clang::LookupResult&&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/include/clang/Sema/Lookup.h:185:19
    #1 0x49b8a2b in BuildNonArrayForRange(clang::Sema&, clang::Expr*, clang::Expr*, clang::QualType, clang::VarDecl*, clang::VarDecl*, clang::SourceLocation, clang::SourceLocation, clang::OverloadCandidateSet*, clang::ActionResult<clang::Expr*, true>*, clang::ActionResult<clang::Expr*, true>*, (anonymous namespace)::BeginEndFunction*)::$_3::operator()((anonymous namespace)::BeginEndFunction, clang::LookupResult&, llvm::function_ref<clang::Sema::ForRangeStatus ()>, llvm::function_ref<clang::Sema::ForRangeStatus ()>) const /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Sema/SemaStmt.cpp:2225:33
    #2 0x49a5ed0 in BuildNonArrayForRange /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Sema/SemaStmt.cpp
    #3 0x49a5ed0 in clang::Sema::BuildCXXForRangeStmt(clang::SourceLocation, clang::SourceLocation, clang::SourceLocation, clang::Stmt*, clang::Stmt*, clang::Stmt*, clang::Expr*, clang::Expr*, clang::Stmt*, clang::SourceLocation, clang::Sema::BuildForRangeKind) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Sema/SemaStmt.cpp:2497
    #4 0x49a49df in clang::Sema::ActOnCXXForRangeStmt(clang::Scope*, clang::SourceLocation, clang::SourceLocation, clang::Stmt*, clang::SourceLocation, clang::Expr*, clang::SourceLocation, clang::Sema::BuildForRangeKind) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Sema/SemaStmt.cpp:2122:10
    #5 0x41a3301 in clang::Parser::ParseForStatement(clang::SourceLocation*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseStmt.cpp:1762:28
    #6 0x419fe76 in clang::Parser::ParseStatementOrDeclarationAfterAttributes(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::AllowedConstructsKind, clang::SourceLocation*, clang::Parser::ParsedAttributesWithRange&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseStmt.cpp:251:12
    #7 0x419f496 in clang::Parser::ParseStatementOrDeclaration(llvm::SmallVector<clang::Stmt*, 32u>&, clang::Parser::AllowedConstructsKind, clang::SourceLocation*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseStmt.cpp:110:20
    #8 0x41a563b in clang::Parser::ParseCompoundStatementBody(bool) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseStmt.cpp:997:11
    #9 0x41a61c8 in clang::Parser::ParseFunctionStatementBody(clang::Decl*, clang::Parser::ParseScope&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseStmt.cpp:1971:21
    #10 0x410fde8 in clang::Parser::ParseFunctionDefinition(clang::ParsingDeclarator&, clang::Parser::ParsedTemplateInfo const&, clang::Parser::LateParsedAttrList*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/Parser.cpp:1246:10
    #11 0x412cc1c in clang::Parser::ParseDeclGroup(clang::ParsingDeclSpec&, clang::DeclaratorContext, clang::SourceLocation*, clang::Parser::ForRangeInit*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseDecl.cpp:1968:11
    #12 0x410e9ab in clang::Parser::ParseDeclOrFunctionDefInternal(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec&, clang::AccessSpecifier) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/Parser.cpp:1015:10
    #13 0x410e167 in clang::Parser::ParseDeclarationOrFunctionDefinition(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*, clang::AccessSpecifier) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/Parser.cpp:1031:12
    #14 0x410d00d in clang::Parser::ParseExternalDeclaration(clang::Parser::ParsedAttributesWithRange&, clang::ParsingDeclSpec*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/Parser.cpp:856:12
    #15 0x410c331 in clang::Parser::ParseTopLevelDecl(clang::OpaquePtr<clang::DeclGroupRef>&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/Parser.cpp:610:12
    #16 0x4106f84 in clang::ParseAST(clang::Sema&, bool, bool) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Parse/ParseAST.cpp:157:20
    #17 0x3229ef5 in clang::FrontendAction::Execute() /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/FrontendAction.cpp:915:8
    #18 0x31e02bf in clang::CompilerInstance::ExecuteAction(clang::FrontendAction&) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/Frontend/CompilerInstance.cpp:964:11
    #19 0x32ef915 in clang::ExecuteCompilerInvocation(clang::CompilerInstance*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp:259:25
    #20 0x9fe4c3 in cc1_main(llvm::ArrayRef<char const*>, char const*, void*) /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/cc1_main.cpp:218:13
    #21 0x9f90d5 in ExecuteCC1Tool /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:310:12
    #22 0x9f90d5 in main /b/sanitizer-x86_64-linux-fast/build/llvm/tools/clang/tools/driver/driver.cpp:382
    #23 0x7fe87da472e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0)
    #24 0x9e0a09 in _start (/b/sanitizer-x86_64-linux-fast/build/llvm_build_ubsan/bin/clang-8+0x9e0a09)</span></pre></div><div dir="ltr"><br></div></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Sep 24, 2018 at 4:19 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Mon Sep 24 16:17:44 2018<br>
New Revision: 342925<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=342925&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=342925&view=rev</a><br>
Log:<br>
P0962R1: only use the member form of 'begin' and 'end' in a range-based<br>
for loop if both members exist.<br>
<br>
This resolves a DR whereby an errant 'begin' or 'end' member in a base<br>
class could result in a derived class not being usable as a range with<br>
non-member 'begin' and 'end'.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
    cfe/trunk/lib/Sema/SemaStmt.cpp<br>
    cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp<br>
    cfe/trunk/test/SemaCXX/for-range-dereference.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=342925&r1=342924&r2=342925&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=342925&r1=342924&r2=342925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)<br>
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Mon Sep 24 16:17:44 2018<br>
@@ -2254,8 +2254,6 @@ def err_for_range_incomplete_type : Erro<br>
   "cannot use incomplete type %0 as a range">;<br>
 def err_for_range_iter_deduction_failure : Error<<br>
   "cannot use type %0 as an iterator">;<br>
-def err_for_range_member_begin_end_mismatch : Error<<br>
-  "range type %0 has '%select{begin|end}1' member but no '%select{end|begin}1' member">;<br>
 def ext_for_range_begin_end_types_differ : ExtWarn<<br>
   "'begin' and 'end' returning different types (%0 and %1) is a C++17 extension">,<br>
   InGroup<CXX17>;<br>
@@ -2268,6 +2266,8 @@ def note_in_for_range: Note<<br>
 def err_for_range_invalid: Error<<br>
   "invalid range expression of type %0; no viable '%select{begin|end}1' "<br>
   "function available">;<br>
+def note_for_range_member_begin_end_ignored : Note<<br>
+  "member is not a candidate because range type %0 has no '%select{end|begin}1' member">;<br>
 def err_range_on_array_parameter : Error<<br>
   "cannot build range expression with array function parameter %0 since "<br>
   "parameter with array type %1 is treated as pointer type %2">;<br>
<br>
Modified: cfe/trunk/lib/Sema/SemaStmt.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=342925&r1=342924&r2=342925&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaStmt.cpp?rev=342925&r1=342924&r2=342925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/lib/Sema/SemaStmt.cpp (original)<br>
+++ cfe/trunk/lib/Sema/SemaStmt.cpp Mon Sep 24 16:17:44 2018<br>
@@ -2149,6 +2149,56 @@ BuildNonArrayForRange(Sema &SemaRef, Exp<br>
                                  Sema::LookupMemberName);<br>
   LookupResult EndMemberLookup(SemaRef, EndNameInfo, Sema::LookupMemberName);<br>
<br>
+  auto BuildBegin = [&] {<br>
+    *BEF = BEF_begin;<br>
+    Sema::ForRangeStatus RangeStatus =<br>
+        SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo,<br>
+                                          BeginMemberLookup, CandidateSet,<br>
+                                          BeginRange, BeginExpr);<br>
+<br>
+    if (RangeStatus != Sema::FRS_Success) {<br>
+      if (RangeStatus == Sema::FRS_DiagnosticIssued)<br>
+        SemaRef.Diag(BeginRange->getBeginLoc(), diag::note_in_for_range)<br>
+            << ColonLoc << BEF_begin << BeginRange->getType();<br>
+      return RangeStatus;<br>
+    }<br>
+    if (!CoawaitLoc.isInvalid()) {<br>
+      // FIXME: getCurScope() should not be used during template instantiation.<br>
+      // We should pick up the set of unqualified lookup results for operator<br>
+      // co_await during the initial parse.<br>
+      *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc,<br>
+                                            BeginExpr->get());<br>
+      if (BeginExpr->isInvalid())<br>
+        return Sema::FRS_DiagnosticIssued;<br>
+    }<br>
+    if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,<br>
+                              diag::err_for_range_iter_deduction_failure)) {<br>
+      NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);<br>
+      return Sema::FRS_DiagnosticIssued;<br>
+    }<br>
+    return Sema::FRS_Success;<br>
+  };<br>
+<br>
+  auto BuildEnd = [&] {<br>
+    *BEF = BEF_end;<br>
+    Sema::ForRangeStatus RangeStatus =<br>
+        SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo,<br>
+                                          EndMemberLookup, CandidateSet,<br>
+                                          EndRange, EndExpr);<br>
+    if (RangeStatus != Sema::FRS_Success) {<br>
+      if (RangeStatus == Sema::FRS_DiagnosticIssued)<br>
+        SemaRef.Diag(EndRange->getBeginLoc(), diag::note_in_for_range)<br>
+            << ColonLoc << BEF_end << EndRange->getType();<br>
+      return RangeStatus;<br>
+    }<br>
+    if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc,<br>
+                              diag::err_for_range_iter_deduction_failure)) {<br>
+      NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF);<br>
+      return Sema::FRS_DiagnosticIssued;<br>
+    }<br>
+    return Sema::FRS_Success;<br>
+  };<br>
+<br>
   if (CXXRecordDecl *D = RangeType->getAsCXXRecordDecl()) {<br>
     // - if _RangeT is a class type, the unqualified-ids begin and end are<br>
     //   looked up in the scope of class _RangeT as if by class member access<br>
@@ -2156,68 +2206,62 @@ BuildNonArrayForRange(Sema &SemaRef, Exp<br>
     //   declaration, begin-expr and end-expr are __range.begin() and<br>
     //   __range.end(), respectively;<br>
     SemaRef.LookupQualifiedName(BeginMemberLookup, D);<br>
+    if (BeginMemberLookup.isAmbiguous())<br>
+      return Sema::FRS_DiagnosticIssued;<br>
+<br>
     SemaRef.LookupQualifiedName(EndMemberLookup, D);<br>
+    if (EndMemberLookup.isAmbiguous())<br>
+      return Sema::FRS_DiagnosticIssued;<br>
<br>
     if (BeginMemberLookup.empty() != EndMemberLookup.empty()) {<br>
-      SourceLocation RangeLoc = BeginVar->getLocation();<br>
-      *BEF = BeginMemberLookup.empty() ? BEF_end : BEF_begin;<br>
-<br>
-      SemaRef.Diag(RangeLoc, diag::err_for_range_member_begin_end_mismatch)<br>
-          << RangeLoc << BeginRange->getType() << *BEF;<br>
-      return Sema::FRS_DiagnosticIssued;<br>
+      // Look up the non-member form of the member we didn't find, first.<br>
+      // This way we prefer a "no viable 'end'" diagnostic over a "i found<br>
+      // a 'begin' but ignored it because there was no member 'end'"<br>
+      // diagnostic.<br>
+      auto BuildNonmember = [&](<br>
+          BeginEndFunction BEFFound, LookupResult &Found,<br>
+          llvm::function_ref<Sema::ForRangeStatus()> BuildFound,<br>
+          llvm::function_ref<Sema::ForRangeStatus()> BuildNotFound) {<br>
+        LookupResult OldFound = std::move(Found);<br>
+        Found.clear();<br>
+<br>
+        if (Sema::ForRangeStatus Result = BuildNotFound())<br>
+          return Result;<br>
+<br>
+        switch (BuildFound()) {<br>
+        case Sema::FRS_Success:<br>
+          return Sema::FRS_Success;<br>
+<br>
+        case Sema::FRS_NoViableFunction:<br>
+          SemaRef.Diag(BeginRange->getBeginLoc(), diag::err_for_range_invalid)<br>
+              << BeginRange->getType() << BEFFound;<br>
+          CandidateSet->NoteCandidates(SemaRef, OCD_AllCandidates, BeginRange);<br>
+          LLVM_FALLTHROUGH;<br>
+<br>
+        case Sema::FRS_DiagnosticIssued:<br>
+          for (NamedDecl *D : OldFound) {<br>
+            SemaRef.Diag(D->getLocation(),<br>
+                         diag::note_for_range_member_begin_end_ignored)<br>
+                << BeginRange->getType() << BEFFound;<br>
+          }<br>
+          return Sema::FRS_DiagnosticIssued;<br>
+        }<br>
+        llvm_unreachable("unexpected ForRangeStatus");<br>
+      };<br>
+      if (BeginMemberLookup.empty())<br>
+        return BuildNonmember(BEF_end, EndMemberLookup, BuildEnd, BuildBegin);<br>
+      return BuildNonmember(BEF_begin, BeginMemberLookup, BuildBegin, BuildEnd);<br>
     }<br>
   } else {<br>
     // - otherwise, begin-expr and end-expr are begin(__range) and<br>
     //   end(__range), respectively, where begin and end are looked up with<br>
     //   argument-dependent lookup (3.4.2). For the purposes of this name<br>
     //   lookup, namespace std is an associated namespace.<br>
-<br>
   }<br>
<br>
-  *BEF = BEF_begin;<br>
-  Sema::ForRangeStatus RangeStatus =<br>
-      SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, BeginNameInfo,<br>
-                                        BeginMemberLookup, CandidateSet,<br>
-                                        BeginRange, BeginExpr);<br>
-<br>
-  if (RangeStatus != Sema::FRS_Success) {<br>
-    if (RangeStatus == Sema::FRS_DiagnosticIssued)<br>
-      SemaRef.Diag(BeginRange->getBeginLoc(), diag::note_in_for_range)<br>
-          << ColonLoc << BEF_begin << BeginRange->getType();<br>
-    return RangeStatus;<br>
-  }<br>
-  if (!CoawaitLoc.isInvalid()) {<br>
-    // FIXME: getCurScope() should not be used during template instantiation.<br>
-    // We should pick up the set of unqualified lookup results for operator<br>
-    // co_await during the initial parse.<br>
-    *BeginExpr = SemaRef.ActOnCoawaitExpr(SemaRef.getCurScope(), ColonLoc,<br>
-                                          BeginExpr->get());<br>
-    if (BeginExpr->isInvalid())<br>
-      return Sema::FRS_DiagnosticIssued;<br>
-  }<br>
-  if (FinishForRangeVarDecl(SemaRef, BeginVar, BeginExpr->get(), ColonLoc,<br>
-                            diag::err_for_range_iter_deduction_failure)) {<br>
-    NoteForRangeBeginEndFunction(SemaRef, BeginExpr->get(), *BEF);<br>
-    return Sema::FRS_DiagnosticIssued;<br>
-  }<br>
-<br>
-  *BEF = BEF_end;<br>
-  RangeStatus =<br>
-      SemaRef.BuildForRangeBeginEndCall(ColonLoc, ColonLoc, EndNameInfo,<br>
-                                        EndMemberLookup, CandidateSet,<br>
-                                        EndRange, EndExpr);<br>
-  if (RangeStatus != Sema::FRS_Success) {<br>
-    if (RangeStatus == Sema::FRS_DiagnosticIssued)<br>
-      SemaRef.Diag(EndRange->getBeginLoc(), diag::note_in_for_range)<br>
-          << ColonLoc << BEF_end << EndRange->getType();<br>
-    return RangeStatus;<br>
-  }<br>
-  if (FinishForRangeVarDecl(SemaRef, EndVar, EndExpr->get(), ColonLoc,<br>
-                            diag::err_for_range_iter_deduction_failure)) {<br>
-    NoteForRangeBeginEndFunction(SemaRef, EndExpr->get(), *BEF);<br>
-    return Sema::FRS_DiagnosticIssued;<br>
-  }<br>
-  return Sema::FRS_Success;<br>
+  if (Sema::ForRangeStatus Result = BuildBegin())<br>
+    return Result;<br>
+  return BuildEnd();<br>
 }<br>
<br>
 /// Speculatively attempt to dereference an invalid range expression.<br>
<br>
Modified: cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp?rev=342925&r1=342924&r2=342925&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp?rev=342925&r1=342924&r2=342925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp (original)<br>
+++ cfe/trunk/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp Mon Sep 24 16:17:44 2018<br>
@@ -150,9 +150,9 @@ void g() {<br>
   struct NoEnd {<br>
     null_t begin();<br>
   };<br>
-  for (auto u : NoBegin()) { // expected-error {{range type 'NoBegin' has 'end' member but no 'begin' member}}<br>
+  for (auto u : NoBegin()) { // expected-error {{no viable 'begin' function available}}<br>
   }<br>
-  for (auto u : NoEnd()) { // expected-error {{range type 'NoEnd' has 'begin' member but no 'end' member}} <br>
+  for (auto u : NoEnd()) { // expected-error {{no viable 'end' function available}}<br>
   }<br>
<br>
   struct NoIncr {<br>
@@ -271,3 +271,58 @@ namespace rdar13712739 {<br>
<br>
   template void foo(const int&); // expected-note{{in instantiation of function template specialization}}<br>
 }<br>
+<br>
+namespace p0962r1 {<br>
+  namespace NA {<br>
+    struct A {<br>
+      void begin();<br>
+    };<br>
+    int *begin(A);<br>
+    int *end(A);<br>
+  }<br>
+<br>
+  namespace NB {<br>
+    struct B {<br>
+      void end();<br>
+    };<br>
+    int *begin(B);<br>
+    int *end(B);<br>
+  }<br>
+<br>
+  namespace NC {<br>
+    struct C {<br>
+      void begin();<br>
+    };<br>
+    int *begin(C);<br>
+  }<br>
+<br>
+  namespace ND {<br>
+    struct D {<br>
+      void end();<br>
+    };<br>
+    int *end(D);<br>
+  }<br>
+<br>
+  namespace NE {<br>
+    struct E {<br>
+      void begin(); // expected-note {{member is not a candidate because range type 'p0962r1::NE::E' has no 'end' member}}<br>
+    };<br>
+    int *end(E);<br>
+  }<br>
+<br>
+  namespace NF {<br>
+    struct F {<br>
+      void end(); // expected-note {{member is not a candidate because range type 'p0962r1::NF::F' has no 'begin' member}}<br>
+    };<br>
+    int *begin(F);<br>
+  }<br>
+<br>
+  void use(NA::A a, NB::B b, NC::C c, ND::D d, NE::E e, NF::F f) {<br>
+    for (auto x : a) {}<br>
+    for (auto x : b) {}<br>
+    for (auto x : c) {} // expected-error {{no viable 'end' function}}<br>
+    for (auto x : d) {} // expected-error {{no viable 'begin' function}}<br>
+    for (auto x : e) {} // expected-error {{no viable 'begin' function}}<br>
+    for (auto x : f) {} // expected-error {{no viable 'end' function}}<br>
+  }<br>
+}<br>
<br>
Modified: cfe/trunk/test/SemaCXX/for-range-dereference.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-dereference.cpp?rev=342925&r1=342924&r2=342925&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/for-range-dereference.cpp?rev=342925&r1=342924&r2=342925&view=diff</a><br>
==============================================================================<br>
--- cfe/trunk/test/SemaCXX/for-range-dereference.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/for-range-dereference.cpp Mon Sep 24 16:17:44 2018<br>
@@ -17,7 +17,7 @@ struct DeletedEnd : public T {<br>
 struct DeletedADLBegin { };<br>
<br>
 int* begin(DeletedADLBegin) = delete; //expected-note {{candidate function has been explicitly deleted}} \<br>
- expected-note 5 {{candidate function not viable: no known conversion}}<br>
+ expected-note 6 {{candidate function not viable: no known conversion}}<br>
<br>
 struct PrivateEnd {<br>
   Data *begin();<br>
@@ -27,7 +27,7 @@ struct PrivateEnd {<br>
 };<br>
<br>
 struct ADLNoEnd { };<br>
-Data * begin(ADLNoEnd); // expected-note 6 {{candidate function not viable: no known conversion}}<br>
+Data * begin(ADLNoEnd); // expected-note 7 {{candidate function not viable: no known conversion}}<br>
<br>
 struct OverloadedStar {<br>
   T operator*();<br>
@@ -45,7 +45,7 @@ void f() {<br>
   for (auto i : parr) { }// expected-error{{invalid range expression of type 'int (*)[10]'; did you mean to dereference it with '*'?}}<br>
<br>
   NoBegin NB;<br>
-  for (auto i : NB) { }// expected-error{{range type 'NoBegin' has 'end' member but no 'begin' member}}<br>
+  for (auto i : NB) { }// expected-error{{invalid range expression of type 'NoBegin'; no viable 'begin' function available}}<br>
   NoBegin *pNB;<br>
   for (auto i : pNB) { }// expected-error{{invalid range expression of type 'NoBegin *'; no viable 'begin' function available}}<br>
   NoBegin **ppNB;<br>
<br>
<br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>