From 01f9e964bd55fd0f52f4a084f70ee7a5e071cfa9 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 5 Jul 2001 11:39:36 -0400 Subject: [PATCH] cvt.c (convert_lvalue): New fn. * cvt.c (convert_lvalue): New fn. * cp-tree.h: Declare it. * method.c (do_build_assign_ref): Use it. (do_build_copy_constructor): Convert parm to base types before calling base constructors. * typeck.c (check_return_expr): Check DECL_ALIGN instead of DECL_USER_ALIGN. Check flag_elide_constructors instead of optimize. * semantics.c (cp_expand_stmt): Don't destroy the named return value. From-SVN: r43780 --- gcc/cp/ChangeLog | 13 +++++++++++++ gcc/cp/cp-tree.h | 1 + gcc/cp/cvt.c | 14 ++++++++++++++ gcc/cp/method.c | 27 ++++++++++++++------------- gcc/cp/semantics.c | 4 +++- gcc/cp/typeck.c | 5 +++-- 6 files changed, 48 insertions(+), 16 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index dfe82c029f8..5e6195cf532 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,16 @@ +2001-07-05 Jason Merrill + + * cvt.c (convert_lvalue): New fn. + * cp-tree.h: Declare it. + * method.c (do_build_assign_ref): Use it. + (do_build_copy_constructor): Convert parm to base types + before calling base constructors. + + * typeck.c (check_return_expr): Check DECL_ALIGN instead of + DECL_USER_ALIGN. Check flag_elide_constructors instead of + optimize. + * semantics.c (cp_expand_stmt): Don't destroy the named return value. + 2001-07-02 Nathan Sidwell * optimize.c (optimize_inline_calls): New function, broken out diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index cebc9262354..2ccb3b71655 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3735,6 +3735,7 @@ extern tree get_primary_binfo PARAMS ((tree)); /* in cvt.c */ extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree)); extern tree convert_from_reference PARAMS ((tree)); +extern tree convert_lvalue PARAMS ((tree, tree)); extern tree convert_pointer_to_real PARAMS ((tree, tree)); extern tree convert_pointer_to PARAMS ((tree, tree)); extern tree ocp_convert PARAMS ((tree, tree, int, int)); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 1dff9e5aadf..33be568ed14 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -597,6 +597,20 @@ convert_from_reference (val) return build_indirect_ref (val, NULL); return val; } + +/* Implicitly convert the lvalue EXPR to another lvalue of type TOTYPE, + preserving cv-qualification. */ + +tree +convert_lvalue (totype, expr) + tree totype, expr; +{ + totype = cp_build_qualified_type (totype, TYPE_QUALS (TREE_TYPE (expr))); + totype = build_reference_type (totype); + expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL, + NULL_TREE); + return convert_from_reference (expr); +} /* Call this when we know (for any reason) that expr is not, in fact, zero. This routine is like convert_pointer_to, but it pays diff --git a/gcc/cp/method.c b/gcc/cp/method.c index ceb569c70d7..6f6a14b53a3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -557,25 +557,31 @@ do_build_copy_constructor (fndecl) int cvquals = CP_TYPE_QUALS (TREE_TYPE (parm)); int i; - /* Initialize all the base-classes. */ + /* Initialize all the base-classes with the parameter converted to + their type so that we get their copy constructor and not another + constructor that takes current_class_type. */ for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; t = TREE_CHAIN (t)) - base_init_list - = tree_cons (BINFO_TYPE (TREE_VALUE (t)), parm, - base_init_list); + { + tree type = BINFO_TYPE (TREE_VALUE (t)); + base_init_list = tree_cons (type, convert_lvalue (type, parm), + base_init_list); + } + for (i = 0; i < n_bases; ++i) { t = TREE_VEC_ELT (binfos, i); if (TREE_VIA_VIRTUAL (t)) continue; - base_init_list - = tree_cons (BINFO_TYPE (t), parm, base_init_list); + t = BINFO_TYPE (t); + base_init_list = tree_cons (t, convert_lvalue (t, parm), + base_init_list); } for (; fields; fields = TREE_CHAIN (fields)) { - tree init, t; + tree init; tree field = fields; if (TREE_CODE (field) != FIELD_DECL) @@ -645,12 +651,7 @@ do_build_assign_ref (fndecl) for (i = 0; i < n_bases; ++i) { tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); - tree p = build_qualified_type (basetype, cvquals); - - p = convert_to_reference - (build_reference_type (p), parm, - CONV_IMPLICIT, LOOKUP_COMPLAIN, NULL_TREE); - p = convert_from_reference (p); + tree p = convert_lvalue (basetype, parm); p = build_member_call (basetype, ansi_assopname (NOP_EXPR), build_tree_list (NULL_TREE, p)); finish_expr_stmt (p); diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 050e1be314c..66f36ab2c5c 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2156,7 +2156,9 @@ cp_expand_stmt (t) switch (TREE_CODE (t)) { case CLEANUP_STMT: - genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t)); + /* Don't destroy the chosen named return value. */ + if (CLEANUP_DECL (t) != current_function_return_value) + genrtl_decl_cleanup (CLEANUP_DECL (t), CLEANUP_EXPR (t)); break; case CTOR_STMT: diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index cb1146ef7d3..43f38f3e1de 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -6684,7 +6684,7 @@ check_return_expr (retval) returned expression uses the chosen variable somehow. And people expect this restriction, anyway. (jason 2000-11-19) */ - if (fn_returns_value_p && optimize) + if (fn_returns_value_p && flag_elide_constructors) { if (retval != NULL_TREE && (current_function_return_value == NULL_TREE @@ -6692,7 +6692,8 @@ check_return_expr (retval) && TREE_CODE (retval) == VAR_DECL && DECL_CONTEXT (retval) == current_function_decl && ! TREE_STATIC (retval) - && ! DECL_USER_ALIGN (retval) + && (DECL_ALIGN (retval) + == DECL_ALIGN (DECL_RESULT (current_function_decl))) && same_type_p (TREE_TYPE (retval), TREE_TYPE (TREE_TYPE (current_function_decl)))) current_function_return_value = retval; -- 2.30.2