]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/cp/pt.c
re PR debug/23336 (enum constants not visible to gdb because of -feliminate-unused...
[thirdparty/gcc.git] / gcc / cp / pt.c
index 89afb5fe3b94e02102638c8ea4b1dd4d58856caa..30e6cd09a4b301df0ec7f89e1c965e31a9610394 100644 (file)
@@ -336,7 +336,12 @@ push_inline_template_parms_recursive (tree parmlist, int levels)
               NULL);
   for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
     {
-      tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+      tree parm;
+
+      if (TREE_VEC_ELT (parms, i) == error_mark_node)
+        continue;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
       gcc_assert (DECL_P (parm));
 
       switch (TREE_CODE (parm))
@@ -1224,7 +1229,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
      template it is specializing.  */
   if (DECL_TEMPLATE_SPECIALIZATION (spec)
       && !check_specialization_namespace (tmpl))
-    DECL_CONTEXT (spec) = decl_namespace_context (tmpl);
+    DECL_CONTEXT (spec) = FROB_CONTEXT (decl_namespace_context (tmpl));
 
   if (!optimize_specialization_lookup_p (tmpl))
     DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
@@ -2140,13 +2145,7 @@ check_explicit_specialization (tree declarator,
             template it specializes.  */
          TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl);
          TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl);
-         /* The specialization has the same visibility as the
-            template it specializes.  */
-         if (DECL_VISIBILITY_SPECIFIED (gen_tmpl))
-           {
-             DECL_VISIBILITY_SPECIFIED (decl) = 1;
-             DECL_VISIBILITY (decl) = DECL_VISIBILITY (gen_tmpl);
-           }
+
          /* If DECL is a friend declaration, declared using an
             unqualified name, the namespace associated with DECL may
             have been set incorrectly.  For example, in:
@@ -2210,8 +2209,15 @@ comp_template_parms (tree parms1, tree parms2)
 
       for (i = 0; i < TREE_VEC_LENGTH (t2); ++i)
        {
-         tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
-         tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
+          tree parm1;
+          tree parm2;
+
+          if (TREE_VEC_ELT (t1, i) == error_mark_node
+              || TREE_VEC_ELT (t2, i) == error_mark_node)
+            continue;
+
+         parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i));
+          parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i));
 
          if (TREE_CODE (parm1) != TREE_CODE (parm2))
            return 0;
@@ -2368,7 +2374,7 @@ process_template_parm (tree list, tree parm, bool is_non_type)
       SET_DECL_TEMPLATE_PARM_P (parm);
 
       if (TREE_TYPE (parm) == error_mark_node)
-       TREE_TYPE (parm) = void_type_node;
+       return chainon(list, error_mark_node);
       else
       {
        /* [temp.param]
@@ -2377,7 +2383,7 @@ process_template_parm (tree list, tree parm, bool is_non_type)
           ignored when determining its type.  */
        TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
        if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
-         TREE_TYPE (parm) = void_type_node;
+         return chainon(list, error_mark_node);
       }
 
       /* A template parameter is not modifiable.  */
@@ -2844,6 +2850,10 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, int is_partial)
       for (i = 0; i < ntparms; ++i)
        {
          tree parm = TREE_VEC_ELT (inner_parms, i);
+
+          if (parm == error_mark_node)
+            continue;
+
          if (TREE_PURPOSE (parm))
            seen_def_arg_p = 1;
          else if (seen_def_arg_p)
@@ -2908,18 +2918,23 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary, int is_partial)
 
       ntparms = TREE_VEC_LENGTH (inner_parms);
       for (i = 0; i < ntparms; ++i)
-       if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
-         {
-           if (msg)
-             {
-               error (msg, decl);
-               msg = 0;
-             }
+        {
+          if (TREE_VEC_ELT (inner_parms, i) == error_mark_node)
+            continue;
 
-           /* Clear out the default argument so that we are not
-              confused later.  */
-           TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
-         }
+         if (TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)))
+           {
+             if (msg)
+               {
+                 error (msg, decl);
+                 msg = 0;
+               }
+
+             /* Clear out the default argument so that we are not
+                confused later.  */
+             TREE_PURPOSE (TREE_VEC_ELT (inner_parms, i)) = NULL_TREE;
+           }
+        }
 
       /* At this point, if we're still interested in issuing messages,
         they must apply to classes surrounding the object declared.  */
