https://github.com/akash-manna-sky updated 
https://github.com/llvm/llvm-project/pull/218145

>From c44743079987f547d4dc807d3a6f8be2eaed21f9 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Sat, 22 Aug 2026 21:51:41 +0530
Subject: [PATCH 1/9] [clang][Sema] Don't blame '__begin1' when a constexpr
 range-for loop variable fails constant initialization

A constexpr loop variable in a range-based for statement is initialized
from '*__begin1', so when constant initialization fails, the evaluator's
notes name the compiler-synthesized '__begin1' variable, which appears
nowhere in the source. Emit a dedicated error in
CheckCompleteVariableDeclaration instead, gated on the initializer
actually reading a non-constexpr implicit iterator variable, so valid
constexpr loop variables (CWG1204) and expansion statements keep
working unchanged.

Fixes #211926
---
 clang/docs/ReleaseNotes.md                    |  4 +
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 +
 clang/lib/Sema/SemaDecl.cpp                   | 45 +++++++---
 clang/test/SemaCXX/GH211926.cpp               | 87 +++++++++++++++++++
 4 files changed, 129 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/SemaCXX/GH211926.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index bdbabf2cd98d0..b665eafc25dc6 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -425,6 +425,10 @@ features cannot lower the translation-unit ABI level;
 
 - Clang now diagnoses more details when a constraint evaluates to false.
 
+- Clang now emits a clearer diagnostic when a `constexpr` range-based for
+  loop variable cannot be initialized by a constant expression, instead of
+  a note about the compiler-synthesized `__begin` variable. (#GH211926)
+
 ### Improvements to Clang's time-trace
 
 ### Improvements to Coverage Mapping
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 24ecc88d2fbc0..aeef0dddf0ae1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2964,6 +2964,10 @@ def err_for_range_decl_must_be_var : Error<
 def err_for_range_storage_class : Error<
   "%select{loop|expansion}0 variable %1 may not be declared 
%select{'extern'|'static'|"
   "'__private_extern__'|'auto'|'register'|'constexpr'|'thread_local'}2">;
+def err_for_range_constexpr_loop_var : Error<
+  "constexpr variable %0 must be initialized by a constant expression; "
+  "a range-based for loop variable is initialized on each iteration from the "
+  "loop's iterator, whose value is not known at compile time">;
 def err_type_defined_in_for_range : Error<
   "types may not be defined in a for range declaration">;
 def err_for_range_deduction_failure : Error<
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 07c6157ab8f31..3460fcaf7cbb2 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15058,6 +15058,23 @@ void 
Sema::addLifetimeBoundToImplicitThis(CXXMethodDecl *MD) {
   MD->setTypeSourceInfo(TLB.getTypeSourceInfo(Context, AttributedType));
 }
 
+/// Determine whether the initializer of a range-based for loop variable reads
+/// one of the loop's implicit non-constexpr iterator variables ('__begin1').
+static bool initReadsForRangeImplicitVar(const Expr *Init) {
+  SmallVector<const Stmt *, 8> Worklist = {Init};
+  while (!Worklist.empty()) {
+    const Stmt *S = Worklist.pop_back_val();
+    if (!S)
+      continue;
+    if (const auto *DRE = dyn_cast<DeclRefExpr>(S))
+      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
+        if (VD->isCXXForRangeImplicitVar() && !VD->isConstexpr())
+          return true;
+    Worklist.append(S->child_begin(), S->child_end());
+  }
+  return false;
+}
+
 void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
   if (var->isInvalidDecl()) return;
 
@@ -15270,18 +15287,24 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl 
*var) {
     if (HasConstInit) {
       // FIXME: Consider replacing the initializer with a ConstantExpr.
     } else if (var->isConstexpr()) {
-      SourceLocation DiagLoc = var->getLocation();
-      // If the note doesn't add any useful information other than a source
-      // location, fold it into the primary diagnostic.
-      if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
-                                   diag::note_invalid_subexpr_in_const_expr) {
-        DiagLoc = Notes[0].first;
-        Notes.clear();
+      if (var->isCXXForRangeDecl() && initReadsForRangeImplicitVar(Init)) {
+        Diag(var->getLocation(), diag::err_for_range_constexpr_loop_var)
+            << var << Init->getSourceRange();
+        var->setInvalidDecl();
+      } else {
+        SourceLocation DiagLoc = var->getLocation();
+        // If the note doesn't add any useful information other than a source
+        // location, fold it into the primary diagnostic.
+        if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+                                     diag::note_invalid_subexpr_in_const_expr) 
{
+          DiagLoc = Notes[0].first;
+          Notes.clear();
+        }
+        Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+            << var << Init->getSourceRange();
+        for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+          Diag(Notes[I].first, Notes[I].second);
       }
-      Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
-          << var << Init->getSourceRange();
-      for (unsigned I = 0, N = Notes.size(); I != N; ++I)
-        Diag(Notes[I].first, Notes[I].second);
     } else if (GlobalStorage && var->hasAttr<ConstInitAttr>()) {
       auto *Attr = var->getAttr<ConstInitAttr>();
       Diag(var->getLocation(), diag::err_require_constant_init_failed)
diff --git a/clang/test/SemaCXX/GH211926.cpp b/clang/test/SemaCXX/GH211926.cpp
new file mode 100644
index 0000000000000..77e2938f0368b
--- /dev/null
+++ b/clang/test/SemaCXX/GH211926.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
+
+// GH211926: constexpr range-based for loop variables used to be diagnosed
+// with a note about the compiler-synthesized '__begin1' variable.
+
+namespace std {
+typedef decltype(sizeof(int)) size_t;
+template <typename T> struct initializer_list {
+  const T *p;
+  size_t n;
+  initializer_list(const T *p, size_t n);
+  const T *begin() const; // expected-note {{selected 'begin' function with 
iterator type 'const int *'}}
+  const T *end() const;
+};
+} // namespace std
+
+void init_list() {
+  for (constexpr auto x : {1, 2, 3}) { // expected-error {{constexpr variable 
'x' must be initialized by a constant expression; a range-based for loop 
variable is initialized on each iteration from the loop's iterator, whose value 
is not known at compile time}}
+  }
+}
+
+void c_array() {
+  int arr[3] = {1, 2, 3};
+  for (constexpr int x : arr) { // expected-error {{constexpr variable 'x' 
must be initialized by a constant expression; a range-based for loop variable 
is initialized on each iteration}}
+  }
+}
+
+struct Vec {
+  int data[3];
+  const int *begin() const; // expected-note {{selected 'begin' function with 
iterator type 'const int *'}}
+  const int *end() const;
+};
+
+void container() {
+  Vec v = {{1, 2, 3}};
+  for (constexpr int x : v) { // expected-error {{constexpr variable 'x' must 
be initialized by a constant expression; a range-based for loop variable is 
initialized on each iteration}}
+  }
+}
+
+template <typename T> void dependent(T &range) {
+  for (constexpr auto x : range) { // expected-error {{constexpr variable 'x' 
must be initialized by a constant expression; a range-based for loop variable 
is initialized on each iteration}}
+  }
+}
+
+void instantiate() {
+  int arr[3] = {1, 2, 3};
+  dependent(arr); // expected-note {{in instantiation of function template 
specialization}}
+}
+
+void plain_loop_var() {
+  for (auto x : {1, 2, 3})
+    (void)x;
+  int arr[3] = {1, 2, 3};
+  for (int &x : arr)
+    x = 0;
+}
+
+// Still valid when the initializer is a constant expression (CWG1204).
+struct StatelessIter {
+  struct It {
+    int pos;
+    It &operator++();
+    bool operator!=(const It &other) const;
+  };
+  It begin();
+  It end();
+};
+constexpr int operator*(const StatelessIter::It &) { return 7; }
+
+void stateless_iterator() {
+  for (constexpr int x : StatelessIter()) {
+    static_assert(x == 7, "");
+  }
+}
+
+void ordinary_constexpr() {
+  constexpr int ok = 42;
+  static_assert(ok == 42, "");
+
+  int runtime = 0;             // expected-note {{declared here}}
+  constexpr int bad = runtime; // expected-error {{constexpr variable 'bad' 
must be initialized by a constant expression}} expected-note {{read of 
non-const variable 'runtime' is not allowed in a constant expression}}
+
+  for (constexpr int i = 0; i != 0;) {
+  }
+}

