X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Fsemantics.c;h=e0c1c1f8de47524899456c517662faf4ddad2a66;hb=6e6e37a11f857096a9d81a8a59f9cb031aab4ca8;hp=89c76d5a12645cca62bd8549b833ff0cf9ec0025;hpb=d4a724ce3b2c29d41537566d96de9b654d416832;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 89c76d5a126..e0c1c1f8de4 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -4,7 +4,7 @@ and during the instantiation of template functions. Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, - 2008, 2009, 2010, 2011 Free Software Foundation, Inc. + 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. Written by Mark Mitchell (mmitchell@usa.net) based on code found formerly in parse.y and pt.c. @@ -33,7 +33,7 @@ along with GCC; see the file COPYING3. If not see #include "c-family/c-common.h" #include "c-family/c-objc.h" #include "tree-inline.h" -#include "tree-mudflap.h" +#include "intl.h" #include "toplev.h" #include "flags.h" #include "output.h" @@ -423,7 +423,7 @@ maybe_cleanup_point_expr (tree expr) expression. The reason why we do this is because the original type might be an aggregate and we cannot create a temporary variable for that type. */ -static tree +tree maybe_cleanup_point_expr_void (tree expr) { if (!processing_template_decl && stmts_are_full_exprs_p ()) @@ -994,6 +994,15 @@ finish_range_for_decl (tree range_for_stmt, tree decl, tree expr) tree finish_break_stmt (void) { + /* In switch statements break is sometimes stylistically used after + a return statement. This can lead to spurious warnings about + control reaching the end of a non-void function when it is + inlined. Note that we are calling block_may_fallthru with + language specific tree nodes; this works because + block_may_fallthru returns true when given something it does not + understand. */ + if (!block_may_fallthru (cur_stmt_list)) + return void_zero_node; return add_stmt (build_stmt (input_location, BREAK_STMT)); } @@ -1561,9 +1570,7 @@ finish_non_static_data_member (tree decl, tree object, tree qualifying_scope) else { /* Set the cv qualifiers. */ - int quals = (current_class_ref - ? cp_type_quals (TREE_TYPE (current_class_ref)) - : TYPE_UNQUALIFIED); + int quals = cp_type_quals (TREE_TYPE (object)); if (DECL_MUTABLE_P (decl)) quals &= ~TYPE_QUAL_CONST; @@ -2312,19 +2319,6 @@ tree finish_unary_op_expr (enum tree_code code, tree expr) { tree result = build_x_unary_op (code, expr, tf_warning_or_error); - /* Inside a template, build_x_unary_op does not fold the - expression. So check whether the result is folded before - setting TREE_NEGATED_INT. */ - if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST - && TREE_CODE (result) == INTEGER_CST - && !TYPE_UNSIGNED (TREE_TYPE (result)) - && INT_CST_LT (result, integer_zero_node)) - { - /* RESULT may be a cached INTEGER_CST, so we must copy it before - setting TREE_NEGATED_INT. */ - result = copy_node (result); - TREE_NEGATED_INT (result) = 1; - } if (TREE_OVERFLOW_P (result) && !TREE_OVERFLOW_P (expr)) overflow_warning (input_location, result); @@ -2381,8 +2375,9 @@ finish_compound_literal (tree type, tree compound_literal, && check_array_initializer (NULL_TREE, type, compound_literal)) return error_mark_node; compound_literal = reshape_init (type, compound_literal, complain); - if (cxx_dialect >= cxx0x && SCALAR_TYPE_P (type) - && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal)) + if (SCALAR_TYPE_P (type) + && !BRACE_ENCLOSED_INITIALIZER_P (compound_literal) + && (complain & tf_warning_or_error)) check_narrowing (type, compound_literal); if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == NULL_TREE) @@ -2518,7 +2513,7 @@ check_template_template_default_arg (tree argument) /* Begin a class definition, as indicated by T. */ tree -begin_class_definition (tree t, tree attributes) +begin_class_definition (tree t) { if (error_operand_p (t) || error_operand_p (TYPE_MAIN_DECL (t))) return error_mark_node; @@ -2575,9 +2570,6 @@ begin_class_definition (tree t, tree attributes) pushclass (t); TYPE_BEING_DEFINED (t) = 1; - cplus_decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE); - fixup_attribute_variants (t); - if (flag_pack_struct) { tree v; @@ -2670,9 +2662,15 @@ finish_member_declaration (tree decl) } } /* Enter the DECL into the scope of the class. */ - else if ((TREE_CODE (decl) == USING_DECL && !DECL_DEPENDENT_P (decl)) - || pushdecl_class_level (decl)) + else if (pushdecl_class_level (decl)) { + if (TREE_CODE (decl) == USING_DECL) + { + /* For now, ignore class-scope USING_DECLS, so that + debugging backends do not see them. */ + DECL_IGNORED_P (decl) = 1; + } + /* All TYPE_DECLs go at the end of TYPE_FIELDS. Ordinary fields go at the beginning. The reason is that lookup_field_1 searches the list in order, and we want a field name to @@ -2745,15 +2743,17 @@ finish_template_decl (tree parms) tree finish_template_type (tree name, tree args, int entering_scope) { - tree decl; + tree type; - decl = lookup_template_class (name, args, + type = lookup_template_class (name, args, NULL_TREE, NULL_TREE, entering_scope, tf_warning_or_error | tf_user); - if (decl != error_mark_node) - decl = TYPE_STUB_DECL (decl); - - return decl; + if (type == error_mark_node) + return type; + else if (CLASS_TYPE_P (type) && !alias_type_or_template_p (type)) + return TYPE_STUB_DECL (type); + else + return TYPE_NAME (type); } /* Finish processing a BASE_CLASS with the indicated ACCESS_SPECIFIER. @@ -2802,39 +2802,44 @@ finish_base_specifier (tree base, tree access, bool virtual_p) tree baselink_for_fns (tree fns) { - tree fn; + tree scope; tree cl; if (BASELINK_P (fns) || error_operand_p (fns)) return fns; - - fn = fns; - if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) - fn = TREE_OPERAND (fn, 0); - fn = get_first_fn (fn); - if (!DECL_FUNCTION_MEMBER_P (fn)) + + scope = ovl_scope (fns); + if (!CLASS_TYPE_P (scope)) return fns; - cl = currently_open_derived_class (DECL_CONTEXT (fn)); + cl = currently_open_derived_class (scope); if (!cl) - cl = DECL_CONTEXT (fn); + cl = scope; cl = TYPE_BINFO (cl); return build_baselink (cl, cl, fns, /*optype=*/NULL_TREE); } -/* Returns true iff DECL is an automatic variable from a function outside +/* Returns true iff DECL is a variable from a function outside the current one. */ static bool -outer_automatic_var_p (tree decl) +outer_var_p (tree decl) { return ((TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL) && DECL_FUNCTION_SCOPE_P (decl) - && !TREE_STATIC (decl) && DECL_CONTEXT (decl) != current_function_decl); } +/* As above, but also checks that DECL is automatic. */ + +static bool +outer_automatic_var_p (tree decl) +{ + return (outer_var_p (decl) + && !TREE_STATIC (decl)); +} + /* ID_EXPRESSION is a representation of parsed, but unprocessed, id-expression. (See cp_parser_id_expression for details.) SCOPE, if non-NULL, is the type or namespace used to explicitly qualify @@ -2883,6 +2888,8 @@ finish_id_expression (tree id_expression, const char **error_msg, location_t location) { + decl = strip_using_decl (decl); + /* Initialize the output parameters. */ *idk = CP_ID_KIND_NONE; *error_msg = NULL; @@ -2939,9 +2946,18 @@ finish_id_expression (tree id_expression, /* Disallow uses of local variables from containing functions, except within lambda-expressions. */ - if (outer_automatic_var_p (decl) + if (!outer_var_p (decl) /* It's not a use (3.2) if we're in an unevaluated context. */ - && !cp_unevaluated_operand) + || cp_unevaluated_operand) + /* OK. */; + else if (TREE_STATIC (decl)) + { + if (processing_template_decl) + /* For a use of an outer static var, return the identifier so + that we'll look it up again in the instantiation. */ + return id_expression; + } + else { tree context = DECL_CONTEXT (decl); tree containing_function = current_function_decl; @@ -2960,7 +2976,14 @@ finish_id_expression (tree id_expression, FIXME update for final resolution of core issue 696. */ if (decl_constant_var_p (decl)) - return integral_constant_value (decl); + { + if (processing_template_decl) + /* In a template, the constant value may not be in a usable + form, so look it up again at instantiation time. */ + return id_expression; + else + return integral_constant_value (decl); + } /* If we are in a lambda function, we can move out until we hit 1. the context, @@ -2998,8 +3021,8 @@ finish_id_expression (tree id_expression, else { error (TREE_CODE (decl) == VAR_DECL - ? "use of % variable from containing function" - : "use of parameter from containing function"); + ? G_("use of % variable from containing function") + : G_("use of parameter from containing function")); error (" %q+#D declared here", decl); return error_mark_node; } @@ -3298,8 +3321,9 @@ finish_id_expression (tree id_expression, if (TREE_CODE (first_fn) == TEMPLATE_DECL) first_fn = DECL_TEMPLATE_RESULT (first_fn); - if (!really_overloaded_fn (decl)) - mark_used (first_fn); + if (!really_overloaded_fn (decl) + && !mark_used (first_fn)) + return error_mark_node; if (!template_arg_p && TREE_CODE (first_fn) == FUNCTION_DECL @@ -3390,7 +3414,7 @@ finish_underlying_type (tree type) if (TREE_CODE (type) != ENUMERAL_TYPE) { - error ("%qE is not an enumeration type", type); + error ("%qT is not an enumeration type", type); return error_mark_node; } @@ -3407,6 +3431,149 @@ finish_underlying_type (tree type) return underlying_type; } +/* Implement the __direct_bases keyword: Return the direct base classes + of type */ + +tree +calculate_direct_bases (tree type) +{ + VEC(tree, gc) *vector = make_tree_vector(); + tree bases_vec = NULL_TREE; + VEC(tree, none) *base_binfos; + tree binfo; + unsigned i; + + complete_type (type); + + if (!NON_UNION_CLASS_TYPE_P (type)) + return make_tree_vec (0); + + base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type)); + + /* Virtual bases are initialized first */ + for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++) + { + if (BINFO_VIRTUAL_P (binfo)) + { + VEC_safe_push (tree, gc, vector, binfo); + } + } + + /* Now non-virtuals */ + for (i = 0; VEC_iterate (tree, base_binfos, i, binfo); i++) + { + if (!BINFO_VIRTUAL_P (binfo)) + { + VEC_safe_push (tree, gc, vector, binfo); + } + } + + + bases_vec = make_tree_vec (VEC_length (tree, vector)); + + for (i = 0; i < VEC_length (tree, vector); ++i) + { + TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE (VEC_index (tree, vector, i)); + } + return bases_vec; +} + +/* Implement the __bases keyword: Return the base classes + of type */ + +/* Find morally non-virtual base classes by walking binfo hierarchy */ +/* Virtual base classes are handled separately in finish_bases */ + +static tree +dfs_calculate_bases_pre (tree binfo, ATTRIBUTE_UNUSED void *data_) +{ + /* Don't walk bases of virtual bases */ + return BINFO_VIRTUAL_P (binfo) ? dfs_skip_bases : NULL_TREE; +} + +static tree +dfs_calculate_bases_post (tree binfo, void *data_) +{ + VEC(tree, gc) **data = (VEC(tree, gc) **) data_; + if (!BINFO_VIRTUAL_P (binfo)) + { + VEC_safe_push (tree, gc, *data, BINFO_TYPE (binfo)); + } + return NULL_TREE; +} + +/* Calculates the morally non-virtual base classes of a class */ +static VEC(tree, gc) * +calculate_bases_helper (tree type) +{ + VEC(tree, gc) *vector = make_tree_vector(); + + /* Now add non-virtual base classes in order of construction */ + dfs_walk_all (TYPE_BINFO (type), + dfs_calculate_bases_pre, dfs_calculate_bases_post, &vector); + return vector; +} + +tree +calculate_bases (tree type) +{ + VEC(tree, gc) *vector = make_tree_vector(); + tree bases_vec = NULL_TREE; + unsigned i; + VEC(tree, gc) *vbases; + VEC(tree, gc) *nonvbases; + tree binfo; + + complete_type (type); + + if (!NON_UNION_CLASS_TYPE_P (type)) + return make_tree_vec (0); + + /* First go through virtual base classes */ + for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0; + VEC_iterate (tree, vbases, i, binfo); i++) + { + VEC(tree, gc) *vbase_bases = calculate_bases_helper (BINFO_TYPE (binfo)); + VEC_safe_splice (tree, gc, vector, vbase_bases); + release_tree_vector (vbase_bases); + } + + /* Now for the non-virtual bases */ + nonvbases = calculate_bases_helper (type); + VEC_safe_splice (tree, gc, vector, nonvbases); + release_tree_vector (nonvbases); + + /* Last element is entire class, so don't copy */ + bases_vec = make_tree_vec (VEC_length (tree, vector) - 1); + + for (i = 0; i < VEC_length (tree, vector) - 1; ++i) + { + TREE_VEC_ELT (bases_vec, i) = VEC_index (tree, vector, i); + } + release_tree_vector (vector); + return bases_vec; +} + +tree +finish_bases (tree type, bool direct) +{ + tree bases = NULL_TREE; + + if (!processing_template_decl) + { + /* Parameter packs can only be used in templates */ + error ("Parameter pack __bases only valid in template declaration"); + return error_mark_node; + } + + bases = cxx_make_type (BASES); + BASES_TYPE (bases) = type; + BASES_DIRECT (bases) = direct; + SET_TYPE_STRUCTURAL_EQUALITY (bases); + + return bases; +} + /* Perform C++-specific checks for __builtin_offsetof before calling fold_offsetof. */ @@ -3437,7 +3604,7 @@ finish_offsetof (tree expr) if (!complete_type_or_else (TREE_TYPE (object), object)) return error_mark_node; } - return fold_offsetof (expr, NULL_TREE); + return fold_offsetof (expr); } /* Replace the AGGR_INIT_EXPR at *TP with an equivalent CALL_EXPR. This @@ -3910,6 +4077,8 @@ finish_omp_clauses (tree clauses) t = maybe_convert_cond (t); if (t == error_mark_node) remove = true; + else if (!processing_template_decl) + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); OMP_CLAUSE_IF_EXPR (c) = t; break; @@ -3918,6 +4087,8 @@ finish_omp_clauses (tree clauses) t = maybe_convert_cond (t); if (t == error_mark_node) remove = true; + else if (!processing_template_decl) + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); OMP_CLAUSE_FINAL_EXPR (c) = t; break; @@ -3931,6 +4102,13 @@ finish_omp_clauses (tree clauses) error ("num_threads expression must be integral"); remove = true; } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + OMP_CLAUSE_NUM_THREADS_EXPR (c) = t; + } break; case OMP_CLAUSE_SCHEDULE: @@ -3945,6 +4123,13 @@ finish_omp_clauses (tree clauses) error ("schedule chunk size expression must be integral"); remove = true; } + else + { + t = mark_rvalue_use (t); + if (!processing_template_decl) + t = fold_build_cleanup_point_expr (TREE_TYPE (t), t); + OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t; + } break; case OMP_CLAUSE_NOWAIT: @@ -4797,7 +4982,7 @@ finish_omp_atomic (enum tree_code code, enum tree_code opcode, tree lhs, void finish_omp_barrier (void) { - tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER]; + tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER); VEC(tree,gc) *vec = make_tree_vector (); tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); release_tree_vector (vec); @@ -4807,7 +4992,7 @@ finish_omp_barrier (void) void finish_omp_flush (void) { - tree fn = built_in_decls[BUILT_IN_SYNC_SYNCHRONIZE]; + tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE); VEC(tree,gc) *vec = make_tree_vector (); tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); release_tree_vector (vec); @@ -4817,7 +5002,7 @@ finish_omp_flush (void) void finish_omp_taskwait (void) { - tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT]; + tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT); VEC(tree,gc) *vec = make_tree_vector (); tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); release_tree_vector (vec); @@ -4827,13 +5012,91 @@ finish_omp_taskwait (void) void finish_omp_taskyield (void) { - tree fn = built_in_decls[BUILT_IN_GOMP_TASKYIELD]; + tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD); VEC(tree,gc) *vec = make_tree_vector (); tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error); release_tree_vector (vec); finish_expr_stmt (stmt); } +/* Begin a __transaction_atomic or __transaction_relaxed statement. + If PCOMPOUND is non-null, this is for a function-transaction-block, and we + should create an extra compound stmt. */ + +tree +begin_transaction_stmt (location_t loc, tree *pcompound, int flags) +{ + tree r; + + if (pcompound) + *pcompound = begin_compound_stmt (0); + + r = build_stmt (loc, TRANSACTION_EXPR, NULL_TREE); + + /* Only add the statement to the function if support enabled. */ + if (flag_tm) + add_stmt (r); + else + error_at (loc, ((flags & TM_STMT_ATTR_RELAXED) != 0 + ? G_("%<__transaction_relaxed%> without " + "transactional memory support enabled") + : G_("%<__transaction_atomic%> without " + "transactional memory support enabled"))); + + TRANSACTION_EXPR_BODY (r) = push_stmt_list (); + return r; +} + +/* End a __transaction_atomic or __transaction_relaxed statement. + If COMPOUND_STMT is non-null, this is for a function-transaction-block, + and we should end the compound. If NOEX is non-NULL, we wrap the body in + a MUST_NOT_THROW_EXPR with NOEX as condition. */ + +void +finish_transaction_stmt (tree stmt, tree compound_stmt, int flags, tree noex) +{ + TRANSACTION_EXPR_BODY (stmt) = pop_stmt_list (TRANSACTION_EXPR_BODY (stmt)); + TRANSACTION_EXPR_OUTER (stmt) = (flags & TM_STMT_ATTR_OUTER) != 0; + TRANSACTION_EXPR_RELAXED (stmt) = (flags & TM_STMT_ATTR_RELAXED) != 0; + TRANSACTION_EXPR_IS_STMT (stmt) = 1; + + /* noexcept specifications are not allowed for function transactions. */ + gcc_assert (!(noex && compound_stmt)); + if (noex) + { + tree body = build_must_not_throw_expr (TRANSACTION_EXPR_BODY (stmt), + noex); + SET_EXPR_LOCATION (body, EXPR_LOCATION (TRANSACTION_EXPR_BODY (stmt))); + TREE_SIDE_EFFECTS (body) = 1; + TRANSACTION_EXPR_BODY (stmt) = body; + } + + if (compound_stmt) + finish_compound_stmt (compound_stmt); + finish_stmt (); +} + +/* Build a __transaction_atomic or __transaction_relaxed expression. If + NOEX is non-NULL, we wrap the body in a MUST_NOT_THROW_EXPR with NOEX as + condition. */ + +tree +build_transaction_expr (location_t loc, tree expr, int flags, tree noex) +{ + tree ret; + if (noex) + { + expr = build_must_not_throw_expr (expr, noex); + SET_EXPR_LOCATION (expr, loc); + TREE_SIDE_EFFECTS (expr) = 1; + } + ret = build1 (TRANSACTION_EXPR, TREE_TYPE (expr), expr); + if (flags & TM_STMT_ATTR_RELAXED) + TRANSACTION_EXPR_RELAXED (ret) = 1; + SET_EXPR_LOCATION (ret, loc); + return ret; +} + void init_cp_semantics (void) { @@ -4888,7 +5151,7 @@ finish_static_assert (tree condition, tree message, location_t location, if (TREE_CODE (condition) == INTEGER_CST && integer_zerop (condition)) /* Report the error. */ - error ("static assertion failed: %E", message); + error ("static assertion failed: %s", TREE_STRING_POINTER (message)); else if (condition && condition != error_mark_node) { error ("non-constant condition for static assertion"); @@ -4984,7 +5247,7 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, step. */ expr = TREE_OPERAND (expr, 1); - if (TREE_CODE (expr) == BASELINK) + if (BASELINK_P (expr)) /* See through BASELINK nodes to the underlying function. */ expr = BASELINK_FUNCTIONS (expr); @@ -5023,8 +5286,9 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, gcc_unreachable (); case INTEGER_CST: + case PTRMEM_CST: /* We can get here when the id-expression refers to an - enumerator. */ + enumerator or non-type template parameter. */ type = TREE_TYPE (expr); break; @@ -5109,6 +5373,7 @@ classtype_has_nothrow_assign_or_copy_p (tree type, bool assign_p) else if (copy_fn_p (fn) <= 0) continue; + maybe_instantiate_noexcept (fn); if (!TYPE_NOTHROW_P (TREE_TYPE (fn))) return false; } @@ -5150,7 +5415,8 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2) || (CLASS_TYPE_P (type1) && (t = locate_ctor (type1)) - && TYPE_NOTHROW_P (TREE_TYPE (t)))); + && (maybe_instantiate_noexcept (t), + TYPE_NOTHROW_P (TREE_TYPE (t))))); case CPTK_HAS_TRIVIAL_CONSTRUCTOR: type1 = strip_array_types (type1); @@ -5199,6 +5465,9 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) case CPTK_IS_ENUM: return (type_code1 == ENUMERAL_TYPE); + case CPTK_IS_FINAL: + return (CLASS_TYPE_P (type1) && CLASSTYPE_FINAL (type1)); + case CPTK_IS_LITERAL_TYPE: return (literal_type_p (type1)); @@ -5223,23 +5492,20 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2) } } -/* Returns true if TYPE is a complete type, an array of unknown bound, - or (possibly cv-qualified) void, returns false otherwise. */ +/* If TYPE is an array of unknown bound, or (possibly cv-qualified) + void, or a complete type, returns it, otherwise NULL_TREE. */ -static bool +static tree check_trait_type (tree type) { - if (COMPLETE_TYPE_P (type)) - return true; - if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type) && COMPLETE_TYPE_P (TREE_TYPE (type))) - return true; + return type; if (VOID_TYPE_P (type)) - return true; + return type; - return false; + return complete_type_or_else (strip_array_types (type), NULL_TREE); } /* Process a trait expression. */ @@ -5261,6 +5527,7 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) || kind == CPTK_IS_CONVERTIBLE_TO || kind == CPTK_IS_EMPTY || kind == CPTK_IS_ENUM + || kind == CPTK_IS_FINAL || kind == CPTK_IS_LITERAL_TYPE || kind == CPTK_IS_POD || kind == CPTK_IS_POLYMORPHIC @@ -5289,10 +5556,6 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) return trait_expr; } - complete_type (type1); - if (type2) - complete_type (type2); - switch (kind) { case CPTK_HAS_NOTHROW_ASSIGN: @@ -5305,26 +5568,22 @@ finish_trait_expr (cp_trait_kind kind, tree type1, tree type2) case CPTK_HAS_VIRTUAL_DESTRUCTOR: case CPTK_IS_ABSTRACT: case CPTK_IS_EMPTY: + case CPTK_IS_FINAL: case CPTK_IS_LITERAL_TYPE: case CPTK_IS_POD: case CPTK_IS_POLYMORPHIC: case CPTK_IS_STD_LAYOUT: case CPTK_IS_TRIVIAL: if (!check_trait_type (type1)) - { - error ("incomplete type %qT not allowed", type1); - return error_mark_node; - } + return error_mark_node; break; case CPTK_IS_BASE_OF: if (NON_UNION_CLASS_TYPE_P (type1) && NON_UNION_CLASS_TYPE_P (type2) && !same_type_ignoring_top_level_qualifiers_p (type1, type2) - && !COMPLETE_TYPE_P (type2)) - { - error ("incomplete type %qT not allowed", type2); - return error_mark_node; - } + && !complete_type_or_else (type2, NULL_TREE)) + /* We already issued an error. */ + return error_mark_node; break; case CPTK_IS_CLASS: @@ -5497,6 +5756,12 @@ is_valid_constexpr_fn (tree fun, bool complain) } } } + else if (CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fun))) + { + ret = false; + if (complain) + error ("%q#T has virtual base classes", DECL_CONTEXT (fun)); + } return ret; } @@ -5544,15 +5809,19 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec) member = TREE_OPERAND (t, 0); init = unshare_expr (TREE_OPERAND (t, 1)); } - else + else if (TREE_CODE (t) == CALL_EXPR) { - gcc_assert (TREE_CODE (t) == CALL_EXPR); member = CALL_EXPR_ARG (t, 0); /* We don't use build_cplus_new here because it complains about abstract bases. Leaving the call unwrapped means that it has the wrong type, but cxx_eval_constant_expression doesn't care. */ init = unshare_expr (t); } + else if (TREE_CODE (t) == DECL_EXPR) + /* Declaring a temporary, don't add it to the CONSTRUCTOR. */ + return true; + else + gcc_unreachable (); if (TREE_CODE (member) == INDIRECT_REF) member = TREE_OPERAND (member, 0); if (TREE_CODE (member) == NOP_EXPR) @@ -5568,14 +5837,17 @@ build_data_member_initialization (tree t, VEC(constructor_elt,gc) **vec) the const_cast. */ member = op; } + else if (op == current_class_ptr + && (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (TREE_TYPE (member)), + current_class_type))) + /* Delegating constructor. */ + member = op; else { - /* We don't put out anything for an empty base. */ + /* This is an initializer for an empty base; keep it for now so + we can check it in cxx_eval_bare_aggregate. */ gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (member)))); - /* But if the initializer isn't constexpr, leave it in so we - complain later. */ - if (potential_constant_expression (init)) - return true; } } if (TREE_CODE (member) == ADDR_EXPR) @@ -5632,6 +5904,44 @@ check_constexpr_ctor_body (tree last, tree list) return ok; } +/* VEC is a vector of constructor elements built up for the base and member + initializers of a constructor for TYPE. They need to be in increasing + offset order, which they might not be yet if TYPE has a primary base + which is not first in the base-clause or a vptr and at least one base + all of which are non-primary. */ + +static VEC(constructor_elt,gc) * +sort_constexpr_mem_initializers (tree type, VEC(constructor_elt,gc) *vec) +{ + tree pri = CLASSTYPE_PRIMARY_BINFO (type); + tree field_type; + constructor_elt elt; + int i; + + if (pri) + field_type = BINFO_TYPE (pri); + else if (TYPE_CONTAINS_VPTR_P (type)) + field_type = vtbl_ptr_type_node; + else + return vec; + + /* Find the element for the primary base or vptr and move it to the + beginning of the vec. */ + for (i = 0; ; ++i) + if (TREE_TYPE (VEC_index (constructor_elt, vec, i)->index) == field_type) + break; + + if (i > 0) + { + elt = *VEC_index (constructor_elt, vec, i); + for (; i > 0; --i) + VEC_replace (constructor_elt, vec, i, + VEC_index (constructor_elt, vec, i-1)); + VEC_replace (constructor_elt, vec, 0, &elt); + } + return vec; +} + /* Build compile-time evalable representations of member-initializer list for a constexpr constructor. */ @@ -5671,10 +5981,26 @@ build_constexpr_constructor_member_initializers (tree type, tree body) break; } } + else if (EXPR_P (body)) + ok = build_data_member_initialization (body, &vec); else gcc_assert (errorcount > 0); if (ok) - return build_constructor (type, vec); + { + if (VEC_length (constructor_elt, vec) > 0) + { + /* In a delegating constructor, return the target. */ + constructor_elt *ce = VEC_index (constructor_elt, vec, 0); + if (ce->index == current_class_ptr) + { + body = ce->value; + VEC_free (constructor_elt, gc, vec); + return body; + } + } + vec = sort_constexpr_mem_initializers (type, vec); + return build_constructor (type, vec); + } else return error_mark_node; } @@ -5740,12 +6066,12 @@ massage_constexpr_body (tree fun, tree body) (DECL_CONTEXT (fun), body); else { - if (TREE_CODE (body) == BIND_EXPR) - body = BIND_EXPR_BODY (body); if (TREE_CODE (body) == EH_SPEC_BLOCK) body = EH_SPEC_STMTS (body); if (TREE_CODE (body) == MUST_NOT_THROW_EXPR) body = TREE_OPERAND (body, 0); + if (TREE_CODE (body) == BIND_EXPR) + body = BIND_EXPR_BODY (body); body = constexpr_fn_retval (body); } return body; @@ -5760,13 +6086,28 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain) bool bad; tree field; unsigned i, nelts; + tree ctype; if (TREE_CODE (body) != CONSTRUCTOR) return false; - bad = false; nelts = CONSTRUCTOR_NELTS (body); - field = TYPE_FIELDS (DECL_CONTEXT (fun)); + ctype = DECL_CONTEXT (fun); + field = TYPE_FIELDS (ctype); + + if (TREE_CODE (ctype) == UNION_TYPE) + { + if (nelts == 0 && next_initializable_field (field)) + { + if (complain) + error ("% constructor for union %qT must " + "initialize exactly one non-static data member", ctype); + return true; + } + return false; + } + + bad = false; for (i = 0; i <= nelts; ++i) { tree index; @@ -5776,26 +6117,29 @@ cx_check_missing_mem_inits (tree fun, tree body, bool complain) { index = CONSTRUCTOR_ELT (body, i)->index; /* Skip base and vtable inits. */ - if (TREE_CODE (index) != FIELD_DECL) + if (TREE_CODE (index) != FIELD_DECL + || DECL_ARTIFICIAL (index)) continue; } for (; field != index; field = DECL_CHAIN (field)) { tree ftype; if (TREE_CODE (field) != FIELD_DECL - || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))) + || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)) + || DECL_ARTIFICIAL (field)) continue; - if (!complain) - return true; ftype = strip_array_types (TREE_TYPE (field)); if (type_has_constexpr_default_constructor (ftype)) { /* It's OK to skip a member with a trivial constexpr ctor. A constexpr ctor that isn't trivial should have been added in by now. */ - gcc_checking_assert (!TYPE_HAS_COMPLEX_DFLT (ftype)); + gcc_checking_assert (!TYPE_HAS_COMPLEX_DFLT (ftype) + || errorcount != 0); continue; } + if (!complain) + return true; error ("uninitialized member %qD in % constructor", field); bad = true; @@ -6303,7 +6647,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t, else { result = entry->result; - if (!result || (result == error_mark_node && !allow_non_constant)) + if (!result || result == error_mark_node) result = (cxx_eval_constant_expression (&new_call, new_call.fundef->body, allow_non_constant, addr, @@ -6561,6 +6905,12 @@ cxx_eval_component_reference (const constexpr_call *call, tree t, error ("%qE is not a constant expression", orig_whole); *non_constant_p = true; } + if (DECL_MUTABLE_P (part)) + { + if (!allow_non_constant) + error ("mutable %qD is not usable in a constant expression", part); + *non_constant_p = true; + } if (*non_constant_p) return t; FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value) @@ -6753,6 +7103,12 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t, constructor_elt *inner = base_field_constructor_elt (n, ce->index); inner->value = elt; } + else if (TREE_CODE (ce->index) == NOP_EXPR) + { + /* This is an initializer for an empty base; now that we've + checked that it's constant, we can ignore it. */ + gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (ce->index)))); + } else CONSTRUCTOR_APPEND_ELT (n, ce->index, elt); } @@ -6826,7 +7182,7 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init, if (TREE_CODE (elttype) == ARRAY_TYPE) { /* A multidimensional array; recurse. */ - if (value_init) + if (value_init || init == NULL_TREE) eltinit = NULL_TREE; else eltinit = cp_build_array_ref (input_location, init, idx, @@ -6915,7 +7271,8 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) sub = op0; STRIP_NOPS (sub); subtype = TREE_TYPE (sub); - gcc_assert (POINTER_TYPE_P (subtype)); + if (!POINTER_TYPE_P (subtype)) + return NULL_TREE; if (TREE_CODE (sub) == ADDR_EXPR) { @@ -7055,15 +7412,17 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base) } } } - /* *(foo *)fooarrptreturn> (*fooarrptr)[0] */ + /* *(foo *)fooarrptr => (*fooarrptr)[0] */ else if (TREE_CODE (TREE_TYPE (subtype)) == ARRAY_TYPE && (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (TREE_TYPE (subtype))))) { tree type_domain; tree min_val = size_zero_node; - sub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); - if (!sub) + tree newsub = cxx_fold_indirect_ref (loc, TREE_TYPE (subtype), sub, NULL); + if (newsub) + sub = newsub; + else sub = build1_loc (loc, INDIRECT_REF, TREE_TYPE (subtype), sub); type_domain = TYPE_DOMAIN (TREE_TYPE (sub)); if (type_domain && TYPE_MIN_VALUE (type_domain)) @@ -7100,9 +7459,15 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t, { tree sub = op0; STRIP_NOPS (sub); - if (TREE_CODE (sub) == ADDR_EXPR - || TREE_CODE (sub) == POINTER_PLUS_EXPR) + if (TREE_CODE (sub) == POINTER_PLUS_EXPR) + { + sub = TREE_OPERAND (sub, 0); + STRIP_NOPS (sub); + } + if (TREE_CODE (sub) == ADDR_EXPR) { + /* We couldn't fold to a constant value. Make sure it's not + something we should have been able to fold. */ gcc_assert (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t))); /* DR 1188 says we don't have to deal with this. */ @@ -7126,7 +7491,11 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t, } if (r == NULL_TREE) - return t; + { + if (!addr) + VERIFY_CONSTANT (t); + return t; + } return r; } @@ -7350,6 +7719,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, /* Check that the LHS is constant and then discard it. */ cxx_eval_constant_expression (call, op0, allow_non_constant, false, non_constant_p); + op1 = TREE_OPERAND (t, 1); r = cxx_eval_constant_expression (call, op1, allow_non_constant, addr, non_constant_p); } @@ -7459,17 +7829,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, tree oldop = TREE_OPERAND (t, 0); tree op = oldop; tree to = TREE_TYPE (t); - tree source = TREE_TYPE (op); - if (TYPE_PTR_P (source) && ARITHMETIC_TYPE_P (to) - && !(TREE_CODE (op) == COMPONENT_REF - && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (op, 0))))) - { - if (!allow_non_constant) - error ("conversion of expression %qE of pointer type " - "cannot yield a constant expression", op); - *non_constant_p = true; - return t; - } op = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), allow_non_constant, addr, non_constant_p); @@ -7494,8 +7853,6 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t, return t; case LAMBDA_EXPR: - case DYNAMIC_CAST_EXPR: - case PSEUDO_DTOR_EXPR: case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: case PREDECREMENT_EXPR: @@ -7548,6 +7905,32 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant) verify_constant (r, allow_non_constant, &non_constant_p); + if (TREE_CODE (t) != CONSTRUCTOR + && cp_has_mutable_p (TREE_TYPE (t))) + { + /* We allow a mutable type if the original expression was a + CONSTRUCTOR so that we can do aggregate initialization of + constexpr variables. */ + if (!allow_non_constant) + error ("%qT cannot be the type of a complete constant expression " + "because it has mutable sub-objects", TREE_TYPE (t)); + non_constant_p = true; + } + + /* Technically we should check this for all subexpressions, but that + runs into problems with our internal representation of pointer + subtraction and the 5.19 rules are still in flux. */ + if (CONVERT_EXPR_CODE_P (TREE_CODE (r)) + && ARITHMETIC_TYPE_P (TREE_TYPE (r)) + && TREE_CODE (TREE_OPERAND (r, 0)) == ADDR_EXPR) + { + if (!allow_non_constant) + error ("conversion from pointer type %qT " + "to arithmetic type %qT in a constant-expression", + TREE_TYPE (TREE_OPERAND (r, 0)), TREE_TYPE (r)); + non_constant_p = true; + } + if (non_constant_p && !allow_non_constant) return error_mark_node; else if (non_constant_p && TREE_CONSTANT (t)) @@ -7748,6 +8131,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case TEMPLATE_PARM_INDEX: case TRAIT_EXPR: case IDENTIFIER_NODE: + case USERDEF_LITERAL: /* We can see a FIELD_DECL in a pointer-to-member expression. */ case FIELD_DECL: case PARM_DECL: @@ -7854,25 +8238,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case NOP_EXPR: case CONVERT_EXPR: case VIEW_CONVERT_EXPR: - /* -- an array-to-pointer conversion that is applied to an lvalue - that designates an object with thread or automatic storage - duration; FIXME not implemented as it breaks constexpr arrays; - need to fix the standard - -- a type conversion from a pointer or pointer-to-member type - to a literal type. */ + /* -- a reinterpret_cast. FIXME not implemented, and this rule + may change to something more specific to type-punning (DR 1312). */ { tree from = TREE_OPERAND (t, 0); - tree source = TREE_TYPE (from); - tree target = TREE_TYPE (t); - if (TYPE_PTR_P (source) && ARITHMETIC_TYPE_P (target) - && !(TREE_CODE (from) == COMPONENT_REF - && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (from, 0))))) - { - if (flags & tf_error) - error ("conversion of expression %qE of pointer type " - "cannot yield a constant expression", from); - return false; - } return (potential_constant_expression_1 (from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags)); } @@ -7960,6 +8329,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case STMT_EXPR: case EXPR_STMT: case BIND_EXPR: + case TRANSACTION_EXPR: + case IF_STMT: + case DO_STMT: + case FOR_STMT: + case WHILE_STMT: if (flags & tf_error) error ("expression %qE is not a constant-expression", t); return false; @@ -8036,6 +8410,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case CONST_CAST_EXPR: case STATIC_CAST_EXPR: case REINTERPRET_CAST_EXPR: + case IMPLICIT_CONV_EXPR: return (potential_constant_expression_1 (TREE_OPERAND (t, 0), TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags)); @@ -8168,6 +8543,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) case UNGT_EXPR: case UNGE_EXPR: case UNEQ_EXPR: + case LTGT_EXPR: case RANGE_EXPR: case COMPLEX_EXPR: want_rval = true; @@ -8223,7 +8599,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) return false; default: - sorry ("unexpected ast of kind %s", tree_code_name[TREE_CODE (t)]); + sorry ("unexpected AST of kind %s", tree_code_name[TREE_CODE (t)]); gcc_unreachable(); return false; } @@ -8338,7 +8714,7 @@ build_lambda_object (tree lambda_expr) /* N2927: "[The closure] class type is not an aggregate." But we briefly treat it as an aggregate to make this simpler. */ - type = TREE_TYPE (lambda_expr); + type = LAMBDA_EXPR_CLOSURE (lambda_expr); CLASSTYPE_NON_AGGREGATE (type) = 0; expr = finish_compound_literal (type, expr, tf_warning_or_error); CLASSTYPE_NON_AGGREGATE (type) = 1; @@ -8376,10 +8752,12 @@ begin_lambda_type (tree lambda) xref_basetypes (type, /*bases=*/NULL_TREE); /* Start the class. */ - type = begin_class_definition (type, /*attributes=*/NULL_TREE); + type = begin_class_definition (type); + if (type == error_mark_node) + return error_mark_node; /* Cross-reference the expression and the type. */ - TREE_TYPE (lambda) = type; + LAMBDA_EXPR_CLOSURE (lambda) = type; CLASSTYPE_LAMBDA_EXPR (type) = lambda; return type; @@ -8413,7 +8791,7 @@ lambda_function (tree lambda) { tree type; if (TREE_CODE (lambda) == LAMBDA_EXPR) - type = TREE_TYPE (lambda); + type = LAMBDA_EXPR_CLOSURE (lambda); else type = lambda; gcc_assert (LAMBDA_TYPE_P (type)); @@ -8422,7 +8800,8 @@ lambda_function (tree lambda) && !COMPLETE_OR_OPEN_TYPE_P (type)) return NULL_TREE; lambda = lookup_member (type, ansi_opname (CALL_EXPR), - /*protect=*/0, /*want_type=*/false); + /*protect=*/0, /*want_type=*/false, + tf_warning_or_error); if (lambda) lambda = BASELINK_FUNCTIONS (lambda); return lambda; @@ -8436,7 +8815,8 @@ tree lambda_capture_field_type (tree expr) { tree type; - if (type_dependent_expression_p (expr)) + if (type_dependent_expression_p (expr) + && !(TREE_TYPE (expr) && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)) { type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = expr; @@ -8577,17 +8957,16 @@ is_normal_capture_proxy (tree decl) /* VAR is a capture proxy created by build_capture_proxy; add it to the current function, which is the operator() for the appropriate lambda. */ -static inline void +void insert_capture_proxy (tree var) { cp_binding_level *b; - int skip; tree stmt_list; /* Put the capture proxy in the extra body block so that it won't clash with a later local variable. */ b = current_binding_level; - for (skip = 0; ; ++skip) + for (;;) { cp_binding_level *n = b->level_chain; if (n->kind == sk_function_parms) @@ -8598,8 +8977,7 @@ insert_capture_proxy (tree var) /* And put a DECL_EXPR in the STATEMENT_LIST for the same block. */ var = build_stmt (DECL_SOURCE_LOCATION (var), DECL_EXPR, var); - stmt_list = VEC_index (tree, stmt_list_stack, - VEC_length (tree, stmt_list_stack) - 1 - skip); + stmt_list = VEC_index (tree, stmt_list_stack, 1); gcc_assert (stmt_list); append_to_statement_list_force (var, &stmt_list); } @@ -8641,7 +9019,8 @@ lambda_proxy_type (tree ref) if (REFERENCE_REF_P (ref)) ref = TREE_OPERAND (ref, 0); type = TREE_TYPE (ref); - if (!dependent_type_p (type)) + if (!dependent_type_p (type) + || (type && TREE_CODE (type) == POINTER_TYPE)) return type; type = cxx_make_type (DECLTYPE_TYPE); DECLTYPE_TYPE_EXPR (type) = ref; @@ -8728,7 +9107,7 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, /* If TREE_TYPE isn't set, we're still in the introducer, so check for duplicates. */ - if (!TREE_TYPE (lambda)) + if (!LAMBDA_EXPR_CLOSURE (lambda)) { if (IDENTIFIER_MARKED (name)) { @@ -8754,13 +9133,14 @@ add_capture (tree lambda, tree id, tree initializer, bool by_reference_p, LAMBDA_EXPR_THIS_CAPTURE (lambda) = member; /* Add it to the appropriate closure class if we've started it. */ - if (current_class_type && current_class_type == TREE_TYPE (lambda)) + if (current_class_type + && current_class_type == LAMBDA_EXPR_CLOSURE (lambda)) finish_member_declaration (member); LAMBDA_EXPR_CAPTURE_LIST (lambda) = tree_cons (member, initializer, LAMBDA_EXPR_CAPTURE_LIST (lambda)); - if (TREE_TYPE (lambda)) + if (LAMBDA_EXPR_CLOSURE (lambda)) return build_capture_proxy (member); /* For explicit captures we haven't started the function yet, so we wait and build the proxy from cp_parser_lambda_body. */ @@ -8803,7 +9183,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer) { tree lambda = TREE_VALUE (node); - current_class_type = TREE_TYPE (lambda); + current_class_type = LAMBDA_EXPR_CLOSURE (lambda); var = add_capture (lambda, id, initializer, @@ -8834,7 +9214,7 @@ lambda_expr_this_capture (tree lambda) if (!this_capture && LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda) != CPLD_NONE) { - tree containing_function = TYPE_CONTEXT (TREE_TYPE (lambda)); + tree containing_function = TYPE_CONTEXT (LAMBDA_EXPR_CLOSURE (lambda)); tree lambda_stack = tree_cons (NULL_TREE, lambda, NULL_TREE); tree init = NULL_TREE; @@ -8884,7 +9264,8 @@ lambda_expr_this_capture (tree lambda) else { /* To make sure that current_class_ref is for the lambda. */ - gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) == TREE_TYPE (lambda)); + gcc_assert (TYPE_MAIN_VARIANT (TREE_TYPE (current_class_ref)) + == LAMBDA_EXPR_CLOSURE (lambda)); result = this_capture; @@ -9053,6 +9434,8 @@ maybe_add_lambda_conv_op (tree type) body = begin_function_body (); compound_stmt = begin_compound_stmt (0); + /* decl_needed_p needs to see that it's used. */ + TREE_USED (statfn) = 1; finish_return_stmt (decay_conversion (statfn)); finish_compound_stmt (compound_stmt);