diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 84 | ||||
-rw-r--r-- | gcc/cp/call.c | 52 | ||||
-rw-r--r-- | gcc/cp/class.c | 90 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 24 | ||||
-rw-r--r-- | gcc/cp/decl.c | 15 | ||||
-rw-r--r-- | gcc/cp/error.c | 5 | ||||
-rw-r--r-- | gcc/cp/init.c | 3 | ||||
-rw-r--r-- | gcc/cp/method.c | 217 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 13 | ||||
-rw-r--r-- | gcc/cp/parser.c | 15 | ||||
-rw-r--r-- | gcc/cp/pt.c | 58 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 28 | ||||
-rw-r--r-- | gcc/cp/tree.c | 2 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 4 |
14 files changed, 524 insertions, 86 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a52b643c638..73ab5a9b0ae 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,87 @@ +2012-10-18 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/54501 + * decl.c (reshape_init_array_1): Avoid infinite loops. + +2012-10-15 Alexandre Oliva <aoliva@redhat.com> + Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/17805 + * call.c (build_new_op_1): Filter out operator functions that don't + satisfy enum-conversion match requirements. + +2012-10-15 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/50080 (again) + * parser.c (cp_parser_optional_template_keyword): When -pedantic + and C++98 mode restore pre-Core/468 behavior. + +2012-10-15 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/50080 + * parser.c (cp_parser_optional_template_keyword): Implement + Core/468, allow outside template. + +2012-10-14 Jason Merrill <jason@redhat.com> + Ville Voutilainen <ville.voutilainen@gmail.com> + + Implement C++11 inheriting constructors. + * cp-tree.h (cpp0x_warn_str): Add CPP0X_INHERITING_CTORS. + (DECL_INHERITED_CTOR_BASE, SET_DECL_INHERITED_CTOR_BASE): New. + (special_function_kind): Add sfk_inheriting_constructor. + * class.c (add_method): An inheriting ctor is hidden by a + user-declared one. + (one_inheriting_sig, one_inherited_ctor): New. + (add_implicitly_declared_members): Handle inheriting ctors. + * error.c (maybe_warn_cpp0x): Handle CPP0X_INHERITING_CTORS. + * init.c (emit_mem_initializers): Don't set LOOKUP_DEFAULTED + for an inheriting constructor. + * method.c (type_has_trivial_fn): Handle sfk_inheriting_constructor. + (type_set_nontrivial_flag): Likewise. + (add_one_base_init): Split out from... + (do_build_copy_constructor): ...here. Handle inheriting constructors. + (locate_fn_flags): Handle a list of arg types. + (synthesized_method_walk): Handle inheriting constructors. + (maybe_explain_implicit_delete): Likewise. + (deduce_inheriting_ctor): New. + (implicitly_declare_fn): Handle inheriting constructors. + * name-lookup.c (push_class_level_binding_1): An inheriting constructor + does not declare the base's name. + (do_class_using_decl): Allow inheriting constructors. + * pt.c (template_parms_to_args): Split from current_template_args. + (add_inherited_template_parms): New. + (tsubst_decl): Handle inheriting constructors. + * tree.c (special_function_p): Handle inheriting constructors. + +2012-10-12 Jakub Jelinek <jakub@redhat.com> + + PR c/54381 + * semantics.c (finish_call_expr): Pass array of 3 sizeof_arg + trees and locs (corresponding to first 3 arguments) to + sizeof_pointer_memaccess_warning. + +2012-10-12 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/24449 + * decl.c (grokfndecl): When checking for ::main declarations + use PROCESSING_REAL_TEMPLATE_DECL_P(). + +2012-10-12 Marc Glisse <marc.glisse@inria.fr> + + PR c++/53055 + * call.c (build_new_op_1): Pass RO_ARROW_STAR to cp_build_indirect_ref. + * typeck.c (cp_build_indirect_ref): Handle RO_ARROW_STAR. + +2012-10-11 Jason Merrill <jason@redhat.com> + + * cp-tree.h (DECL_THUNKS): NULL_TREE for non-virtual functions. + (SET_DECL_THUNKS): New. + * decl.c (duplicate_decls): Adjust. + * method.c (make_thunk): Adjust. + + * decl.c (grokdeclarator): Set DECL_GNU_TLS_P for static data + members, too. + 2012-10-09 Dodji Seketeli <dodji@redhat.com> PR c++/53540 - using fails to be equivalent to typedef diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 3351a585f2b..e21049b8e64 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -5043,6 +5043,11 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, NULL_TREE, arglist, NULL_TREE, NULL_TREE, false, NULL_TREE, NULL_TREE, flags, &candidates, complain); + + args[0] = arg1; + args[1] = arg2; + args[2] = NULL_TREE; + /* Add class-member operators to the candidate set. */ if (CLASS_TYPE_P (TREE_TYPE (arg1))) { @@ -5062,10 +5067,49 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, BASELINK_ACCESS_BINFO (fns), flags, &candidates, complain); } + /* Per 13.3.1.2/3, 2nd bullet, if no operand has a class type, then + only non-member functions that have type T1 or reference to + cv-qualified-opt T1 for the first argument, if the first argument + has an enumeration type, or T2 or reference to cv-qualified-opt + T2 for the second argument, if the the second argument has an + enumeration type. Filter out those that don't match. */ + else if (! arg2 || ! CLASS_TYPE_P (TREE_TYPE (arg2))) + { + struct z_candidate **candp, **next; - args[0] = arg1; - args[1] = arg2; - args[2] = NULL_TREE; + for (candp = &candidates; *candp; candp = next) + { + tree parmlist, parmtype; + int i, nargs = (arg2 ? 2 : 1); + + cand = *candp; + next = &cand->next; + + parmlist = TYPE_ARG_TYPES (TREE_TYPE (cand->fn)); + + for (i = 0; i < nargs; ++i) + { + parmtype = TREE_VALUE (parmlist); + + if (TREE_CODE (parmtype) == REFERENCE_TYPE) + parmtype = TREE_TYPE (parmtype); + if (TREE_CODE (TREE_TYPE (args[i])) == ENUMERAL_TYPE + && (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (args[i]), parmtype))) + break; + + parmlist = TREE_CHAIN (parmlist); + } + + /* No argument has an appropriate type, so remove this + candidate function from the list. */ + if (i == nargs) + { + *candp = cand->next; + next = candp; + } + } + } add_builtin_candidates (&candidates, code, code2, fnname, args, flags, complain); @@ -5309,7 +5353,7 @@ build_new_op_1 (location_t loc, enum tree_code code, int flags, tree arg1, return cp_build_array_ref (input_location, arg1, arg2, complain); case MEMBER_REF: - return build_m_component_ref (cp_build_indirect_ref (arg1, RO_NULL, + return build_m_component_ref (cp_build_indirect_ref (arg1, RO_ARROW_STAR, complain), arg2, complain); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 0e77b81c85b..a478de80563 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -132,7 +132,7 @@ static void finish_struct_methods (tree); static void maybe_warn_about_overly_private_class (tree); static int method_name_cmp (const void *, const void *); static int resort_method_name_cmp (const void *, const void *); -static void add_implicitly_declared_members (tree, int, int); +static void add_implicitly_declared_members (tree, tree*, int, int); static tree fixed_type_or_null (tree, int *, int *); static tree build_simple_base_path (tree expr, tree binfo); static tree build_vtbl_ref_1 (tree, tree); @@ -1087,6 +1087,20 @@ add_method (tree type, tree method, tree using_decl) || same_type_p (TREE_TYPE (fn_type), TREE_TYPE (method_type)))) { + if (DECL_INHERITED_CTOR_BASE (method)) + { + if (DECL_INHERITED_CTOR_BASE (fn)) + { + error_at (DECL_SOURCE_LOCATION (method), + "%q#D inherited from %qT", method, + DECL_INHERITED_CTOR_BASE (method)); + error_at (DECL_SOURCE_LOCATION (fn), + "conflicts with version inherited from %qT", + DECL_INHERITED_CTOR_BASE (fn)); + } + /* Otherwise defer to the other function. */ + return false; + } if (using_decl) { if (DECL_CONTEXT (fn) == type) @@ -2750,6 +2764,51 @@ declare_virt_assop_and_dtor (tree t) NULL, t); } +/* Declare the inheriting constructor for class T inherited from base + constructor CTOR with the parameter array PARMS of size NPARMS. */ + +static void +one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms) +{ + /* We don't declare an inheriting ctor that would be a default, + copy or move ctor. */ + if (nparms == 0 + || (nparms == 1 + && TREE_CODE (parms[0]) == REFERENCE_TYPE + && TYPE_MAIN_VARIANT (TREE_TYPE (parms[0])) == t)) + return; + int i; + tree parmlist = void_list_node; + for (i = nparms - 1; i >= 0; i--) + parmlist = tree_cons (NULL_TREE, parms[i], parmlist); + tree fn = implicitly_declare_fn (sfk_inheriting_constructor, + t, false, ctor, parmlist); + if (add_method (t, fn, NULL_TREE)) + { + DECL_CHAIN (fn) = TYPE_METHODS (t); + TYPE_METHODS (t) = fn; + } +} + +/* Declare all the inheriting constructors for class T inherited from base + constructor CTOR. */ + +static void +one_inherited_ctor (tree ctor, tree t) +{ + tree parms = FUNCTION_FIRST_USER_PARMTYPE (ctor); + + tree *new_parms = XALLOCAVEC (tree, list_length (parms)); + int i = 0; + for (; parms && parms != void_list_node; parms = TREE_CHAIN (parms)) + { + if (TREE_PURPOSE (parms)) + one_inheriting_sig (t, ctor, new_parms, i); + new_parms[i++] = TREE_VALUE (parms); + } + one_inheriting_sig (t, ctor, new_parms, i); +} + /* Create default constructors, assignment operators, and so forth for the type indicated by T, if they are needed. CANT_HAVE_CONST_CTOR, and CANT_HAVE_CONST_ASSIGNMENT are nonzero if, for whatever reason, @@ -2758,7 +2817,7 @@ declare_virt_assop_and_dtor (tree t) a const reference, respectively. */ static void -add_implicitly_declared_members (tree t, +add_implicitly_declared_members (tree t, tree* access_decls, int cant_have_const_cctor, int cant_have_const_assignment) { @@ -2826,6 +2885,26 @@ add_implicitly_declared_members (tree t, /* We can't be lazy about declaring functions that might override a virtual function from a base class. */ declare_virt_assop_and_dtor (t); + + while (*access_decls) + { + tree using_decl = TREE_VALUE (*access_decls); + tree decl = USING_DECL_DECLS (using_decl); + if (DECL_SELF_REFERENCE_P (decl)) + { + /* declare, then remove the decl */ + tree ctor_list = CLASSTYPE_CONSTRUCTORS (TREE_TYPE (decl)); + location_t loc = input_location; + input_location = DECL_SOURCE_LOCATION (using_decl); + if (ctor_list) + for (; ctor_list; ctor_list = OVL_NEXT (ctor_list)) + one_inherited_ctor (OVL_CURRENT (ctor_list), t); + *access_decls = TREE_CHAIN (*access_decls); + input_location = loc; + } + else + access_decls = &TREE_CHAIN (*access_decls); + } } /* Subroutine of insert_into_classtype_sorted_fields. Recursively @@ -4342,7 +4421,8 @@ deduce_noexcept_on_destructor (tree dtor) { tree ctx = DECL_CONTEXT (dtor); tree implicit_fn = implicitly_declare_fn (sfk_destructor, ctx, - /*const_p=*/false); + /*const_p=*/false, + NULL, NULL); tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn)); TREE_TYPE (dtor) = build_exception_variant (TREE_TYPE (dtor), eh_spec); } @@ -5135,14 +5215,14 @@ check_bases_and_members (tree t) } /* Synthesize any needed methods. */ - add_implicitly_declared_members (t, + add_implicitly_declared_members (t, &access_decls, cant_have_const_ctor, no_const_asn_ref); /* Check defaulted declarations here so we have cant_have_const_ctor and don't need to worry about clones. */ for (fn = TYPE_METHODS (t); fn; fn = DECL_CHAIN (fn)) - if (DECL_DEFAULTED_IN_CLASS_P (fn)) + if (!DECL_ARTIFICIAL (fn) && DECL_DEFAULTED_IN_CLASS_P (fn)) { int copy = copy_fn_p (fn); if (copy > 0) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 35819ed10c4..7b4277b05b7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -420,6 +420,8 @@ typedef enum cpp0x_warn_str CPP0X_USER_DEFINED_LITERALS, /* delegating constructors */ CPP0X_DELEGATING_CTORS, + /* inheriting constructors */ + CPP0X_INHERITING_CTORS, /* C++11 attributes */ CPP0X_ATTRIBUTES } cpp0x_warn_str; @@ -2378,7 +2380,20 @@ struct GTY((variable_size)) lang_decl { /* The thunks associated with NODE, a FUNCTION_DECL. */ #define DECL_THUNKS(NODE) \ - (LANG_DECL_FN_CHECK (NODE)->context) + (DECL_VIRTUAL_P (NODE) ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE) + +/* Set DECL_THUNKS. */ +#define SET_DECL_THUNKS(NODE,THUNKS) \ + (LANG_DECL_FN_CHECK (NODE)->context = (THUNKS)) + +/* If NODE, a FUNCTION_DECL, is a C++11 inheriting constructor, then this + is the base it inherits from. */ +#define DECL_INHERITED_CTOR_BASE(NODE) \ + (DECL_CONSTRUCTOR_P (NODE) ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE) + +/* Set the inherited base. */ +#define SET_DECL_INHERITED_CTOR_BASE(NODE,INH) \ + (LANG_DECL_FN_CHECK (NODE)->context = (INH)) /* Nonzero if NODE is a thunk, rather than an ordinary function. */ #define DECL_THUNK_P(NODE) \ @@ -4138,7 +4153,8 @@ typedef enum special_function_kind { sfk_deleting_destructor, /* A destructor for complete objects that deletes the object after it has been destroyed. */ - sfk_conversion /* A conversion operator. */ + sfk_conversion, /* A conversion operator. */ + sfk_inheriting_constructor /* An inheriting constructor */ } special_function_kind; /* The various kinds of linkage. From [basic.link], @@ -5319,6 +5335,7 @@ extern void use_thunk (tree, bool); extern bool trivial_fn_p (tree); extern bool maybe_explain_implicit_delete (tree); extern void explain_implicit_non_constexpr (tree); +extern void deduce_inheriting_ctor (tree); extern void synthesize_method (tree); extern tree lazily_declare_fn (special_function_kind, tree); @@ -5331,7 +5348,7 @@ extern tree get_default_ctor (tree); extern tree get_dtor (tree, tsubst_flags_t); extern tree locate_ctor (tree); extern tree implicitly_declare_fn (special_function_kind, tree, - bool); + bool, tree, tree); /* In optimize.c */ extern bool maybe_clone_body (tree); @@ -5366,6 +5383,7 @@ extern tree maybe_update_decl_type (tree, tree); extern bool check_default_tmpl_args (tree, tree, bool, bool, int); extern tree push_template_decl (tree); extern tree push_template_decl_real (tree, bool); +extern tree add_inherited_template_parms (tree, tree); extern bool redeclare_class_template (tree, tree); extern tree lookup_template_class (tree, tree, tree, tree, int, tsubst_flags_t); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 0b936ea1a8b..d25aa804971 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2052,7 +2052,7 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend) /* DECL_THUNKS is only valid for virtual functions, otherwise it is a DECL_FRIEND_CONTEXT. */ if (DECL_VIRTUAL_P (newdecl)) - DECL_THUNKS (newdecl) = DECL_THUNKS (olddecl); + SET_DECL_THUNKS (newdecl, DECL_THUNKS (olddecl)); } /* Only variables have this field. */ else if (TREE_CODE (newdecl) == VAR_DECL @@ -5040,6 +5040,7 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, ++index) { tree elt_init; + constructor_elt *old_cur = d->cur; check_array_designated_initializer (d->cur, index); elt_init = reshape_init_r (elt_type, d, /*first_initializer_p=*/false, @@ -5050,6 +5051,10 @@ reshape_init_array_1 (tree elt_type, tree max_index, reshape_iter *d, size_int (index), elt_init); if (!TREE_CONSTANT (elt_init)) TREE_CONSTANT (new_init) = false; + + /* This can happen with an invalid initializer (c++/54501). */ + if (d->cur == old_cur && !sized_array_p) + break; } return new_init; @@ -7416,7 +7421,7 @@ grokfndecl (tree ctype, if (ctype == NULL_TREE && DECL_MAIN_P (decl)) { - if (processing_template_decl) + if (PROCESSING_REAL_TEMPLATE_DECL_P()) error ("cannot declare %<::main%> to be a template"); if (inlinep) error ("cannot declare %<::main%> to be inline"); @@ -10446,7 +10451,11 @@ grokdeclarator (const cp_declarator *declarator, DECL_EXTERNAL (decl) = 1; if (thread_p) - DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); + { + DECL_TLS_MODEL (decl) = decl_default_tls_model (decl); + if (declspecs->gnu_thread_keyword_p) + DECL_GNU_TLS_P (decl) = true; + } if (constexpr_p && !initialized) { diff --git a/gcc/cp/error.c b/gcc/cp/error.c index 2934c9b1078..76f939f1049 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -3374,6 +3374,11 @@ maybe_warn_cpp0x (cpp0x_warn_str str) "delegating constructors " "only available with -std=c++11 or -std=gnu++11"); break; + case CPP0X_INHERITING_CTORS: + pedwarn (input_location, 0, + "inheriting constructors " + "only available with -std=c++11 or -std=gnu++11"); + break; case CPP0X_ATTRIBUTES: pedwarn (input_location, 0, "c++11 attributes " diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 40d0ce325f3..044603887e8 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -1036,7 +1036,8 @@ emit_mem_initializers (tree mem_inits) return; } - if (DECL_DEFAULTED_FN (current_function_decl)) + if (DECL_DEFAULTED_FN (current_function_decl) + && ! DECL_INHERITED_CTOR_BASE (current_function_decl)) flags |= LOOKUP_DEFAULTED; /* Sort the mem-initializers into the order in which the diff --git a/gcc/cp/method.c b/gcc/cp/method.c index a42ed60a99f..4da5cc9ebca 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -126,7 +126,8 @@ make_thunk (tree function, bool this_adjusting, FUNCTION_DECL, NULL_TREE, TREE_TYPE (function)); DECL_LANG_SPECIFIC (thunk) = DECL_LANG_SPECIFIC (function); cxx_dup_lang_specific_decl (thunk); - DECL_THUNKS (thunk) = NULL_TREE; + DECL_VIRTUAL_P (thunk) = true; + SET_DECL_THUNKS (thunk, NULL_TREE); DECL_CONTEXT (thunk) = DECL_CONTEXT (function); TREE_READONLY (thunk) = TREE_READONLY (function); @@ -157,7 +158,7 @@ make_thunk (tree function, bool this_adjusting, /* Add it to the list of thunks associated with FUNCTION. */ DECL_CHAIN (thunk) = DECL_THUNKS (function); - DECL_THUNKS (function) = thunk; + SET_DECL_THUNKS (function, thunk); return thunk; } @@ -428,6 +429,8 @@ type_has_trivial_fn (tree ctype, special_function_kind sfk) return !TYPE_HAS_COMPLEX_MOVE_ASSIGN (ctype); case sfk_destructor: return !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype); + case sfk_inheriting_constructor: + return false; default: gcc_unreachable (); } @@ -459,6 +462,7 @@ type_set_nontrivial_flag (tree ctype, special_function_kind sfk) case sfk_destructor: TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype) = true; return; + case sfk_inheriting_constructor: default: gcc_unreachable (); } @@ -477,7 +481,46 @@ trivial_fn_p (tree fn) return type_has_trivial_fn (DECL_CONTEXT (fn), special_function_p (fn)); } -/* Generate code for default X(X&) or X(X&&) constructor. */ +/* Subroutine of do_build_copy_constructor: Add a mem-initializer for BINFO + given the parameter or parameters PARM, possibly inherited constructor + base INH, or move flag MOVE_P. */ + +static tree +add_one_base_init (tree binfo, tree parm, bool move_p, tree inh, + tree member_init_list) +{ + tree init; + if (inh) + { + /* An inheriting constructor only has a mem-initializer for + the base it inherits from. */ + if (BINFO_TYPE (binfo) != inh) + return member_init_list; + + tree *p = &init; + init = NULL_TREE; + for (; parm; parm = DECL_CHAIN (parm)) + { + tree exp = convert_from_reference (parm); + if (TREE_CODE (TREE_TYPE (parm)) != REFERENCE_TYPE) + exp = move (exp); + *p = build_tree_list (NULL_TREE, exp); + p = &TREE_CHAIN (*p); + } + } + else + { + init = build_base_path (PLUS_EXPR, parm, binfo, 1, + tf_warning_or_error); + if (move_p) + init = move (init); + init = build_tree_list (NULL_TREE, init); + } + return tree_cons (binfo, init, member_init_list); +} + +/* Generate code for default X(X&) or X(X&&) constructor or an inheriting + constructor. */ static void do_build_copy_constructor (tree fndecl) @@ -485,8 +528,10 @@ do_build_copy_constructor (tree fndecl) tree parm = FUNCTION_FIRST_USER_PARM (fndecl); bool move_p = DECL_MOVE_CONSTRUCTOR_P (fndecl); bool trivial = trivial_fn_p (fndecl); + tree inh = DECL_INHERITED_CTOR_BASE (fndecl); - parm = convert_from_reference (parm); + if (!inh) + parm = convert_from_reference (parm); if (trivial && is_empty_class (current_class_type)) @@ -515,14 +560,8 @@ do_build_copy_constructor (tree fndecl) for (vbases = CLASSTYPE_VBASECLASSES (current_class_type), i = 0; VEC_iterate (tree, vbases, i, binfo); i++) { - init = build_base_path (PLUS_EXPR, parm, binfo, 1, - tf_warning_or_error); - if (move_p) - init = move (init); - member_init_list - = tree_cons (binfo, - build_tree_list (NULL_TREE, init), - member_init_list); + member_init_list = add_one_base_init (binfo, parm, move_p, inh, + member_init_list); } for (binfo = TYPE_BINFO (current_class_type), i = 0; @@ -530,15 +569,8 @@ do_build_copy_constructor (tree fndecl) { if (BINFO_VIRTUAL_P (base_binfo)) continue; - - init = build_base_path (PLUS_EXPR, parm, base_binfo, 1, - tf_warning_or_error); - if (move_p) - init = move (init); - member_init_list - = tree_cons (base_binfo, - build_tree_list (NULL_TREE, init), - member_init_list); + member_init_list = add_one_base_init (base_binfo, parm, move_p, + inh, member_init_list); } for (; fields; fields = DECL_CHAIN (fields)) @@ -548,6 +580,8 @@ do_build_copy_constructor (tree fndecl) if (TREE_CODE (field) != FIELD_DECL) continue; + if (inh) + continue; expr_type = TREE_TYPE (field); if (DECL_NAME (field)) @@ -832,8 +866,23 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags, args = make_tree_vector (); if (argtype) { - tree arg = build_stub_object (argtype); - VEC_quick_push (tree, args, arg); + if (TREE_CODE (argtype) == TREE_LIST) + { + for (tree elt = argtype; elt != void_list_node; + elt = TREE_CHAIN (elt)) + { + tree type = TREE_VALUE (elt); + if (TREE_CODE (type) != REFERENCE_TYPE) + type = cp_build_reference_type (type, /*rval*/true); + tree arg = build_stub_object (type); + VEC_safe_push (tree, gc, args, arg); + } + } + else + { + tree arg = build_stub_object (argtype); + VEC_quick_push (tree, args, arg); + } } fns = lookup_fnfields (binfo, name, 0); @@ -1109,7 +1158,8 @@ walk_field_subobs (tree fields, tree fnname, special_function_kind sfk, static void synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, tree *spec_p, bool *trivial_p, bool *deleted_p, - bool *constexpr_p, bool *no_implicit_p, bool diag) + bool *constexpr_p, bool *no_implicit_p, bool diag, + tree inherited_base, tree inherited_parms) { tree binfo, base_binfo, scope, fnname, rval, argtype; bool move_p, copy_arg_p, assign_p, expected_trivial, check_vdtor; @@ -1161,6 +1211,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, case sfk_constructor: case sfk_move_constructor: case sfk_copy_constructor: + case sfk_inheriting_constructor: ctor_p = true; fnname = complete_ctor_identifier; break; @@ -1169,6 +1220,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, gcc_unreachable (); } + gcc_assert ((sfk == sfk_inheriting_constructor) + == (inherited_base != NULL_TREE)); + /* If that user-written default constructor would satisfy the requirements of a constexpr constructor (7.1.5), the implicitly-defined default constructor is constexpr. */ @@ -1180,6 +1234,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, { case sfk_constructor: case sfk_destructor: + case sfk_inheriting_constructor: copy_arg_p = false; break; @@ -1230,7 +1285,9 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, scope = push_scope (ctype); - flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE|LOOKUP_DEFAULTED; + flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE; + if (!inherited_base) + flags |= LOOKUP_DEFAULTED; complain = diag ? tf_warning_or_error : tf_none; @@ -1251,7 +1308,11 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, if (copy_arg_p) argtype = build_stub_type (basetype, quals, move_p); + else if (basetype == inherited_base) + argtype = inherited_parms; rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain); + if (inherited_base) + argtype = NULL_TREE; process_subob_fn (rval, move_p, spec_p, trivial_p, deleted_p, constexpr_p, no_implicit_p, diag, basetype); @@ -1404,14 +1465,16 @@ maybe_explain_implicit_delete (tree decl) } if (!informed) { - tree parm_type = TREE_VALUE (FUNCTION_FIRST_USER_PARMTYPE (decl)); + tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl); + tree parm_type = TREE_VALUE (parms); bool const_p = CP_TYPE_CONST_P (non_reference (parm_type)); tree scope = push_scope (ctype); inform (0, "%q+#D is implicitly deleted because the default " "definition would be ill-formed:", decl); pop_scope (scope); synthesized_method_walk (ctype, sfk, const_p, - NULL, NULL, NULL, NULL, NULL, true); + NULL, NULL, NULL, NULL, NULL, true, + DECL_INHERITED_CTOR_BASE (decl), parms); } input_location = loc; @@ -1431,7 +1494,27 @@ explain_implicit_non_constexpr (tree decl) bool dummy; synthesized_method_walk (DECL_CLASS_CONTEXT (decl), special_function_p (decl), const_p, - NULL, NULL, NULL, &dummy, NULL, true); + NULL, NULL, NULL, &dummy, NULL, true, + NULL_TREE, NULL_TREE); +} + +/* DECL is an instantiation of an inheriting constructor template. Deduce + the correct exception-specification and deletedness for this particular + specialization. */ + +void +deduce_inheriting_ctor (tree decl) +{ + gcc_assert (DECL_INHERITED_CTOR_BASE (decl)); + tree spec; + bool trivial, constexpr_, deleted, no_implicit; + synthesized_method_walk (DECL_CONTEXT (decl), sfk_inheriting_constructor, + false, &spec, &trivial, &deleted, &constexpr_, + &no_implicit, /*diag*/false, + DECL_INHERITED_CTOR_BASE (decl), + FUNCTION_FIRST_USER_PARMTYPE (decl)); + DECL_DELETED_FN (decl) = deleted; + TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec); } /* Implicitly declare the special function indicated by KIND, as a @@ -1441,7 +1524,9 @@ explain_implicit_non_constexpr (tree decl) FUNCTION_DECL for the implicitly declared function. */ tree -implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) +implicitly_declare_fn (special_function_kind kind, tree type, + bool const_p, tree inherited_ctor, + tree inherited_parms) { tree fn; tree parameter_types = void_list_node; @@ -1498,6 +1583,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) case sfk_copy_assignment: case sfk_move_constructor: case sfk_move_assignment: + case sfk_inheriting_constructor: { bool move_p; if (kind == sfk_copy_assignment @@ -1509,23 +1595,44 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) else name = constructor_name (type); - if (const_p) - rhs_parm_type = cp_build_qualified_type (type, TYPE_QUAL_CONST); + if (kind == sfk_inheriting_constructor) + parameter_types = inherited_parms; else - rhs_parm_type = type; - move_p = (kind == sfk_move_assignment - || kind == sfk_move_constructor); - rhs_parm_type = cp_build_reference_type (rhs_parm_type, move_p); + { + if (const_p) + rhs_parm_type = cp_build_qualified_type (type, TYPE_QUAL_CONST); + else + rhs_parm_type = type; + move_p = (kind == sfk_move_assignment + || kind == sfk_move_constructor); + rhs_parm_type = cp_build_reference_type (rhs_parm_type, move_p); - parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types); + parameter_types = tree_cons (NULL_TREE, rhs_parm_type, parameter_types); + } break; } default: gcc_unreachable (); } - synthesized_method_walk (type, kind, const_p, &raises, &trivial_p, - &deleted_p, &constexpr_p, &no_implicit_p, false); + tree inherited_base = (inherited_ctor + ? DECL_CONTEXT (inherited_ctor) + : NULL_TREE); + if (inherited_ctor && TREE_CODE (inherited_ctor) == TEMPLATE_DECL) + { + /* For an inheriting constructor template, just copy these flags from + the inherited constructor template for now. */ + raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (inherited_ctor)); + trivial_p = false; + deleted_p = DECL_DELETED_FN (DECL_TEMPLATE_RESULT (inherited_ctor)); + constexpr_p + = DECL_DECLARED_CONSTEXPR_P (DECL_TEMPLATE_RESULT (inherited_ctor)); + no_implicit_p = false; + } + else + synthesized_method_walk (type, kind, const_p, &raises, &trivial_p, + &deleted_p, &constexpr_p, &no_implicit_p, false, + inherited_base, inherited_parms); /* Don't bother marking a deleted constructor as constexpr. */ if (deleted_p) constexpr_p = false; @@ -1543,9 +1650,10 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) if (raises) fn_type = build_exception_variant (fn_type, raises); fn = build_lang_decl (FUNCTION_DECL, name, fn_type); - DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type)); + if (kind != sfk_inheriting_constructor) + DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (TYPE_NAME (type)); if (kind == sfk_constructor || kind == sfk_copy_constructor - || kind == sfk_move_constructor) + || kind == sfk_move_constructor || kind == sfk_inheriting_constructor) DECL_CONSTRUCTOR_P (fn) = 1; else if (kind == sfk_destructor) DECL_DESTRUCTOR_P (fn) = 1; @@ -1574,6 +1682,27 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) DECL_PARM_INDEX (decl) = DECL_PARM_LEVEL (decl) = 1; DECL_ARGUMENTS (fn) = decl; } + else if (kind == sfk_inheriting_constructor) + { + tree *p = &DECL_ARGUMENTS (fn); + for (tree parm = inherited_parms; parm != void_list_node; + parm = TREE_CHAIN (parm)) + { + *p = cp_build_parm_decl (NULL_TREE, TREE_VALUE (parm)); + DECL_CONTEXT (*p) = fn; + p = &DECL_CHAIN (*p); + } + SET_DECL_INHERITED_CTOR_BASE (fn, inherited_base); + DECL_NONCONVERTING_P (fn) = DECL_NONCONVERTING_P (inherited_ctor); + /* A constructor so declared has the same access as the corresponding + constructor in X. */ + TREE_PRIVATE (fn) = TREE_PRIVATE (inherited_ctor); + TREE_PROTECTED (fn) = TREE_PROTECTED (inherited_ctor); + /* Copy constexpr from the inherited constructor even if the + inheriting constructor doesn't satisfy the requirements. */ + constexpr_p + = DECL_DECLARED_CONSTEXPR_P (STRIP_TEMPLATE (inherited_ctor)); + } /* Add the "this" parameter. */ this_parm = build_this_parm (fn_type, TYPE_UNQUALIFIED); DECL_CHAIN (this_parm) = DECL_ARGUMENTS (fn); @@ -1599,6 +1728,9 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p) /* Restore PROCESSING_TEMPLATE_DECL. */ processing_template_decl = saved_processing_template_decl; + if (inherited_ctor && TREE_CODE (inherited_ctor) == TEMPLATE_DECL) + fn = add_inherited_template_parms (fn, inherited_ctor); + return fn; } @@ -1612,7 +1744,8 @@ defaulted_late_check (tree fn) tree ctx = DECL_CONTEXT (fn); special_function_kind kind = special_function_p (fn); bool fn_const_p = (copy_fn_p (fn) == 2); - tree implicit_fn = implicitly_declare_fn (kind, ctx, fn_const_p); + tree implicit_fn = implicitly_declare_fn (kind, ctx, fn_const_p, + NULL, NULL); if (!same_type_p (TREE_TYPE (TREE_TYPE (fn)), TREE_TYPE (TREE_TYPE (implicit_fn))) @@ -1765,7 +1898,7 @@ lazily_declare_fn (special_function_kind sfk, tree type) } /* Declare the function. */ - fn = implicitly_declare_fn (sfk, type, const_p); + fn = implicitly_declare_fn (sfk, type, const_p, NULL, NULL); /* [class.copy]/8 If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index cd328b31c72..f0105604921 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -3026,6 +3026,14 @@ push_class_level_binding_1 (tree name, tree x) && TREE_TYPE (decl) == error_mark_node) decl = TREE_VALUE (decl); + if (TREE_CODE (decl) == USING_DECL + && TREE_CODE (USING_DECL_SCOPE (decl)) == TEMPLATE_TYPE_PARM + && DECL_NAME (decl) == TYPE_IDENTIFIER (USING_DECL_SCOPE (decl))) + /* This using-declaration declares constructors that inherit from the + constructors for the template parameter. It does not redeclare the + name of the template parameter. */ + return true; + if (!check_template_shadow (decl)) return false; @@ -3218,10 +3226,7 @@ do_class_using_decl (tree scope, tree name) return NULL_TREE; } if (MAYBE_CLASS_TYPE_P (scope) && constructor_name_p (name, scope)) - { - error ("%<%T::%D%> names constructor", scope, name); - return NULL_TREE; - } + maybe_warn_cpp0x (CPP0X_INHERITING_CTORS); if (constructor_name_p (name, current_class_type)) { error ("%<%T::%D%> names constructor in %qT", diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a7939c87647..853d789f987 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -23252,15 +23252,17 @@ cp_parser_optional_template_keyword (cp_parser *parser) { if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE)) { - /* The `template' keyword can only be used within templates; + /* In C++98 the `template' keyword can only be used within templates; outside templates the parser can always figure out what is a - template and what is not. */ - if (!processing_template_decl) + template and what is not. In C++11, per the resolution of DR 468, + `template' is allowed in cases where it is not strictly necessary. */ + if (!processing_template_decl + && pedantic && cxx_dialect == cxx98) { cp_token *token = cp_lexer_peek_token (parser->lexer); - error_at (token->location, - "%<template%> (as a disambiguator) is only allowed " - "within templates"); + pedwarn (token->location, OPT_Wpedantic, + "in C++98 %<template%> (as a disambiguator) is only " + "allowed within templates"); /* If this part of the token stream is rescanned, the same error message would be generated. So, we purge the token from the stream. */ @@ -23274,7 +23276,6 @@ cp_parser_optional_template_keyword (cp_parser *parser) return true; } } - return false; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index d81626cb35e..7e8d8b0880d 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3847,17 +3847,16 @@ arg_from_parm_pack_p (tree arg_pack, tree parm_pack) return false; } -/* Within the declaration of a template, return all levels of template - parameters that apply. The template parameters are represented as - a TREE_VEC, in the form documented in cp-tree.h for template - arguments. */ +/* Given a set of template parameters, return them as a set of template + arguments. The template parameters are represented as a TREE_VEC, in + the form documented in cp-tree.h for template arguments. */ static tree -current_template_args (void) +template_parms_to_args (tree parms) { tree header; tree args = NULL_TREE; - int length = TMPL_PARMS_DEPTH (current_template_parms); + int length = TMPL_PARMS_DEPTH (parms); int l = length; /* If there is only one level of template parameters, we do not @@ -3866,7 +3865,7 @@ current_template_args (void) if (length > 1) args = make_tree_vec (length); - for (header = current_template_parms; header; header = TREE_CHAIN (header)) + for (header = parms; header; header = TREE_CHAIN (header)) { tree a = copy_node (TREE_VALUE (header)); int i; @@ -3903,6 +3902,15 @@ current_template_args (void) return args; } +/* Within the declaration of a template, return the currently active + template parameters as an argument TREE_VEC. */ + +static tree +current_template_args (void) +{ + return template_parms_to_args (current_template_parms); +} + /* Update the declared TYPE by doing any lookups which were thought to be dependent, but are not now that we know the SCOPE of the declarator. */ @@ -4904,6 +4912,29 @@ push_template_decl (tree decl) return push_template_decl_real (decl, false); } +/* FN is an inheriting constructor that inherits from the constructor + template INHERITED; turn FN into a constructor template with a matching + template header. */ + +tree +add_inherited_template_parms (tree fn, tree inherited) +{ + tree inner_parms + = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (inherited)); + inner_parms = copy_node (inner_parms); + tree parms + = tree_cons (size_int (processing_template_decl + 1), + inner_parms, current_template_parms); + tree tmpl = build_template_decl (fn, parms, /*member*/true); + tree args = template_parms_to_args (parms); + DECL_TEMPLATE_INFO (fn) = build_template_info (tmpl, args); + TREE_TYPE (tmpl) = TREE_TYPE (fn); + DECL_TEMPLATE_RESULT (tmpl) = fn; + DECL_ARTIFICIAL (tmpl) = true; + DECL_PRIMARY_TEMPLATE (tmpl) = tmpl; + return tmpl; +} + /* Called when a class template TYPE is redeclared with the indicated template PARMS, e.g.: @@ -10136,6 +10167,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) maybe_retrofit_in_chrg (r); if (DECL_CONSTRUCTOR_P (r)) grok_ctor_properties (ctx, r); + if (DECL_INHERITED_CTOR_BASE (r)) + deduce_inheriting_ctor (r); /* If this is an instantiation of a member template, clone it. If it isn't, that'll be handled by clone_constructors_and_destructors. */ @@ -10336,9 +10369,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) if (DECL_DEPENDENT_P (t) || uses_template_parms (USING_DECL_SCOPE (t))) { - r = do_class_using_decl - (tsubst_copy (USING_DECL_SCOPE (t), args, complain, in_decl), - tsubst_copy (DECL_NAME (t), args, complain, in_decl)); + tree scope = USING_DECL_SCOPE (t); + tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args, + complain, in_decl); + tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl); + if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM + && name == TYPE_IDENTIFIER (scope)) + name = TYPE_IDENTIFIER (inst_scope); + r = do_class_using_decl (inst_scope, name); if (!r) r = error_mark_node; else diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 4beed0073fb..6798c1bf5d4 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2173,16 +2173,30 @@ finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual, { if (warn_sizeof_pointer_memaccess && !VEC_empty(tree, *args) - && TREE_CODE (VEC_last(tree, *args)) == SIZEOF_EXPR && !processing_template_decl) { - tree sizeof_arg = VEC_last(tree, *args); - if (SIZEOF_EXPR_TYPE_P (sizeof_arg)) - sizeof_arg = TREE_TYPE (TREE_OPERAND (sizeof_arg, 0)); - else - sizeof_arg = TREE_OPERAND (sizeof_arg, 0); + location_t sizeof_arg_loc[3]; + tree sizeof_arg[3]; + unsigned int i; + for (i = 0; i < 3; i++) + { + tree t; + + sizeof_arg_loc[i] = UNKNOWN_LOCATION; + sizeof_arg[i] = NULL_TREE; + if (i >= VEC_length (tree, *args)) + continue; + t = VEC_index (tree, *args, i); + if (TREE_CODE (t) != SIZEOF_EXPR) + continue; + if (SIZEOF_EXPR_TYPE_P (t)) + sizeof_arg[i] = TREE_TYPE (TREE_OPERAND (t, 0)); + else + sizeof_arg[i] = TREE_OPERAND (t, 0); + sizeof_arg_loc[i] = EXPR_LOCATION (t); + } sizeof_pointer_memaccess_warning - (EXPR_LOCATION (VEC_last(tree, *args)), fn, *args, + (sizeof_arg_loc, fn, *args, sizeof_arg, same_type_ignoring_top_level_qualifiers_p); } diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index a41337c2116..8d555c2e2b1 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3337,6 +3337,8 @@ special_function_p (const_tree decl) /* Rather than doing all this stuff with magic names, we should probably have a field of type `special_function_kind' in DECL_LANG_SPECIFIC. */ + if (DECL_INHERITED_CTOR_BASE (decl)) + return sfk_inheriting_constructor; if (DECL_COPY_CONSTRUCTOR_P (decl)) return sfk_copy_constructor; if (DECL_MOVE_CONSTRUCTOR_P (decl)) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 13e75ab9ebf..eaa0935dc98 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -2908,6 +2908,10 @@ cp_build_indirect_ref (tree ptr, ref_operator errorstring, case RO_IMPLICIT_CONVERSION: error ("invalid use of implicit conversion on pointer to member"); break; + case RO_ARROW_STAR: + error ("left hand operand of %<->*%> must be a pointer to class, " + "but is a pointer to member of type %qT", type); + break; default: gcc_unreachable (); } |