>From 613b9659c15be3712c105e8a00f7cb91cb675e7e Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Tue, 25 Aug 2026 12:01:44 +0530
Subject: [PATCH 2/9] [clang][Sema] Don't blame '__begin1' when a constexpr
 range-for loop variable fails constant initialization

A constexpr loop variable in a range-based for statement is initialized
from '*__begin1', so when constant initialization fails the evaluator
notes a read of the compiler-synthesized '__begin1', which appears
nowhere in the source. Emit a dedicated note from both constant
evaluators when they encounter a read of a for-range implicit variable,
explaining that the loop variable is initialized on each iteration from
the loop's iterator.

Fixes #211926
---
 clang/docs/ReleaseNotes.md                    |  5 ++
 .../include/clang/Basic/DiagnosticASTKinds.td |  3 +
 .../clang/Basic/DiagnosticSemaKinds.td        |  4 -
 clang/lib/AST/ByteCode/Interp.cpp             |  6 ++
 clang/lib/AST/ExprConstant.cpp                |  5 ++
 clang/lib/Sema/SemaDecl.cpp                   | 45 +++-------
 clang/test/AST/ByteCode/cxx11.cpp             |  8 ++
 .../stmt.stmt/stmt.iter/stmt.ranged/p1.cpp    |  3 +
 clang/test/SemaCXX/GH211926.cpp               | 87 -------------------
 .../SemaCXX/constant-expression-cxx11.cpp     |  4 +
 10 files changed, 45 insertions(+), 125 deletions(-)
 delete mode 100644 clang/test/SemaCXX/GH211926.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index b665eafc25dc6..f3b650a20ca3a 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -429,6 +429,11 @@ features cannot lower the translation-unit ABI level;
   loop variable cannot be initialized by a constant expression, instead of
   a note about the compiler-synthesized `__begin` variable. (#GH211926)
 
+- When a `constexpr` range-based for loop variable cannot be initialized by a
+  constant expression, Clang now explains in a note that the loop variable is
+  initialized from the loop's iterator, instead of referring to the
+  compiler-synthesized `__begin` variable. (#GH211926)
+
 ### Improvements to Clang's time-trace
 
 ### Improvements to Coverage Mapping
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 219d66de2fa61..edbf125a0804b 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -222,6 +222,9 @@ def note_constexpr_ltor_non_integral : Note<
   "is not allowed in a constant expression">;
 def note_constexpr_ltor_non_constexpr : Note<
   "read of non-constexpr variable %0 is not allowed in a constant expression">;
+def note_constexpr_ltor_for_range_var : Note<
+  "range-based for loop variable is initialized on each iteration from the "
+  "loop's iterator, whose value is not known at compile time">;
 def note_constexpr_ltor_incomplete_type : Note<
   "read of incomplete type %0 is not allowed in a constant expression">;
 def note_constexpr_access_null : Note<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index aeef0dddf0ae1..24ecc88d2fbc0 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2964,10 +2964,6 @@ def err_for_range_decl_must_be_var : Error<
 def err_for_range_storage_class : Error<
   "%select{loop|expansion}0 variable %1 may not be declared 
%select{'extern'|'static'|"
   "'__private_extern__'|'auto'|'register'|'constexpr'|'thread_local'}2">;
-def err_for_range_constexpr_loop_var : Error<
-  "constexpr variable %0 must be initialized by a constant expression; "
-  "a range-based for loop variable is initialized on each iteration from the "
-  "loop's iterator, whose value is not known at compile time">;
 def err_type_defined_in_for_range : Error<
   "types may not be defined in a for range declaration">;
 def err_for_range_deduction_failure : Error<
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 896b2ab4494e7..589ef62650223 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -161,6 +161,12 @@ static void diagnoseNonConstVariable(InterpState &S, 
CodePtr OpPC,
     return;
   }
 
+  if (const auto *VarD = dyn_cast<VarDecl>(VD);
+      VarD && VarD->isCXXForRangeImplicitVar()) {
+    S.FFDiag(Loc, diag::note_constexpr_ltor_for_range_var);
+    return;
+  }
+
   if (const auto *VarD = dyn_cast<VarDecl>(VD);
       VarD && VarD->getType().isConstQualified() &&
       (VarD->isConstexpr() || !VarD->getType()->isArrayType()) &&
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 9702105951b7b..90543e6e31c74 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4773,6 +4773,11 @@ static CompleteObject findCompleteObject(EvalInfo &Info, 
const Expr *E,
       } else if (Info.getLangOpts().C23 && ConstexprVar) {
         Info.FFDiag(E);
         return CompleteObject();
+      } else if (VD->isCXXForRangeImplicitVar()) {
+        if (!IsAccess)
+          return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
+        Info.FFDiag(E, diag::note_constexpr_ltor_for_range_var);
+        return CompleteObject();
       } else if (BaseType->isIntegralOrEnumerationType()) {
         if (!IsConstant) {
           if (!IsAccess)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 3460fcaf7cbb2..07c6157ab8f31 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15058,23 +15058,6 @@ void 
Sema::addLifetimeBoundToImplicitThis(CXXMethodDecl *MD) {
   MD->setTypeSourceInfo(TLB.getTypeSourceInfo(Context, AttributedType));
 }
 
-/// Determine whether the initializer of a range-based for loop variable reads
-/// one of the loop's implicit non-constexpr iterator variables ('__begin1').
-static bool initReadsForRangeImplicitVar(const Expr *Init) {
-  SmallVector<const Stmt *, 8> Worklist = {Init};
-  while (!Worklist.empty()) {
-    const Stmt *S = Worklist.pop_back_val();
-    if (!S)
-      continue;
-    if (const auto *DRE = dyn_cast<DeclRefExpr>(S))
-      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))
-        if (VD->isCXXForRangeImplicitVar() && !VD->isConstexpr())
-          return true;
-    Worklist.append(S->child_begin(), S->child_end());
-  }
-  return false;
-}
-
 void Sema::CheckCompleteVariableDeclaration(VarDecl *var) {
   if (var->isInvalidDecl()) return;
 
@@ -15287,24 +15270,18 @@ void Sema::CheckCompleteVariableDeclaration(VarDecl 
*var) {
     if (HasConstInit) {
       // FIXME: Consider replacing the initializer with a ConstantExpr.
     } else if (var->isConstexpr()) {
-      if (var->isCXXForRangeDecl() && initReadsForRangeImplicitVar(Init)) {
-        Diag(var->getLocation(), diag::err_for_range_constexpr_loop_var)
-            << var << Init->getSourceRange();
-        var->setInvalidDecl();
-      } else {
-        SourceLocation DiagLoc = var->getLocation();
-        // If the note doesn't add any useful information other than a source
-        // location, fold it into the primary diagnostic.
-        if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
-                                     diag::note_invalid_subexpr_in_const_expr) 
{
-          DiagLoc = Notes[0].first;
-          Notes.clear();
-        }
-        Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
-            << var << Init->getSourceRange();
-        for (unsigned I = 0, N = Notes.size(); I != N; ++I)
-          Diag(Notes[I].first, Notes[I].second);
+      SourceLocation DiagLoc = var->getLocation();
+      // If the note doesn't add any useful information other than a source
+      // location, fold it into the primary diagnostic.
+      if (Notes.size() == 1 && Notes[0].second.getDiagID() ==
+                                   diag::note_invalid_subexpr_in_const_expr) {
+        DiagLoc = Notes[0].first;
+        Notes.clear();
       }
+      Diag(DiagLoc, diag::err_constexpr_var_requires_const_init)
+          << var << Init->getSourceRange();
+      for (unsigned I = 0, N = Notes.size(); I != N; ++I)
+        Diag(Notes[I].first, Notes[I].second);
     } else if (GlobalStorage && var->hasAttr<ConstInitAttr>()) {
       auto *Attr = var->getAttr<ConstInitAttr>();
       Diag(var->getLocation(), diag::err_require_constant_init_failed)
diff --git a/clang/test/AST/ByteCode/cxx11.cpp 
b/clang/test/AST/ByteCode/cxx11.cpp
index d920f0d4eb7f9..bdd613511f2b3 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -501,3 +501,11 @@ namespace SubPtr {
                                                      // both-note {{subtracted 
pointers are not elements of the same array}}
   constexpr auto diff8 = &a[1][2].n - (&a[1][2].n + 1);
 }
+
+namespace ConstexprForRangeVar {
+  void f() {
+    int arr[] = {1, 2, 3};
+    for (constexpr int a : arr) {} // both-error {{constexpr variable 'a' must 
be initialized by a constant expression}} \
+                                   // both-note {{range-based for loop 
variable is initialized on each iteration from the loop's iterator, whose value 
is not known at compile time}}
+  }
+}
diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp 
b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index 45d02d4272d22..50b722a9bec20 100644
--- a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -154,6 +154,9 @@ void g() {
   for (thread_local int a : A()) {} // expected-error {{loop variable 'a' may 
not be declared 'thread_local'}}
   for (register int a : A()) {} // expected-error {{loop variable 'a' may not 
