--- gcc/tree-core.h.jj	2022-09-09 12:27:23.180736449 +0200
+++ gcc/tree-core.h	2022-09-09 18:46:07.257922609 +0200
@@ -690,6 +690,10 @@ enum tree_index {
 			     - TI_FLOATN_NX_TYPE_FIRST		\
 			     + 1)
 
+  /* Type used by certain backends for __float128, which in C++ should be
+     distinct type from _Float128 for backwards compatibility reasons.  */
+  TI_FLOAT128T_TYPE,
+
   /* Put the complex types after their component types, so that in (sequential)
      tree streaming we can assert that their component types have already been
      handled (see tree-streamer.cc:record_common_node).  */
--- gcc/tree.h.jj	2022-09-09 12:27:23.183736409 +0200
+++ gcc/tree.h	2022-09-09 18:46:07.258922596 +0200
@@ -4302,6 +4302,10 @@ tree_strip_any_location_wrapper (tree ex
 #define float64x_type_node		global_trees[TI_FLOAT64X_TYPE]
 #define float128x_type_node		global_trees[TI_FLOAT128X_TYPE]
 
+/* Type used by certain backends for __float128, which in C++ should be
+   distinct type from _Float128 for backwards compatibility reasons.  */
+#define float128t_type_node		global_trees[TI_FLOAT128T_TYPE]
+
 #define float_ptr_type_node		global_trees[TI_FLOAT_PTR_TYPE]
 #define double_ptr_type_node		global_trees[TI_DOUBLE_PTR_TYPE]
 #define long_double_ptr_type_node	global_trees[TI_LONG_DOUBLE_PTR_TYPE]
--- gcc/tree.cc.jj	2022-09-09 18:44:27.153255900 +0200
+++ gcc/tree.cc	2022-09-09 18:46:07.260922569 +0200
@@ -9459,6 +9459,7 @@ build_common_tree_nodes (bool signed_cha
       layout_type (FLOATN_NX_TYPE_NODE (i));
       SET_TYPE_MODE (FLOATN_NX_TYPE_NODE (i), mode);
     }
+  float128t_type_node = float128_type_node;
 
   float_ptr_type_node = build_pointer_type (float_type_node);
   double_ptr_type_node = build_pointer_type (double_type_node);
--- gcc/builtins.def.jj	2022-09-09 12:27:23.136737041 +0200
+++ gcc/builtins.def	2022-09-09 18:46:07.261922555 +0200
@@ -115,8 +115,8 @@ along with GCC; see the file COPYING3.
    we are compiling for the C language with GNU extensions, we enable the name
    without the __builtin_ prefix as well as the name with the __builtin_
    prefix.  C++ does not enable these names by default because they don't have
-   the _Float<N> and _Float<N>X keywords, and a class based library should use
-   the __builtin_ names.  */
+   the _Float<N>x keywords, and a class based library should use the __builtin_
+   names.  */
 #undef DEF_FLOATN_BUILTIN
 #define DEF_FLOATN_BUILTIN(ENUM, NAME, TYPE, ATTRS)	\
   DEF_BUILTIN (ENUM, "__builtin_" NAME, BUILT_IN_NORMAL, TYPE, TYPE,	\
--- gcc/config/i386/i386.cc.jj	2022-09-09 12:27:23.141736974 +0200
+++ gcc/config/i386/i386.cc	2022-09-10 11:21:26.997205883 +0200
@@ -22711,7 +22711,10 @@ ix86_mangle_type (const_tree type)
       return "DF16_";
     case E_TFmode:
       /* __float128 is "g".  */
-      return "g";
+      if (type == float128t_type_node)
+	return "g";
+      /* _Float128 should mangle as "DF128_" done in generic code.  */
+      return NULL;
     case E_XFmode:
       /* "long double" or __float80 is "e".  */
       return "e";
--- gcc/config/i386/i386-builtins.cc.jj	2022-09-09 12:27:23.138737014 +0200
+++ gcc/config/i386/i386-builtins.cc	2022-09-09 18:46:07.264922515 +0200
@@ -1409,9 +1409,18 @@ ix86_init_builtin_types (void)
   lang_hooks.types.register_builtin_type (float80_type_node, "__float80");
 
   /* The __float128 type.  The node has already been created as
-     _Float128, so we only need to register the __float128 name for
-     it.  */
-  lang_hooks.types.register_builtin_type (float128_type_node, "__float128");
+     _Float128, so for C we only need to register the __float128 name for
+     it.  For C++, we create a distinct type which will mangle differently
+     (g) vs. _Float128 (DF128_) and behave backwards compatibly.  */
+  if (float128t_type_node == NULL_TREE)
+    {
+      float128t_type_node = make_node (REAL_TYPE);
+      TYPE_PRECISION (float128t_type_node)
+	= TYPE_PRECISION (float128_type_node);
+      SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node));
+      layout_type (float128t_type_node);
+    }
+  lang_hooks.types.register_builtin_type (float128t_type_node, "__float128");
 
   ix86_register_float16_builtin_type ();
 
--- gcc/config/i386/avx512fp16intrin.h.jj	2022-01-11 22:31:40.696768297 +0100
+++ gcc/config/i386/avx512fp16intrin.h	2022-09-11 23:23:28.617437158 +0200
@@ -183,21 +183,21 @@ extern __inline __m128h
 __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
 _mm_setzero_ph (void)
 {
-  return _mm_set1_ph (0.0f);
+  return _mm_set1_ph (0.0f16);
 }
 
 extern __inline __m256h
 __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
 _mm256_setzero_ph (void)
 {
-  return _mm256_set1_ph (0.0f);
+  return _mm256_set1_ph (0.0f16);
 }
 
 extern __inline __m512h
 __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
 _mm512_setzero_ph (void)
 {
-  return _mm512_set1_ph (0.0f);
+  return _mm512_set1_ph (0.0f16);
 }
 
 extern __inline __m128h
@@ -358,7 +358,8 @@ extern __inline __m128h
 __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
 _mm_set_sh (_Float16 __F)
 {
-  return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, __F);
+  return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16,
+		     __F);
 }
 
 /* Create a vector with element 0 as *P and the rest zero.  */
@@ -366,7 +367,7 @@ extern __inline __m128h
 __attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
 _mm_load_sh (void const *__P)
 {
-  return _mm_set_ph (0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+  return _mm_set_ph (0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16, 0.0f16,
 		     *(_Float16 const *) __P);
 }
 
--- gcc/config/ia64/ia64.cc.jj	2022-09-09 12:27:23.143736947 +0200
+++ gcc/config/ia64/ia64.cc	2022-09-09 18:46:07.265922502 +0200
@@ -10466,11 +10466,19 @@ ia64_init_builtins (void)
 	= build_pointer_type (build_qualified_type
 			      (char_type_node, TYPE_QUAL_CONST));
 
-      (*lang_hooks.types.register_builtin_type) (float128_type_node,
+      if (float128t_type_node == NULL_TREE)
+	{
+	  float128t_type_node = make_node (REAL_TYPE);
+	  TYPE_PRECISION (float128t_type_node)
+	    = TYPE_PRECISION (float128_type_node);
+	  layout_type (float128t_type_node);
+	  SET_TYPE_MODE (float128t_type_node, TYPE_MODE (float128_type_node));
+	}
+      (*lang_hooks.types.register_builtin_type) (float128t_type_node,
 						 "__float128");
 
       /* TFmode support builtins.  */
-      ftype = build_function_type_list (float128_type_node, NULL_TREE);
+      ftype = build_function_type_list (float128t_type_node, NULL_TREE);
       decl = add_builtin_function ("__builtin_infq", ftype,
 				   IA64_BUILTIN_INFQ, BUILT_IN_MD,
 				   NULL, NULL_TREE);
@@ -10481,7 +10489,7 @@ ia64_init_builtins (void)
 				   NULL, NULL_TREE);
       ia64_builtins[IA64_BUILTIN_HUGE_VALQ] = decl;
 
-      ftype = build_function_type_list (float128_type_node,
+      ftype = build_function_type_list (float128t_type_node,
 					const_string_type,
 					NULL_TREE);
       decl = add_builtin_function ("__builtin_nanq", ftype,
@@ -10496,8 +10504,8 @@ ia64_init_builtins (void)
       TREE_READONLY (decl) = 1;
       ia64_builtins[IA64_BUILTIN_NANSQ] = decl;
 
-      ftype = build_function_type_list (float128_type_node,
-					float128_type_node,
+      ftype = build_function_type_list (float128t_type_node,
+					float128t_type_node,
 					NULL_TREE);
       decl = add_builtin_function ("__builtin_fabsq", ftype,
 				   IA64_BUILTIN_FABSQ, BUILT_IN_MD,
@@ -10505,9 +10513,9 @@ ia64_init_builtins (void)
       TREE_READONLY (decl) = 1;
       ia64_builtins[IA64_BUILTIN_FABSQ] = decl;
 
-      ftype = build_function_type_list (float128_type_node,
-					float128_type_node,
-					float128_type_node,
+      ftype = build_function_type_list (float128t_type_node,
+					float128t_type_node,
+					float128t_type_node,
 					NULL_TREE);
       decl = add_builtin_function ("__builtin_copysignq", ftype,
 				   IA64_BUILTIN_COPYSIGNQ, BUILT_IN_MD,
--- gcc/config/rs6000/rs6000-c.cc.jj	2022-09-09 12:27:23.144736933 +0200
+++ gcc/config/rs6000/rs6000-c.cc	2022-09-10 11:21:53.958838545 +0200
@@ -808,6 +808,7 @@ static inline bool
 is_float128_p (tree t)
 {
   return (t == float128_type_node
+	  || (t && t == float128t_type_node)
 	  || (TARGET_IEEEQUAD
 	      && TARGET_LONG_DOUBLE_128
 	      && t == long_double_type_node));
--- gcc/config/rs6000/rs6000.cc.jj	2022-09-09 12:27:23.147736893 +0200
+++ gcc/config/rs6000/rs6000.cc	2022-09-09 18:46:07.269922448 +0200
@@ -20118,7 +20118,11 @@ rs6000_mangle_type (const_tree type)
 
   if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IBM_P (TYPE_MODE (type)))
     return "g";
-  if (SCALAR_FLOAT_TYPE_P (type) && FLOAT128_IEEE_P (TYPE_MODE (type)))
+  if (SCALAR_FLOAT_TYPE_P (type)
+      && FLOAT128_IEEE_P (TYPE_MODE (type))
+      /* _Float128 should mangle as DF128_ (done in generic code)
+	 rather than u9__ieee128 (used for __ieee128 and __float128).  */
+      && type != float128_type_node)
     return "u9__ieee128";
 
   if (type == vector_pair_type_node)
--- gcc/config/rs6000/rs6000-builtin.cc.jj	2022-09-09 12:27:23.143736947 +0200
+++ gcc/config/rs6000/rs6000-builtin.cc	2022-09-09 18:46:07.270922435 +0200
@@ -733,7 +733,22 @@ rs6000_init_builtins (void)
       if (TARGET_IEEEQUAD && TARGET_LONG_DOUBLE_128)
 	ieee128_float_type_node = long_double_type_node;
       else
-	ieee128_float_type_node = float128_type_node;
+	{
+	  /* For C we only need to register the __ieee128 name for
+	     it.  For C++, we create a distinct type which will mangle
+	     differently (u9__ieee128) vs. _Float128 (DF128_) and behave
+	     backwards compatibly.  */
+	  if (float128t_type_node == NULL_TREE)
+	    {
+	      float128t_type_node = make_node (REAL_TYPE);
+	      TYPE_PRECISION (float128t_type_node)
+		= TYPE_PRECISION (float128_type_node);
+	      layout_type (float128t_type_node);
+	      SET_TYPE_MODE (float128t_type_node,
+			     TYPE_MODE (float128_type_node));
+	    }
+	  ieee128_float_type_node = float128t_type_node;
+	}
       t = build_qualified_type (ieee128_float_type_node, TYPE_QUAL_CONST);
       lang_hooks.types.register_builtin_type (ieee128_float_type_node,
 					      "__ieee128");
--- gcc/c-family/c-common.cc.jj	2022-09-09 12:27:23.137737028 +0200
+++ gcc/c-family/c-common.cc	2022-09-09 19:43:50.730802597 +0200
@@ -352,10 +352,10 @@ const struct c_common_resword c_common_r
   { "_Bool",		RID_BOOL,      D_CONLY },
   { "_Complex",		RID_COMPLEX,	0 },
   { "_Imaginary",	RID_IMAGINARY, D_CONLY },
-  { "_Float16",         RID_FLOAT16,   D_CONLY },
-  { "_Float32",         RID_FLOAT32,   D_CONLY },
-  { "_Float64",         RID_FLOAT64,   D_CONLY },
-  { "_Float128",        RID_FLOAT128,  D_CONLY },
+  { "_Float16",         RID_FLOAT16,    0 },
+  { "_Float32",         RID_FLOAT32,    0 },
+  { "_Float64",         RID_FLOAT64,    0 },
+  { "_Float128",        RID_FLOAT128,   0 },
   { "_Float32x",        RID_FLOAT32X,  D_CONLY },
   { "_Float64x",        RID_FLOAT64X,  D_CONLY },
   { "_Float128x",       RID_FLOAT128X, D_CONLY },
@@ -1429,8 +1429,11 @@ shorten_binary_op (tree result_type, tre
 	  == TYPE_PRECISION (TREE_TYPE (arg0)))
       && unsigned0 == unsigned1
       && (unsigned0 || !uns))
-    return c_common_signed_or_unsigned_type
-      (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+    {
+      tree ctype = common_type (TREE_TYPE (arg0), TREE_TYPE (arg1));
+      if (ctype != error_mark_node)
+	return c_common_signed_or_unsigned_type (unsigned0, ctype);
+    }
 
   else if (TREE_CODE (arg0) == INTEGER_CST
 	   && (unsigned1 || !uns)
@@ -3202,9 +3205,10 @@ shorten_compare (location_t loc, tree *o
 
   else if (unsignedp0 == unsignedp1 && real1 == real2
 	   && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr)
-	   && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr))
+	   && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr)
+	   && (type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1)))
+	      != error_mark_node)
     {
-      type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
       type = c_common_signed_or_unsigned_type (unsignedp0
 					       || TYPE_UNSIGNED (*restype_ptr),
 					       type);
@@ -4378,11 +4382,21 @@ c_common_nodes_and_builtins (void)
   record_builtin_type (RID_DOUBLE, NULL, double_type_node);
   record_builtin_type (RID_MAX, "long double", long_double_type_node);
 
-  if (!c_dialect_cxx ())
-    for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+  for (i = 0; i < NUM_FLOATN_NX_TYPES; i++)
+    {
       if (FLOATN_NX_TYPE_NODE (i) != NULL_TREE)
 	record_builtin_type ((enum rid) (RID_FLOATN_NX_FIRST + i), NULL,
 			     FLOATN_NX_TYPE_NODE (i));
+      /* Don't register _FloatNX types for C++, just _FloatN.  */
+      if (i == NUM_FLOATN_TYPES && c_dialect_cxx ())
+	break;
+    }
+
+  /* For C, let float128t_type_node (__float128 in some backends) be the
+     same type as float128_type_node (_Float128), for C++ let those
+     be distinct types that mangle and behave differently.  */
+  if (c_dialect_cxx ())
+    float128t_type_node = NULL_TREE;
 
   /* Only supported decimal floating point extension if the target
      actually supports underlying modes. */
--- gcc/c-family/c-cppbuiltin.cc.jj	2022-09-09 12:27:23.138737014 +0200
+++ gcc/c-family/c-cppbuiltin.cc	2022-09-09 18:46:07.271922421 +0200
@@ -1246,6 +1246,14 @@ c_cpp_builtins (cpp_reader *pfile)
     {
       if (FLOATN_NX_TYPE_NODE (i) == NULL_TREE)
 	continue;
+      if (floatn_nx_types[i].extended && c_dialect_cxx ())
+	continue;
+      if (c_dialect_cxx () && cxx_dialect > cxx20)
+	{
+	  char name[sizeof ("__STDCPP_FLOAT128_T__=1")];
+	  sprintf (name, "__STDCPP_FLOAT%d_T__=1", floatn_nx_types[i].n);
+	  cpp_define (pfile, name);
+	}
       char prefix[20], csuffix[20];
       sprintf (prefix, "FLT%d%s", floatn_nx_types[i].n,
 	       floatn_nx_types[i].extended ? "X" : "");
--- gcc/c-family/c-common.h.jj	2022-09-09 12:27:23.137737028 +0200
+++ gcc/c-family/c-common.h	2022-09-09 18:46:07.271922421 +0200
@@ -120,8 +120,10 @@ enum rid
   RID_FLOAT32X,
   RID_FLOAT64X,
   RID_FLOAT128X,
+#define CASE_RID_FLOATN							\
+  case RID_FLOAT16: case RID_FLOAT32: case RID_FLOAT64: case RID_FLOAT128
 #define CASE_RID_FLOATN_NX						\
-  case RID_FLOAT16: case RID_FLOAT32: case RID_FLOAT64: case RID_FLOAT128: \
+  CASE_RID_FLOATN:							\
   case RID_FLOAT32X: case RID_FLOAT64X: case RID_FLOAT128X
 
   RID_FRACT, RID_ACCUM, RID_AUTO_TYPE, RID_BUILTIN_CALL_WITH_STATIC_CHAIN,
--- gcc/c-family/c-lex.cc.jj	2022-09-09 12:27:23.138737014 +0200
+++ gcc/c-family/c-lex.cc	2022-09-09 18:46:07.271922421 +0200
@@ -960,6 +960,10 @@ interpret_float (const cpp_token *token,
 	  pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant");
 
 	type = c_common_type_for_mode (mode, 0);
+	/* For Q suffix, prefer float128t_type_node (__float128) type
+	   over float128_type_node (_Float128) type if they are distinct.  */
+	if (type == float128_type_node && float128t_type_node)
+	  type = float128t_type_node;
 	gcc_assert (type);
       }
     else if ((flags & (CPP_N_FLOATN | CPP_N_FLOATNX)) != 0)
@@ -979,8 +983,17 @@ interpret_float (const cpp_token *token,
 	    error ("unsupported non-standard suffix on floating constant");
 	    return error_mark_node;
 	  }
+	else if (c_dialect_cxx ())
+	  {
+	    if (cxx_dialect < cxx23)
+	      pedwarn (input_location, OPT_Wpedantic,
+		       "%<f%d%> or %<F%d%> suffix on floating constant only "
+		       "available with %<-std=c++2b%> or %<-std=gnu++2b%>",
+		       n, n);
+	  }
 	else
-	  pedwarn (input_location, OPT_Wpedantic, "non-standard suffix on floating constant");
+	  pedwarn (input_location, OPT_Wpedantic,
+		   "non-standard suffix on floating constant");
       }
     else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
       type = long_double_type_node;
@@ -990,7 +1003,10 @@ interpret_float (const cpp_token *token,
     else
       type = double_type_node;
 
-  const_type = excess_precision_type (type);
+  if (c_dialect_cxx ())
+    const_type = NULL_TREE;
+  else
+    const_type = excess_precision_type (type);
   if (!const_type)
     const_type = type;
 
--- gcc/cp/cp-tree.h.jj	2022-09-09 12:27:23.170736583 +0200
+++ gcc/cp/cp-tree.h	2022-09-10 11:22:11.612598030 +0200
@@ -7942,6 +7942,7 @@ extern tree require_complete_type_sfinae
 extern tree complete_type			(tree);
 extern tree complete_type_or_else		(tree, tree);
 extern tree complete_type_or_maybe_complain	(tree, tree, tsubst_flags_t);
+extern int cp_compare_floating_point_conversion_ranks (tree, tree);
 inline bool type_unknown_p			(const_tree);
 enum { ce_derived, ce_type, ce_normal, ce_exact };
 extern bool comp_except_specs			(const_tree, const_tree, int);
@@ -8682,6 +8683,18 @@ struct push_access_scope_guard
   }
 };
 
+/* True if TYPE is an extended floating-point type.  */
+
+inline bool
+extended_float_type_p (tree type)
+{
+  type = TYPE_MAIN_VARIANT (type);
+  for (int i = 0; i < NUM_FLOATN_TYPES; ++i)
+    if (type == FLOATN_TYPE_NODE (i))
+      return true;
+  return false;
+}
+
 #if CHECKING_P
 namespace selftest {
   extern void run_cp_tests (void);
--- gcc/cp/mangle.cc.jj	2022-09-09 12:27:23.171736570 +0200
+++ gcc/cp/mangle.cc	2022-09-09 18:46:07.273922394 +0200
@@ -2648,63 +2648,18 @@ write_builtin_type (tree type)
 	write_string ("Dd");
       else if (type == dfloat128_type_node || type == fallback_dfloat128_type)
 	write_string ("De");
+      else if (type == float16_type_node)
+	write_string ("DF16_");
+      else if (type == float32_type_node)
+	write_string ("DF32_");
+      else if (type == float64_type_node)
+	write_string ("DF64_");
+      else if (type == float128_type_node)
+	write_string ("DF128_");
       else
 	gcc_unreachable ();
       break;
 
-    case FIXED_POINT_TYPE:
-      write_string ("DF");
-      if (GET_MODE_IBIT (TYPE_MODE (type)) > 0)
-	write_unsigned_number (GET_MODE_IBIT (TYPE_MODE (type)));
-      if (type == fract_type_node
-	  || type == sat_fract_type_node
-	  || type == accum_type_node
-	  || type == sat_accum_type_node)
-	write_char ('i');
-      else if (type == unsigned_fract_type_node
-	       || type == sat_unsigned_fract_type_node
-	       || type == unsigned_accum_type_node
-	       || type == sat_unsigned_accum_type_node)
-	write_char ('j');
-      else if (type == short_fract_type_node
-	       || type == sat_short_fract_type_node
-	       || type == short_accum_type_node
-	       || type == sat_short_accum_type_node)
-	write_char ('s');
-      else if (type == unsigned_short_fract_type_node
-	       || type == sat_unsigned_short_fract_type_node
-	       || type == unsigned_short_accum_type_node
-	       || type == sat_unsigned_short_accum_type_node)
-	write_char ('t');
-      else if (type == long_fract_type_node
-	       || type == sat_long_fract_type_node
-	       || type == long_accum_type_node
-	       || type == sat_long_accum_type_node)
-	write_char ('l');
-      else if (type == unsigned_long_fract_type_node
-	       || type == sat_unsigned_long_fract_type_node
-	       || type == unsigned_long_accum_type_node
-	       || type == sat_unsigned_long_accum_type_node)
-	write_char ('m');
-      else if (type == long_long_fract_type_node
-	       || type == sat_long_long_fract_type_node
-	       || type == long_long_accum_type_node
-	       || type == sat_long_long_accum_type_node)
-	write_char ('x');
-      else if (type == unsigned_long_long_fract_type_node
-	       || type == sat_unsigned_long_long_fract_type_node
-	       || type == unsigned_long_long_accum_type_node
-	       || type == sat_unsigned_long_long_accum_type_node)
-	write_char ('y');
-      else
-	sorry ("mangling unknown fixed point type");
-      write_unsigned_number (GET_MODE_FBIT (TYPE_MODE (type)));
-      if (TYPE_SATURATING (type))
-	write_char ('s');
-      else
-	write_char ('n');
-      break;
-
     default:
       gcc_unreachable ();
     }
--- gcc/cp/typeck2.cc.jj	2022-09-09 12:27:23.179736463 +0200
+++ gcc/cp/typeck2.cc	2022-09-09 18:46:07.273922394 +0200
@@ -1010,12 +1010,25 @@ check_narrowing (tree type, tree init, t
   else if (TREE_CODE (ftype) == REAL_TYPE
 	   && TREE_CODE (type) == REAL_TYPE)
     {
-      if ((same_type_p (ftype, long_double_type_node)
-	   && (same_type_p (type, double_type_node)
-	       || same_type_p (type, float_type_node)))
-	  || (same_type_p (ftype, double_type_node)
-	      && same_type_p (type, float_type_node))
-	  || (TYPE_PRECISION (type) < TYPE_PRECISION (ftype)))
+      if ((extended_float_type_p (ftype) || extended_float_type_p (type))
+	  ? /* "from a floating-point type T to another floating-point type
+	       whose floating-point conversion rank is neither greater than
+	       nor equal to that of T".
+	       So, it is ok if
+	       cp_compare_floating_point_conversion_ranks (ftype, type)
+	       returns -2 (type has greater conversion rank than ftype)
+	       or [-1..1] (type has equal conversion rank as ftype, possibly
+	       different subrank.  Only do this if at least one of the
+	       types is extended floating-point type, otherwise keep doing
+	       what we did before (for the sake of non-standard
+	       backend types).  */
+	    cp_compare_floating_point_conversion_ranks (ftype, type) >= 2
+	  : ((same_type_p (ftype, long_double_type_node)
+	      && (same_type_p (type, double_type_node)
+		  || same_type_p (type, float_type_node)))
+	     || (same_type_p (ftype, double_type_node)
+		 && same_type_p (type, float_type_node))
+	     || (TYPE_PRECISION (type) < TYPE_PRECISION (ftype))))
 	{
 	  if (TREE_CODE (init) == REAL_CST)
 	    {
--- gcc/cp/parser.cc.jj	2022-09-09 12:27:23.177736489 +0200
+++ gcc/cp/parser.cc	2022-09-09 18:46:07.278922327 +0200
@@ -1129,6 +1129,7 @@ cp_keyword_starts_decl_specifier_p (enum
     case RID_UNSIGNED:
     case RID_FLOAT:
     case RID_DOUBLE:
+    CASE_RID_FLOATN:
     case RID_VOID:
       /* CV qualifiers.  */
     case RID_CONST:
@@ -19706,6 +19707,12 @@ cp_parser_simple_type_specifier (cp_pars
     case RID_DOUBLE:
       type = double_type_node;
       break;
+    CASE_RID_FLOATN:
+      type = FLOATN_TYPE_NODE (token->keyword - RID_FLOATN_NX_FIRST);
+      if (type == NULL_TREE)
+	error ("%<_Float%d%> is not supported on this target",
+	       floatn_nx_types[token->keyword - RID_FLOATN_NX_FIRST].n);
+      break;
     case RID_VOID:
       type = void_type_node;
       break;
--- gcc/cp/typeck.cc.jj	2022-09-09 12:27:23.179736463 +0200
+++ gcc/cp/typeck.cc	2022-09-09 19:54:17.360423639 +0200
@@ -272,6 +272,116 @@ merge_type_attributes_from (tree type, t
   return cp_build_type_attribute_variant (type, attrs);
 }
 
+/* Compare floating point conversion ranks and subranks of T1 and T2
+   types.  If T1 and T2 have unordered conversion ranks, return 3.
+   If T1 has greater conversion rank than T2, return 2.
+   If T2 has greater conversion rank than T1, return -2.
+   If T1 has equal conversion rank as T2, return -1, 0 or 1 depending
+   on if T1 has smaller, equal or greater conversion subrank than
+   T2.  */
+
+int
+cp_compare_floating_point_conversion_ranks (tree t1, tree t2)
+{
+  tree mv1 = TYPE_MAIN_VARIANT (t1);
+  tree mv2 = TYPE_MAIN_VARIANT (t2);
+  bool extended1 = false;
+  bool extended2 = false;
+
+  if (mv1 == mv2)
+    return 0;
+
+  for (int i = 0; i < NUM_FLOATN_TYPES; ++i)
+    {
+      if (mv1 == FLOATN_TYPE_NODE (i))
+	extended1 = true;
+      if (mv2 == FLOATN_TYPE_NODE (i))
+	extended2 = true;
+    }
+  if (extended2 && !extended1)
+    {
+      int ret = cp_compare_floating_point_conversion_ranks (t2, t1);
+      return ret == 3 ? 3 : -ret;
+    }
+
+  const struct real_format *fmt1 = REAL_MODE_FORMAT (TYPE_MODE (t1));
+  const struct real_format *fmt2 = REAL_MODE_FORMAT (TYPE_MODE (t2));
+  gcc_assert (fmt1->b == 2 && fmt2->b == 2);
+  /* For {ibm,mips}_extended_format formats, the type has variable
+     precision up to ~2150 bits when the first double is around maximum
+     representable double and second double is subnormal minimum.
+     So, e.g. for __ibm128 vs. std::float128_t, they have unordered
+     ranks.  */
+  int p1 = (MODE_COMPOSITE_P (TYPE_MODE (t1))
+	    ? fmt1->emax - fmt1->emin + fmt1->p - 1 : fmt1->p);
+  int p2 = (MODE_COMPOSITE_P (TYPE_MODE (t2))
+	    ? fmt2->emax - fmt2->emin + fmt2->p - 1 : fmt2->p);
+  /* The rank of a floating point type T is greater than the rank of
+     any floating-point type whose set of values is a proper subset
+     of the set of values of T.  */
+  if ((p1 > p2 && fmt1->emax >= fmt2->emax)
+       || (p1 == p2 && fmt1->emax > fmt2->emax))
+    return 2;
+  if ((p1 < p2 && fmt1->emax <= fmt2->emax)
+       || (p1 == p2 && fmt1->emax < fmt2->emax))
+    return -2;
+  if ((p1 > p2 && fmt1->emax < fmt2->emax)
+       || (p1 < p2 && fmt1->emax > fmt2->emax))
+    return 3;
+  if (!extended1 && !extended2)
+    {
+      /* The rank of long double is greater than the rank of double, which
+	 is greater than the rank of float.  */
+      if (t1 == long_double_type_node)
+	return 2;
+      else if (t2 == long_double_type_node)
+	return -2;
+      if (t1 == double_type_node)
+	return 2;
+      else if (t2 == double_type_node)
+	return -2;
+      if (t1 == float_type_node)
+	return 2;
+      else if (t2 == float_type_node)
+	return -2;
+      return 0;
+    }
+  /* Two extended floating-point types with the same set of values have equal
+     ranks.  */
+  if (extended1 && extended2)
+    /* We shouldn't have multiple different extended floating-point types
+       with the same set of values.  */
+    gcc_unreachable ();
+
+  tree *p;
+  int cnt = 0;
+  for (p = &float_type_node; p <= &long_double_type_node; ++p)
+    {
+      const struct real_format *fmt3 = REAL_MODE_FORMAT (TYPE_MODE (*p));
+      gcc_assert (fmt3->b == 2);
+      int p3 = (MODE_COMPOSITE_P (TYPE_MODE (*p))
+		? fmt3->emax - fmt3->emin + fmt3->p - 1 : fmt3->p);
+      if (p1 == p3 && fmt1->emax == fmt3->emax)
+	++cnt;
+    }
+  /* An extended floating-point type with the same set of values
+     as exactly one cv-unqualified standard floating-point type
+     has a rank equal to the rank of that standard floating-point
+     type.
+
+     An extended floating-point type with the same set of values
+     as more than one cv-unqualified standard floating-point type
+     has a rank equal to the rank of double.
+
+     Thus, if the latter is true and t2 is long double, t2
+     has higher rank.  */
+  if (cnt > 1 && mv2 == long_double_type_node)
+    return -2;
+  /* Otherwise, they have equal rank, but extended types
+     (other than std::bfloat16_t) have higher subrank.  */
+  return 1;
+}
+
 /* Return the common type for two arithmetic types T1 and T2 under the
    usual arithmetic conversions.  The default conversions have already
    been applied, and enumerated types converted to their compatible
@@ -342,6 +452,23 @@ cp_common_type (tree t1, tree t2)
   if (code2 == REAL_TYPE && code1 != REAL_TYPE)
     return build_type_attribute_variant (t2, attributes);
 
+  if (code1 == REAL_TYPE
+      && (extended_float_type_p (t1) || extended_float_type_p (t2)))
+    {
+      tree mv1 = TYPE_MAIN_VARIANT (t1);
+      tree mv2 = TYPE_MAIN_VARIANT (t2);
+      if (mv1 == mv2)
+	return build_type_attribute_variant (t1, attributes);
+
+      int cmpret = cp_compare_floating_point_conversion_ranks (mv1, mv2);
+      if (cmpret == 3)
+	return error_mark_node;
+      else if (cmpret >= 0)
+	return build_type_attribute_variant (t1, attributes);
+      else
+	return build_type_attribute_variant (t2, attributes);
+    }
+
   /* Both real or both integers; use the one with greater precision.  */
   if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
     return build_type_attribute_variant (t1, attributes);
@@ -5041,7 +5168,20 @@ cp_build_binary_op (const op_location_t
        = targetm.invalid_binary_op (code, type0, type1)))
     {
       if (complain & tf_error)
-	error (invalid_op_diag);
+	{
+	  if (code0 == REAL_TYPE
+	      && code1 == REAL_TYPE
+	      && (extended_float_type_p (type0)
+		  || extended_float_type_p (type1))
+	      && cp_compare_floating_point_conversion_ranks (type0,
+							     type1) == 3)
+	    {
+	      rich_location richloc (line_table, location);
+	      binary_op_error (&richloc, code, type0, type1);
+	    }
+	  else
+	    error (invalid_op_diag);
+	}
       return error_mark_node;
     }
 
@@ -5911,6 +6051,19 @@ cp_build_binary_op (const op_location_t
       && (shorten || common || short_compare))
     {
       result_type = cp_common_type (type0, type1);
+      if (result_type == error_mark_node
+	  && code0 == REAL_TYPE
+	  && code1 == REAL_TYPE
+	  && (extended_float_type_p (type0) || extended_float_type_p (type1))
+	  && cp_compare_floating_point_conversion_ranks (type0, type1) == 3)
+	{
+	  if (complain & tf_error)
+	    {
+	      rich_location richloc (line_table, location);
+	      binary_op_error (&richloc, code, type0, type1);
+	    }
+	  return error_mark_node;
+	}
       if (complain & tf_warning)
 	{
 	  do_warn_double_promotion (result_type, type0, type1,
--- gcc/cp/call.cc.jj	2022-09-09 12:27:23.169736597 +0200
+++ gcc/cp/call.cc	2022-09-10 11:14:41.361732371 +0200
@@ -1519,6 +1519,22 @@ standard_conversion (tree to, tree from,
           || SCOPED_ENUM_P (from))
 	return NULL;
 
+      /* A prvalue of floating-point type can be converted to a prvalue of
+	 another floating-point type with a greater or equal conversion
+	 rank ([conv.rank]).  A prvalue of standard floating-point type can
+	 be converted to a prvalue of another standard floating-point type.
+	 For backwards compatibility with handling __float128 and other
+	 non-standard floating point types, allow all implicit floating
+	 point conversions if neither type is extended floating-point
+	 type and if at least one of them is, fail if they have unordered
+	 conversion rank or from has higher conversion rank.  */
+      if (fcode == REAL_TYPE
+	  && tcode == REAL_TYPE
+	  && (extended_float_type_p (from)
+	      || extended_float_type_p (to))
+	  && cp_compare_floating_point_conversion_ranks (from, to) >= 2)
+	return NULL;
+
       /* If we're parsing an enum with no fixed underlying type, we're
 	 dealing with an incomplete type, which renders the conversion
 	 ill-formed.  */
@@ -5842,6 +5858,21 @@ build_conditional_expr (const op_locatio
       /* In this case, there is always a common type.  */
       result_type = type_after_usual_arithmetic_conversions (arg2_type,
 							     arg3_type);
+      if (result_type == error_mark_node
+	  && TREE_CODE (arg2_type) == REAL_TYPE
+	  && TREE_CODE (arg3_type) == REAL_TYPE
+	  && (extended_float_type_p (arg2_type)
+	      || extended_float_type_p (arg3_type))
+	  && cp_compare_floating_point_conversion_ranks (arg2_type,
+							 arg3_type) == 3)
+	{
+	  if (complain & tf_error)
+	    error_at (loc, "operands to %<?:%> have unordered conversion rank "
+			   "of types %qT and %qT",
+		      arg2_type, arg3_type);
+	  return error_mark_node;
+	}
+
       if (complain & tf_warning)
 	do_warn_double_promotion (result_type, arg2_type, arg3_type,
 				  "implicit conversion from %qH to %qI to "
@@ -8531,7 +8562,8 @@ convert_arg_to_ellipsis (tree arg, tsubs
   if (TREE_CODE (arg_type) == REAL_TYPE
       && (TYPE_PRECISION (arg_type)
 	  < TYPE_PRECISION (double_type_node))
-      && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type)))
+      && !DECIMAL_FLOAT_MODE_P (TYPE_MODE (arg_type))
+      && !extended_float_type_p (arg_type))
     {
       if ((complain & tf_warning)
 	  && warn_double_promotion && !c_inhibit_evaluation_warnings)
@@ -11719,6 +11751,75 @@ compare_ics (conversion *ics1, conversio
 	return 1;
     }
 
+  {
+    /* A conversion in either direction between floating-point type FP1 and
+       floating-point type FP2 is better than a conversion in the same
+       direction between FP1 and arithmetic type T3 if
+       - the floating-point conversion rank of FP1 is equal to the rank of
+	 FP2, and
+       - T3 is not a floating-point type, or T3 is a floating-point type
+	 whose rank is not equal to the rank of FP1, or the floating-point
+	 conversion subrank of FP2 is greater than the subrank of T3.  */
+    tree fp1 = from_type1;
+    tree fp2 = to_type1;
+    tree fp3 = from_type2;
+    tree t3 = to_type2;
+    int ret = 1;
+    if (TYPE_MAIN_VARIANT (fp2) == TYPE_MAIN_VARIANT (t3))
+      {
+	std::swap (fp1, fp2);
+	std::swap (fp3, t3);
+      }
+    if (TYPE_MAIN_VARIANT (fp1) == TYPE_MAIN_VARIANT (fp3)
+	&& TREE_CODE (fp1) == REAL_TYPE
+	/* Only apply this rule if at least one of the 3 types is
+	   extended floating-point type, otherwise keep them as
+	   before for compatibility reasons with types like __float128.
+	   float, double and long double alone have different conversion
+	   ranks and so when just those 3 types are involved, this
+	   rule doesn't trigger.  */
+	&& (extended_float_type_p (fp1)
+	    || (TREE_CODE (fp2) == REAL_TYPE && extended_float_type_p (fp2))
+	    || (TREE_CODE (t3) == REAL_TYPE && extended_float_type_p (t3))))
+      {
+	if (TREE_CODE (fp2) != REAL_TYPE)
+	  {
+	    ret = -ret;
+	    std::swap (fp2, t3);
+	  }
+	if (TREE_CODE (fp2) == REAL_TYPE)
+	  {
+	    if (cp_compare_floating_point_conversion_ranks (fp1, fp2) + 1U
+		<= 2U)
+	      {
+		/* Conversion ranks of FP1 and FP2 are equal.  */
+		if (TREE_CODE (t3) != REAL_TYPE
+		    || (cp_compare_floating_point_conversion_ranks (fp1, t3)
+			+ 1U > 2U))
+		  /* FP1 <-> FP2 conversion is better.  */
+		  return ret;
+		int c = cp_compare_floating_point_conversion_ranks (fp2, t3);
+		gcc_assert (c + 1U <= 2U);
+		if (c == 1)
+		  /* Conversion subrank of FP2 is greater than subrank of T3.
+		     FP1 <-> FP2 conversion is better.  */
+		  return ret;
+		else if (c == -1)
+		  /* Conversion subrank of FP2 is less than subrank of T3.
+		     FP1 <-> T3 conversion is better.  */
+		  return -ret;
+	      }
+	    else if (TREE_CODE (t3) == REAL_TYPE
+		     && (cp_compare_floating_point_conversion_ranks (fp1, t3)
+			 + 1U <= 2U))
+	      /* Conversion ranks of FP1 and FP2 are not equal, conversion
+		 ranks of FP1 and T3 are equal.
+		 FP1 <-> T3 conversion is better.  */
+	      return -ret;
+	  }
+      }
+  }
+
   if (TYPE_PTR_P (from_type1)
       && TYPE_PTR_P (from_type2)
       && TYPE_PTR_P (to_type1)
--- gcc/testsuite/g++.dg/cpp23/ext-floating1.C.jj	2022-09-09 18:46:07.281922287 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating1.C	2022-09-09 18:46:07.281922287 +0200
@@ -0,0 +1,248 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do compile { target c++23 } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#ifdef __STRICT_ANSI__
+#undef __SIZEOF_FLOAT128__
+#endif
+
+using namespace std;
+
+static_assert (!is_same<float, double>::value);
+static_assert (!is_same<float, long double>::value);
+static_assert (!is_same<double, long double>::value);
+static_assert (is_same<decltype (0.0f), float>::value);
+static_assert (is_same<decltype (0.0F), float>::value);
+static_assert (is_same<decltype (0.0), double>::value);
+static_assert (is_same<decltype (0.0l), long double>::value);
+static_assert (is_same<decltype (0.0L), long double>::value);
+static_assert (is_same<decltype (0.0f + 0.0F), float>::value);
+static_assert (is_same<decltype (0.0F + 0.0f), float>::value);
+static_assert (is_same<decltype (0.0 + 0.0), double>::value);
+static_assert (is_same<decltype (0.0l + 0.0L), long double>::value);
+static_assert (is_same<decltype (0.0L + 0.0l), long double>::value);
+#ifdef __SIZEOF_FLOAT128__
+static_assert (is_same<decltype (0.0q), __float128>::value);
+static_assert (is_same<decltype (0.0Q), __float128>::value);
+static_assert (is_same<decltype (0.0q + 0.0q), __float128>::value);
+static_assert (is_same<decltype (0.0Q + 0.0Q), __float128>::value);
+#endif
+#ifdef __STDCPP_FLOAT16_T__
+static_assert (!is_same<float, float16_t>::value);
+static_assert (!is_same<double, float16_t>::value);
+static_assert (!is_same<long double, float16_t>::value);
+static_assert (is_same<decltype (0.0f16), float16_t>::value);
+static_assert (is_same<decltype (0.0F16), float16_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f16), float16_t>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0F16), float16_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+static_assert (!is_same<float, float32_t>::value);
+static_assert (!is_same<double, float32_t>::value);
+static_assert (!is_same<long double, float32_t>::value);
+static_assert (!is_same<decltype (0.0f), float32_t>::value);
+static_assert (!is_same<decltype (0.0F), float32_t>::value);
+static_assert (is_same<decltype (0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32), float32_t>::value);
+static_assert (!is_same<decltype (0.0f32), float>::value);
+static_assert (!is_same<decltype (0.0F32), float>::value);
+static_assert (is_same<decltype (0.0f32 + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0F32), float32_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+static_assert (!is_same<float, float64_t>::value);
+static_assert (!is_same<double, float64_t>::value);
+static_assert (!is_same<long double, float64_t>::value);
+static_assert (!is_same<decltype (0.0), float64_t>::value);
+static_assert (is_same<decltype (0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64), float64_t>::value);
+static_assert (!is_same<decltype (0.0f64), double>::value);
+static_assert (!is_same<decltype (0.0F64), double>::value);
+static_assert (is_same<decltype (0.0f64 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F64), float64_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+static_assert (!is_same<float, float128_t>::value);
+static_assert (!is_same<double, float128_t>::value);
+static_assert (!is_same<long double, float128_t>::value);
+static_assert (!is_same<decltype (0.0l), float128_t>::value);
+static_assert (!is_same<decltype (0.0L), float128_t>::value);
+static_assert (is_same<decltype (0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128), float128_t>::value);
+static_assert (!is_same<decltype (0.0f128), long double>::value);
+static_assert (!is_same<decltype (0.0F128), long double>::value);
+static_assert (is_same<decltype (0.0f128 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F128), float128_t>::value);
+#ifdef __SIZEOF_FLOAT128__
+static_assert (!is_same<float128_t, __float128>::value);
+static_assert (!is_same<decltype (0.0q), float128_t>::value);
+static_assert (!is_same<decltype (0.0Q), float128_t>::value);
+static_assert (!is_same<decltype (0.0f128), __float128>::value);
+static_assert (!is_same<decltype (0.0F128), __float128>::value);
+#endif
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+static_assert (!is_same<float, bfloat16_t>::value);
+static_assert (!is_same<double, bfloat16_t>::value);
+static_assert (!is_same<long double, bfloat16_t>::value);
+static_assert (is_same<decltype (0.0bf16), bfloat16_t>::value);
+static_assert (is_same<decltype (0.0BF16), bfloat16_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0bf16), bfloat16_t>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0BF16), bfloat16_t>::value);
+#endif
+static_assert (is_same<decltype (0.0f + 0.0), double>::value);
+static_assert (is_same<decltype (0.0 + 0.0F), double>::value);
+static_assert (is_same<decltype (0.0L + 0.0), long double>::value);
+static_assert (is_same<decltype (0.0 + 0.0L), long double>::value);
+static_assert (is_same<decltype (0.0L + 0.0f), long double>::value);
+static_assert (is_same<decltype (0.0F + 0.0l), long double>::value);
+#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT32_T__)
+static_assert (!is_same<float16_t, float32_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0F16), float32_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT64_T__)
+static_assert (!is_same<float16_t, float64_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F16), float64_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT16_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<float16_t, float128_t>::value);
+static_assert (is_same<decltype (0.0f16 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F16), float128_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT64_T__)
+static_assert (!is_same<float32_t, float64_t>::value);
+static_assert (is_same<decltype (0.0f32 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F32), float64_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<float32_t, float128_t>::value);
+static_assert (is_same<decltype (0.0f32 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F32), float128_t>::value);
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<float64_t, float128_t>::value);
+static_assert (is_same<decltype (0.0f64 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F64), float128_t>::value);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT32_T__)
+static_assert (!is_same<bfloat16_t, float32_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0BF16), float32_t>::value);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT64_T__)
+static_assert (!is_same<bfloat16_t, float64_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0BF16), float64_t>::value);
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(__STDCPP_FLOAT128_T__)
+static_assert (!is_same<bfloat16_t, float128_t>::value);
+static_assert (is_same<decltype (0.0bf16 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0BF16), float128_t>::value);
+#endif
+#ifdef __STDCPP_FLOAT16_T__
+#if __FLT_MAX_EXP__ > __FLT16_MAX_EXP__ && __FLT_MANT_DIG__ > __FLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f16), float>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0F), float>::value);
+#endif
+#if __DBL_MAX_EXP__ > __FLT16_MAX_EXP__ && __DBL_MANT_DIG__ > __FLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f16), double>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0), double>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __FLT16_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0f16), long double>::value);
+static_assert (is_same<decltype (0.0F16 + 0.0l), long double>::value);
+#endif
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+#if __FLT_MAX_EXP__ == __FLT32_MAX_EXP__ && __FLT_MANT_DIG__ == __FLT32_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f32), float32_t>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0F), float32_t>::value);
+#endif
+#if __DBL_MAX_EXP__ > __FLT32_MAX_EXP__ && __DBL_MANT_DIG__ > __FLT32_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f32), double>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0), double>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __FLT32_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT32_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0f32), long double>::value);
+static_assert (is_same<decltype (0.0F32 + 0.0l), long double>::value);
+#endif
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+#if __FLT_MAX_EXP__ < __FLT64_MAX_EXP__ && __FLT_MANT_DIG__ < __FLT64_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0F), float64_t>::value);
+#endif
+#if __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ == __FLT64_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f64), float64_t>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0), float64_t>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __FLT64_MAX_EXP__ && __LDBL_MANT_DIG__ > __FLT64_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0f64), long double>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0l), long double>::value);
+#endif
+#if __LDBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __LDBL_MANT_DIG__ == __FLT64_MANT_DIG__ \
+    && __DBL_MAX_EXP__ == __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ == __FLT64_MANT_DIG__
+// An extended floating-point type with the same set of values as more than one
+// cv-unqualified standard floating-point type has a rank equal to the rank of
+// double.
+// Then long double will have higher rank than float64_t.
+static_assert (is_same<decltype (0.0L + 0.0f64), long double>::value);
+static_assert (is_same<decltype (0.0F64 + 0.0l), long double>::value);
+#endif
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+#if __FLT_MAX_EXP__ < __FLT128_MAX_EXP__ && __FLT_MANT_DIG__ < __FLT128_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0F), float128_t>::value);
+#endif
+#if __DBL_MAX_EXP__ < __FLT128_MAX_EXP__ && __DBL_MANT_DIG__ < __FLT128_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0), float128_t>::value);
+#endif
+#if __LDBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __LDBL_MANT_DIG__ <= __FLT128_MANT_DIG__ \
+    && __LDBL_MANT_DIG__ != 106 // IBM extended long double and IEEE quad are unordered.
+static_assert (is_same<decltype (0.0L + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0l), float128_t>::value);
+#endif
+#ifdef __SIZEOF_FLOAT128__
+static_assert (is_same<decltype (0.0Q + 0.0f128), float128_t>::value);
+static_assert (is_same<decltype (0.0F128 + 0.0q), float128_t>::value);
+#endif
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+#if __FLT_MAX_EXP__ > __BFLT16_MAX_EXP__ && __FLT_MANT_DIG__ > __BFLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0f + 0.0bf16), float>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0F), float>::value);
+#endif
+#if __DBL_MAX_EXP__ > __BFLT16_MAX_EXP__ && __DBL_MANT_DIG__ > __BFLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0 + 0.0bf16), double>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0), double>::value);
+#endif
+#if __LDBL_MAX_EXP__ > __BFLT16_MAX_EXP__ && __LDBL_MANT_DIG__ > __BFLT16_MANT_DIG__
+static_assert (is_same<decltype (0.0L + 0.0bf16), long double>::value);
+static_assert (is_same<decltype (0.0BF16 + 0.0l), long double>::value);
+#endif
+#endif
+
+void foo (float) {}
+void foo (double) {}
+void foo (long double) {}
+#ifdef __STDCPP_FLOAT16_T__
+void foo (float16_t) {}
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+void foo (float32_t) {}
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+void foo (float64_t) {}
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+void foo (float128_t) {}
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+void foo (bfloat16_t) {}
+#endif
--- gcc/testsuite/g++.dg/cpp23/ext-floating2.C.jj	2022-09-09 18:46:07.281922287 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating2.C	2022-09-09 18:46:07.281922287 +0200
@@ -0,0 +1,157 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do compile { target c++23 } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#ifdef __STRICT_ANSI__
+#undef __SIZEOF_FLOAT128__
+#endif
+
+using namespace std;
+
+float fa = 1.0f;
+float fb = (float) 1.0f;
+float fc = 1.0;
+float fd = (float) 1.0;
+float fe = 1.0L;
+float ff = (float) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float fg = 1.0Q;
+float fh = (float) 1.0Q;
+#endif
+double da = 1.0f;
+double db = (double) 1.0f;
+double dc = 1.0;
+double dd = (double) 1.0;
+double de = 1.0L;
+double df = (double) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+double dg = 1.0Q;
+double dh = (double) 1.0Q;
+#endif
+long double lda = 1.0f;
+long double ldb = (long double) 1.0f;
+long double ldc = 1.0;
+long double ldd = (long double) 1.0;
+long double lde = 1.0L;
+long double ldf = (long double) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+long double ldg = 1.0Q;
+long double ldh = (long double) 1.0Q;
+__float128 qa = 1.0f;
+__float128 qb = (__float128) 1.0f;
+__float128 qc = 1.0;
+__float128 qd = (__float128) 1.0;
+__float128 qe = 1.0L;
+__float128 qf = (__float128) 1.0L;
+__float128 qg = 1.0Q;
+__float128 qh = (__float128) 1.0Q;
+#endif
+#ifdef __STDCPP_FLOAT16_T__
+float16_t f16a = 1.0F16;
+float16_t f16b = (float16_t) 1.0F16;
+#ifdef __STDCPP_FLOAT32_T__
+float16_t f16c = 1.0F32;		// { dg-error "cannot convert '_Float32' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target { float16 && float32 } } }
+float16_t f16d = (float16_t) 1.0F32;
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+float16_t f16e = 1.0F64;		// { dg-error "cannot convert '_Float64' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target { float16 && float64 } } }
+float16_t f16f = (float16_t) 1.0F64;
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+float16_t f16g = 1.0F128;		// { dg-error "cannot convert '_Float128' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target { float16 && float128 } } }
+float16_t f16h = (float16_t) 1.0F128;
+#endif
+float16_t f16j = (float16_t) 1.0f;
+float16_t f16l = (float16_t) 1.0;
+float16_t f16n = (float16_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float16_t f16p = (float16_t) 1.0Q;
+#endif
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+#ifdef __STDCPP_FLOAT16_T__
+float32_t f32a = 1.0F16;
+float32_t f32b = (float32_t) 1.0F16;
+#endif
+float32_t f32c = 1.0F32;
+float32_t f32d = (float32_t) 1.0F32;
+#ifdef __STDCPP_FLOAT64_T__
+float32_t f32e = 1.0F64;		// { dg-error "cannot convert '_Float64' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" "" { target { float32 && float64 } } }
+float32_t f32f = (float32_t) 1.0F64;
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+float32_t f32g = 1.0F128;		// { dg-error "cannot convert '_Float128' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" "" { target { float32 && float128 } } }
+float32_t f32h = (float32_t) 1.0F128;
+#endif
+#if __FLT_MAX_EXP__ <= __FLT32_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT32_MANT_DIG__
+float32_t f32i = 1.0f;
+#endif
+float32_t f32j = (float32_t) 1.0f;
+float32_t f32l = (float32_t) 1.0;
+float32_t f32n = (float32_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float32_t f32p = (float32_t) 1.0Q;
+#endif
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+#ifdef __STDCPP_FLOAT16_T__
+float64_t f64a = 1.0F16;
+float64_t f64b = (float64_t) 1.0F16;
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+float64_t f64c = 1.0F32;
+float64_t f64d = (float64_t) 1.0F32;
+#endif
+float64_t f64e = 1.0F64;
+float64_t f64f = (float64_t) 1.0F64;
+#ifdef __STDCPP_FLOAT128_T__
+float64_t f64g = 1.0F128;		// { dg-error "cannot convert '_Float128' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" "" { target { float64 && float128 } } }
+float64_t f64h = (float64_t) 1.0F128;
+#endif
+#if __FLT_MAX_EXP__ <= __FLT64_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT64_MANT_DIG__
+float64_t f64i = 1.0f;
+#endif
+float64_t f64j = (float64_t) 1.0f;
+#if __DBL_MAX_EXP__ <= __FLT64_MAX_EXP__ && __DBL_MANT_DIG__ <= __FLT64_MANT_DIG__
+float64_t f64k = 1.0;
+#endif
+float64_t f64l = (float64_t) 1.0;
+float64_t f64n = (float64_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float64_t f64p = (float64_t) 1.0Q;
+#endif
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+#ifdef __STDCPP_FLOAT16_T__
+float128_t f128a = 1.0F16;
+float128_t f128b = (float128_t) 1.0F16;
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+float128_t f128c = 1.0F32;
+float128_t f128d = (float128_t) 1.0F32;
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+float128_t f128e = 1.0F64;
+float128_t f128f = (float128_t) 1.0F64;
+#endif
+float128_t f128g = 1.0F128;
+float128_t f128h = (float128_t) 1.0F128;
+#if __FLT_MAX_EXP__ <= __FLT128_MAX_EXP__ && __FLT_MANT_DIG__ <= __FLT128_MANT_DIG__
+float128_t f128i = 1.0f;
+#endif
+float128_t f128j = (float128_t) 1.0f;
+#if __DBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __DBL_MANT_DIG__ <= __FLT128_MANT_DIG__
+float128_t f128k = 1.0;
+#endif
+float128_t f128l = (float128_t) 1.0;
+#if __LDBL_MAX_EXP__ <= __FLT128_MAX_EXP__ && __LDBL_MANT_DIG__ <= __FLT128_MANT_DIG__ && __LDBL_MANT_DIG__ != 106
+float128_t f128m = 1.0L;
+#endif
+float128_t f128n = (float128_t) 1.0L;
+#ifdef __SIZEOF_FLOAT128__
+float128_t f128o = 1.0Q;
+float128_t f128p = (float128_t) 1.0Q;
+#endif
+#endif
--- gcc/testsuite/g++.dg/cpp23/ext-floating3.C.jj	2022-09-09 18:46:07.281922287 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating3.C	2022-09-10 10:21:25.748210213 +0200
@@ -0,0 +1,128 @@
+// P1467R9 - Extended floating-point types and standard names.
+// Variant of ext-floating2.C test with x86 specific assumptions
+// about float, double, long double and existence of __float128.
+// And some further tests.
+// { dg-do compile { target { c++23 && { i?86-*-linux* x86_64-*-linux* } } } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#if !defined(__STDCPP_FLOAT32_T__) \
+    || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \
+    || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \
+    || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \
+    || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ >= __FLT128_MANT_DIG__ \
+    || !defined(__SIZEOF_FLOAT128__)
+#error Unexpected set of floating point types
+#endif
+
+using namespace std;
+
+#ifdef __STDCPP_FLOAT16_T__
+float16_t f16i = 1.0f;			// { dg-error "cannot convert 'float' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } }
+float16_t f16k = 1.0;			// { dg-error "cannot convert 'double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } }
+float16_t f16m = 1.0L;			// { dg-error "cannot convert 'long double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } }
+float16_t f16o = 1.0Q;			// { dg-error "cannot convert '__float128' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } }
+#endif
+float32_t f32i = 1.0f;
+float32_t f32k = 1.0;			// { dg-error "cannot convert 'double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" }
+float32_t f32m = 1.0L;			// { dg-error "cannot convert 'long double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" }
+float32_t f32o = 1.0Q;			// { dg-error "cannot convert '__float128' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" }
+float64_t f64i = 1.0f;
+float64_t f64k = 1.0;
+float64_t f64m = 1.0L;			// { dg-error "cannot convert 'long double' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" }
+float64_t f64o = 1.0Q;			// { dg-error "cannot convert '__float128' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" }
+float128_t f128i = 1.0f;
+float128_t f128k = 1.0;
+float128_t f128m = 1.0L;
+float128_t f128o = 1.0Q;
+
+#ifdef __STDCPP_FLOAT16_T__
+constexpr float16_t f16x = 1.0F16;
+#endif
+constexpr float32_t f32x = 2.0F32;
+constexpr float64_t f64x = 3.0F64;
+constexpr float128_t f128x = 4.0F128;
+constexpr float fx = 5.0f;
+constexpr double dx = 6.0;
+constexpr long double ldx = 7.0L;
+
+constexpr int foo (float32_t) { return 1; }
+constexpr int foo (float64_t) { return 2; }
+constexpr int bar (float) { return 3; }
+constexpr int bar (double) { return 4; }
+constexpr int bar (long double) { return 5; }
+constexpr int baz (float32_t) { return 6; }
+constexpr int baz (float64_t) { return 7; }
+constexpr int baz (float128_t) { return 8; }
+constexpr int qux (float64_t) { return 9; }
+constexpr int qux (float32_t) { return 10; }
+constexpr int fred (long double) { return 11; }
+constexpr int fred (double) { return 12; }
+constexpr int fred (float) { return 13; }
+constexpr int thud (float128_t) { return 14; }
+constexpr int thud (float64_t) { return 15; }
+constexpr int thud (float32_t) { return 16; }
+struct S {
+  constexpr operator float32_t () const { return 1.0f32; }
+  constexpr operator float64_t () const { return 2.0f64; }
+};
+struct T {
+  constexpr operator float64_t () const { return 3.0f64; }
+  constexpr operator float32_t () const { return 4.0f32; }
+};
+
+void
+test (S s, T t)
+{
+#ifdef __STDCPP_FLOAT16_T__
+  foo (float16_t (1.0));			// { dg-error "call of overloaded 'foo\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (foo (float (2.0)) == 1);
+  static_assert (foo (double (3.0)) == 2);
+  constexpr double x (s);
+  static_assert (x == 2.0);
+#ifdef __STDCPP_FLOAT16_T__
+  bar (f16x);					// { dg-error "call of overloaded 'bar\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (bar (f32x) == 3);
+  static_assert (bar (f64x) == 4);
+  bar (f128x);					// { dg-error "no matching function for call to 'bar\\\(const std::float128_t\\\&\\\)'" }
+  static_assert (bar (fx) == 3);
+  static_assert (bar (dx) == 4);
+  static_assert (bar (ldx) == 5);
+#ifdef __STDCPP_FLOAT16_T__
+  baz (f16x);					// { dg-error "call of overloaded 'baz\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (baz (f32x) == 6);
+  static_assert (baz (f64x) == 7);
+  static_assert (baz (f128x) == 8);
+  static_assert (baz (fx) == 6);
+  static_assert (baz (dx) == 7);
+  static_assert (baz (ldx) == 8);
+#ifdef __STDCPP_FLOAT16_T__
+  qux (float16_t (1.0));			// { dg-error "call of overloaded 'qux\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (qux (float (2.0)) == 10);
+  static_assert (qux (double (3.0)) == 9);
+  constexpr double y (t);
+  static_assert (y == 3.0);
+#ifdef __STDCPP_FLOAT16_T__
+  fred (f16x);					// { dg-error "call of overloaded 'fred\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (fred (f32x) == 13);
+  static_assert (fred (f64x) == 12);
+  fred (f128x);					// { dg-error "no matching function for call to 'fred\\\(const std::float128_t\\\&\\\)'" }
+  static_assert (fred (fx) == 13);
+  static_assert (fred (dx) == 12);
+  static_assert (fred (ldx) == 11);
+#ifdef __STDCPP_FLOAT16_T__
+  thud (f16x);					// { dg-error "call of overloaded 'thud\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (thud (f32x) == 16);
+  static_assert (thud (f64x) == 15);
+  static_assert (thud (f128x) == 14);
+  static_assert (thud (fx) == 16);
+  static_assert (thud (dx) == 15);
+  static_assert (thud (ldx) == 14);
+}
--- gcc/testsuite/g++.dg/cpp23/ext-floating4.C.jj	2022-09-09 18:48:11.979261440 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating4.C	2022-09-10 10:55:24.105457186 +0200
@@ -0,0 +1,126 @@
+// P1467R9 - Extended floating-point types and standard names.
+// Variant of ext-floating3.C test with different specific assumptions
+// about float, double, long double.
+// float, double and long double are assumed to be IEEE 754 single, double
+// and quad.
+// { dg-do compile { target { c++23 && { aarch64*-*-* powerpc64le*-*-linux* riscv*-*-* s390*-*-* sparc*-*-linux* } } } }
+// { dg-options "" }
+// { dg-additional-options "-mlong-double-128" { target s390*-*-* sparc*-*-linux* } }
+// { dg-additional-options "-mvsx -mfloat128 -mlong-double-128 -mabi=ieeelongdouble -Wno-psabi" { target powerpc64le*-*-linux* } }
+
+#include "ext-floating.h"
+
+#if !defined(__STDCPP_FLOAT32_T__) \
+    || !defined(__STDCPP_FLOAT64_T__) || !defined(__STDCPP_FLOAT128_T__) \
+    || __FLT_MAX_EXP__ != __FLT32_MAX_EXP__ || __FLT_MANT_DIG__ != __FLT32_MANT_DIG__ \
+    || __DBL_MAX_EXP__ != __FLT64_MAX_EXP__ || __DBL_MANT_DIG__ != __FLT64_MANT_DIG__ \
+    || __LDBL_MAX_EXP__ != __FLT128_MAX_EXP__ || __LDBL_MANT_DIG__ != __FLT128_MANT_DIG__
+#error Unexpected set of floating point types
+#endif
+
+using namespace std;
+
+#ifdef __STDCPP_FLOAT16_T__
+float16_t f16i = 1.0f;			// { dg-error "cannot convert 'float' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } }
+float16_t f16k = 1.0;			// { dg-error "cannot convert 'double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } }
+float16_t f16m = 1.0L;			// { dg-error "cannot convert 'long double' to 'std::float16_t' \\\{aka '_Float16'\\\} in initialization" "" { target float16 } }
+#endif
+float32_t f32i = 1.0f;
+float32_t f32k = 1.0;			// { dg-error "cannot convert 'double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" }
+float32_t f32m = 1.0L;			// { dg-error "cannot convert 'long double' to 'std::float32_t' \\\{aka '_Float32'\\\} in initialization" }
+float64_t f64i = 1.0f;
+float64_t f64k = 1.0;
+float64_t f64m = 1.0L;			// { dg-error "cannot convert 'long double' to 'std::float64_t' \\\{aka '_Float64'\\\} in initialization" }
+float128_t f128i = 1.0f;
+float128_t f128k = 1.0;
+float128_t f128m = 1.0L;
+
+#ifdef __STDCPP_FLOAT16_T__
+constexpr float16_t f16x = 1.0F16;
+#endif
+constexpr float32_t f32x = 2.0F32;
+constexpr float64_t f64x = 3.0F64;
+constexpr float128_t f128x = 4.0F128;
+constexpr float fx = 5.0f;
+constexpr double dx = 6.0;
+constexpr long double ldx = 7.0L;
+
+constexpr int foo (float32_t) { return 1; }
+constexpr int foo (float64_t) { return 2; }
+constexpr int bar (float) { return 3; }
+constexpr int bar (double) { return 4; }
+constexpr int bar (long double) { return 5; }
+constexpr int baz (float32_t) { return 6; }
+constexpr int baz (float64_t) { return 7; }
+constexpr int baz (float128_t) { return 8; }
+constexpr int qux (float64_t) { return 9; }
+constexpr int qux (float32_t) { return 10; }
+constexpr int fred (long double) { return 11; }
+constexpr int fred (double) { return 12; }
+constexpr int fred (float) { return 13; }
+constexpr int thud (float128_t) { return 14; }
+constexpr int thud (float64_t) { return 15; }
+constexpr int thud (float32_t) { return 16; }
+struct S {
+  constexpr operator float32_t () const { return 1.0f32; }
+  constexpr operator float64_t () const { return 2.0f64; }
+};
+struct T {
+  constexpr operator float64_t () const { return 3.0f64; }
+  constexpr operator float32_t () const { return 4.0f32; }
+};
+
+void
+test (S s, T t)
+{
+#ifdef __STDCPP_FLOAT16_T__
+  foo (float16_t (1.0));			// { dg-error "call of overloaded 'foo\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (foo (float (2.0)) == 1);
+  static_assert (foo (double (3.0)) == 2);
+  constexpr double x (s);
+  static_assert (x == 2.0);
+#ifdef __STDCPP_FLOAT16_T__
+  bar (f16x);					// { dg-error "call of overloaded 'bar\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (bar (f32x) == 3);
+  static_assert (bar (f64x) == 4);
+  static_assert (bar (f128x) == 5);
+  static_assert (bar (fx) == 3);
+  static_assert (bar (dx) == 4);
+  static_assert (bar (ldx) == 5);
+#ifdef __STDCPP_FLOAT16_T__
+  baz (f16x);					// { dg-error "call of overloaded 'baz\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (baz (f32x) == 6);
+  static_assert (baz (f64x) == 7);
+  static_assert (baz (f128x) == 8);
+  static_assert (baz (fx) == 6);
+  static_assert (baz (dx) == 7);
+  static_assert (baz (ldx) == 8);
+#ifdef __STDCPP_FLOAT16_T__
+  qux (float16_t (1.0));			// { dg-error "call of overloaded 'qux\\\(std::float16_t\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (qux (float (2.0)) == 10);
+  static_assert (qux (double (3.0)) == 9);
+  constexpr double y (t);
+  static_assert (y == 3.0);
+#ifdef __STDCPP_FLOAT16_T__
+  fred (f16x);					// { dg-error "call of overloaded 'fred\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (fred (f32x) == 13);
+  static_assert (fred (f64x) == 12);
+  static_assert (fred (f128x) == 11);
+  static_assert (fred (fx) == 13);
+  static_assert (fred (dx) == 12);
+  static_assert (fred (ldx) == 11);
+#ifdef __STDCPP_FLOAT16_T__
+  thud (f16x);					// { dg-error "call of overloaded 'thud\\\(const std::float16_t\\\&\\\)' is ambiguous" "" { target float16 } }
+#endif
+  static_assert (thud (f32x) == 16);
+  static_assert (thud (f64x) == 15);
+  static_assert (thud (f128x) == 14);
+  static_assert (thud (fx) == 16);
+  static_assert (thud (dx) == 15);
+  static_assert (thud (ldx) == 14);
+}
--- gcc/testsuite/g++.dg/cpp23/ext-floating5.C.jj	2022-09-09 20:00:22.489534397 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating5.C	2022-09-10 10:44:59.653943267 +0200
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// IBM extended long double and _Float128 should have unordered conversion
+// ranks as IBM extended long double has variable precision from 53 bits
+// for denormals to more than 2150 bits for certain numbers.
+// { dg-do compile { target { c++23 && { powerpc*-*-linux* } } } }
+// { dg-require-effective-target ppc_float128_sw }
+// { dg-options "-mvsx -mfloat128 -mlong-double-128 -mabi=ibmlongdouble" }
+
+auto a = 1.0F128 + 1.0L;	// { dg-error "invalid operands to binary \\\+ \\\(have '_Float128' and 'long double'\\\)" }
+auto b = 1.0L + 1.0F128;	// { dg-error "invalid operands to binary \\\+ \\\(have 'long double' and '_Float128'\\\)" }
+bool c;
+auto d = c ? 1.0F128 : 1.0L;	// { dg-error "operands to '\\\?:' have unordered conversion rank of types '_Float128' and 'long double'" }
+auto e = c ? 1.0L : 1.0F128;	// { dg-error "operands to '\\\?:' have unordered conversion rank of types 'long double' and '_Float128'" }
--- gcc/testsuite/g++.dg/cpp23/ext-floating6.C.jj	2022-09-10 10:19:12.402030094 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating6.C	2022-09-09 18:46:07.281922287 +0200
@@ -0,0 +1,30 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do compile { target c++23 } }
+// { dg-options "" }
+
+#include "ext-floating.h"
+
+#ifdef __STRICT_ANSI__
+#undef __SIZEOF_FLOAT128__
+#endif
+
+using namespace std;
+
+float foo (float x, float y, float z) { return x * y + z; }
+double foo (double x, double y, double z) { return x * y + z; }
+long double foo (long double x, long double y, long double z) { return x * y + z; }
+#ifdef __STDCPP_FLOAT16_T__
+float16_t foo (float16_t x, float16_t y, float16_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_FLOAT32_T__
+float32_t foo (float32_t x, float32_t y, float32_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_FLOAT64_T__
+float64_t foo (float64_t x, float64_t y, float64_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_FLOAT128_T__
+float128_t foo (float128_t x, float128_t y, float128_t z) { return x * y + z; }
+#endif
+#ifdef __STDCPP_BFLOAT16_T__
+bfloat16_t foo (bfloat16_t x, bfloat16_t y, bfloat16_t z) { return x * y + z; }
+#endif
--- gcc/testsuite/g++.dg/cpp23/ext-floating7.C.jj	2022-09-10 10:47:37.550796997 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating7.C	2022-09-10 10:53:25.622065903 +0200
@@ -0,0 +1,119 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float16_runtime } } }
+// { dg-options "" }
+// { dg-add-options float16 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT16_T__
+#error Unexpected
+#endif
+#define WIDTH 16
+#endif
+
+#include <stdarg.h>
+#include "ext-floating.h"
+
+#define CONCATX(X, Y) X ## Y
+#define CONCAT(X, Y) CONCATX (X, Y)
+#define CONCAT3(X, Y, Z) CONCAT (CONCAT (X, Y), Z)
+#define TYPE CONCAT (_Float, WIDTH)
+#define CST(C) CONCAT3 (C, f, WIDTH)
+#define CSTU(C) CONCAT3 (C, F, WIDTH)
+
+extern "C" void abort ();
+
+volatile TYPE a = CST (1.0), b = CSTU (2.5), c = -CST (2.5);
+volatile TYPE a2 = CST (1.0), z = CST (0.0), nz = -CST (0.0);
+
+// These types are not subject to default argument promotions.
+
+TYPE
+vafn (TYPE arg1, ...)
+{
+  va_list ap;
+  TYPE ret;
+  va_start (ap, arg1);
+  ret = arg1 + va_arg (ap, TYPE);
+  va_end (ap);
+  return ret;
+}
+
+TYPE
+fn (TYPE arg)
+{
+  return arg / 4;
+}
+
+int
+main (void)
+{
+  volatile TYPE r;
+  r = -b;
+  if (r != c)
+    abort ();
+  r = a + b;
+  if (r != CST (3.5))
+    abort ();
+  r = a - b;
+  if (r != -CST (1.5))
+    abort ();
+  r = 2 * c;
+  if (r != -5)
+    abort ();
+  r = b * c;
+  if (r != -CST (6.25))
+    abort ();
+  r = b / (a + a);
+  if (r != CST (1.25))
+    abort ();
+  r = c * 3;
+  if (r != -CST (7.5))
+    abort ();
+  volatile int i = r;
+  if (i != -7)
+    abort ();
+  r = vafn (a, c);
+  if (r != -CST (1.5))
+    abort ();
+  r = fn (a);
+  if (r != CST (0.25))
+    abort ();
+  if ((a < b) != 1)
+    abort ();
+  if ((b < a) != 0)
+    abort ();
+  if ((a < a2) != 0)
+    abort ();
+  if ((nz < z) != 0)
+    abort ();
+  if ((a <= b) != 1)
+    abort ();
+  if ((b <= a) != 0)
+    abort ();
+  if ((a <= a2) != 1)
+    abort ();
+  if ((nz <= z) != 1)
+    abort ();
+  if ((a > b) != 0)
+    abort ();
+  if ((b > a) != 1)
+    abort ();
+  if ((a > a2) != 0)
+    abort ();
+  if ((nz > z) != 0)
+    abort ();
+  if ((a >= b) != 0)
+    abort ();
+  if ((b >= a) != 1)
+    abort ();
+  if ((a >= a2) != 1)
+    abort ();
+  if ((nz >= z) != 1)
+    abort ();
+  i = (nz == z);
+  if (i != 1)
+    abort ();
+  i = (a == b);
+  if (i != 0)
+    abort ();
+}
--- gcc/testsuite/g++.dg/cpp23/ext-floating8.C.jj	2022-09-10 10:52:54.654486646 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating8.C	2022-09-10 10:53:41.424851341 +0200
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float32_runtime } } }
+// { dg-options "" }
+// { dg-add-options float32 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT32_T__
+#error Unexpected
+#endif
+#define WIDTH 32
+#endif
+
+#include "ext-floating7.C"
--- gcc/testsuite/g++.dg/cpp23/ext-floating9.C.jj	2022-09-10 10:53:49.328744035 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating9.C	2022-09-10 10:53:57.280636056 +0200
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float64_runtime } } }
+// { dg-options "" }
+// { dg-add-options float64 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT64_T__
+#error Unexpected
+#endif
+#define WIDTH 64
+#endif
+
+#include "ext-floating7.C"
--- gcc/testsuite/g++.dg/cpp23/ext-floating10.C.jj	2022-09-10 10:54:08.224487463 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating10.C	2022-09-10 10:54:21.578306159 +0200
@@ -0,0 +1,13 @@
+// P1467R9 - Extended floating-point types and standard names.
+// { dg-do run { target { c++23 && float128_runtime } } }
+// { dg-options "" }
+// { dg-add-options float128 }
+
+#ifndef WIDTH
+#ifndef __STDCPP_FLOAT128_T__
+#error Unexpected
+#endif
+#define WIDTH 128
+#endif
+
+#include "ext-floating7.C"
--- gcc/testsuite/g++.dg/cpp23/ext-floating.h.jj	2022-09-09 18:46:07.281922287 +0200
+++ gcc/testsuite/g++.dg/cpp23/ext-floating.h	2022-09-09 18:46:07.281922287 +0200
@@ -0,0 +1,30 @@
+// P1467R9 - Extended floating-point types and standard names.
+
+namespace std
+{
+  #ifdef __STDCPP_FLOAT16_T__
+  using float16_t = _Float16;
+  #endif
+  #ifdef __STDCPP_FLOAT32_T__
+  using float32_t = _Float32;
+  #endif
+  #ifdef __STDCPP_FLOAT64_T__
+  using float64_t = _Float64;
+  #endif
+  #ifdef __STDCPP_FLOAT128_T__
+  using float128_t = _Float128;
+  #endif
+  #undef __STDCPP_BFLOAT16_T__
+  #ifdef __STDCPP_BFLOAT16_T__
+  using bfloat16_t = __bf16; // ???
+  #endif
+  template<typename T, T v> struct integral_constant {
+    static constexpr T value = v;
+  };
+  typedef integral_constant<bool, false> false_type;
+  typedef integral_constant<bool, true> true_type;
+  template<class T, class U>
+  struct is_same : std::false_type {};
+  template <class T>
+  struct is_same<T, T> : std::true_type {};
+}
--- gcc/testsuite/g++.target/i386/float16-1.C.jj	2021-12-30 15:12:43.315149146 +0100
+++ gcc/testsuite/g++.target/i386/float16-1.C	2022-09-12 08:49:38.178955414 +0200
@@ -1,8 +1,8 @@
 /* { dg-do compile } */
 /* { dg-options "-O2 -mno-sse2" } */
 
-_Float16/* { dg-error "does not name a type" } */
+_Float16	/* { dg-error "expected unqualified-id before '_Float16'" } */
 foo (_Float16 x) 
 {
   return x;
-}
+}		/* { dg-error "'_Float16' is not supported on this target" } */
--- libcpp/expr.cc.jj	2022-09-08 13:01:19.837771596 +0200
+++ libcpp/expr.cc	2022-09-09 09:52:46.533798139 +0200
@@ -215,7 +215,6 @@ interpret_float_suffix (cpp_reader *pfil
 	case 'f': case 'F':
 	  f++;
 	  if (len > 0
-	      && !CPP_OPTION (pfile, cplusplus)
 	      && s[1] >= '1'
 	      && s[1] <= '9'
 	      && fn_bits == 0)
@@ -230,7 +229,9 @@ interpret_float_suffix (cpp_reader *pfil
 		  len--;
 		  s++;
 		}
-	      if (len > 0 && s[1] == 'x')
+	      if (len > 0
+		  && s[1] == 'x'
+		  && !CPP_OPTION (pfile, cplusplus))
 		{
 		  fnx++;
 		  len--;
--- include/demangle.h.jj	2022-08-26 09:23:37.788064821 +0200
+++ include/demangle.h	2022-09-09 09:52:46.533798139 +0200
@@ -457,6 +457,11 @@ enum demangle_component_type
   DEMANGLE_COMPONENT_MODULE_PARTITION,
   DEMANGLE_COMPONENT_MODULE_ENTITY,
   DEMANGLE_COMPONENT_MODULE_INIT,
+
+  /* A builtin type with argument.  This holds the builtin type
+     information.  */
+  DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE
+
 };
 
 /* Types which are only used internally.  */
@@ -543,6 +548,14 @@ struct demangle_component
       const struct demangle_builtin_type_info *type;
     } s_builtin;
 
