--- gcc/cp/cp-tree.h.jj	2024-06-14 19:45:07.909797753 +0200
+++ gcc/cp/cp-tree.h	2024-07-02 08:28:30.500979154 +0200
@@ -4472,10 +4472,18 @@ get_vec_init_expr (tree t)
    ? DECL_LANG_SPECIFIC (NODE)->u.base.selector == lds_decomp		\
    : false)
 
-/* The underlying artificial VAR_DECL for structured binding.  */
+/* The underlying artificial VAR_DECL for structured binding.  On the
+   artificial base VAR_DECL this can be NULL, or integer_{zero,one}_node
+   for structured binding used in if/while/for resp. switch conditions,
+   or a TARGET_EXPR with the condition value after cp_finish_decomp in
+   those cases.  */
 #define DECL_DECOMP_BASE(NODE) \
   (LANG_DECL_DECOMP_CHECK (NODE)->base)
 
+/* True for the artificial VAR_DECL for structured binding.  */
+#define DECL_DECOMP_IS_BASE(NODE) \
+  (!DECL_DECOMP_BASE (NODE) || !VAR_P (DECL_DECOMP_BASE (NODE)))
+
 /* Nonzero if NODE is an inline VAR_DECL.  In C++17, static data members
    declared with constexpr specifier are implicitly inline variables.  */
 #define DECL_INLINE_VAR_P(NODE) \
--- gcc/cp/parser.cc.jj	2024-07-01 11:28:22.466241033 +0200
+++ gcc/cp/parser.cc	2024-07-02 09:02:10.635422397 +0200
@@ -2449,7 +2449,7 @@ static void cp_parser_statement_seq_opt
 static tree cp_parser_selection_statement
   (cp_parser *, bool *, vec<tree> *);
 static tree cp_parser_condition
-  (cp_parser *);
+  (cp_parser *, enum rid);
 static tree cp_parser_iteration_statement
   (cp_parser *, bool *, bool, tree, bool);
 static bool cp_parser_init_statement
@@ -2562,7 +2562,7 @@ static void cp_parser_static_assert
 static tree cp_parser_decltype
   (cp_parser *);
 static tree cp_parser_decomposition_declaration
-  (cp_parser *, cp_decl_specifier_seq *, tree *, location_t *);
+  (cp_parser *, cp_decl_specifier_seq *, tree *, location_t *, enum rid);
 
 /* Declarators [gram.dcl.decl] */
 
@@ -13690,7 +13690,7 @@ cp_parser_selection_statement (cp_parser
 	  }
 
 	/* Parse the condition.  */