be declared 'register'}} expected-warning 0-1{{register}} expected-error 
0-1{{register}}
   for (constexpr int a : X::C()) {} // OK per CWG issue #1204.
+  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{range-based for 
loop variable is initialized on each iteration from the loop's iterator, whose 
value is not known at compile time}}
+  int arr[] = {1, 2, 3};
+  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{range-based for 
loop variable is initialized on each iteration}}
 
   for (auto u : X::NoBeginADL()) { // expected-error {{invalid range 
expression of type 'X::NoBeginADL'; no viable 'begin' function available}}
   }
diff --git a/clang/test/SemaCXX/GH211926.cpp b/clang/test/SemaCXX/GH211926.cpp
deleted file mode 100644
index 77e2938f0368b..0000000000000
--- a/clang/test/SemaCXX/GH211926.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
-
-// GH211926: constexpr range-based for loop variables used to be diagnosed
-// with a note about the compiler-synthesized '__begin1' variable.
-
-namespace std {
-typedef decltype(sizeof(int)) size_t;
-template <typename T> struct initializer_list {
-  const T *p;
-  size_t n;
-  initializer_list(const T *p, size_t n);
-  const T *begin() const; // expected-note {{selected 'begin' function with 
iterator type 'const int *'}}
-  const T *end() const;
-};
-} // namespace std
-
-void init_list() {
-  for (constexpr auto x : {1, 2, 3}) { // expected-error {{constexpr variable 
'x' must be initialized by a constant expression; a range-based for loop 
variable is initialized on each iteration from the loop's iterator, whose value 
is not known at compile time}}
-  }
-}
-
-void c_array() {
-  int arr[3] = {1, 2, 3};
-  for (constexpr int x : arr) { // expected-error {{constexpr variable 'x' 
must be initialized by a constant expression; a range-based for loop variable 
is initialized on each iteration}}
-  }
-}
-
-struct Vec {
-  int data[3];
-  const int *begin() const; // expected-note {{selected 'begin' function with 
iterator type 'const int *'}}
-  const int *end() const;
-};
-
-void container() {
-  Vec v = {{1, 2, 3}};
-  for (constexpr int x : v) { // expected-error {{constexpr variable 'x' must 
be initialized by a constant expression; a range-based for loop variable is 
initialized on each iteration}}
-  }
-}
-
-template <typename T> void dependent(T &range) {
-  for (constexpr auto x : range) { // expected-error {{constexpr variable 'x' 
must be initialized by a constant expression; a range-based for loop variable 
is initialized on each iteration}}
-  }
-}
-
-void instantiate() {
-  int arr[3] = {1, 2, 3};
-  dependent(arr); // expected-note {{in instantiation of function template 
specialization}}
-}
-
-void plain_loop_var() {
-  for (auto x : {1, 2, 3})
-    (void)x;
-  int arr[3] = {1, 2, 3};
-  for (int &x : arr)
-    x = 0;
-}
-
-// Still valid when the initializer is a constant expression (CWG1204).
-struct StatelessIter {
-  struct It {
-    int pos;
-    It &operator++();
-    bool operator!=(const It &other) const;
-  };
-  It begin();
-  It end();
-};
-constexpr int operator*(const StatelessIter::It &) { return 7; }
-
-void stateless_iterator() {
-  for (constexpr int x : StatelessIter()) {
-    static_assert(x == 7, "");
-  }
-}
-
-void ordinary_constexpr() {
-  constexpr int ok = 42;
-  static_assert(ok == 42, "");
-
-  int runtime = 0;             // expected-note {{declared here}}
-  constexpr int bad = runtime; // expected-error {{constexpr variable 'bad' 
must be initialized by a constant expression}} expected-note {{read of 
non-const variable 'runtime' is not allowed in a constant expression}}
-
-  for (constexpr int i = 0; i != 0;) {
-  }
-}
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp 
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 47a064c4026b4..0219461f05ae8 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1943,6 +1943,10 @@ namespace InitializerList {
     constexpr std::initializer_list<float> il = {1.0, 2.0, 3.0};
     static_assert(il.begin()[1] == 2.0, "");
   }
