@@ -13740,6 +13740,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
1374013740 case CPTK_TYPE_ORDER:
1374113741 case CPTK_STRUCTURED_BINDING_SIZE:
1374213742 case CPTK_GET_POLYMORPHIC_FACILITATOR:
13743+ case CPTK_CONTAINS_MUTABLE:
1374313744 gcc_unreachable ();
1374413745
1374513746#define DEFTRAIT_TYPE (CODE, NAME, ARITY ) \
@@ -13889,6 +13890,10 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
1388913890 {
1389013891 TREE_TYPE (trait_expr) = const_ptr_type_node; // void const *
1389113892 }
13893+ else if (kind == CPTK_CONTAINS_MUTABLE)
13894+ {
13895+ TREE_TYPE (trait_expr) = boolean_type_node; // bool
13896+ }
1389213897 else
1389313898 TREE_TYPE (trait_expr) = boolean_type_node;
1389413899 TRAIT_EXPR_TYPE1 (trait_expr) = type1;
@@ -13900,6 +13905,80 @@ finish_trait_expr (location_t loc, cp_trait_kind kind, tree type1, tree type2)
1390013905
1390113906 switch (kind)
1390213907 {
13908+ case CPTK_CONTAINS_MUTABLE:
13909+ {
13910+ tree type = type1;
13911+
13912+ /* Reference types are treated as having no mutable subobjects. */
13913+ if (TYPE_REF_P (type))
13914+ return boolean_false_node;
13915+
13916+ /* Strip cv-qualifiers and get the main variant. */
13917+ type = cv_unqualified (TYPE_MAIN_VARIANT (type));
13918+
13919+ /* Only class/union types can contain mutable members. */
13920+ if (!CLASS_TYPE_P (type))
13921+ return boolean_false_node;
13922+
13923+ /* Ensure we have a complete type. */
13924+ if (complete_type_or_else (type, NULL_TREE) == error_mark_node)
13925+ return boolean_false_node;
13926+
13927+ /* Worklist of types to visit (this type, its bases, and
13928+ any member subobject types). */
13929+ auto_vec<tree, 8 > worklist;
13930+ worklist.safe_push (type);
13931+
13932+ while (!worklist.is_empty ())
13933+ {
13934+ tree t = worklist.pop ();
13935+ t = cv_unqualified (TYPE_MAIN_VARIANT (t));
13936+
13937+ /* Check non-static data members. */
13938+ for (tree fld = TYPE_FIELDS (t); fld; fld = DECL_CHAIN (fld))
13939+ {
13940+ if (TREE_CODE (fld) != FIELD_DECL)
13941+ continue ;
13942+
13943+ if (DECL_MUTABLE_P (fld))
13944+ return boolean_true_node;
13945+
13946+ tree ftype = TREE_TYPE (fld);
13947+ ftype = cv_unqualified (TYPE_MAIN_VARIANT (ftype));
13948+
13949+ if (TREE_CODE (ftype) == ARRAY_TYPE)
13950+ {
13951+ tree elem = TREE_TYPE (ftype);
13952+ elem = cv_unqualified (TYPE_MAIN_VARIANT (elem));
13953+ if (CLASS_TYPE_P (elem))
13954+ worklist.safe_push (elem);
13955+ }
13956+ else if (CLASS_TYPE_P (ftype))
13957+ worklist.safe_push (ftype);
13958+ }
13959+
13960+ /* Check direct base classes. */
13961+ tree binfo = TYPE_BINFO (t);
13962+ if (!binfo)
13963+ continue ;
13964+
13965+ int nbases = BINFO_N_BASE_BINFOS (binfo);
13966+ for (int i = 0 ; i < nbases; ++i)
13967+ {
13968+ tree base_binfo = BINFO_BASE_BINFO (binfo, i);
13969+ tree btype = BINFO_TYPE (base_binfo);
13970+ btype = cv_unqualified (TYPE_MAIN_VARIANT (btype));
13971+
13972+ if (CLASS_TYPE_P (btype))
13973+ worklist.safe_push (btype);
13974+ }
13975+ }
13976+
13977+ /* No mutable members found anywhere in the hierarchy. */
13978+ return boolean_false_node;
13979+ }
13980+ break ;
13981+
1390313982 case CPTK_GET_POLYMORPHIC_FACILITATOR:
1390413983 {
1390513984 tree type = type1;
0 commit comments