@@ -3592,9 +3607,9 @@ convert_nontype_argument (tree type, tree expr)
 
       if (!constant_address_p)
        {
-           error ("%qE is not a valid template argument for type %qT "
-                 "because it is not a constant pointer", expr, type);
-           return NULL_TREE;
+         error ("%qE is not a valid template argument for type %qT "
+                "because it is not a constant pointer", expr, type);
+         return NULL_TREE;
        }
     }
   /* [temp.arg.nontype]/5, bullet 3
@@ -3770,6 +3785,9 @@ coerce_template_template_parms (tree parm_parms,
 
   for (i = 0; i < nparms; ++i)
     {
+      if (TREE_VEC_ELT (parm_parms, i) == error_mark_node)
+        continue;
+
       parm = TREE_VALUE (TREE_VEC_ELT (parm_parms, i));
       arg = TREE_VALUE (TREE_VEC_ELT (arg_parms, i));
 
@@ -3837,11 +3855,8 @@ convert_template_argument (tree parm,
                           tree in_decl)
 {
   tree val;
-  tree inner_args;
   int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
 
-  inner_args = INNERMOST_TEMPLATE_ARGS (args);
-
   if (TREE_CODE (arg) == TREE_LIST
       && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
     {
@@ -3933,7 +3948,7 @@ convert_template_argument (tree parm,
 
              if (coerce_template_template_parms (parmparm, argparm,
                                                  complain, in_decl,
-                                                 inner_args))
+                                                 args))
                {
                  val = arg;
 
@@ -4032,7 +4047,8 @@ coerce_template_parms (tree parms,
       || (nargs < nparms
          && require_all_args
          && (!use_default_args
-             || !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs)))))
+             || (TREE_VEC_ELT (parms, nargs) != error_mark_node
+                  && !TREE_PURPOSE (TREE_VEC_ELT (parms, nargs))))))
     {
       if (complain & tf_error)
        {
@@ -4055,6 +4071,9 @@ coerce_template_parms (tree parms,
 
       /* Get the Ith template parameter.  */
       parm = TREE_VEC_ELT (parms, i);
+      if (parm == error_mark_node)
+        continue;
 
       /* Calculate the Ith argument.  */
       if (i < nargs)
@@ -4155,8 +4174,14 @@ mangle_class_name_for_template (const char* name, tree parms, tree arglist)
   gcc_assert (nparms == TREE_VEC_LENGTH (arglist));
   for (i = 0; i < nparms; i++)
     {
-      tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
-      tree arg = TREE_VEC_ELT (arglist, i);
+      tree parm;
+      tree arg;
+
+      if (TREE_VEC_ELT (parms, i) == error_mark_node)
+        continue;
+
+      parm = TREE_VALUE (TREE_VEC_ELT (parms, i));
+      arg = TREE_VEC_ELT (arglist, i);
 
       if (i)
        ccat (',');
@@ -4785,6 +4810,10 @@ lookup_template_class (tree d1,
           code that generates debugging information will crash.  */
        DECL_IGNORED_P (TYPE_STUB_DECL (t)) = 1;
 
+      /* Possibly limit visibility based on template args.  */
+      TREE_PUBLIC (type_decl) = 1;
+      determine_visibility (type_decl);
+
       POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
     }
   timevar_pop (TV_NAME_LOOKUP);
@@ -5413,8 +5442,21 @@ tsubst_friend_class (tree friend_tmpl, tree args)
        push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
     }
 
-  /* First, we look for a class template.  */
-  tmpl = lookup_name (DECL_NAME (friend_tmpl));
+  /* Look for a class template declaration.  We look for hidden names
+     because two friend declarations of the same template are the
+     same.  For example, in:
+
+       struct A { 
+         template <typename> friend class F;
+       };
+       template <typename> struct B { 
+         template <typename> friend class F;
+       };
+
+     both F templates are the same.  */
+  tmpl = lookup_name_real (DECL_NAME (friend_tmpl), 0, 0,
+                          /*block_p=*/true, 0, 
+                          LOOKUP_COMPLAIN | LOOKUP_HIDDEN);
 
   /* But, if we don't find one, it might be because we're in a
      situation like this:
@@ -6045,9 +6087,20 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
 
       for (i = 0; i < TREE_VEC_LENGTH (new_vec); ++i)
        {
-         tree tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
-         tree default_value = TREE_PURPOSE (tuple);
-         tree parm_decl = TREE_VALUE (tuple);
+          tree tuple;
+          tree default_value;
+          tree parm_decl;
+
+          if (parms == error_mark_node)
+            continue;
+
+          tuple = TREE_VEC_ELT (TREE_VALUE (parms), i);
+
+          if (tuple == error_mark_node)
+            continue;
+
+          default_value = TREE_PURPOSE (tuple);
+          parm_decl = TREE_VALUE (tuple);
 
          parm_decl = tsubst (parm_decl, args, complain, NULL_TREE);
          if (TREE_CODE (parm_decl) == PARM_DECL
@@ -6591,6 +6644,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
          SET_DECL_FRIEND_CONTEXT (r,
                                   tsubst (DECL_FRIEND_CONTEXT (t),
                                            args, complain, in_decl));
+
+       /* Possibly limit visibility based on template args.  */
+       DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
+       if (DECL_VISIBILITY_SPECIFIED (t))
+         {
+           DECL_VISIBILITY_SPECIFIED (r) = 0;
+           DECL_ATTRIBUTES (r)
+             = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
+         }
+       determine_visibility (r);
       }
       break;
 
@@ -6673,7 +6736,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        tree tmpl = NULL_TREE;
        tree ctx;
        tree type = NULL_TREE;
-       int local_p;
+       bool local_p;
 
        if (TREE_CODE (t) == TYPE_DECL)
          {
@@ -6691,40 +6754,64 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
              }
          }
 