+
+  void constexpr_loop_var() {
+    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note 
{{range-based for loop variable is initialized on each iteration from the 
loop's iterator, whose value is not known at compile time}}
+  }
 }
 
 namespace StmtExpr {

>From c018aca534909ab9782b80310e775e83925f34e2 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Wed, 26 Aug 2026 20:01:25 +0530
Subject: [PATCH 3/9] [clang] Name the range in the constexpr range-for
 iterator note

Reword note_constexpr_ltor_for_range_var to state the actual cause: the
loop's iterator is not a constant expression, which holds even when the
range itself is constexpr. Name the range variable when there is one and
point the note at the range expression, in both constant evaluators.
---
 clang/docs/ReleaseNotes.md                    |  6 +--
 .../include/clang/Basic/DiagnosticASTKinds.td |  4 +-
 clang/lib/AST/ByteCode/Interp.cpp             |  9 ++++-
 clang/lib/AST/ExprConstShared.h               |  9 +++++
 clang/lib/AST/ExprConstant.cpp                | 38 ++++++++++++++++++-
 clang/test/AST/ByteCode/cxx11.cpp             |  2 +-
 .../stmt.stmt/stmt.iter/stmt.ranged/p1.cpp    |  6 ++-
 .../SemaCXX/constant-expression-cxx11.cpp     |  2 +-
 8 files changed, 65 insertions(+), 11 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index f3b650a20ca3a..f4c40f6ba736b 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -430,9 +430,9 @@ features cannot lower the translation-unit ABI level;
   a note about the compiler-synthesized `__begin` variable. (#GH211926)
 
 - When a `constexpr` range-based for loop variable cannot be initialized by a
-  constant expression, Clang now explains in a note that the loop variable is
-  initialized from the loop's iterator, instead of referring to the
-  compiler-synthesized `__begin` variable. (#GH211926)
+  constant expression, Clang now notes that the loop's iterator is not a
+  constant expression, naming the range being iterated, instead of referring
+  to the compiler-synthesized `__begin` variable. (#GH211926)
 
 ### Improvements to Clang's time-trace
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index edbf125a0804b..2cbb3ade70ac2 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -223,8 +223,8 @@ def note_constexpr_ltor_non_integral : Note<
 def note_constexpr_ltor_non_constexpr : Note<
   "read of non-constexpr variable %0 is not allowed in a constant expression">;
 def note_constexpr_ltor_for_range_var : Note<
-  "range-based for loop variable is initialized on each iteration from the "
-  "loop's iterator, whose value is not known at compile time">;
+  "iterator of the range-based for loop%select{| over %1}0 is not a constant "
+  "expression">;
 def note_constexpr_ltor_incomplete_type : Note<
   "read of incomplete type %0 is not allowed in a constant expression">;
 def note_constexpr_access_null : Note<
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 589ef62650223..b9467eaccc64d 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -163,7 +163,14 @@ static void diagnoseNonConstVariable(InterpState &S, 
CodePtr OpPC,
 
   if (const auto *VarD = dyn_cast<VarDecl>(VD);
       VarD && VarD->isCXXForRangeImplicitVar()) {
-    S.FFDiag(Loc, diag::note_constexpr_ltor_for_range_var);
+    auto [Range, RangeDecl] = GetCXXForRangeRange(VarD);
+    OptionalDiagnostic Diag =
+        Range ? S.FFDiag(Range, diag::note_constexpr_ltor_for_range_var)
+              : S.FFDiag(Loc, diag::note_constexpr_ltor_for_range_var);
+    if (RangeDecl)
+      Diag << 1 << RangeDecl;
+    else
+      Diag << 0;
     return;
   }
 
diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h
index cdf2a5697528e..4da24ab12649e 100644
--- a/clang/lib/AST/ExprConstShared.h
+++ b/clang/lib/AST/ExprConstShared.h
@@ -17,6 +17,7 @@
 #include "clang/Basic/BuiltinTraits.h"
 #include <cstdint>
 #include <optional>
+#include <utility>
 
 namespace llvm {
 class APFloat;
@@ -30,6 +31,8 @@ class ASTContext;
 class CharUnits;
 class Expr;
 class CallExpr;
+class NamedDecl;
+class VarDecl;
 } // namespace clang
 using namespace clang;
 /// Values returned by __builtin_classify_type, chosen to match the values
@@ -79,6 +82,12 @@ void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat 
B, llvm::APFloat C,
 CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
                          UnaryExprOrTypeTrait ExprKind);
 
+/// Given an implicit variable of a range-based for statement ('__range',
+/// '__begin' or '__end'), return the range expression the loop iterates over
+/// and, if that expression names a variable, the variable.
+std::pair<const Expr *, const NamedDecl *>
+GetCXXForRangeRange(const VarDecl *ImplicitVar);
+
 /// Convert a builtin ID to the canonical x86 builtin ID the constant 
evaluators
 /// dispatch on in their x86 target-specific cases.
 ///
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 90543e6e31c74..b06b4130c39dc 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4776,7 +4776,13 @@ static CompleteObject findCompleteObject(EvalInfo &Info, 
const Expr *E,
       } else if (VD->isCXXForRangeImplicitVar()) {
         if (!IsAccess)
           return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
-        Info.FFDiag(E, diag::note_constexpr_ltor_for_range_var);
+        auto [Range, RangeDecl] = GetCXXForRangeRange(VD);
+        OptionalDiagnostic Diag = Info.FFDiag(
+            Range ? Range : E, diag::note_constexpr_ltor_for_range_var);
+        if (RangeDecl)
+          Diag << 1 << RangeDecl;
+        else
+          Diag << 0;
         return CompleteObject();
       } else if (BaseType->isIntegralOrEnumerationType()) {
         if (!IsConstant) {
@@ -10564,6 +10570,36 @@ CharUnits GetAlignOfExpr(const ASTContext &Ctx, const 
Expr *E,
   return GetAlignOfType(Ctx, E->getType(), ExprKind);
 }
 
+std::pair<const Expr *, const NamedDecl *>
+GetCXXForRangeRange(const VarDecl *ImplicitVar) {
+  const Expr *Range = ImplicitVar->getInit();
+  if (!Range)
+    return {nullptr, nullptr};
+
+  // '__begin' and '__end' are initialized from '__range', whose initializer
+  // is the range expression.
+  SmallVector<const Stmt *, 8> Worklist = {Range};
+  while (!Worklist.empty()) {
+    const Stmt *S = Worklist.pop_back_val();
+    if (!S)
+      continue;
+    if (const auto *DRE = dyn_cast<DeclRefExpr>(S)) {
+      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
+          VD && VD->isCXXForRangeImplicitVar()) {
+        Range = VD->getInit();
+        break;
+      }
+    }
+    Worklist.append(S->child_begin(), S->child_end());
+  }
+
+  const NamedDecl *RangeDecl = nullptr;
+  if (Range)
+    if (const auto *DRE = dyn_cast<DeclRefExpr>(Range->IgnoreParenImpCasts()))
+      RangeDecl = DRE->getDecl();
+  return {Range, RangeDecl};
+}
+
 static CharUnits getBaseAlignment(EvalInfo &Info, const LValue &Value) {
   if (const auto *VD = Value.Base.dyn_cast<const ValueDecl *>())
     return Info.Ctx.getDeclAlign(VD);
diff --git a/clang/test/AST/ByteCode/cxx11.cpp 
b/clang/test/AST/ByteCode/cxx11.cpp
index bdd613511f2b3..685847887ee84 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -506,6 +506,6 @@ namespace ConstexprForRangeVar {
   void f() {
     int arr[] = {1, 2, 3};
     for (constexpr int a : arr) {} // both-error {{constexpr variable 'a' must 
be initialized by a constant expression}} \
-                                   // both-note {{range-based for loop 
variable is initialized on each iteration from the loop's iterator, whose value 
is not known at compile time}}
+                                   // both-note {{iterator of the range-based 
for loop over 'arr' is not a constant expression}}
   }
 }
diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp 
b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index 50b722a9bec20..efdf90d4118a2 100644
--- a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -154,9 +154,11 @@ void g() {
   for (thread_local int a : A()) {} // expected-error {{loop variable 'a' may 
not be declared 'thread_local'}}
   for (register int a : A()) {} // expected-error {{loop variable 'a' may not 
