================
@@ -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;) {
+  }
----------------
Fznamznon wrote:

What is the point of adding this test case?

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

Reply via email to