-       /* Assume this is a non-local variable.  */
-       local_p = 0;
+       /* Check to see if we already have the specialization we
+          need.  */
+       spec = NULL_TREE;
+       if (DECL_CLASS_SCOPE_P (t) || DECL_NAMESPACE_SCOPE_P (t))
+         {
+           /* T is a static data member or namespace-scope entity.
+              We have to substitute into namespace-scope variables
+              (even though such entities are never templates) because
+              of cases like:
+              
+                template <class T> void f() { extern T t; }
+
+              where the entity referenced is not known until
+              instantiation time.  */
+           local_p = false;
+           ctx = DECL_CONTEXT (t);
+           if (DECL_CLASS_SCOPE_P (t))
+             {
+               ctx = tsubst_aggr_type (ctx, args,
+                                       complain,
+                                       in_decl, /*entering_scope=*/1);
+               /* If CTX is unchanged, then T is in fact the
+                  specialization we want.  That situation occurs when
+                  referencing a static data member within in its own
+                  class.  We can use pointer equality, rather than
+                  same_type_p, because DECL_CONTEXT is always
+                  canonical.  */
+               if (ctx == DECL_CONTEXT (t))
+                 spec = t;
+             }
 
-       if (TYPE_P (CP_DECL_CONTEXT (t)))
-         ctx = tsubst_aggr_type (DECL_CONTEXT (t), args,
-                                 complain,
-                                 in_decl, /*entering_scope=*/1);
-       else if (DECL_NAMESPACE_SCOPE_P (t))
-         ctx = DECL_CONTEXT (t);
+           if (!spec)
+             {
+               tmpl = DECL_TI_TEMPLATE (t);
+               gen_tmpl = most_general_template (tmpl);
+               argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
+               spec = (retrieve_specialization 
+                       (gen_tmpl, argvec,
+                        /*class_specializations_p=*/false));
+             }
+         }
        else
          {
+           /* A local variable.  */
+           local_p = true;
            /* Subsequent calls to pushdecl will fill this in.  */
            ctx = NULL_TREE;
-           local_p = 1;
+           spec = retrieve_local_specialization (t);
          }
-
-       /* Check to see if we already have this specialization.  */
-       if (!local_p)
-         {
-           tmpl = DECL_TI_TEMPLATE (t);
-           gen_tmpl = most_general_template (tmpl);
-           argvec = tsubst (DECL_TI_ARGS (t), args, complain, in_decl);
-           spec = retrieve_specialization (gen_tmpl, argvec,
-                                           /*class_specializations_p=*/false);
-         }
-       else
-         spec = retrieve_local_specialization (t);
-
+       /* If we already have the specialization we need, there is
+          nothing more to do.  */ 
        if (spec)
          {
            r = spec;
            break;
          }
 
+       /* Create a new node for the specialization we need.  */
        r = copy_decl (t);
        if (TREE_CODE (r) == VAR_DECL)
          {
@@ -6763,6 +6850,18 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        if (CODE_CONTAINS_STRUCT (TREE_CODE (t), TS_DECL_WRTL))
          SET_DECL_RTL (r, NULL_RTX);
        DECL_SIZE (r) = DECL_SIZE_UNIT (r) = 0;
+       if (TREE_CODE (r) == VAR_DECL)
+         {
+           /* Possibly limit visibility based on template args.  */
+           DECL_VISIBILITY (r) = VISIBILITY_DEFAULT;
+           if (DECL_VISIBILITY_SPECIFIED (t))
+             {
+               DECL_VISIBILITY_SPECIFIED (r) = 0;
+               DECL_ATTRIBUTES (r)
+                 = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
+             }
+           determine_visibility (r);
+         }
 
        if (!local_p)
          {
@@ -8450,20 +8549,18 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
     case HANDLER:
       {
-       tree decl;
+       tree decl = HANDLER_PARMS (t);
 
-       stmt = begin_handler ();
-       if (HANDLER_PARMS (t))
+       if (decl)
          {
-           decl = HANDLER_PARMS (t);
            decl = tsubst (decl, args, complain, in_decl);
            /* Prevent instantiate_decl from trying to instantiate
               this variable.  We've already done all that needs to be
               done.  */
-           DECL_TEMPLATE_INSTANTIATED (decl) = 1;
+           if (decl != error_mark_node)
+             DECL_TEMPLATE_INSTANTIATED (decl) = 1;
          }
-       else
-         decl = NULL_TREE;
+       stmt = begin_handler ();
        finish_handler_parms (decl, stmt);
        tsubst_expr (HANDLER_BODY (t), args, complain, in_decl);
        finish_handler (stmt);
@@ -9143,7 +9240,10 @@ tsubst_copy_and_build (tree t,
       /* As in finish_id_expression, we resolve enumeration constants
         to their underlying values.  */
       if (TREE_CODE (t) == CONST_DECL)
-       return DECL_INITIAL (t);
+       {
+         used_types_insert (TREE_TYPE (t));
+         return DECL_INITIAL (t);
+       }
       return t;
 
     default: