diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-03-18 11:54:04 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2014-03-18 11:54:04 +0000 |
commit | 63f3c6bcb4f99fa87d29566c1ffdae7e7323eb73 (patch) | |
tree | 544f59df718a97a96b5785df69707cfea87a1e9a /gcc/cp | |
parent | e2fe47a8304852a566bf052e7f23069b007fa2e4 (diff) | |
download | gcc-63f3c6bcb4f99fa87d29566c1ffdae7e7323eb73.tar.gz |
2014-03-18 Basile Starynkevitch <basile@starynkevitch.net>
{{merge using svnmerge.py with trunk GCC 4.9 svn rev.208631. All
is well compiled.}}
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@208642 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 49 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/method.c | 19 | ||||
-rw-r--r-- | gcc/cp/parser.c | 46 | ||||
-rw-r--r-- | gcc/cp/pt.c | 4 | ||||
-rw-r--r-- | gcc/cp/search.c | 16 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 35 | ||||
-rw-r--r-- | gcc/cp/typeck2.c | 2 |
8 files changed, 150 insertions, 22 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 4aa90ee4008..3cf68583fcc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,52 @@ +2014-03-17 Adam Butcher <adam@jessamine.co.uk> + + PR c++/60390 + * parser.c (cp_parser_member_declaration): Don't allow + finish_fully_implicit_template to consider friend declarations to be + class member templates. + (synthesize_implicit_template_parm): Handling winding back through class + scope to the class being defined in order to inject a template argument + list. + + PR c++/60391 + * parser.c (cp_parser_skip_to_end_of_block_or_statement): Unwind generic + function scope as per cp_parser_skip_to_end_of_statement. + +2014-03-17 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/59571 + * typeck2.c (check_narrowing): Use fold_non_dependent_expr_sfinae. + +2014-03-14 Jason Merrill <jason@redhat.com> + + PR c++/60532 + PR c++/58678 + * search.c (get_pure_virtuals): Handle abstract dtor here. + (dfs_get_pure_virtuals): Not here. + + PR c++/58678 + * search.c (dfs_get_pure_virtuals): Treat the destructor of an + abstract class as pure. + +2014-03-13 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/60383 + * pt.c (maybe_process_partial_specialization): Check return value + of check_specialization_namespace. + +2014-03-13 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/60254 + * semantics.c (finish_static_assert): Call cxx_constant_value only + if require_potential_rvalue_constant_expression returns true. + +2014-03-11 Paolo Carlini <paolo.carlini@oracle.com> + + PR c++/60389 + * method.c (get_inherited_ctor): New. + * cp-tree.h (get_inherited_ctor): Declare it. + * semantics.c (is_valid_constexpr_fn): Use it. + 2014-03-10 Jason Merrill <jason@redhat.com> PR c++/60367 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 45e4d821746..e9fe86ee4cd 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5476,6 +5476,7 @@ extern tree get_copy_ctor (tree, tsubst_flags_t); extern tree get_copy_assign (tree); extern tree get_default_ctor (tree); extern tree get_dtor (tree, tsubst_flags_t); +extern tree get_inherited_ctor (tree); extern tree locate_ctor (tree); extern tree implicitly_declare_fn (special_function_kind, tree, bool, tree, tree); diff --git a/gcc/cp/method.c b/gcc/cp/method.c index c3940f2d9b4..d72b564a464 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -971,6 +971,25 @@ get_copy_assign (tree type) return fn; } +/* Locate the inherited constructor of constructor CTOR. */ + +tree +get_inherited_ctor (tree ctor) +{ + gcc_assert (DECL_INHERITED_CTOR_BASE (ctor)); + + push_deferring_access_checks (dk_no_check); + tree fn = locate_fn_flags (DECL_INHERITED_CTOR_BASE (ctor), + complete_ctor_identifier, + FUNCTION_FIRST_USER_PARMTYPE (ctor), + LOOKUP_NORMAL|LOOKUP_SPECULATIVE, + tf_none); + pop_deferring_access_checks (); + if (fn == error_mark_node) + return NULL_TREE; + return fn; +} + /* Subroutine of synthesized_method_walk. Update SPEC_P, TRIVIAL_P and DELETED_P or give an error message MSG with argument ARG. */ diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a3c8d7ecb3f..46e2453e51b 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -3225,6 +3225,10 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser) { int nesting_depth = 0; + /* Unwind generic function template scope if necessary. */ + if (parser->fully_implicit_function_template_p) + finish_fully_implicit_template (parser, /*member_decl_opt=*/0); + while (nesting_depth >= 0) { cp_token *token = cp_lexer_peek_token (parser->lexer); @@ -20523,8 +20527,13 @@ cp_parser_member_declaration (cp_parser* parser) decl = grokfield (declarator, &decl_specifiers, initializer, /*init_const_expr_p=*/true, asm_specification, attributes); - if (parser->fully_implicit_function_template_p) - decl = finish_fully_implicit_template (parser, decl); + if (parser->fully_implicit_function_template_p) + { + if (friend_p) + finish_fully_implicit_template (parser, 0); + else + decl = finish_fully_implicit_template (parser, decl); + } } cp_finalize_omp_declare_simd (parser, decl); @@ -31978,13 +31987,32 @@ synthesize_implicit_template_parm (cp_parser *parser) parent_scope = scope; scope = scope->level_chain; } - if (current_class_type && !LAMBDA_TYPE_P (current_class_type) - && parser->num_classes_being_defined == 0) - while (scope->kind == sk_class) - { - parent_scope = scope; - scope = scope->level_chain; - } + if (current_class_type && !LAMBDA_TYPE_P (current_class_type)) + { + /* If not defining a class, then any class scope is a scope level in + an out-of-line member definition. In this case simply wind back + beyond the first such scope to inject the template argument list. + Otherwise wind back to the class being defined. The latter can + occur in class member friend declarations such as: + + class A { + void foo (auto); + }; + class B { + friend void A::foo (auto); + }; + + The template argument list synthesized for the friend declaration + must be injected in the scope of 'B', just beyond the scope of 'A' + introduced by 'A::'. */ + + while (scope->kind == sk_class + && !TYPE_BEING_DEFINED (scope->this_entity)) + { + parent_scope = scope; + scope = scope->level_chain; + } + } current_binding_level = scope; diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7e287f793e8..c791d031ae1 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -850,7 +850,9 @@ maybe_process_partial_specialization (tree type) if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) { - check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type)); + if (!check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type)) + && !at_namespace_scope_p ()) + return error_mark_node; SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location; if (processing_template_decl) diff --git a/gcc/cp/search.c b/gcc/cp/search.c index c3eed90f6c3..d99e18215fa 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -2115,6 +2115,22 @@ get_pure_virtuals (tree type) which it is a primary base will contain vtable entries for the pure virtuals in the base class. */ dfs_walk_once (TYPE_BINFO (type), NULL, dfs_get_pure_virtuals, type); + + /* Treat a virtual destructor in an abstract class as pure even if it + isn't declared as pure; there is no way it would be called through the + vtable except during construction, which causes undefined behavior. */ + if (CLASSTYPE_PURE_VIRTUALS (type) + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) + { + tree dtor = CLASSTYPE_DESTRUCTORS (type); + if (dtor && DECL_VIRTUAL_P (dtor) && !DECL_PURE_VIRTUAL_P (dtor)) + { + tree clone; + DECL_PURE_VIRTUAL_P (dtor) = true; + FOR_EACH_CLONE (clone, dtor) + DECL_PURE_VIRTUAL_P (clone) = true; + } + } } /* Debug info for C++ classes can get very large; try to avoid diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index fcd84095657..886fbb88bc9 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -6860,7 +6860,8 @@ finish_static_assert (tree condition, tree message, location_t location, else if (condition && condition != error_mark_node) { error ("non-constant condition for static assertion"); - cxx_constant_value (condition); + if (require_potential_rvalue_constant_expression (condition)) + cxx_constant_value (condition); } input_location = saved_loc; } @@ -7438,19 +7439,31 @@ retrieve_constexpr_fundef (tree fun) static bool is_valid_constexpr_fn (tree fun, bool complain) { - tree parm = FUNCTION_FIRST_USER_PARM (fun); bool ret = true; - for (; parm != NULL; parm = TREE_CHAIN (parm)) - if (!literal_type_p (TREE_TYPE (parm))) - { - ret = false; - if (complain) + + if (DECL_INHERITED_CTOR_BASE (fun) + && TREE_CODE (fun) == TEMPLATE_DECL) + { + ret = false; + if (complain) + error ("inherited constructor %qD is not constexpr", + get_inherited_ctor (fun)); + } + else + { + for (tree parm = FUNCTION_FIRST_USER_PARM (fun); + parm != NULL_TREE; parm = TREE_CHAIN (parm)) + if (!literal_type_p (TREE_TYPE (parm))) { - error ("invalid type for parameter %d of constexpr " - "function %q+#D", DECL_PARM_INDEX (parm), fun); - explain_non_literal_class (TREE_TYPE (parm)); + ret = false; + if (complain) + { + error ("invalid type for parameter %d of constexpr " + "function %q+#D", DECL_PARM_INDEX (parm), fun); + explain_non_literal_class (TREE_TYPE (parm)); + } } - } + } if (!DECL_CONSTRUCTOR_P (fun)) { diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 3a4caa0dafc..bd21ad8c3f3 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -861,7 +861,7 @@ check_narrowing (tree type, tree init) return; } - init = maybe_constant_value (init); + init = maybe_constant_value (fold_non_dependent_expr_sfinae (init, tf_none)); if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (ftype) == REAL_TYPE) |