summaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2014-03-18 11:54:04 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2014-03-18 11:54:04 +0000
commit63f3c6bcb4f99fa87d29566c1ffdae7e7323eb73 (patch)
tree544f59df718a97a96b5785df69707cfea87a1e9a /gcc/cp
parente2fe47a8304852a566bf052e7f23069b007fa2e4 (diff)
downloadgcc-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/ChangeLog49
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/method.c19
-rw-r--r--gcc/cp/parser.c46
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/cp/search.c16
-rw-r--r--gcc/cp/semantics.c35
-rw-r--r--gcc/cp/typeck2.c2
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)