Skip to content

Commit 94d3089

Browse files
committed
Now has std::contains_mutable
1 parent 38ab55d commit 94d3089

File tree

4 files changed

+96
-0
lines changed

4 files changed

+96
-0
lines changed

gcc/cp/constraint.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,6 +3087,9 @@ diagnose_trait_expr (location_t loc, tree expr, tree args)
30873087

30883088
switch (TRAIT_EXPR_KIND (expr))
30893089
{
3090+
case CPTK_CONTAINS_MUTABLE:
3091+
// Pure boolean trait; diagnostics are handled by the enclosing constraint.
3092+
break;
30903093
case CPTK_GET_POLYMORPHIC_FACILITATOR:
30913094
/* Never gives a compiler error for any type *
30923095
* because it returns a nullptr if the type *

gcc/cp/cp-trait.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
DEFTRAIT_TYPE (ADD_LVALUE_REFERENCE, "__add_lvalue_reference", 1)
5252
DEFTRAIT_TYPE (ADD_POINTER, "__add_pointer", 1)
5353
DEFTRAIT_TYPE (ADD_RVALUE_REFERENCE, "__add_rvalue_reference", 1)
54+
DEFTRAIT_EXPR (CONTAINS_MUTABLE, "__builtin_contains_mutable", 1)
5455
DEFTRAIT_TYPE (DECAY, "__decay", 1)
5556
DEFTRAIT_EXPR (GET_POLYMORPHIC_FACILITATOR, "__builtin_get_polymorphic_facilitator", 1)
5657
DEFTRAIT_EXPR (HAS_NOTHROW_ASSIGN, "__has_nothrow_assign", 1)

gcc/cp/semantics.cc

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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;

libstdc++-v3/include/std/type_traits

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4690,6 +4690,19 @@ template<typename _Ret, typename _Fn, typename... _Args>
46904690
constexpr auto cw = constant_wrapper<_Tp>{};
46914691
#endif
46924692

4693+
#if __cplusplus >= 201103L
4694+
/// Determine if a type contains any mutable objects
4695+
template<typename _Tp>
4696+
struct contains_mutable
4697+
: integral_constant<bool, __builtin_contains_mutable(_Tp)>
4698+
{ };
4699+
4700+
# if __cplusplus >= 201402L
4701+
template<typename _Tp>
4702+
constexpr bool contains_mutable_v = contains_mutable<_Tp>::value;
4703+
# endif
4704+
#endif // if __cplusplus >= 201103L
4705+
46934706
/// @} group metaprogramming
46944707

46954708
_GLIBCXX_END_NAMESPACE_VERSION

0 commit comments

Comments
 (0)