aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r--gcc/cp/tree.c171
1 files changed, 131 insertions, 40 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 3acb643..3c62dd7 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -450,11 +450,17 @@ builtin_valid_in_constant_expr_p (const_tree decl)
return false;
if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL)
{
- if (fndecl_built_in_p (decl, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
- BUILT_IN_FRONTEND)
- || fndecl_built_in_p (decl, CP_BUILT_IN_SOURCE_LOCATION,
- BUILT_IN_FRONTEND))
- return true;
+ if (fndecl_built_in_p (decl, BUILT_IN_FRONTEND))
+ switch (DECL_FE_FUNCTION_CODE (decl))
+ {
+ case CP_BUILT_IN_IS_CONSTANT_EVALUATED:
+ case CP_BUILT_IN_SOURCE_LOCATION:
+ case CP_BUILT_IN_IS_CORRESPONDING_MEMBER:
+ case CP_BUILT_IN_IS_POINTER_INTERCONVERTIBLE_WITH_CLASS:
+ return true;
+ default:
+ break;
+ }
/* Not a built-in. */
return false;
}
@@ -843,21 +849,22 @@ tree
build_target_expr_with_type (tree init, tree type, tsubst_flags_t complain)
{
gcc_assert (!VOID_TYPE_P (type));
+ gcc_assert (!VOID_TYPE_P (TREE_TYPE (init)));
if (TREE_CODE (init) == TARGET_EXPR
|| init == error_mark_node)
return init;
else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type)
- && !VOID_TYPE_P (TREE_TYPE (init))
&& TREE_CODE (init) != COND_EXPR
&& TREE_CODE (init) != CONSTRUCTOR
- && TREE_CODE (init) != VA_ARG_EXPR)
- /* We need to build up a copy constructor call. A void initializer
- means we're being called from bot_manip. COND_EXPR is a special
+ && TREE_CODE (init) != VA_ARG_EXPR
+ && TREE_CODE (init) != CALL_EXPR)
+ /* We need to build up a copy constructor call. COND_EXPR is a special
case because we already have copies on the arms and we don't want
another one here. A CONSTRUCTOR is aggregate initialization, which
is handled separately. A VA_ARG_EXPR is magic creation of an
- aggregate; there's no additional work to be done. */
+ aggregate; there's no additional work to be done. A CALL_EXPR
+ already creates a prvalue. */
return force_rvalue (init, complain);
return force_target_expr (type, init, complain);
@@ -940,7 +947,12 @@ rvalue (tree expr)
/* We need to do this for rvalue refs as well to get the right answer
from decltype; see c++/36628. */
if (!processing_template_decl && glvalue_p (expr))
- expr = build1 (NON_LVALUE_EXPR, type, expr);
+ {
+ /* But don't use this function for class lvalues; use move (to treat an
+ lvalue as an xvalue) or force_rvalue (to make a prvalue copy). */
+ gcc_checking_assert (!CLASS_TYPE_P (type));
+ expr = build1 (NON_LVALUE_EXPR, type, expr);
+ }
else if (type != TREE_TYPE (expr))
expr = build_nop (type, expr);
@@ -1121,7 +1133,7 @@ build_cplus_array_type (tree elt_type, tree index_type, int dependent)
/* Avoid spurious warnings with VLAs (c++/54583). */
if (TYPE_SIZE (t) && EXPR_P (TYPE_SIZE (t)))
- TREE_NO_WARNING (TYPE_SIZE (t)) = 1;
+ suppress_warning (TYPE_SIZE (t), OPT_Wunused);
/* Push these needs up to the ARRAY_TYPE so that initialization takes
place more easily. */
@@ -1201,12 +1213,14 @@ vla_type_p (tree t)
return false;
}
-/* Return a reference type node referring to TO_TYPE. If RVAL is
+
+/* Return a reference type node of MODE referring to TO_TYPE. If MODE
+ is VOIDmode the standard pointer mode will be picked. If RVAL is
true, return an rvalue reference type, otherwise return an lvalue
reference type. If a type node exists, reuse it, otherwise create
a new one. */
tree
-cp_build_reference_type (tree to_type, bool rval)
+cp_build_reference_type_for_mode (tree to_type, machine_mode mode, bool rval)
{
tree lvalue_ref, t;
@@ -1219,7 +1233,8 @@ cp_build_reference_type (tree to_type, bool rval)
to_type = TREE_TYPE (to_type);
}
- lvalue_ref = build_reference_type (to_type);
+ lvalue_ref = build_reference_type_for_mode (to_type, mode, false);
+
if (!rval)
return lvalue_ref;
@@ -1245,7 +1260,7 @@ cp_build_reference_type (tree to_type, bool rval)
SET_TYPE_STRUCTURAL_EQUALITY (t);
else if (TYPE_CANONICAL (to_type) != to_type)
TYPE_CANONICAL (t)
- = cp_build_reference_type (TYPE_CANONICAL (to_type), rval);
+ = cp_build_reference_type_for_mode (TYPE_CANONICAL (to_type), mode, rval);
else
TYPE_CANONICAL (t) = t;
@@ -1255,6 +1270,16 @@ cp_build_reference_type (tree to_type, bool rval)
}
+/* Return a reference type node referring to TO_TYPE. If RVAL is
+ true, return an rvalue reference type, otherwise return an lvalue
+ reference type. If a type node exists, reuse it, otherwise create
+ a new one. */
+tree
+cp_build_reference_type (tree to_type, bool rval)
+{
+ return cp_build_reference_type_for_mode (to_type, VOIDmode, rval);
+}
+
/* Returns EXPR cast to rvalue reference type, like std::move. */
tree
@@ -1556,11 +1581,11 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
{
case POINTER_TYPE:
type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
- result = build_pointer_type (type);
+ result = build_pointer_type_for_mode (type, TYPE_MODE (t), false);
break;
case REFERENCE_TYPE:
type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
- result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
+ result = cp_build_reference_type_for_mode (type, TYPE_MODE (t), TYPE_REF_IS_RVALUE (t));
break;
case OFFSET_TYPE:
t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes, flags);
@@ -1722,6 +1747,20 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
remove_attributes, flags);
result = finish_underlying_type (type);
break;
+ case TYPE_PACK_EXPANSION:
+ {
+ tree pat = PACK_EXPANSION_PATTERN (t);
+ if (TYPE_P (pat))
+ {
+ type = strip_typedefs (pat, remove_attributes, flags);
+ if (type != pat)
+ {
+ result = copy_node (t);
+ PACK_EXPANSION_PATTERN (result) = type;
+ }
+ }
+ }
+ break;
default:
break;
}
@@ -3080,8 +3119,8 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_)
AGGR_INIT_ZERO_FIRST (TREE_OPERAND (u, 1)) = true;
}
else
- u = build_target_expr_with_type (TREE_OPERAND (t, 1), TREE_TYPE (t),
- tf_warning_or_error);
+ u = force_target_expr (TREE_TYPE (t), TREE_OPERAND (t, 1),
+ tf_warning_or_error);
TARGET_EXPR_IMPLICIT_P (u) = TARGET_EXPR_IMPLICIT_P (t);
TARGET_EXPR_LIST_INIT_P (u) = TARGET_EXPR_LIST_INIT_P (t);
@@ -3128,6 +3167,48 @@ bot_manip (tree* tp, int* walk_subtrees, void* data_)
}
return NULL_TREE;
}
+ if (TREE_CODE (*tp) == DECL_EXPR
+ && VAR_P (DECL_EXPR_DECL (*tp))
+ && DECL_ARTIFICIAL (DECL_EXPR_DECL (*tp))
+ && !TREE_STATIC (DECL_EXPR_DECL (*tp)))
+ {
+ tree t;
+ splay_tree_node n
+ = splay_tree_lookup (target_remap,
+ (splay_tree_key) DECL_EXPR_DECL (*tp));
+ if (n)
+ t = (tree) n->value;
+ else
+ {
+ t = create_temporary_var (TREE_TYPE (DECL_EXPR_DECL (*tp)));
+ DECL_INITIAL (t) = DECL_INITIAL (DECL_EXPR_DECL (*tp));
+ splay_tree_insert (target_remap,
+ (splay_tree_key) DECL_EXPR_DECL (*tp),
+ (splay_tree_value) t);
+ }
+ copy_tree_r (tp, walk_subtrees, NULL);
+ DECL_EXPR_DECL (*tp) = t;
+ if (data.clear_location && EXPR_HAS_LOCATION (*tp))
+ SET_EXPR_LOCATION (*tp, input_location);
+ return NULL_TREE;
+ }
+ if (TREE_CODE (*tp) == BIND_EXPR && BIND_EXPR_VARS (*tp))
+ {
+ copy_tree_r (tp, walk_subtrees, NULL);
+ for (tree *p = &BIND_EXPR_VARS (*tp); *p; p = &DECL_CHAIN (*p))
+ {
+ gcc_assert (VAR_P (*p) && DECL_ARTIFICIAL (*p) && !TREE_STATIC (*p));
+ tree t = create_temporary_var (TREE_TYPE (*p));
+ DECL_INITIAL (t) = DECL_INITIAL (*p);
+ DECL_CHAIN (t) = DECL_CHAIN (*p);
+ splay_tree_insert (target_remap, (splay_tree_key) *p,
+ (splay_tree_value) t);
+ *p = t;
+ }
+ if (data.clear_location && EXPR_HAS_LOCATION (*tp))
+ SET_EXPR_LOCATION (*tp, input_location);
+ return NULL_TREE;
+ }
/* Make a copy of this node. */
t = copy_tree_r (tp, walk_subtrees, NULL);
@@ -3167,15 +3248,11 @@ bot_replace (tree* t, int* /*walk_subtrees*/, void* data_)
else if (TREE_CODE (*t) == CONVERT_EXPR
&& CONVERT_EXPR_VBASE_PATH (*t))
{
- /* In an NSDMI build_base_path defers building conversions to virtual
- bases, and we handle it here. */
- tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (*t)));
- vec<tree, va_gc> *vbases = CLASSTYPE_VBASECLASSES (current_class_type);
- int i; tree binfo;
- FOR_EACH_VEC_SAFE_ELT (vbases, i, binfo)
- if (BINFO_TYPE (binfo) == basetype)
- break;
- *t = build_base_path (PLUS_EXPR, TREE_OPERAND (*t, 0), binfo, true,
+ /* In an NSDMI build_base_path defers building conversions to morally
+ virtual bases, and we handle it here. */
+ tree basetype = TREE_TYPE (*t);
+ *t = convert_to_base (TREE_OPERAND (*t, 0), basetype,
+ /*check_access=*/false, /*nonnull=*/true,
tf_warning_or_error);
}
@@ -4124,7 +4201,8 @@ member_p (const_tree decl)
}
/* Create a placeholder for member access where we don't actually have an
- object that the access is against. */
+ object that the access is against. For a general declval<T> equivalent,
+ use build_stub_object instead. */
tree
build_dummy_object (tree type)
@@ -4629,20 +4707,26 @@ zero_init_expr_p (tree t)
tree type = TREE_TYPE (t);
if (!type || uses_template_parms (type))
return false;
- if (zero_init_p (type))
- return initializer_zerop (t);
if (TYPE_PTRMEM_P (type))
return null_member_pointer_value_p (t);
- if (TREE_CODE (t) == CONSTRUCTOR
- && CP_AGGREGATE_TYPE_P (type))
+ if (TREE_CODE (t) == CONSTRUCTOR)
{
- tree elt_init;
- unsigned HOST_WIDE_INT i;
- FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (t), i, elt_init)
- if (!zero_init_expr_p (elt_init))
- return false;
+ if (COMPOUND_LITERAL_P (t)
+ || BRACE_ENCLOSED_INITIALIZER_P (t))
+ /* Undigested, conversions might change the zeroness. */
+ return false;
+ for (constructor_elt &elt : CONSTRUCTOR_ELTS (t))
+ {
+ if (TREE_CODE (type) == UNION_TYPE
+ && elt.index != first_field (type))
+ return false;
+ if (!zero_init_expr_p (elt.value))
+ return false;
+ }
return true;
}
+ if (zero_init_p (type))
+ return initializer_zerop (t);
return false;
}
@@ -5303,7 +5387,9 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
// walk the parameter list. Doing so causes false
// positives in the pack expansion checker since the
// requires parameters are introduced as pack expansions.
- WALK_SUBTREE (TREE_OPERAND (*tp, 1));
+ ++cp_unevaluated_operand;
+ result = cp_walk_tree (&REQUIRES_EXPR_REQS (*tp), func, data, pset);
+ --cp_unevaluated_operand;
*walk_subtrees_p = 0;
break;
@@ -5364,6 +5450,11 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
}
break;
+ case STATIC_ASSERT:
+ WALK_SUBTREE (STATIC_ASSERT_CONDITION (*tp));
+ WALK_SUBTREE (STATIC_ASSERT_MESSAGE (*tp));
+ break;
+
default:
return NULL_TREE;
}