be declared 'register'}} expected-warning 0-1{{register}} expected-error 
0-1{{register}}
   for (constexpr int a : X::C()) {} // OK per CWG issue #1204.
-  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{range-based for 
loop variable is initialized on each iteration from the loop's iterator, whose 
value is not known at compile time}}
+  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{iterator of the 
range-based for loop is not a constant expression}}
   int arr[] = {1, 2, 3};
-  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{range-based for 
loop variable is initialized on each iteration}}
+  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{iterator of the 
range-based for loop over 'arr' is not a constant expression}}
+  constexpr int carr[] = {1, 2, 3};
+  for (constexpr int a : carr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{iterator of the 
range-based for loop over 'carr' is not a constant expression}}
 
   for (auto u : X::NoBeginADL()) { // expected-error {{invalid range 
expression of type 'X::NoBeginADL'; no viable 'begin' function available}}
   }
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp 
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 0219461f05ae8..197b38f65dac2 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1945,7 +1945,7 @@ namespace InitializerList {
   }
 
   void constexpr_loop_var() {
-    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note 
{{range-based for loop variable is initialized on each iteration from the 
loop's iterator, whose value is not known at compile time}}
+    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note 
{{iterator of the range-based for loop is not a constant expression}}
   }
 }
 

>From d48417472a432b9850c66a2c3e06d3e41b680a35 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Wed, 26 Aug 2026 20:25:05 +0530
Subject: [PATCH 4/9] [clang] Improve diagnostic for constexpr range-based for
 loop variable initialization

---
 clang/docs/ReleaseNotes.md | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index f4c40f6ba736b..6fbde953bc71d 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -425,10 +425,6 @@ features cannot lower the translation-unit ABI level;
 
 - Clang now diagnoses more details when a constraint evaluates to false.
 
-- Clang now emits a clearer diagnostic when a `constexpr` range-based for
-  loop variable cannot be initialized by a constant expression, instead of
-  a note about the compiler-synthesized `__begin` variable. (#GH211926)
-
 - When a `constexpr` range-based for loop variable cannot be initialized by a
   constant expression, Clang now notes that the loop's iterator is not a
   constant expression, naming the range being iterated, instead of referring

>From 17bedcaf4624af5cc82ad7f4c6f67fdcd80a3ef8 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Wed, 26 Aug 2026 23:18:51 +0530
Subject: [PATCH 5/9] [clang] Say which range-for variable fails constant
 evaluation

Replace the two notes about reading the compiler-synthesized '__begin1'
with a single note, emitted by both constant evaluators, that the loop's
'begin' variable is not a constant expression, and drop the attempt to
name the range being iterated.
---
 clang/docs/ReleaseNotes.md                    |  6 +--
 .../include/clang/Basic/DiagnosticASTKinds.td |  3 +-
 clang/lib/AST/ByteCode/Interp.cpp             |  9 +----
 clang/lib/AST/ExprConstShared.h               |  9 -----
 clang/lib/AST/ExprConstant.cpp                | 38 +------------------
 clang/test/AST/ByteCode/cxx11.cpp             |  2 +-
 .../stmt.stmt/stmt.iter/stmt.ranged/p1.cpp    |  8 ++--
 .../SemaCXX/constant-expression-cxx11.cpp     | 25 +++++++++++-
 8 files changed, 33 insertions(+), 67 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 6fbde953bc71d..7f1afb8f6ba26 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -426,9 +426,9 @@ features cannot lower the translation-unit ABI level;
 - Clang now diagnoses more details when a constraint evaluates to false.
 
 - When a `constexpr` range-based for loop variable cannot be initialized by a
-  constant expression, Clang now notes that the loop's iterator is not a
-  constant expression, naming the range being iterated, instead of referring
-  to the compiler-synthesized `__begin` variable. (#GH211926)
+  constant expression, Clang now emits a single note explaining that the
+  loop's `begin` variable is not a constant expression, instead of two notes
+  about reading the compiler-synthesized `__begin1` variable. (#GH211926)
 
 ### Improvements to Clang's time-trace
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 2cbb3ade70ac2..97fd12567de5e 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -223,8 +223,7 @@ def note_constexpr_ltor_non_integral : Note<
 def note_constexpr_ltor_non_constexpr : Note<
   "read of non-constexpr variable %0 is not allowed in a constant expression">;
 def note_constexpr_ltor_for_range_var : Note<
-  "iterator of the range-based for loop%select{| over %1}0 is not a constant "
-  "expression">;
+  "'begin' variable of range-based 'for' loop is not a constant expression">;
 def note_constexpr_ltor_incomplete_type : Note<
   "read of incomplete type %0 is not allowed in a constant expression">;
 def note_constexpr_access_null : Note<
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index b9467eaccc64d..589ef62650223 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -163,14 +163,7 @@ static void diagnoseNonConstVariable(InterpState &S, 
CodePtr OpPC,
 
   if (const auto *VarD = dyn_cast<VarDecl>(VD);
       VarD && VarD->isCXXForRangeImplicitVar()) {
-    auto [Range, RangeDecl] = GetCXXForRangeRange(VarD);
-    OptionalDiagnostic Diag =
-        Range ? S.FFDiag(Range, diag::note_constexpr_ltor_for_range_var)
-              : S.FFDiag(Loc, diag::note_constexpr_ltor_for_range_var);
-    if (RangeDecl)
-      Diag << 1 << RangeDecl;
-    else
-      Diag << 0;
+    S.FFDiag(Loc, diag::note_constexpr_ltor_for_range_var);
     return;
   }
 
diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h
index 4da24ab12649e..cdf2a5697528e 100644
--- a/clang/lib/AST/ExprConstShared.h
+++ b/clang/lib/AST/ExprConstShared.h
@@ -17,7 +17,6 @@
 #include "clang/Basic/BuiltinTraits.h"
 #include <cstdint>
 #include <optional>
-#include <utility>
 
 namespace llvm {
 class APFloat;
@@ -31,8 +30,6 @@ class ASTContext;
 class CharUnits;
 class Expr;
 class CallExpr;
-class NamedDecl;
-class VarDecl;
 } // namespace clang
 using namespace clang;
 /// Values returned by __builtin_classify_type, chosen to match the values
@@ -82,12 +79,6 @@ void HandleComplexComplexDiv(llvm::APFloat A, llvm::APFloat 
B, llvm::APFloat C,
 CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E,
                          UnaryExprOrTypeTrait ExprKind);
 
-/// Given an implicit variable of a range-based for statement ('__range',
-/// '__begin' or '__end'), return the range expression the loop iterates over
-/// and, if that expression names a variable, the variable.
-std::pair<const Expr *, const NamedDecl *>
-GetCXXForRangeRange(const VarDecl *ImplicitVar);
-
 /// Convert a builtin ID to the canonical x86 builtin ID the constant 
evaluators
 /// dispatch on in their x86 target-specific cases.
 ///
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index b06b4130c39dc..90543e6e31c74 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4776,13 +4776,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, 
const Expr *E,
       } else if (VD->isCXXForRangeImplicitVar()) {
         if (!IsAccess)
           return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
-        auto [Range, RangeDecl] = GetCXXForRangeRange(VD);
-        OptionalDiagnostic Diag = Info.FFDiag(
-            Range ? Range : E, diag::note_constexpr_ltor_for_range_var);
-        if (RangeDecl)
-          Diag << 1 << RangeDecl;
-        else
-          Diag << 0;
+        Info.FFDiag(E, diag::note_constexpr_ltor_for_range_var);
         return CompleteObject();
       } else if (BaseType->isIntegralOrEnumerationType()) {
         if (!IsConstant) {
@@ -10570,36 +10564,6 @@ CharUnits GetAlignOfExpr(const ASTContext &Ctx, const 
Expr *E,
   return GetAlignOfType(Ctx, E->getType(), ExprKind);
 }
 
-std::pair<const Expr *, const NamedDecl *>
-GetCXXForRangeRange(const VarDecl *ImplicitVar) {
-  const Expr *Range = ImplicitVar->getInit();
-  if (!Range)
-    return {nullptr, nullptr};
-
-  // '__begin' and '__end' are initialized from '__range', whose initializer
-  // is the range expression.
-  SmallVector<const Stmt *, 8> Worklist = {Range};
-  while (!Worklist.empty()) {
-    const Stmt *S = Worklist.pop_back_val();
-    if (!S)
-      continue;
-    if (const auto *DRE = dyn_cast<DeclRefExpr>(S)) {
-      if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl());
-          VD && VD->isCXXForRangeImplicitVar()) {
-        Range = VD->getInit();
-        break;
-      }
-    }
-    Worklist.append(S->child_begin(), S->child_end());
-  }
-
-  const NamedDecl *RangeDecl = nullptr;
-  if (Range)
-    if (const auto *DRE = dyn_cast<DeclRefExpr>(Range->IgnoreParenImpCasts()))
-      RangeDecl = DRE->getDecl();
-  return {Range, RangeDecl};
-}
-
 static CharUnits getBaseAlignment(EvalInfo &Info, const LValue &Value) {
   if (const auto *VD = Value.Base.dyn_cast<const ValueDecl *>())
     return Info.Ctx.getDeclAlign(VD);
diff --git a/clang/test/AST/ByteCode/cxx11.cpp 
b/clang/test/AST/ByteCode/cxx11.cpp
index 685847887ee84..32159a61edd99 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -506,6 +506,6 @@ namespace ConstexprForRangeVar {
   void f() {
     int arr[] = {1, 2, 3};
     for (constexpr int a : arr) {} // both-error {{constexpr variable 'a' must 
be initialized by a constant expression}} \
-                                   // both-note {{iterator of the range-based 
for loop over 'arr' is not a constant expression}}
+                                   // both-note {{'begin' variable of 
range-based 'for' loop is not a constant expression}}
   }
 }
diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp 
b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index efdf90d4118a2..51989e09ce78f 100644
--- a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -154,11 +154,9 @@ void g() {
   for (thread_local int a : A()) {} // expected-error {{loop variable 'a' may 
not be declared 'thread_local'}}
   for (register int a : A()) {} // expected-error {{loop variable 'a' may not 
be declared 'register'}} expected-warning 0-1{{register}} expected-error 
0-1{{register}}
   for (constexpr int a : X::C()) {} // OK per CWG issue #1204.
-  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{iterator of the 
range-based for loop is not a constant expression}}
-  int arr[] = {1, 2, 3};
-  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{iterator of the 
range-based for loop over 'arr' is not a constant expression}}
-  constexpr int carr[] = {1, 2, 3};
-  for (constexpr int a : carr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{iterator of the 
range-based for loop over 'carr' is not a constant expression}}
+  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{'begin' variable 
of range-based 'for' loop is not a constant expression}}
+  constexpr int arr[] = {1, 2, 3};
+  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{'begin' variable 
of range-based 'for' loop is not a constant expression}}
 
   for (auto u : X::NoBeginADL()) { // expected-error {{invalid range 
expression of type 'X::NoBeginADL'; no viable 'begin' function available}}
   }
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp 
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index 197b38f65dac2..cf9a4b2e6d5fb 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1943,9 +1943,30 @@ namespace InitializerList {
     constexpr std::initializer_list<float> il = {1.0, 2.0, 3.0};
     static_assert(il.begin()[1] == 2.0, "");
   }
+}
+
+namespace ConstexprForRangeVar {
+  void invalid() {
+    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note 
{{'begin' variable of range-based 'for' loop is not a constant expression}}
+  }
 
-  void constexpr_loop_var() {
-    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note 
{{iterator of the range-based for loop is not a constant expression}}
+  struct S {
+    struct iterator {
+      constexpr iterator operator++() const { return {}; }
+      constexpr bool operator!=(const iterator &) const { return false; }
+      constexpr int operator*() const { return 42; }
+    };
+    static constexpr iterator begin() { return iterator(); }
+    static constexpr iterator end() { return iterator(); }
+  };
+
+  template <int x> constexpr int g() { return x; }
+
+  void valid() {
+    for (constexpr int x : S()) {
+      static_assert(x == 42, "");
+      static_assert(g<x>() == 42, "");
+    }
   }
 }
 

>From fd686d49f3bd99ea11b2e311d22581867ff99c9a Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Thu, 27 Aug 2026 08:35:52 +0530
Subject: [PATCH 6/9] [clang] Name the implicit variable in the range-for
 constant evaluation note

isCXXForRangeImplicitVar() is also true for '__range' and '__end', so a
note hard-coded to 'begin' could be wrong. Pass the variable to the note
so it names whichever implicit variable was actually read.
---
 clang/docs/ReleaseNotes.md                            | 5 +++--
 clang/include/clang/Basic/DiagnosticASTKinds.td       | 2 +-
 clang/lib/AST/ByteCode/Interp.cpp                     | 2 +-
 clang/lib/AST/ExprConstant.cpp                        | 2 +-
 clang/test/AST/ByteCode/cxx11.cpp                     | 2 +-
 clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp | 4 ++--
 clang/test/SemaCXX/constant-expression-cxx11.cpp      | 2 +-
 7 files changed, 10 insertions(+), 9 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7f1afb8f6ba26..96abd50622923 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -427,8 +427,9 @@ features cannot lower the translation-unit ABI level;
 
 - When a `constexpr` range-based for loop variable cannot be initialized by a
   constant expression, Clang now emits a single note explaining that the
-  loop's `begin` variable is not a constant expression, instead of two notes
-  about reading the compiler-synthesized `__begin1` variable. (#GH211926)
+  loop's implicit `__begin` variable is not a constant expression, instead of
+  a generic note about reading a non-constexpr variable followed by a
+  `declared here` note. (#GH211926)
 
 ### Improvements to Clang's time-trace
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 97fd12567de5e..4939a3bdd94bd 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -223,7 +223,7 @@ def note_constexpr_ltor_non_integral : Note<
 def note_constexpr_ltor_non_constexpr : Note<
   "read of non-constexpr variable %0 is not allowed in a constant expression">;
 def note_constexpr_ltor_for_range_var : Note<
-  "'begin' variable of range-based 'for' loop is not a constant expression">;
+  "%0-variable of range-based 'for' loop is not a constant expression">;
 def note_constexpr_ltor_incomplete_type : Note<
   "read of incomplete type %0 is not allowed in a constant expression">;
 def note_constexpr_access_null : Note<
diff --git a/clang/lib/AST/ByteCode/Interp.cpp 
b/clang/lib/AST/ByteCode/Interp.cpp
index 589ef62650223..d92d301750c9c 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -163,7 +163,7 @@ static void diagnoseNonConstVariable(InterpState &S, 
CodePtr OpPC,
 
   if (const auto *VarD = dyn_cast<VarDecl>(VD);
       VarD && VarD->isCXXForRangeImplicitVar()) {
-    S.FFDiag(Loc, diag::note_constexpr_ltor_for_range_var);
+    S.FFDiag(Loc, diag::note_constexpr_ltor_for_range_var) << VarD;
     return;
   }
 
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 90543e6e31c74..ce1d629d9f735 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -4776,7 +4776,7 @@ static CompleteObject findCompleteObject(EvalInfo &Info, 
const Expr *E,
       } else if (VD->isCXXForRangeImplicitVar()) {
         if (!IsAccess)
           return CompleteObject(LVal.getLValueBase(), nullptr, BaseType);
-        Info.FFDiag(E, diag::note_constexpr_ltor_for_range_var);
+        Info.FFDiag(E, diag::note_constexpr_ltor_for_range_var) << VD;
         return CompleteObject();
       } else if (BaseType->isIntegralOrEnumerationType()) {
         if (!IsConstant) {
diff --git a/clang/test/AST/ByteCode/cxx11.cpp 
b/clang/test/AST/ByteCode/cxx11.cpp
index 32159a61edd99..51667cfde8211 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -506,6 +506,6 @@ namespace ConstexprForRangeVar {
   void f() {
     int arr[] = {1, 2, 3};
     for (constexpr int a : arr) {} // both-error {{constexpr variable 'a' must 
be initialized by a constant expression}} \
-                                   // both-note {{'begin' variable of 
range-based 'for' loop is not a constant expression}}
+                                   // both-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
   }
 }
diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp 
b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index 51989e09ce78f..dabbbcb55209b 100644
--- a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -154,9 +154,9 @@ void g() {
   for (thread_local int a : A()) {} // expected-error {{loop variable 'a' may 
not be declared 'thread_local'}}
   for (register int a : A()) {} // expected-error {{loop variable 'a' may not 
be declared 'register'}} expected-warning 0-1{{register}} expected-error 
0-1{{register}}
   for (constexpr int a : X::C()) {} // OK per CWG issue #1204.
-  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{'begin' variable 
of range-based 'for' loop is not a constant expression}}
+  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
   constexpr int arr[] = {1, 2, 3};
-  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note {{'begin' variable 
of range-based 'for' loop is not a constant expression}}
+  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
 
   for (auto u : X::NoBeginADL()) { // expected-error {{invalid range 
expression of type 'X::NoBeginADL'; no viable 'begin' function available}}
   }
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp 
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index cf9a4b2e6d5fb..ac210c6c2f732 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1947,7 +1947,7 @@ namespace InitializerList {
 
 namespace ConstexprForRangeVar {
   void invalid() {
-    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note 
{{'begin' variable of range-based 'for' loop is not a constant expression}}
+    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
   }
 
   struct S {

>From 35016b53476390b2e4631ad4eb3ffd159b3a1b49 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Thu, 27 Aug 2026 23:31:52 +0530
Subject: [PATCH 7/9] [clang] Add constexpr range-based for loop tests for
 C++20 and C++23 features

---
 .../SemaCXX/constant-expression-cxx11.cpp     | 50 +++++++++++++++++++
 1 file changed, 50 insertions(+)

diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp 
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index ac210c6c2f732..a5a6af4df653c 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1968,6 +1968,56 @@ namespace ConstexprForRangeVar {
       static_assert(g<x>() == 42, "");
     }
   }
+
+  struct T {
+    struct iterator {
+      int n;
+      constexpr iterator operator++() const { return {n + 1}; }
+      constexpr bool operator!=(const iterator &o) const { return n != o.n; }
+      constexpr int operator*() const { return n; } // #member-read
+    };
+    static constexpr iterator begin() { return {0}; }
+    static constexpr iterator end() { return {3}; }
+  };
+
+  void member_read() {
+    for (constexpr int x : T()) {} // expected-error {{constexpr variable 'x' 
must be initialized by a constant expression}} \
+                                   // expected-note-re {{in call to 
'__begin{{[0-9]+}}.operator*()'}} \
+                                   // expected-note-re@#member-read 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+  }
+
+#if __cplusplus >= 202002L
+  struct Sentinel {
+    struct iterator {
+      friend consteval bool operator!=(const iterator &, const iterator &end) 
{ return end.b; } // #sentinel-read
+      int operator*();
+      void operator++();
+      bool b;
+    };
+    iterator begin();
+    iterator end();
+  };
+
+  void end_var() {
+    Sentinel s = {};
+    for (int n : s) {} // cxx20_23-error-re {{call to consteval function 
'{{.*}}operator!=' is not a constant expression}} \
+                       // cxx20_23-note-re {{in call to 
'{{.*}}operator!=({{.*}})'}} \
+                       // cxx20_23-note-re@#sentinel-read 
{{'__end{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+  }
+#endif
+
+#if __cplusplus >= 202302L
+  struct ByValueBegin { int *p; };
+  consteval int *begin(ByValueBegin r) { return r.p; }
+  int *end(ByValueBegin r);
+
+  void range_var() {
+    ByValueBegin r = {nullptr};
+    for (int n : r) {} // cxx23-error-re {{call to consteval function 
'{{.*}}begin' is not a constant expression}} \
+                       // cxx23-note-re {{in call to 
'ByValueBegin(__range{{[0-9]+}})'}} \
+                       // cxx23-note-re {{'__range{{[0-9]+}}'-variable of 
range-based 'for' loop is not a constant expression}}
+  }
+#endif
 }
 
 namespace StmtExpr {

>From 82c3c8c2f61fa3390dbe783458c61f28d4ebc16c Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Fri, 28 Aug 2026 10:17:13 +0530
Subject: [PATCH 8/9] [clang] Reword the range-for constant evaluation note as
 a disallowed read

A variable is not an expression; phrase the note like the neighbouring
read-of-variable notes while still naming the implicit variable.
---
 clang/docs/ReleaseNotes.md                            | 8 ++++----
 clang/include/clang/Basic/DiagnosticASTKinds.td       | 3 ++-
 clang/test/AST/ByteCode/cxx11.cpp                     | 2 +-
 clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp | 4 ++--
 clang/test/SemaCXX/constant-expression-cxx11.cpp      | 8 ++++----
 5 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 96abd50622923..e7690d7966aa7 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -426,10 +426,10 @@ features cannot lower the translation-unit ABI level;
 - Clang now diagnoses more details when a constraint evaluates to false.
 
 - When a `constexpr` range-based for loop variable cannot be initialized by a
-  constant expression, Clang now emits a single note explaining that the
-  loop's implicit `__begin` variable is not a constant expression, instead of
-  a generic note about reading a non-constexpr variable followed by a
-  `declared here` note. (#GH211926)
+  constant expression, Clang now emits a single note identifying the read of
+  the loop's implicit `__begin` variable, instead of a generic note about
+  reading a non-constexpr variable followed by a `declared here` note.
+  (#GH211926)
 
 ### Improvements to Clang's time-trace
 
diff --git a/clang/include/clang/Basic/DiagnosticASTKinds.td 
b/clang/include/clang/Basic/DiagnosticASTKinds.td
index 4939a3bdd94bd..0aca1f75428f8 100644
--- a/clang/include/clang/Basic/DiagnosticASTKinds.td
+++ b/clang/include/clang/Basic/DiagnosticASTKinds.td
@@ -223,7 +223,8 @@ def note_constexpr_ltor_non_integral : Note<
 def note_constexpr_ltor_non_constexpr : Note<
   "read of non-constexpr variable %0 is not allowed in a constant expression">;
 def note_constexpr_ltor_for_range_var : Note<
-  "%0-variable of range-based 'for' loop is not a constant expression">;
+  "read of implicit variable %0 of range-based 'for' loop is not allowed in a "
+  "constant expression">;
 def note_constexpr_ltor_incomplete_type : Note<
   "read of incomplete type %0 is not allowed in a constant expression">;
 def note_constexpr_access_null : Note<
diff --git a/clang/test/AST/ByteCode/cxx11.cpp 
b/clang/test/AST/ByteCode/cxx11.cpp
index 51667cfde8211..f2e0ce45154de 100644
--- a/clang/test/AST/ByteCode/cxx11.cpp
+++ b/clang/test/AST/ByteCode/cxx11.cpp
@@ -506,6 +506,6 @@ namespace ConstexprForRangeVar {
   void f() {
     int arr[] = {1, 2, 3};
     for (constexpr int a : arr) {} // both-error {{constexpr variable 'a' must 
be initialized by a constant expression}} \
-                                   // both-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+                                   // both-note-re {{read of implicit variable 
'__begin{{[0-9]+}}' of range-based 'for' loop is not allowed in a constant 
expression}}
   }
 }
