diff options
Diffstat (limited to 'gcc/cp/semantics.c')
-rw-r--r-- | gcc/cp/semantics.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 17b1e5dee49..3bcab9407d4 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-iterator.h" #include "vec.h" #include "target.h" +#include "gimple.h" /* There routines provide a modular interface to perform many parsing operations. They may therefore be used during actual parsing, or @@ -3201,6 +3202,8 @@ expand_or_defer_fn (tree fn) return; } + gcc_assert (gimple_body (fn)); + /* Replace AGGR_INIT_EXPRs with appropriate CALL_EXPRs. */ cp_walk_tree_without_duplicates (&DECL_SAVED_TREE (fn), simplify_aggr_init_exprs_r, @@ -4472,7 +4475,7 @@ tree finish_decltype_type (tree expr, bool id_expression_or_member_access_p) { tree orig_expr = expr; - tree type; + tree type = NULL_TREE; if (!expr || error_operand_p (expr)) return error_mark_node; @@ -4583,8 +4586,6 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) } else { - tree fndecl; - /* Expressions of reference type are sometimes wrapped in INDIRECT_REFs. INDIRECT_REFs are just internal compiler representation, not part of the language, so we have to look @@ -4594,14 +4595,28 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p) == REFERENCE_TYPE) expr = TREE_OPERAND (expr, 0); - if (TREE_CODE (expr) == CALL_EXPR - && (fndecl = get_callee_fndecl (expr)) - && (fndecl != error_mark_node)) - /* If e is a function call (5.2.2 [expr.call]) or an + if (TREE_CODE (expr) == CALL_EXPR) + { + /* If e is a function call (5.2.2 [expr.call]) or an invocation of an overloaded operator (parentheses around e are ignored), decltype(e) is defined as the return type of that function. */ - type = TREE_TYPE (TREE_TYPE (fndecl)); + tree fndecl = get_callee_fndecl (expr); + if (fndecl && fndecl != error_mark_node) + type = TREE_TYPE (TREE_TYPE (fndecl)); + else + { + tree target_type = TREE_TYPE (CALL_EXPR_FN (expr)); + if ((TREE_CODE (target_type) == REFERENCE_TYPE + || TREE_CODE (target_type) == POINTER_TYPE) + && (TREE_CODE (TREE_TYPE (target_type)) == FUNCTION_TYPE + || TREE_CODE (TREE_TYPE (target_type)) == METHOD_TYPE)) + type = TREE_TYPE (TREE_TYPE (target_type)); + else + sorry ("unable to determine the declared type of expression %<%E%>", + expr); + } + } else { type = is_bitfield_expr_with_lowered_type (expr); @@ -4677,8 +4692,20 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p) return false; for (; fns; fns = OVL_NEXT (fns)) - if (!TREE_NOTHROW (OVL_CURRENT (fns))) - return false; + { + tree fn = OVL_CURRENT (fns); + + if (assign_p) + { + if (copy_fn_p (fn) == 0) + continue; + } + else if (copy_fn_p (fn) <= 0) + continue; + + if (!TYPE_NOTHROW_P (TREE_TYPE (fn))) + return false; + } return true; } @@ -4712,7 +4739,8 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) type1 = strip_array_types (type1); return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) || (CLASS_TYPE_P (type1) - && (t = locate_ctor (type1, NULL)) && TREE_NOTHROW (t))); + && (t = locate_ctor (type1, NULL)) + && TYPE_NOTHROW_P (TREE_TYPE (t)))); case CPTK_HAS_TRIVIAL_CONSTRUCTOR: type1 = strip_array_types (type1); @@ -4730,7 +4758,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_HAS_TRIVIAL_DESTRUCTOR: type1 = strip_array_types (type1); - return (pod_type_p (type1) + return (pod_type_p (type1) || type_code1 == REFERENCE_TYPE || (CLASS_TYPE_P (type1) && TYPE_HAS_TRIVIAL_DESTRUCTOR (type1))); |