+    /* For DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE.  */
+    struct
+    {
+      /* Builtin type.  */
+      const struct demangle_builtin_type_info *type;
+      int arg;
+    } s_extended_builtin;
+
     /* For DEMANGLE_COMPONENT_SUB_STD.  */
     struct
     {
--- libiberty/cp-demangle.c.jj	2022-08-26 09:23:37.788064821 +0200
+++ libiberty/cp-demangle.c	2022-09-09 09:52:46.957792397 +0200
@@ -648,6 +648,10 @@ d_dump (struct demangle_component *dc, i
     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
       printf ("builtin type %s\n", dc->u.s_builtin.type->name);
       return;
+    case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
+      printf ("builtin type %s%d\n", dc->u.s_extended_builtin.type->name,
+	      dc->u.s_extended_builtin.type->arg);
+      return;
     case DEMANGLE_COMPONENT_OPERATOR:
       printf ("operator %s\n", dc->u.s_operator.op->name);
       return;
@@ -771,11 +775,6 @@ d_dump (struct demangle_component *dc, i
     case DEMANGLE_COMPONENT_PTRMEM_TYPE:
       printf ("pointer to member type\n");
       break;
-    case DEMANGLE_COMPONENT_FIXED_TYPE:
-      printf ("fixed-point type, accum? %d, sat? %d\n",
-              dc->u.s_fixed.accum, dc->u.s_fixed.sat);
-      d_dump (dc->u.s_fixed.length, indent + 2);
-      break;
     case DEMANGLE_COMPONENT_ARGLIST:
       printf ("argument list\n");
       break;
@@ -1109,6 +1108,27 @@ d_make_builtin_type (struct d_info *di,
   return p;
 }
 
+/* Add a new extended builtin type component.  */
+
+static struct demangle_component *
+d_make_extended_builtin_type (struct d_info *di,
+			      const struct demangle_builtin_type_info *type,
+			      int arg)
+{
+  struct demangle_component *p;
+
+  if (type == NULL)
+    return NULL;
+  p = d_make_empty (di);
+  if (p != NULL)
+    {
+      p->type = DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE;
+      p->u.s_extended_builtin.type = type;
+      p->u.s_extended_builtin.arg = arg;
+    }
+  return p;
+}
+
 /* Add a new operator component.  */
 
 static struct demangle_component *
@@ -2464,6 +2484,7 @@ cplus_demangle_builtin_types[D_BUILTIN_T
   /* 32 */ { NL ("char32_t"),	NL ("char32_t"),	D_PRINT_DEFAULT },
   /* 33 */ { NL ("decltype(nullptr)"),	NL ("decltype(nullptr)"),
 	     D_PRINT_DEFAULT },
+  /* 34 */ { NL ("_Float"),	NL ("_Float"),		D_PRINT_FLOAT },
 };
 
 CP_STATIC_IF_GLIBCPP_V3
@@ -2727,19 +2748,22 @@ cplus_demangle_type (struct d_info *di)
 	  break;
 
 	case 'F':
-	  /* Fixed point types. DF<int bits><length><fract bits><sat>  */
-	  ret = d_make_empty (di);
-	  ret->type = DEMANGLE_COMPONENT_FIXED_TYPE;
-	  if ((ret->u.s_fixed.accum = IS_DIGIT (d_peek_char (di))))
-	    /* For demangling we don't care about the bits.  */
-	    d_number (di);
-	  ret->u.s_fixed.length = cplus_demangle_type (di);
-	  if (ret->u.s_fixed.length == NULL)
-	    return NULL;
-	  d_number (di);
-	  peek = d_next_char (di);
-	  ret->u.s_fixed.sat = (peek == 's');
-	  break;
+	  /* DF<number>_ - _Float<number>.  */
+	  {
+	    int arg = d_number (di);
+	    char buf[12];
+	    if (d_peek_char (di) != '_')
+	      return NULL;
+	    ret
+	      = d_make_extended_builtin_type (di,
+					      &cplus_demangle_builtin_types[34],
+					      arg);
+	    d_advance (di, 1);
+	    sprintf (buf, "%d", arg);
+	    di->expansion += ret->u.s_extended_builtin.type->len
+			     + strlen (buf);
+	    break;
+	  }
 
 	case 'v':
 	  ret = d_vector_type (di);
@@ -4202,6 +4226,7 @@ d_count_templates_scopes (struct d_print
     case DEMANGLE_COMPONENT_FUNCTION_PARAM:
     case DEMANGLE_COMPONENT_SUB_STD:
     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+    case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
     case DEMANGLE_COMPONENT_OPERATOR:
     case DEMANGLE_COMPONENT_CHARACTER:
     case DEMANGLE_COMPONENT_NUMBER:
@@ -4210,6 +4235,7 @@ d_count_templates_scopes (struct d_print
     case DEMANGLE_COMPONENT_MODULE_NAME:
     case DEMANGLE_COMPONENT_MODULE_PARTITION:
     case DEMANGLE_COMPONENT_MODULE_INIT:
+    case DEMANGLE_COMPONENT_FIXED_TYPE:
       break;
 
     case DEMANGLE_COMPONENT_TEMPLATE:
@@ -4309,10 +4335,6 @@ d_count_templates_scopes (struct d_print
       d_count_templates_scopes (dpi, dc->u.s_extended_operator.name);
       break;
 
-    case DEMANGLE_COMPONENT_FIXED_TYPE:
-      d_count_templates_scopes (dpi, dc->u.s_fixed.length);
-      break;
-
     case DEMANGLE_COMPONENT_GLOBAL_CONSTRUCTORS:
     case DEMANGLE_COMPONENT_GLOBAL_DESTRUCTORS:
     case DEMANGLE_COMPONENT_MODULE_ENTITY:
@@ -4580,11 +4602,11 @@ d_find_pack (struct d_print_info *dpi,
     case DEMANGLE_COMPONENT_TAGGED_NAME:
     case DEMANGLE_COMPONENT_OPERATOR:
     case DEMANGLE_COMPONENT_BUILTIN_TYPE:
+    case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
     case DEMANGLE_COMPONENT_SUB_STD:
     case DEMANGLE_COMPONENT_CHARACTER:
     case DEMANGLE_COMPONENT_FUNCTION_PARAM:
     case DEMANGLE_COMPONENT_UNNAMED_TYPE:
-    case DEMANGLE_COMPONENT_FIXED_TYPE:
     case DEMANGLE_COMPONENT_DEFAULT_ARG:
     case DEMANGLE_COMPONENT_NUMBER:
       return NULL;
@@ -5387,6 +5409,16 @@ d_print_comp_inner (struct d_print_info
 			 dc->u.s_builtin.type->java_len);
       return;
 
+    case DEMANGLE_COMPONENT_EXTENDED_BUILTIN_TYPE:
+      if ((options & DMGL_JAVA) == 0)
+	d_append_buffer (dpi, dc->u.s_extended_builtin.type->name,
+			 dc->u.s_extended_builtin.type->len);
+      else
+	d_append_buffer (dpi, dc->u.s_extended_builtin.type->java_name,
+			 dc->u.s_extended_builtin.type->java_len);
+      d_append_num (dpi, dc->u.s_extended_builtin.arg);
+      return;
+
     case DEMANGLE_COMPONENT_VENDOR_TYPE:
       d_print_comp (dpi, options, d_left (dc));
       return;
@@ -5525,22 +5557,6 @@ d_print_comp_inner (struct d_print_info
 	return;
       }
 
-    case DEMANGLE_COMPONENT_FIXED_TYPE:
-      if (dc->u.s_fixed.sat)
-	d_append_string (dpi, "_Sat ");
-      /* Don't print "int _Accum".  */
-      if (dc->u.s_fixed.length->u.s_builtin.type
-	  != &cplus_demangle_builtin_types['i'-'a'])
-	{
-	  d_print_comp (dpi, options, dc->u.s_fixed.length);
-	  d_append_char (dpi, ' ');
-	}
-      if (dc->u.s_fixed.accum)
-	d_append_string (dpi, "_Accum");
-      else
-	d_append_string (dpi, "_Fract");
-      return;
-
     case DEMANGLE_COMPONENT_ARGLIST:
     case DEMANGLE_COMPONENT_TEMPLATE_ARGLIST:
       if (d_left (dc) != NULL)
--- libiberty/cp-demangle.h.jj	2022-08-26 09:23:37.788064821 +0200
+++ libiberty/cp-demangle.h	2022-09-09 09:52:46.978792113 +0200
@@ -180,7 +180,7 @@ d_advance (struct d_info *di, int i)
 extern const struct demangle_operator_info cplus_demangle_operators[];
 #endif
 
-#define D_BUILTIN_TYPE_COUNT (34)
+#define D_BUILTIN_TYPE_COUNT (35)
 
 CP_STATIC_IF_GLIBCPP_V3
 const struct demangle_builtin_type_info
--- libiberty/testsuite/demangle-expected.jj	2022-08-26 09:23:37.788064821 +0200
+++ libiberty/testsuite/demangle-expected	2022-09-09 09:52:46.993791909 +0200
@@ -1242,8 +1242,8 @@ _ZNSt9_Any_data9_M_accessIPZ4postISt8fun
 post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*& std::_Any_data::_M_access<post<std::function<void ()> >(post<std::function<void ()> >(std::function<void ()>&&)::{lambda()#1}*&&)::{lambda()#1}*>()
 #
 --format=auto --no-params
-_Z3xxxDFyuVb
-xxx(unsigned long long _Fract, bool volatile)
+_Z3xxxDF16_DF32_DF64_DF128_CDF16_Vb
+xxx(_Float16, _Float32, _Float64, _Float128, _Float16 _Complex, bool volatile)
 xxx
 # https://sourceware.org/bugzilla/show_bug.cgi?id=16817
 --format=auto --no-params
--- fixincludes/inclhack.def.jj	2022-03-01 19:42:39.183264899 +0100
+++ fixincludes/inclhack.def	2022-09-11 20:08:07.787691125 +0200
@@ -2015,6 +2015,102 @@ fix = {
 	EOT;
 };
 
+/*  glibc-2.27 to 2.36 assume GCC 7 or later supports some or all
+ *  of _Float{16,32,64,128} and _Float{32,64,128}x keywords for C,
+ *  but doesn't for C++.
+ */
+fix = {
+    hackname  = glibc_cxx_floatn_1;
+    files     = bits/floatn.h, bits/floatn-common.h;
+    select    = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n"
+		"(([ \t]*/\\*[^\n]*\\*/\n)?"
+		"([ \t]*#[ \t]*if[^\n]*\n)?"
+		"[ \t]*#[ \t]*define __f(16|32|64|128)\\()";
+    c_fix     = format;
+    c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n%2";
+    test_text = <<-EOT
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	/* The literal suffix f128 exists only since GCC 7.0.  */
+	#   define __f128(x) x##l
+	#  else
+	#   define __f128(x) x##f128
+	#  endif
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	/* The literal suffix (f128) exist for powerpc only since GCC 7.0.  */
+	#   if __LDBL_MANT_DIG__ == 113
+	#    define __f128(x) x##l
+	#   else
+	#    define __f128(x) x##q
+	#   endif
+	#  else
+	#   define __f128(x) x##f128
+	#  endif
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	#   ifdef __NO_LONG_DOUBLE_MATH
+	#    define __f64(x) x##l
+	#   else
+	#    define __f64(x) x
+	#   endif
+	#  else
+	#   define __f64(x) x##f64
+	#  endif
+	EOT;
+};
+
+fix = {
+    hackname  = glibc_cxx_floatn_2;
+    files     = bits/floatn.h, bits/floatn-common.h;
+    select    = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n"
+		"(([ \t]*/\\*[^\n]*\\*/\n)?"
+		"[ \t]*typedef[ \t]+[^\n]*[ \t]+_Float(16|32|64|128)([ \t]+__attribute__ \\(\\(__mode__ \\(__HF__\\)\\)\\))?;)";
+    c_fix     = format;
+    c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n%2";
+    test_text = <<-EOT
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
+	#  endif
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	typedef __float128 _Float128;
+	#  endif
+	EOT;
+};
+
+fix = {
+    hackname  = glibc_cxx_floatn_3;
+    files     = bits/floatn.h, bits/floatn-common.h;
+    select    = "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n"
+		"(([ \t]*/\\*[^\n]*\n?[^\n]*\\*/\n)?"
+		"([ \t]*#[ \t]*if[^\n]*\n)?"
+		"([ \t]*typedef[ \t]+[^\n]*;\n)?"
+		"[ \t]*#[ \t]*define __CFLOAT(16|32|64|128)[ \t]+)";
+    c_fix     = format;
+    c_fix_arg = "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n%2";
+    test_text = <<-EOT
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	#   define __CFLOAT128 _Complex long double
+	#  else
+	#   define __CFLOAT128 _Complex _Float128
+	#  endif
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	/* Add a typedef for older GCC compilers which don't natively support
+	   _Complex _Float128.  */
+	typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
+	#   define __CFLOAT128 __cfloat128
+	#  else
+	#   define __CFLOAT128 _Complex _Float128
+	#  endif
+	#  if !__GNUC_PREREQ (7, 0) || defined __cplusplus
+	#   ifdef __NO_LONG_DOUBLE_MATH
+	#    define __CFLOAT64 _Complex long double
+	#   else
+	#    define __CFLOAT64 _Complex double
+	#   endif
+	#  else
+	#   define __CFLOAT64 _Complex _Float64
+	#  endif
+	EOT;
+};
+
 /*  glibc-2.3.5 defines pthread mutex initializers incorrectly,
  *  so we replace them with versions that correspond to the
  *  definition.
--- fixincludes/tests/base/bits/floatn.h.jj	2022-09-11 20:11:34.991962782 +0200
+++ fixincludes/tests/base/bits/floatn.h	2022-09-11 20:09:48.323368533 +0200
@@ -0,0 +1,74 @@
+/*  DO NOT EDIT THIS FILE.
+
+    It has been auto-edited by fixincludes from:
+
+	"fixinc/tests/inc/bits/floatn.h"
+
+    This had to be done to correct non-standard usages in the
+    original, manufacturer supplied header file.  */
+
+
+
+#if defined( GLIBC_CXX_FLOATN_1_CHECK )
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+/* The literal suffix f128 exists only since GCC 7.0.  */
+#   define __f128(x) x##l
+#  else
+#   define __f128(x) x##f128
+#  endif
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+/* The literal suffix (f128) exist for powerpc only since GCC 7.0.  */
+#   if __LDBL_MANT_DIG__ == 113
+#    define __f128(x) x##l
+#   else
+#    define __f128(x) x##q
+#   endif
+#  else
+#   define __f128(x) x##f128
+#  endif
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+#   ifdef __NO_LONG_DOUBLE_MATH
+#    define __f64(x) x##l
+#   else
+#    define __f64(x) x
+#   endif
+#  else
+#   define __f64(x) x##f64
+#  endif
+#endif  /* GLIBC_CXX_FLOATN_1_CHECK */
+
+
+#if defined( GLIBC_CXX_FLOATN_2_CHECK )
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+typedef float _Float16 __attribute__ ((__mode__ (__HF__)));
+#  endif
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+typedef __float128 _Float128;
+#  endif
+#endif  /* GLIBC_CXX_FLOATN_2_CHECK */
+
+
+#if defined( GLIBC_CXX_FLOATN_3_CHECK )
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+#   define __CFLOAT128 _Complex long double
+#  else
+#   define __CFLOAT128 _Complex _Float128
+#  endif
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+/* Add a typedef for older GCC compilers which don't natively support
+   _Complex _Float128.  */
+typedef _Complex float __cfloat128 __attribute__ ((__mode__ (__TC__)));
+#   define __CFLOAT128 __cfloat128
+#  else
+#   define __CFLOAT128 _Complex _Float128
+#  endif
+#  if !__GNUC_PREREQ (7, 0) || (defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)
+#   ifdef __NO_LONG_DOUBLE_MATH
+#    define __CFLOAT64 _Complex long double
+#   else
+#    define __CFLOAT64 _Complex double
+#   endif
+#  else
+#   define __CFLOAT64 _Complex _Float64
+#  endif
+#endif  /* GLIBC_CXX_FLOATN_3_CHECK */
--- fixincludes/fixincl.x.jj	2022-03-01 19:42:39.169265091 +0100
+++ fixincludes/fixincl.x	2022-09-11 20:09:37.668565341 +0200
@@ -2,11 +2,11 @@
  *
  * DO NOT EDIT THIS FILE   (fixincl.x)
  *
- * It has been AutoGen-ed  February 27, 2022 at 07:47:03 PM by AutoGen 5.18.16
+ * It has been AutoGen-ed  September 11, 2022 at 08:09:37 PM by AutoGen 5.18.16
  * From the definitions    inclhack.def
  * and the template file   fixincl
  */
-/* DO NOT SVN-MERGE THIS FILE, EITHER Sun Feb 27 19:47:03 UTC 2022
+/* DO NOT SVN-MERGE THIS FILE, EITHER Sun Sep 11 20:09:37 CEST 2022
  *
  * You must regenerate it.  Use the ./genfixes script.
  *
@@ -15,7 +15,7 @@
  * certain ANSI-incompatible system header files which are fixed to work
  * correctly with ANSI C and placed in a directory that GNU C will search.
  *
- * This file contains 267 fixup descriptions.
+ * This file contains 270 fixup descriptions.
  *
  * See README for more information.
  *
@@ -4107,6 +4107,132 @@ static const char* apzGlibc_C99_Inline_4
 
 /* * * * * * * * * * * * * * * * * * * * * * * * * *
  *
+ *  Description of Glibc_Cxx_Floatn_1 fix
+ */
+tSCC zGlibc_Cxx_Floatn_1Name[] =
+     "glibc_cxx_floatn_1";
+
+/*
+ *  File name selection pattern
+ */
+tSCC zGlibc_Cxx_Floatn_1List[] =
+  "bits/floatn.h\0bits/floatn-common.h\0";
+/*
+ *  Machine/OS name selection pattern
+ */
+#define apzGlibc_Cxx_Floatn_1Machs (const char**)NULL
+
+/*
+ *  content selection pattern - do fix if pattern found
+ */
+tSCC zGlibc_Cxx_Floatn_1Select0[] =
+       "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\
+(([ \t]*/\\*[^\n\
+]*\\*/\n\
+)?([ \t]*#[ \t]*if[^\n\
+]*\n\
+)?[ \t]*#[ \t]*define __f(16|32|64|128)\\()";
+
+#define    GLIBC_CXX_FLOATN_1_TEST_CT  1
+static tTestDesc aGlibc_Cxx_Floatn_1Tests[] = {
+  { TT_EGREP,    zGlibc_Cxx_Floatn_1Select0, (regex_t*)NULL }, };
+
+/*
+ *  Fix Command Arguments for Glibc_Cxx_Floatn_1
+ */
+static const char* apzGlibc_Cxx_Floatn_1Patch[] = {
+    "format",
+    "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n\
+%2",
+    (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Description of Glibc_Cxx_Floatn_2 fix
+ */
+tSCC zGlibc_Cxx_Floatn_2Name[] =
+     "glibc_cxx_floatn_2";
+
+/*
+ *  File name selection pattern
+ */
+tSCC zGlibc_Cxx_Floatn_2List[] =
+  "bits/floatn.h\0bits/floatn-common.h\0";
+/*
+ *  Machine/OS name selection pattern
+ */
+#define apzGlibc_Cxx_Floatn_2Machs (const char**)NULL
+
+/*
+ *  content selection pattern - do fix if pattern found
+ */
+tSCC zGlibc_Cxx_Floatn_2Select0[] =
+       "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\
+(([ \t]*/\\*[^\n\
+]*\\*/\n\
+)?[ \t]*typedef[ \t]+[^\n\
+]*[ \t]+_Float(16|32|64|128)([ \t]+__attribute__ \\(\\(__mode__ \\(__HF__\\)\\)\\))?;)";
+
+#define    GLIBC_CXX_FLOATN_2_TEST_CT  1
+static tTestDesc aGlibc_Cxx_Floatn_2Tests[] = {
+  { TT_EGREP,    zGlibc_Cxx_Floatn_2Select0, (regex_t*)NULL }, };
+
+/*
+ *  Fix Command Arguments for Glibc_Cxx_Floatn_2
+ */
+static const char* apzGlibc_Cxx_Floatn_2Patch[] = {
+    "format",
+    "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n\
+%2",
+    (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
+ *  Description of Glibc_Cxx_Floatn_3 fix
+ */
+tSCC zGlibc_Cxx_Floatn_3Name[] =
+     "glibc_cxx_floatn_3";
+
+/*
+ *  File name selection pattern
+ */
+tSCC zGlibc_Cxx_Floatn_3List[] =
+  "bits/floatn.h\0bits/floatn-common.h\0";
+/*
+ *  Machine/OS name selection pattern
+ */
+#define apzGlibc_Cxx_Floatn_3Machs (const char**)NULL
+
+/*
+ *  content selection pattern - do fix if pattern found
+ */
+tSCC zGlibc_Cxx_Floatn_3Select0[] =
+       "^([ \t]*#[ \t]*if !__GNUC_PREREQ \\(7, 0\\) \\|\\| )defined __cplusplus\n\
+(([ \t]*/\\*[^\n\
+]*\n\
+?[^\n\
+]*\\*/\n\
+)?([ \t]*#[ \t]*if[^\n\
+]*\n\
+)?([ \t]*typedef[ \t]+[^\n\
+]*;\n\
+)?[ \t]*#[ \t]*define __CFLOAT(16|32|64|128)[ \t]+)";
+
+#define    GLIBC_CXX_FLOATN_3_TEST_CT  1
+static tTestDesc aGlibc_Cxx_Floatn_3Tests[] = {
+  { TT_EGREP,    zGlibc_Cxx_Floatn_3Select0, (regex_t*)NULL }, };
+
+/*
+ *  Fix Command Arguments for Glibc_Cxx_Floatn_3
+ */
+static const char* apzGlibc_Cxx_Floatn_3Patch[] = {
+    "format",
+    "%1(defined __cplusplus && !__GNUC_PREREQ (13, 1) && defined __FLT32X_MANT_DIG__)\n\
+%2",
+    (char*)NULL };
+
+/* * * * * * * * * * * * * * * * * * * * * * * * * *
+ *
  *  Description of Glibc_Mutex_Init fix
  */
 tSCC zGlibc_Mutex_InitName[] =
@@ -10872,9 +10998,9 @@ static const char* apzX11_SprintfPatch[]
  *
  *  List of all fixes
  */
-#define REGEX_COUNT          305
+#define REGEX_COUNT          308
 #define MACH_LIST_SIZE_LIMIT 187
-#define FIX_COUNT            267
+#define FIX_COUNT            270
 
 /*
  *  Enumerate the fixes
@@ -10977,6 +11103,9 @@ typedef enum {
     GLIBC_C99_INLINE_2_FIXIDX,
     GLIBC_C99_INLINE_3_FIXIDX,
     GLIBC_C99_INLINE_4_FIXIDX,
+    GLIBC_CXX_FLOATN_1_FIXIDX,
+    GLIBC_CXX_FLOATN_2_FIXIDX,
+    GLIBC_CXX_FLOATN_3_FIXIDX,
     GLIBC_MUTEX_INIT_FIXIDX,
     GLIBC_STDINT_FIXIDX,
     GLIBC_STRNCPY_FIXIDX,
@@ -11635,6 +11764,21 @@ tFixDesc fixDescList[ FIX_COUNT ] = {
      GLIBC_C99_INLINE_4_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
      aGlibc_C99_Inline_4Tests,   apzGlibc_C99_Inline_4Patch, 0 },
 
+  {  zGlibc_Cxx_Floatn_1Name,    zGlibc_Cxx_Floatn_1List,
+     apzGlibc_Cxx_Floatn_1Machs,
+     GLIBC_CXX_FLOATN_1_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+     aGlibc_Cxx_Floatn_1Tests,   apzGlibc_Cxx_Floatn_1Patch, 0 },
+
+  {  zGlibc_Cxx_Floatn_2Name,    zGlibc_Cxx_Floatn_2List,
+     apzGlibc_Cxx_Floatn_2Machs,
+     GLIBC_CXX_FLOATN_2_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+     aGlibc_Cxx_Floatn_2Tests,   apzGlibc_Cxx_Floatn_2Patch, 0 },
+
+  {  zGlibc_Cxx_Floatn_3Name,    zGlibc_Cxx_Floatn_3List,
+     apzGlibc_Cxx_Floatn_3Machs,
+     GLIBC_CXX_FLOATN_3_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE,
+     aGlibc_Cxx_Floatn_3Tests,   apzGlibc_Cxx_Floatn_3Patch, 0 },
+
   {  zGlibc_Mutex_InitName,    zGlibc_Mutex_InitList,
      apzGlibc_Mutex_InitMachs,
      GLIBC_MUTEX_INIT_TEST_CT, FD_MACH_ONLY,