diff --git a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp 
b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
index dabbbcb55209b..e82b4d33d5a6a 100644
--- a/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
+++ b/clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
@@ -154,9 +154,9 @@ void g() {
   for (thread_local int a : A()) {} // expected-error {{loop variable 'a' may 
not be declared 'thread_local'}}
   for (register int a : A()) {} // expected-error {{loop variable 'a' may not 
be declared 'register'}} expected-warning 0-1{{register}} expected-error 
0-1{{register}}
   for (constexpr int a : X::C()) {} // OK per CWG issue #1204.
-  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+  for (constexpr int a : A()) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note-re {{read of 
implicit variable '__begin{{[0-9]+}}' of range-based 'for' loop is not allowed 
in a constant expression}}
   constexpr int arr[] = {1, 2, 3};
-  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+  for (constexpr int a : arr) {} // expected-error {{constexpr variable 'a' 
must be initialized by a constant expression}} expected-note-re {{read of 
implicit variable '__begin{{[0-9]+}}' of range-based 'for' loop is not allowed 
in a constant expression}}
 
   for (auto u : X::NoBeginADL()) { // expected-error {{invalid range 
expression of type 'X::NoBeginADL'; no viable 'begin' function available}}
   }
diff --git a/clang/test/SemaCXX/constant-expression-cxx11.cpp 
b/clang/test/SemaCXX/constant-expression-cxx11.cpp
index a5a6af4df653c..7b483a4238652 100644
--- a/clang/test/SemaCXX/constant-expression-cxx11.cpp
+++ b/clang/test/SemaCXX/constant-expression-cxx11.cpp
@@ -1947,7 +1947,7 @@ namespace InitializerList {
 
 namespace ConstexprForRangeVar {
   void invalid() {
-    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note-re 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+    for (constexpr auto x : {1, 2, 3}) {} // expected-error {{constexpr 
variable 'x' must be initialized by a constant expression}} expected-note-re 
{{read of implicit variable '__begin{{[0-9]+}}' of range-based 'for' loop is 
not allowed in a constant expression}}
   }
 
   struct S {
@@ -1983,7 +1983,7 @@ namespace ConstexprForRangeVar {
   void member_read() {
     for (constexpr int x : T()) {} // expected-error {{constexpr variable 'x' 
must be initialized by a constant expression}} \
                                    // expected-note-re {{in call to 
'__begin{{[0-9]+}}.operator*()'}} \
-                                   // expected-note-re@#member-read 
{{'__begin{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+                                   // expected-note-re@#member-read {{read of 
implicit variable '__begin{{[0-9]+}}' of range-based 'for' loop is not allowed 
in a constant expression}}
   }
 
 #if __cplusplus >= 202002L
@@ -2002,7 +2002,7 @@ namespace ConstexprForRangeVar {
     Sentinel s = {};
     for (int n : s) {} // cxx20_23-error-re {{call to consteval function 
'{{.*}}operator!=' is not a constant expression}} \
                        // cxx20_23-note-re {{in call to 
'{{.*}}operator!=({{.*}})'}} \
-                       // cxx20_23-note-re@#sentinel-read 
{{'__end{{[0-9]+}}'-variable of range-based 'for' loop is not a constant 
expression}}
+                       // cxx20_23-note-re@#sentinel-read {{read of implicit 
variable '__end{{[0-9]+}}' of range-based 'for' loop is not allowed in a 
constant expression}}
   }
 #endif
 
@@ -2015,7 +2015,7 @@ namespace ConstexprForRangeVar {
     ByValueBegin r = {nullptr};
     for (int n : r) {} // cxx23-error-re {{call to consteval function 
'{{.*}}begin' is not a constant expression}} \
                        // cxx23-note-re {{in call to 
'ByValueBegin(__range{{[0-9]+}})'}} \
-                       // cxx23-note-re {{'__range{{[0-9]+}}'-variable of 
range-based 'for' loop is not a constant expression}}
+                       // cxx23-note-re {{read of implicit variable 
'__range{{[0-9]+}}' of range-based 'for' loop is not allowed in a constant 
expression}}
   }
 #endif
 }

>From 1b8b897a70df3e78fb2e9091ea365496647ad200 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Wed, 2 Sep 2026 00:58:12 +0530
Subject: [PATCH 9/9] Reposition the release notes to avoid the conflicts

---
 clang/docs/ReleaseNotes.md | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index e7690d7966aa7..d1005349b5531 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -253,6 +253,12 @@ features cannot lower the translation-unit ABI level;
 - Fixed bug in `-Wdocumentation` so that it correctly handles explicit
   function template instantiations (#64087).
 
+- When a `constexpr` range-based for loop variable cannot be initialized by a
+  constant expression, Clang now emits a single note identifying the read of
+  the loop's implicit `__begin` variable, instead of a generic note about
+  reading a non-constexpr variable followed by a `declared here` note.
+  (#GH211926)
+
 - Fixed concept template parameters not being recognized in `-Wdocumentation`
   when mentioned in tparam comments. (#GH64087)
 
@@ -425,12 +431,6 @@ features cannot lower the translation-unit ABI level;
 
 - Clang now diagnoses more details when a constraint evaluates to false.
 
-- When a `constexpr` range-based for loop variable cannot be initialized by a
-  constant expression, Clang now emits a single note identifying the read of
-  the loop's implicit `__begin` variable, instead of a generic note about
-  reading a non-constexpr variable followed by a `declared here` note.
-  (#GH211926)
-
 ### Improvements to Clang's time-trace
 
 ### Improvements to Coverage Mapping

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to