pt.c (tsubst_default_argument): Use push_to/pop_from_top_level.
authorJason Merrill <jason@redhat.com>
Fri, 15 Jun 2018 20:23:00 +0000 (16:23 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 15 Jun 2018 20:23:00 +0000 (16:23 -0400)
* 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

gcc/cp/ChangeLog
gcc/cp/name-lookup.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/template/crash108.C

index d8ce66eb22c401187b60e0f4339867575c4c287d..56fe205fdbc2863676c3d1ab6ca010ed43ee2902 100644 (file)
@@ -1,5 +1,9 @@
 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.
 
        PR c++/82882 - ICE with lambda in template default argument.
index 7990029d70cd16f7dd5374245a801edcebbecd70..ec001016d3ed40a0ef4c57fa1035f5ba7c659ea2 100644 (file)
@@ -6521,12 +6521,7 @@ do_pushtag (tree name, tree type, tag_scope scope)
         || (b->kind == sk_template_parms
             && (b->explicit_spec_p || scope == ts_global))
         || (b->kind == sk_class
-            && (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))))
+            && scope != ts_current))
     b = b->level_chain;
 
   gcc_assert (identifier_p (name));
@@ -6540,15 +6535,18 @@ do_pushtag (tree name, tree type, tag_scope scope)
 
       if (! context)
        {
-         tree cs = current_scope ();
-
-         /* Avoid setting the lambda context to a current_function_decl that
-            we aren't actually inside, e.g. one set by push_access_scope
-            during tsubst_default_argument.  */
-         if (cs && TREE_CODE (cs) == FUNCTION_DECL
-             && LAMBDA_TYPE_P (type)
-             && !at_function_scope_p ())
-           cs = DECL_CONTEXT (cs);
+         cp_binding_level *cb = b;
+         while (cb->kind != sk_namespace
+                && cb->kind != sk_class
+                && (cb->kind != sk_function_parms
+                    || !cb->this_entity))
+           cb = cb->level_chain;
+         tree cs = cb->this_entity;
+
+         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
              || (cs && TREE_CODE (cs) == FUNCTION_DECL))
@@ -6587,11 +6585,11 @@ do_pushtag (tree name, tree type, tag_scope scope)
 
       if (b->kind == sk_class)
        {
-         if (!TYPE_BEING_DEFINED (current_class_type)
-             && !LAMBDA_TYPE_P (type))
-           return error_mark_node;
-
-         if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
+         if (!TYPE_BEING_DEFINED (current_class_type))
+           /* Don't push anywhere if the class is complete; a lambda in an
+              NSDMI is not a member of the class.  */
+           ;
+         else if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
            /* Put this TYPE_DECL on the TYPE_FIELDS list for the
               class.  But if it's a member template class, we want
               the TEMPLATE_DECL, not the TYPE_DECL, so this is done
index ed634ddeefbdc2fde0bc38621024e249e61c3371..4ee84b201e9e9f5d27e37f4d8ca2b90d052a8c87 100644 (file)
@@ -12675,8 +12675,6 @@ tree
 tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
                         tsubst_flags_t complain)
 {
-  tree saved_class_ptr = NULL_TREE;
-  tree saved_class_ref = NULL_TREE;
   int errs = errorcount + sorrycount;
 
   /* This can happen in invalid code.  */
@@ -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>,
      rather than in the current class.  */
+  push_to_top_level ();
   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);
 
-  push_deferring_access_checks(dk_no_deferred);
   /* The default argument expression may cause implicitly defined
      member functions to be synthesized, which will result in garbage
      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,
                     complain, NULL_TREE,
                     /*integral_constant_expression_p=*/false);
   --function_depth;
-  pop_deferring_access_checks();
 
   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
       && (complain & tf_warning_or_error))
     inform (input_location,
@@ -12752,6 +12733,7 @@ tsubst_default_argument (tree fn, int parmnum, tree type, tree arg,
   arg = check_default_argument (type, arg, complain);
 
   pop_access_scope (fn);
+  pop_from_top_level ();
 
   if (arg != error_mark_node && !cp_unevaluated_operand)
     {
index 9bcabc6009bb4f4ff489f8f5046f93240564344a..3ffadc14c256cac39733a9a59c607e026bd69d23 100644 (file)
@@ -1,5 +1,5 @@
 // PR c++/50861
 
-template<class T> struct A {A(int b=k(0));}; // { dg-error "parameter|argument" }
-void f(int k){A<int> a;} // // { dg-message "declared" }
-// { dg-message "note" "note" { target *-*-* } 3 }
+template<class T> struct A {A(int b=k(0));}; // { dg-error "not declared" }
+ // { dg-error "that depend on a template parameter" "" { target *-*-* } .-1 }
+void f(int k){A<int> a;}