-	condition = cp_parser_condition (parser);
+	condition = cp_parser_condition (parser, keyword);
 	/* Look for the `)'.  */
 	if (!parens.require_close (parser))
 	  cp_parser_skip_to_closing_parenthesis (parser, true, false,
@@ -13909,6 +13909,7 @@ cp_parser_check_condition_declarator (cp
      expression
      type-specifier-seq declarator = initializer-clause
      type-specifier-seq declarator braced-init-list
+     structured-binding-declaration initializer (C++26)
 
    GNU Extension:
 
@@ -13919,7 +13920,7 @@ cp_parser_check_condition_declarator (cp
    Returns the expression that should be tested.  */
 
 static tree
-cp_parser_condition (cp_parser* parser)
+cp_parser_condition (cp_parser* parser, enum rid keyword)
 {
   cp_decl_specifier_seq type_specifiers;
   const char *saved_message;
@@ -13956,6 +13957,26 @@ cp_parser_condition (cp_parser* parser)
       tree initializer = NULL_TREE;
       location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
+      /* Look for C++26 structured binding declaration.  */
+      for (size_t n = 1; ; n++)
+	if (cp_lexer_nth_token_is (parser->lexer, n, CPP_AND)
+	    || cp_lexer_nth_token_is (parser->lexer, n, CPP_AND_AND))
+	  continue;
+	else if (cp_lexer_nth_token_is (parser->lexer, n, CPP_OPEN_SQUARE)
+		 && !cp_lexer_nth_token_is (parser->lexer, n + 1,
+					    CPP_OPEN_SQUARE)
+		 && type_specifiers.any_specifiers_p
+		 && cp_parser_parse_definitely (parser))
+	  {
+	    location_t init_loc;
+	    tree decl
+	      = cp_parser_decomposition_declaration (parser, &type_specifiers,
+						     NULL, &init_loc, keyword);
+	    return decl;
+	  }
+	else
+	  break;
+
       /* Parse the declarator.  */
       declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
 					 CP_PARSER_FLAGS_NONE,
@@ -14095,7 +14116,7 @@ cp_parser_c_for (cp_parser *parser, tree
 
   /* If there's a condition, process it.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    condition = cp_parser_condition (parser);
+    condition = cp_parser_condition (parser, RID_FOR);
   else if (ivdep)
     {
       cp_parser_error (parser, "missing loop condition in loop with "
@@ -14660,7 +14681,7 @@ cp_parser_iteration_statement (cp_parser
 	matching_parens parens;
 	parens.require_open (parser);
 	/* Parse the condition.  */
-	condition = cp_parser_condition (parser);
+	condition = cp_parser_condition (parser, RID_WHILE);
 	finish_while_stmt_cond (condition, statement, ivdep, unroll, novector);
 	/* Look for the `)'.  */
 	parens.require_close (parser);
@@ -15966,7 +15987,7 @@ cp_parser_simple_declaration (cp_parser*
 	tree decl
 	  = cp_parser_decomposition_declaration (parser, &decl_specifiers,
 						 maybe_range_for_decl,
-						 &init_loc);
+						 &init_loc, RID_MAX);
 
 	/* The next token should be either a `,' or a `;'.  */
 	cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -16210,7 +16231,7 @@ static tree
 cp_parser_decomposition_declaration (cp_parser *parser,
 				     cp_decl_specifier_seq *decl_specifiers,
 				     tree *maybe_range_for_decl,
-				     location_t *init_loc)
+				     location_t *init_loc, enum rid keyword)
 {
   cp_ref_qualifier ref_qual = cp_parser_ref_qualifier_opt (parser);
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -16269,7 +16290,11 @@ cp_parser_decomposition_declaration (cp_
 	}
     }
 
-  if (cxx_dialect < cxx17)
+  if (keyword != RID_MAX && cxx_dialect < cxx26)
+    pedwarn (loc, OPT_Wc__26_extensions,
+	     "structured bindings in conditions only available with "
+	     "%<-std=c++2c%> or %<-std=gnu++2c%>");
+  else if (cxx_dialect < cxx17)
     pedwarn (loc, OPT_Wc__17_extensions,
 	     "structured bindings only available with "
 	     "%<-std=c++17%> or %<-std=gnu++17%>");
@@ -16357,6 +16382,9 @@ cp_parser_decomposition_declaration (cp_
 	  cp_finish_decl (decl, initializer, non_constant_p, NULL_TREE,
 			  (is_direct_init ? LOOKUP_NORMAL : LOOKUP_IMPLICIT),
 			  &decomp);
+	  if (keyword != RID_MAX)
+	    DECL_DECOMP_BASE (decl)
+	      = keyword == RID_SWITCH ? integer_one_node : integer_zero_node;
 	  cp_finish_decomp (decl, &decomp);
 	}
     }
--- gcc/cp/decl.cc.jj	2024-06-14 19:45:07.928797504 +0200
+++ gcc/cp/decl.cc	2024-07-02 09:07:29.764226608 +0200
@@ -697,7 +697,7 @@ poplevel (int keep, int reverse, int fun
 	    && ! DECL_IN_SYSTEM_HEADER (decl)
 	    /* For structured bindings, consider only real variables, not
 	       subobjects.  */
-	    && (DECL_DECOMPOSITION_P (decl) ? !DECL_DECOMP_BASE (decl)
+	    && (DECL_DECOMPOSITION_P (decl) ? DECL_DECOMP_IS_BASE (decl)
 		: (DECL_NAME (decl) && !DECL_ARTIFICIAL (decl)))
 	    /* Don't warn about name-independent declarations.  */
 	    && !name_independent_decl_p (decl)
@@ -7561,7 +7561,7 @@ check_array_initializer (tree decl, tree
      to have complete type.  */
   if (decl
       && DECL_DECOMPOSITION_P (decl)
-      && !DECL_DECOMP_BASE (decl)
+      && DECL_DECOMP_IS_BASE (decl)
       && !COMPLETE_TYPE_P (type))
     {
       error_at (DECL_SOURCE_LOCATION (decl),
@@ -9426,6 +9426,12 @@ cp_finish_decomp (tree decl, cp_decomp *
       nelts = array_type_nelts_top (type);
       if (nelts == error_mark_node)
 	goto error_out;
+      if (DECL_DECOMP_BASE (decl))
+	{
+	  error_at (loc, "array initializer for structured binding "
+		    "declaration in condition");
+	  goto error_out;
+	}
       if (!tree_fits_uhwi_p (nelts))
 	{
 	  error_at (loc, "cannot decompose variable length array %qT", type);
@@ -9525,6 +9531,30 @@ cp_finish_decomp (tree decl, cp_decomp *
       eltscnt = tree_to_uhwi (tsize);
       if (count != eltscnt)
 	goto cnt_mismatch;
+      if (!processing_template_decl && DECL_DECOMP_BASE (decl))
+	{
+	  /* For structured bindings used in conditions we need to evaluate
+	     the conversion of decl (aka e in the standard) to bool or
+	     integral/enumeral type (the latter for switch conditions)
+	     before the get methods.  */
+	  tree cond = convert_from_reference (decl);
+	  if (integer_onep (DECL_DECOMP_BASE (decl)))
+	    /* switch condition.  */
+	    cond = build_expr_type_conversion (WANT_INT | WANT_ENUM,
+					       cond, true);
+	  else
+	    /* if/while/for condition.  */
+	    cond = contextual_conv_bool (cond, tf_warning_or_error);
+	  if (cond && !error_operand_p (cond))
+	    {
+	      /* Wrap that value into a TARGET_EXPR, emit it right
+		 away and save for later uses in the cp_parse_condition
+		 or its instantiation.  */
+	      cond = get_target_expr (cond);
+	      add_stmt (cond);
+	      DECL_DECOMP_BASE (decl) = cond;
+	    }
+	}
       int save_read = DECL_READ_P (decl);	
       for (unsigned i = 0; i < count; ++i)
 	{
--- gcc/cp/decl2.cc.jj	2024-07-01 11:28:22.446241290 +0200
+++ gcc/cp/decl2.cc	2024-07-02 08:29:23.000288981 +0200
@@ -5893,7 +5893,7 @@ mark_used (tree decl, tsubst_flags_t com
   TREE_USED (decl) = true;
 
   /* And for structured bindings also the underlying decl.  */
-  if (DECL_DECOMPOSITION_P (decl) && DECL_DECOMP_BASE (decl))
+  if (DECL_DECOMPOSITION_P (decl) && !DECL_DECOMP_IS_BASE (decl))
     TREE_USED (DECL_DECOMP_BASE (decl)) = true;
 
   if (TREE_CODE (decl) == TEMPLATE_DECL)
--- gcc/cp/module.cc.jj	2024-06-14 19:45:07.958797110 +0200
+++ gcc/cp/module.cc	2024-07-02 08:32:31.041816753 +0200
@@ -10142,7 +10142,7 @@ trees_in::tree_node (bool is_use)
       TREE_USED (res) = true;
 
       /* And for structured bindings also the underlying decl.  */
-      if (DECL_DECOMPOSITION_P (res) && DECL_DECOMP_BASE (res))
+      if (DECL_DECOMPOSITION_P (res) && !DECL_DECOMP_IS_BASE (res))
 	TREE_USED (DECL_DECOMP_BASE (res)) = true;
 
       if (DECL_CLONED_FUNCTION_P (res))
--- gcc/cp/typeck.cc.jj	2024-07-01 11:28:22.500240597 +0200
+++ gcc/cp/typeck.cc	2024-07-02 08:33:12.541271107 +0200
@@ -10659,7 +10659,7 @@ maybe_warn_about_returning_address_of_lo
 	   || TREE_PUBLIC (whats_returned)))
     {
       if (DECL_DECOMPOSITION_P (whats_returned)
-	  && DECL_DECOMP_BASE (whats_returned)
+	  && !DECL_DECOMP_IS_BASE (whats_returned)
 	  && DECL_HAS_VALUE_EXPR_P (whats_returned))
 	{
 	  /* When returning address of a structured binding, if the structured
--- gcc/cp/semantics.cc.jj	2024-07-01 11:28:22.497240636 +0200
+++ gcc/cp/semantics.cc	2024-07-02 16:16:21.521924979 +0200
@@ -966,6 +966,15 @@ maybe_convert_cond (tree cond)
   if (type_dependent_expression_p (cond))
     return cond;
 
+  /* For structured binding used in condition, the conversion needs to be
+     evaluated before the individual variables are initialized in the
+     std::tuple_{size,elemenet} case.  cp_finish_decomp saved the conversion
+     result in a TARGET_EXPR, pick it up from there.  */
+  if (DECL_DECOMPOSITION_P (cond)
+      && DECL_DECOMP_IS_BASE (cond)
+      && TREE_CODE (DECL_DECOMP_BASE (cond)) == TARGET_EXPR)
+    cond = TARGET_EXPR_SLOT (DECL_DECOMP_BASE (cond));
+
   if (warn_sequence_point && !processing_template_decl)
     verify_sequence_points (cond);
 
@@ -1699,6 +1708,14 @@ finish_switch_cond (tree cond, tree swit
     {
       /* Convert the condition to an integer or enumeration type.  */
       tree orig_cond = cond;
+      /* For structured binding used in condition, the conversion needs to be
+	 evaluated before the individual variables are initialized in the
+	 std::tuple_{size,elemenet} case.  cp_finish_decomp saved the
+	 conversion result in a TARGET_EXPR, pick it up from there.  */
+      if (DECL_DECOMPOSITION_P (cond)
+	  && DECL_DECOMP_IS_BASE (cond)
+	  && TREE_CODE (DECL_DECOMP_BASE (cond)) == TARGET_EXPR)
+	cond = TARGET_EXPR_SLOT (DECL_DECOMP_BASE (cond));
       cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true);
       if (cond == NULL_TREE)
 	{
--- gcc/testsuite/g++.dg/cpp1z/decomp16.C.jj	2024-07-02 18:04:35.184990721 +0200
+++ gcc/testsuite/g++.dg/cpp1z/decomp16.C	2024-07-02 18:04:39.750932526 +0200
@@ -7,23 +7,23 @@ void
 foo ()
 {
   auto [ a, b ] = A ();
-  for (; auto [ a, b ] = A (); )			// { dg-error "expected" }
-    ;
+  for (; auto [ a, b ] = A (); )			// { dg-error "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;							// { dg-error "could not convert '<structured bindings>' from 'A' to 'bool'" "" { target *-*-* } .-1 }
   for (; false; auto [ a, b ] = A ())			// { dg-error "expected" }
     ;
-  if (auto [ a, b ] = A ())				// { dg-error "expected" }
-    ;
-  if (auto [ a, b ] = A (); auto [ c, d ] = A ())	// { dg-error "expected" }
-    ;
-  if (int d = 5; auto [ a, b ] = A ())			// { dg-error "expected" }
-    ;
-  switch (auto [ a, b ] = B ())				// { dg-error "expected" }
-    {
+  if (auto [ a, b ] = A ())				// { dg-error "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;							// { dg-error "could not convert '<structured bindings>' from 'A' to 'bool'" "" { target *-*-* } .-1 }
+  if (auto [ a, b ] = A (); auto [ c, d ] = A ())	// { dg-error "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;							// { dg-error "could not convert '<structured bindings>' from 'A' to 'bool'" "" { target *-*-* } .-1 }
+  if (int d = 5; auto [ a, b ] = A ())			// { dg-error "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;							// { dg-error "could not convert '<structured bindings>' from 'A' to 'bool'" "" { target *-*-* } .-1 }
+  switch (auto [ a, b ] = B ())				// { dg-error "structured bindings in conditions only available with" "" { target c++23_down } }
+    {							// { dg-error "switch quantity not an integer" "" { target *-*-* } .-1 }
     case 2:
       break;
     }
-  switch (int d = 5; auto [ a, b ] = B ())		// { dg-error "expected" }
-    {
+  switch (int d = 5; auto [ a, b ] = B ())		// { dg-error "structured bindings in conditions only available with" "" { target c++23_down } }
+    {							// { dg-error "switch quantity not an integer" "" { target *-*-* } .-1 }
     case 2:
       break;
     }
--- gcc/testsuite/g++.dg/cpp26/decomp3.C.jj	2024-07-01 17:11:02.086877632 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp3.C	2024-07-01 17:22:54.434805423 +0200
@@ -0,0 +1,168 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct S {
+  int a, b;
+  explicit operator bool () const noexcept { return a == b; }
+};
+
+struct T {
+  int a, b, c;
+  static int d;
+  explicit operator bool () const noexcept { d = 42; return a == b; }
+  template <int I> int &get () { if (d != 42) __builtin_abort (); return I ? a : b; }
+};
+int T::d = 0;
+
+template<> struct std::tuple_size<T> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,T> { using type = int; };
+
+void
+foo (T t)
+{
+  if (auto [ i, j ] = S { 1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 1 || j != 1)
+	__builtin_abort ();
+    }
+  else
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  T::d = 0;
+  if (int m = 78; auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {					// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+      if (i != 42 || j != 42 || T::d != 42 || m != 78)
+	__builtin_abort ();
+    }
+  else
+    {
+      ++i;
+      ++j;
+      ++m;
+      __builtin_abort ();
+    }
+  if (auto m = 15; auto [ i, j ] = S { -1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+      ++i;
+      ++j;
+      ++m;
+      __builtin_abort ();
+    }
+  else
+    {
+      if (i != -1 || j != 1 || m != 15)
+	__builtin_abort ();
+    }
+  t.a = -42;
+  T::d = 0;
+  if (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  else
+    {
+      if (i != 42 || j != -42 || T::d != 42)
+	__builtin_abort ();
+    }
+}
+
+void
+bar (T t)
+{
+  int cnt = 0;
+  while (auto [ i, j ] = S { 7, 7 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 7 || j != 7)
+	__builtin_abort ();
+      if (++cnt == 5)
+	break;
+    }
+  if (cnt != 5)
+    __builtin_abort ();
+  T::d = 0;
+  while (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 31 || j != 31 || T::d != 42)
+	__builtin_abort ();
+      T::d = 0;
+      if (++cnt == 10)
+	break;
+    }
+  if (cnt != 10)
+    __builtin_abort ();
+  while (auto [ i, j ] = S { 7, -7 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  t.a = -31;
+  T::d = 0;
+  while (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+}
+
+void
+baz (T t)
+{
+  int cntc = 0;
+  for (int cnt = 0; auto [ i, j ] = S { 12, 12 }; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 12 || j != 12)
+	__builtin_abort ();
+      cntc = cnt;
+      if (cnt == 5)
+	break;
+    }
+  if (cntc != 5)
+    __builtin_abort ();
+  T::d = 0;
+  for (int cnt = 5; auto & [ i, j ] = t; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != -15 || j != -15 || T::d != 42)
+	__builtin_abort ();
+      T::d = 0;
+      cntc = cnt;
+      if (cnt == 10)
+	break;
+    }
+  if (cntc != 10)
+    __builtin_abort ();
+  for (int cnt = 0; auto [ i, j ] = S { -27, 27 }; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  t.a = 15;
+  T::d = 0;
+  for (int cnt = 0; auto & [ i, j ] = t; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  foo ({ 42, 42, 0 });
+  bar ({ 31, 31, 7 });
+  baz ({ -15, -15, 6 });
+}
--- gcc/testsuite/g++.dg/cpp26/decomp4.C.jj	2024-07-01 17:23:12.987569162 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp4.C	2024-07-01 18:59:19.010012299 +0200
@@ -0,0 +1,74 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct S {
+  int a, b;
+  operator int () const noexcept { return a * 2; }
+};
+
+struct T {
+  int a, b, c;
+  static int d;
+  operator long long () const noexcept { d = 42; return a * 4; }
+  template <int I> int &get () { if (d != 42) __builtin_abort (); return I ? a : b; }
+};
+int T::d = 0;
+
+template<> struct std::tuple_size<T> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,T> { using type = int; };
+
+void
+foo (T t)
+{
+  switch (auto [ i, j ] = S { 53, 62 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+    case 2 * 53:
+      if (i != 53 || j != 62)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+  T::d = 0;
+  switch (int m = 78; auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+    case 4 * 42LL:
+      if (i != 43 || j != 42 || T::d != 42 || m != 78)
+	__builtin_abort ();
+      break;
+    default:
+      break;
+    }
+  switch (auto m = 15; auto [ i, j ] = S { -1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+    case 2 * -1:
+      if (i != -1 || j != 1 || m != 15)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+  t.a = -42;
+  T::d = 0;
+  switch (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+    case 4LL * -42:
+      if (i != 43 || j != -42 || T::d != 42)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  foo ({ 42, 43, 0 });
+}
--- gcc/testsuite/g++.dg/cpp26/decomp5.C.jj	2024-07-02 09:10:17.414020872 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp5.C	2024-07-02 09:10:52.370560957 +0200
@@ -0,0 +1,171 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct S {
+  int a, b;
+  explicit operator bool () const noexcept { return a == b; }
+};
+
+struct T {
+  int a, b, c;
+  static int d;
+  explicit operator bool () const noexcept { d = 42; return a == b; }
+  template <int I> int &get () { if (d != 42) __builtin_abort (); return I ? a : b; }
+};
+int T::d = 0;
+
+template<> struct std::tuple_size<T> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,T> { using type = int; };
+
+template <int N>
+void
+foo (T t)
+{
+  if (auto [ i, j ] = S { 1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 1 || j != 1)
+	__builtin_abort ();
+    }
+  else
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  T::d = 0;
+  if (int m = 78; auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {					// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+      if (i != 42 || j != 42 || T::d != 42 || m != 78)
+	__builtin_abort ();
+    }
+  else
+    {
+      ++i;
+      ++j;
+      ++m;
+      __builtin_abort ();
+    }
+  if (auto m = 15; auto [ i, j ] = S { -1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+      ++i;
+      ++j;
+      ++m;
+      __builtin_abort ();
+    }
+  else
+    {
+      if (i != -1 || j != 1 || m != 15)
+	__builtin_abort ();
+    }
+  t.a = -42;
+  T::d = 0;
+  if (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  else
+    {
+      if (i != 42 || j != -42 || T::d != 42)
+	__builtin_abort ();
+    }
+}
+
+template <int N>
+void
+bar (T t)
+{
+  int cnt = 0;
+  while (auto [ i, j ] = S { 7, 7 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 7 || j != 7)
+	__builtin_abort ();
+      if (++cnt == 5)
+	break;
+    }
+  if (cnt != 5)
+    __builtin_abort ();
+  T::d = 0;
+  while (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 31 || j != 31 || T::d != 42)
+	__builtin_abort ();
+      T::d = 0;
+      if (++cnt == 10)
+	break;
+    }
+  if (cnt != 10)
+    __builtin_abort ();
+  while (auto [ i, j ] = S { 7, -7 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  t.a = -31;
+  T::d = 0;
+  while (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+}
+
+template <int N>
+void
+baz (T t)
+{
+  int cntc = 0;
+  for (int cnt = 0; auto [ i, j ] = S { 12, 12 }; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 12 || j != 12)
+	__builtin_abort ();
+      cntc = cnt;
+      if (cnt == 5)
+	break;
+    }
+  if (cntc != 5)
+    __builtin_abort ();
+  T::d = 0;
+  for (int cnt = 5; auto & [ i, j ] = t; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != -15 || j != -15 || T::d != 42)
+	__builtin_abort ();
+      T::d = 0;
+      cntc = cnt;
+      if (cnt == 10)
+	break;
+    }
+  if (cntc != 10)
+    __builtin_abort ();
+  for (int cnt = 0; auto [ i, j ] = S { -27, 27 }; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  t.a = 15;
+  T::d = 0;
+  for (int cnt = 0; auto & [ i, j ] = t; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  foo<0> ({ 42, 42, 0 });
+  bar<0> ({ 31, 31, 7 });
+  baz<0> ({ -15, -15, 6 });
+}
--- gcc/testsuite/g++.dg/cpp26/decomp6.C.jj	2024-07-02 09:10:22.141958669 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp6.C	2024-07-02 09:11:12.848291540 +0200
@@ -0,0 +1,75 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct S {
+  int a, b;
+  operator int () const noexcept { return a * 2; }
+};
+
+struct T {
+  int a, b, c;
+  static int d;
+  operator long long () const noexcept { d = 42; return a * 4; }
+  template <int I> int &get () { if (d != 42) __builtin_abort (); return I ? a : b; }
+};
+int T::d = 0;
+
+template<> struct std::tuple_size<T> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,T> { using type = int; };
+
+template <int N>
+void
+foo (T t)
+{
+  switch (auto [ i, j ] = S { 53, 62 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+    case 2 * 53:
+      if (i != 53 || j != 62)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+  T::d = 0;
+  switch (int m = 78; auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+    case 4 * 42LL:
+      if (i != 43 || j != 42 || T::d != 42 || m != 78)
+	__builtin_abort ();
+      break;
+    default:
+      break;
+    }
+  switch (auto m = 15; auto [ i, j ] = S { -1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+    case 2 * -1:
+      if (i != -1 || j != 1 || m != 15)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+  t.a = -42;
+  T::d = 0;
+  switch (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+    case 4LL * -42:
+      if (i != 43 || j != -42 || T::d != 42)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  foo<0> ({ 42, 43, 0 });
+}
--- gcc/testsuite/g++.dg/cpp26/decomp7.C.jj	2024-07-02 09:11:27.140103504 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp7.C	2024-07-02 09:12:08.027565554 +0200
@@ -0,0 +1,171 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct S {
+  int a, b;
+  explicit operator bool () const noexcept { return a == b; }
+};
+
+struct T {
+  int a, b, c;
+  static int d;
+  explicit operator bool () const noexcept { d = 42; return a == b; }
+  template <int I> int &get () { if (d != 42) __builtin_abort (); return I ? a : b; }
+};
+int T::d = 0;
+
+template<> struct std::tuple_size<T> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,T> { using type = int; };
+
+template <typename S, typename T>
+void
+foo (T t)
+{
+  if (auto [ i, j ] = S { 1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 1 || j != 1)
+	__builtin_abort ();
+    }
+  else
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  T::d = 0;
+  if (int m = 78; auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {					// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+      if (i != 42 || j != 42 || T::d != 42 || m != 78)
+	__builtin_abort ();
+    }
+  else
+    {
+      ++i;
+      ++j;
+      ++m;
+      __builtin_abort ();
+    }
+  if (auto m = 15; auto [ i, j ] = S { -1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+      ++i;
+      ++j;
+      ++m;
+      __builtin_abort ();
+    }
+  else
+    {
+      if (i != -1 || j != 1 || m != 15)
+	__builtin_abort ();
+    }
+  t.a = -42;
+  T::d = 0;
+  if (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  else
+    {
+      if (i != 42 || j != -42 || T::d != 42)
+	__builtin_abort ();
+    }
+}
+
+template <typename S, typename T>
+void
+bar (T t)
+{
+  int cnt = 0;
+  while (auto [ i, j ] = S { 7, 7 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 7 || j != 7)
+	__builtin_abort ();
+      if (++cnt == 5)
+	break;
+    }
+  if (cnt != 5)
+    __builtin_abort ();
+  T::d = 0;
+  while (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 31 || j != 31 || T::d != 42)
+	__builtin_abort ();
+      T::d = 0;
+      if (++cnt == 10)
+	break;
+    }
+  if (cnt != 10)
+    __builtin_abort ();
+  while (auto [ i, j ] = S { 7, -7 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  t.a = -31;
+  T::d = 0;
+  while (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+}
+
+template <typename S, typename T>
+void
+baz (T t)
+{
+  int cntc = 0;
+  for (int cnt = 0; auto [ i, j ] = S { 12, 12 }; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != 12 || j != 12)
+	__builtin_abort ();
+      cntc = cnt;
+      if (cnt == 5)
+	break;
+    }
+  if (cntc != 5)
+    __builtin_abort ();
+  T::d = 0;
+  for (int cnt = 5; auto & [ i, j ] = t; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      if (i != -15 || j != -15 || T::d != 42)
+	__builtin_abort ();
+      T::d = 0;
+      cntc = cnt;
+      if (cnt == 10)
+	break;
+    }
+  if (cntc != 10)
+    __builtin_abort ();
+  for (int cnt = 0; auto [ i, j ] = S { -27, 27 }; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+  t.a = 15;
+  T::d = 0;
+  for (int cnt = 0; auto & [ i, j ] = t; ++cnt)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+      ++i;
+      ++j;
+      __builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  foo<S, T> ({ 42, 42, 0 });
+  bar<S, T> ({ 31, 31, 7 });
+  baz<S, T> ({ -15, -15, 6 });
+}
--- gcc/testsuite/g++.dg/cpp26/decomp8.C.jj	2024-07-02 09:11:30.461059812 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp8.C	2024-07-02 09:12:22.298377789 +0200
@@ -0,0 +1,75 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do run { target c++11 } }
+// { dg-options "" }
+
+namespace std {
+  template<typename T> struct tuple_size;
+  template<int, typename> struct tuple_element;
+}
+
+struct S {
+  int a, b;
+  operator int () const noexcept { return a * 2; }
+};
+
+struct T {
+  int a, b, c;
+  static int d;
+  operator long long () const noexcept { d = 42; return a * 4; }
+  template <int I> int &get () { if (d != 42) __builtin_abort (); return I ? a : b; }
+};
+int T::d = 0;
+
+template<> struct std::tuple_size<T> { static const int value = 2; };
+template<int I> struct std::tuple_element<I,T> { using type = int; };
+
+template <typename S, typename T>
+void
+foo (T t)
+{
+  switch (auto [ i, j ] = S { 53, 62 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+    case 2 * 53:
+      if (i != 53 || j != 62)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+  T::d = 0;
+  switch (int m = 78; auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+    case 4 * 42LL:
+      if (i != 43 || j != 42 || T::d != 42 || m != 78)
+	__builtin_abort ();
+      break;
+    default:
+      break;
+    }
+  switch (auto m = 15; auto [ i, j ] = S { -1, 1 })	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-warning "init-statement in selection statements only available with" "" { target c++14_down } .-1 }
+    case 2 * -1:
+      if (i != -1 || j != 1 || m != 15)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+  t.a = -42;
+  T::d = 0;
+  switch (auto & [ i, j ] = t)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+    case 4LL * -42:
+      if (i != 43 || j != -42 || T::d != 42)
+	__builtin_abort ();
+      break;
+    default:
+      __builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  foo<S, T> ({ 42, 43, 0 });
+}
--- gcc/testsuite/g++.dg/cpp26/decomp9.C.jj	2024-07-02 09:14:45.503493673 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp9.C	2024-07-02 09:57:23.430826126 +0200
@@ -0,0 +1,68 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+int a[4];
+struct S { int i, j; };
+struct T { int i, j, k; explicit operator bool () const noexcept; } t;
+enum E { E0, E1 };
+struct U { int i, j, k, l; operator E () const noexcept; } u;
+int w;
+union X { int i; long j; } x;
+
+void
+foo (const S &&s)
+{
+  if (auto [ i, j, k, l ] = a)			// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "array initializer for structured binding declaration in condition" "" { target *-*-* } .-1 }
+  if (auto & [a, b, c] = "ht")			// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "array initializer for structured binding declaration in condition" "" { target *-*-* } .-1 }
+  if (auto const & [i, j] = s)			// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "could not convert '<structured bindings>' from 'const S' to 'bool'" "" { target *-*-* } .-1 }
+  if (auto const & [i, j, k] = t)		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    w = i + j + k;
+  else
+    w = i - j * k;
+  if (auto [i, j, k, l] = u)			// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;
+  if (auto [i] = x)				// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "cannot decompose union type 'X'" "" { target *-*-* } .-1 }
+						// { dg-error "could not convert '<structured bindings>' from 'X' to 'bool'" "" { target *-*-* } .-2 }
+  if (auto [i, j, k] = s)			// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "3 names provided for structured binding" "" { target *-*-* } .-1 }
+						// { dg-error "could not convert '<structured bindings>' from 'S' to 'bool'" "" { target *-*-* } .-2 }
+  if (auto [i] = s)				// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "only 1 name provided for structured binding" "" { target *-*-* } .-1 }
+						// { dg-error "could not convert '<structured bindings>' from 'S' to 'bool'" "" { target *-*-* } .-2 }
+  switch (auto [a, b, c] = "ht")		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-error "array initializer for structured binding declaration in condition" "" { target *-*-* } .-1 }
+    default:					// { dg-error "switch quantity not an integer" "" { target *-*-* } .-2 }
+      break;
+    }
+  switch (auto const & [i, j] = s)		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-error "switch quantity not an integer" "" { target *-*-* } .-1 }
+    case 1:
+    default:
+      break;
+    }
+  switch (auto const & [i, j, k] = t)		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {						// { dg-error "switch quantity not an integer" "" { target *-*-* } .-1 }
+    case 1:
+    default:
+      break;
+    }
+  switch (auto [i, j, k, l] = u)		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    {
+    case E0:
+      ++i; ++j;
+      break;
+    default:
+      ++k; ++l;
+      break;
+    }
+  if (static auto [i, j, k] = t)		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "'static' invalid in condition" "" { target *-*-* } .-1 }
+						// { dg-warning "structured binding declaration can be 'static' only in" "" { target c++17_down } .-2 }
+  if (constexpr auto [i, j, k] = t)		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;						// { dg-error "structured binding declaration cannot be 'constexpr'" "" { target *-*-* } .-1 }
+}
--- gcc/testsuite/g++.dg/cpp26/decomp10.C.jj	2024-07-02 10:01:45.298378163 +0200
+++ gcc/testsuite/g++.dg/cpp26/decomp10.C	2024-07-02 10:05:19.586556702 +0200
@@ -0,0 +1,15 @@
+// P0963R3 - Structured binding declaration as a condition
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+_Complex int c;
+int __attribute__((__vector_size__ (4 * sizeof (int)))) v;
+
+void
+foo ()
+{
+  if (auto [i,j] = c)		// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;
+  if (auto [i,j,k,l] = v)	// { dg-warning "structured bindings in conditions only available with" "" { target c++23_down } }
+    ;				// { dg-error "could not convert '<structured bindings>' from '\[^\n\r]*' to 'bool'" "" { target *-*-* } .-1 }
+}
