Commit fe7a23a6 by Jason Merrill Committed by Jason Merrill

pt.c (tsubst_default_argument): Use push_to/pop_from_top_level.

	* pt.c (tsubst_default_argument): Use push_to/pop_from_top_level.

	* name-lookup.c (do_pushtag): Don't look through complete types, but
	don't add to them either.  Get context from current_binding_level.

From-SVN: r261656
parent b4cf2e42
2018-06-15 Jason Merrill <jason@redhat.com> 2018-06-15 Jason Merrill <jason@redhat.com>
* name-lookup.c (do_pushtag): Don't look through complete types, but
don't add to them either. Get context from current_binding_level.
* pt.c (tsubst_default_argument): Use push_to/pop_from_top_level.
* decl.c (start_enum): Do compare dependent underlying type. * decl.c (start_enum): Do compare dependent underlying type.
PR c++/82882 - ICE with lambda in template default argument. PR c++/82882 - ICE with lambda in template default argument.
......
...@@ -6521,12 +6521,7 @@ do_pushtag (tree name, tree type, tag_scope scope) ...@@ -6521,12 +6521,7 @@ do_pushtag (tree name, tree type, tag_scope scope)
|| (b->kind == sk_template_parms || (b->kind == sk_template_parms
&& (b->explicit_spec_p || scope == ts_global)) && (b->explicit_spec_p || scope == ts_global))
|| (b->kind == sk_class || (b->kind == sk_class
&& (scope != ts_current && scope != ts_current))
/* We may be defining a new type in the initializer
of a static member variable. We allow this when
not pedantic, and it is particularly useful for
type punning via an anonymous union. */
|| COMPLETE_TYPE_P (b->this_entity))))
b = b->level_chain; b = b->level_chain;
gcc_assert (identifier_p (name)); gcc_assert (identifier_p (name));
...@@ -6540,15 +6535,18 @@ do_pushtag (tree name, tree type, tag_scope scope) ...@@ -6540,15 +6535,18 @@ do_pushtag (tree name, tree type, tag_scope scope)
if (! context) if (! context)
{ {
tree cs = current_scope (); cp_binding_level *cb = b;
while (cb->kind != sk_namespace
/* Avoid setting the lambda context to a current_function_decl that && cb->kind != sk_class
we aren't actually inside, e.g. one set by push_access_scope && (cb->kind != sk_function_parms
during tsubst_default_argument. */ || !cb->this_entity))
if (cs && TREE_CODE (cs) == FUNCTION_DECL cb = cb->level_chain;
&& LAMBDA_TYPE_P (type) tree cs = cb->this_entity;
&& !at_function_scope_p ())
cs = DECL_CONTEXT (cs); gcc_checking_assert (TREE_CODE (cs) == FUNCTION_DECL
? cs == current_function_decl
: TYPE_P (cs) ? cs == current_class_type
: cs == current_namespace);
if (scope == ts_current if (scope == ts_current
|| (cs && TREE_CODE (cs) == FUNCTION_DECL)) || (cs && TREE_CODE (cs) == FUNCTION_DECL))
...@@ -6587,11 +6585,11 @@ do_pushtag (tree name, tree type, tag_scope scope) ...@@ -6587,11 +6585,11 @@ do_pushtag (tree name, tree type, tag_scope scope)
if (b->kind == sk_class) if (b->kind == sk_class)
{ {
if (!TYPE_BEING_DEFINED (current_class_type) if (!TYPE_BEING_DEFINED (current_class_type))
&& !LAMBDA_TYPE_P (type)) /* Don't push anywhere if the class is complete; a lambda in an
return error_mark_node; NSDMI is not a member of the class. */
;
if (!PROCESSING_REAL_TEMPLATE_DECL_P ()) else if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
/* Put this TYPE_DECL on the TYPE_FIELDS list for the /* Put this TYPE_DECL on the TYPE_FIELDS list for the
class. But if it's a member template class, we want class. But if it's a member template class, we want
the TEMPLATE_DECL, not the TYPE_DECL, so this is done the TEMPLATE_DECL, not the TYPE_DECL, so this is done
......
...@@ -12675,8 +12675,6 @@ tree ...@@ -12675,8 +12675,6 @@ tree
tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
tsubst_flags_t complain) tsubst_flags_t complain)
{ {
tree saved_class_ptr = NULL_TREE;
tree saved_class_ref = NULL_TREE;
int errs = errorcount + sorrycount; int errs = errorcount + sorrycount;
/* This can happen in invalid code. */ /* This can happen in invalid code. */
...@@ -12709,19 +12707,10 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, ...@@ -12709,19 +12707,10 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
we must be careful to do name lookup in the scope of S<T>, we must be careful to do name lookup in the scope of S<T>,
rather than in the current class. */ rather than in the current class. */
push_to_top_level ();
push_access_scope (fn); push_access_scope (fn);
/* The "this" pointer is not valid in a default argument. */
if (cfun)
{
saved_class_ptr = current_class_ptr;
cp_function_chain->x_current_class_ptr = NULL_TREE;
saved_class_ref = current_class_ref;
cp_function_chain->x_current_class_ref = NULL_TREE;
}
start_lambda_scope (parm); start_lambda_scope (parm);
push_deferring_access_checks(dk_no_deferred);
/* The default argument expression may cause implicitly defined /* The default argument expression may cause implicitly defined
member functions to be synthesized, which will result in garbage member functions to be synthesized, which will result in garbage
collection. We must treat this situation as if we were within collection. We must treat this situation as if we were within
...@@ -12732,17 +12721,9 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, ...@@ -12732,17 +12721,9 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
complain, NULL_TREE, complain, NULL_TREE,
/*integral_constant_expression_p=*/false); /*integral_constant_expression_p=*/false);
--function_depth; --function_depth;
pop_deferring_access_checks();
finish_lambda_scope (); finish_lambda_scope ();
/* Restore the "this" pointer. */
if (cfun)
{
cp_function_chain->x_current_class_ptr = saved_class_ptr;
cp_function_chain->x_current_class_ref = saved_class_ref;
}
if (errorcount+sorrycount > errs if (errorcount+sorrycount > errs
&& (complain & tf_warning_or_error)) && (complain & tf_warning_or_error))
inform (input_location, inform (input_location,
...@@ -12752,6 +12733,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg, ...@@ -12752,6 +12733,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
arg = check_default_argument (type, arg, complain); arg = check_default_argument (type, arg, complain);
pop_access_scope (fn); pop_access_scope (fn);
pop_from_top_level ();
if (arg != error_mark_node && !cp_unevaluated_operand) if (arg != error_mark_node && !cp_unevaluated_operand)
{ {
......
// PR c++/50861 // PR c++/50861
template<class T> struct A {A(int b=k(0));}; // { dg-error "parameter|argument" } template<class T> struct A {A(int b=k(0));}; // { dg-error "not declared" }
void f(int k){A<int> a;} // // { dg-message "declared" } // { dg-error "that depend on a template parameter" "" { target *-*-* } .-1 }
// { dg-message "note" "note" { target *-*-* } 3 } void f(int k){A<int> a;}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment