]> gcc.gnu.org Git - gcc.git/commitdiff
decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
authorMark Mitchell <mark@markmitchell.com>
Mon, 25 May 1998 10:28:16 +0000 (10:28 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 25 May 1998 10:28:16 +0000 (10:28 +0000)
1998-05-25  Mark Mitchell  <mark@markmitchell.com>
* decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
* cp-tree.h (processing_template_parmlist): Declare.
* decl.c (pushtag): Don't call push_template_decl when we
shouldn't.
* pt.c (processing_template_parmlist): New variable.
(TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
(complete_template_args): Use it.
(add_to_template_args): Likewise.
(innermost_args): Likewise.
(tsubst): Likewise.
(begin_template_parm_list): Use processing_template_parmlist.
(end_template_parm_list): Likewise.
* cp-tree.h (ANON_UNION_TYPE_P): New macro.
* decl.c (grokdeclarator): Use it.
* decl2.c (grok_x_components): Likewise.
* init.c (initializing_context): Likewise.
* method.c (do_build_copy_constructor): Likewise.
(do_build_assign_ref): Likewise.
* search.c (compute_access): Likewise.
* typeck.c (build_component_ref): Likewise.
* decl.c (grokdeclarator): Don't give a cv-qualified version of an
unnamed type a typedef name "for linkage purposes".
* pt.c (lookup_template_class): Don't look at
IDENTIFIER_CLASS_VALUE when there's no current_class_type.
* method.c (build_overload_int): Handle error cases gracefully.
* pt.c (instantiate_decl): Handle static member variables
correctly.
* pt.c (tsubst): Use the tsubst'd type when producing new
TEMPLATE_PARM_INDEX nodes.

From-SVN: r20045

14 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.other/typedef1.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/crash5.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/memtemp75.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/spec18.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/static2.C [new file with mode: 0644]

index b54b78fadd5f8de61d8e812bdaa02a3f253d4583..23b61d0e491d8ed017e7b7372c9eb155f4c494fa 100644 (file)
@@ -1,3 +1,42 @@
+1998-05-25  Mark Mitchell  <mark@markmitchell.com>
+
+       * decl2.c (build_anon_union_vars): Don't crash on empty sub-unions.
+
+       * cp-tree.h (processing_template_parmlist): Declare.
+       * decl.c (pushtag): Don't call push_template_decl when we
+       shouldn't. 
+       * pt.c (processing_template_parmlist): New variable.
+       (TMPL_ARGS_HAVE_MULTIPLE_LEVELS): New macro.
+       (complete_template_args): Use it.
+       (add_to_template_args): Likewise.
+       (innermost_args): Likewise.
+       (tsubst): Likewise.
+       (begin_template_parm_list): Use processing_template_parmlist.
+       (end_template_parm_list): Likewise.
+
+       * cp-tree.h (ANON_UNION_TYPE_P): New macro.
+       * decl.c (grokdeclarator): Use it.
+       * decl2.c (grok_x_components): Likewise.
+       * init.c (initializing_context): Likewise.
+       * method.c (do_build_copy_constructor): Likewise.
+       (do_build_assign_ref): Likewise.
+       * search.c (compute_access): Likewise.
+       * typeck.c (build_component_ref): Likewise.
+
+       * decl.c (grokdeclarator): Don't give a cv-qualified version of an
+       unnamed type a typedef name "for linkage purposes".
+
+       * pt.c (lookup_template_class): Don't look at
+       IDENTIFIER_CLASS_VALUE when there's no current_class_type.
+
+       * method.c (build_overload_int): Handle error cases gracefully.
+
+       * pt.c (instantiate_decl): Handle static member variables
+       correctly.
+
+       * pt.c (tsubst): Use the tsubst'd type when producing new
+       TEMPLATE_PARM_INDEX nodes.
+
 1998-05-24  Mark Mitchell  <mark@markmitchell.com>
 
        * tree.c (cp_tree_equal): Handle pointers to member functions.
index f12a82eb253c6e4c2a7c394d2a62fc9b3d34d643..f65fbd437ef5d05569cac9d56ea8abe3817e8765 100644 (file)
@@ -1452,6 +1452,11 @@ extern int flag_new_for_scope;
 
 #define ANON_UNION_P(NODE) (DECL_NAME (NODE) == 0)
 
+/* Nonzero if TYPE is an anonymous union type.  */
+#define ANON_UNION_TYPE_P(TYPE) \
+  (TREE_CODE (TYPE) == UNION_TYPE \
+   && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TYPE)))
+
 #define UNKNOWN_TYPE LANG_TYPE
 
 /* Define fields and accessors for nodes representing declared names.  */
@@ -2644,6 +2649,7 @@ extern int comp_template_args                   PROTO((tree, tree));
 
 extern int processing_specialization;
 extern int processing_explicit_instantiation;
+extern int processing_template_parmlist;
 
 /* in repo.c */
 extern void repo_template_used                 PROTO((tree));
index 1fb79382e6fe82ceff24d59a3c24e9082cf1ca12..67604d7cd08d20dbb2b55f8688d87c07aa39c91b 100644 (file)
@@ -2291,9 +2291,15 @@ pushtag (name, type, globalize)
                         friend class S2; 
                       };
 
-                    declares S2 to be at global scope.  */
-                 || (processing_template_decl > 
-                     template_class_depth (current_class_type))))
+                    declares S2 to be at global scope.  We must be
+                    careful, however, of the following case:
+
+                      template <class A*> struct S;
+
+                    which declares a non-template class `A'.  */
+                 || (!processing_template_parmlist
+                     && (processing_template_decl > 
+                         template_class_depth (current_class_type)))))
            {
              d = push_template_decl_real (d, globalize);
              /* If the current binding level is the binding level for
@@ -8750,8 +8756,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
   /* Static anonymous unions are dealt with here.  */
   if (staticp && decl_context == TYPENAME
       && TREE_CODE (declspecs) == TREE_LIST
-      && TREE_CODE (TREE_VALUE (declspecs)) == UNION_TYPE
-      && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_VALUE (declspecs))))
+      && ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
     decl_context = FIELD;
 
   /* Give error if `const,' `volatile,' `inline,' `friend,' or `virtual'
@@ -9659,6 +9664,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
         refer to it, so nothing needs know about the name change.
         The TYPE_NAME field was filled in by build_struct_xref.  */
       if (type != error_mark_node
+         && !TYPE_READONLY (type) && !TYPE_VOLATILE (type)
          && TYPE_NAME (type)
          && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
          && ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
index 2ad9bbe5f22ec2a70fa16ae1f49bc9735ee3cab8..e4c14abb30acbe0a441ac43a1c2ece7bab9e1dfc 100644 (file)
@@ -865,8 +865,7 @@ grok_x_components (specs, components)
        {
        case VAR_DECL:
          /* Static anonymous unions come out as VAR_DECLs.  */
-         if (TREE_CODE (TREE_TYPE (t)) == UNION_TYPE
-             && ANON_AGGRNAME_P (TYPE_IDENTIFIER (TREE_TYPE (t))))
+         if (ANON_UNION_TYPE_P (TREE_TYPE (t)))
            return t;
 
          /* We return SPECS here, because in the parser it was ending
@@ -904,8 +903,7 @@ grok_x_components (specs, components)
            tcode = enum_type_node;
 
          t = xref_tag (tcode, TYPE_IDENTIFIER (t), NULL_TREE, 0);
-         if (TREE_CODE (t) == UNION_TYPE
-             && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+         if (ANON_UNION_TYPE_P (t))
            {
              /* See also shadow_tag.  */
 
@@ -2176,7 +2174,11 @@ build_anon_union_vars (anon_decl, elems, static_p, external_p)
 
       if (DECL_NAME (field) == NULL_TREE
          && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE)
-       decl = build_anon_union_vars (field, elems, static_p, external_p);
+       {
+         decl = build_anon_union_vars (field, elems, static_p, external_p);
+         if (!decl)
+           continue;
+       }
       else
        {
          decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
index 0d0fa8c80237acced57fa5d6d7013e32424a510e..c706a04ba31fac0957c02e5a0cdf599226bc78cc 100644 (file)
@@ -866,7 +866,7 @@ initializing_context (field)
 
   /* Anonymous union members can be initialized in the first enclosing
      non-anonymous union context.  */
-  while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
+  while (t && ANON_UNION_TYPE_P (t))
     t = TYPE_CONTEXT (t);
   return t;
 }
index 5cf4133166d6dd4a5583499e234f1deabcc99182..054cfddb9f312b637ce998aca3e1c4156f22c221 100644 (file)
@@ -515,7 +515,13 @@ build_overload_int (value, in_template)
          id = ansi_opname [(int) TREE_CODE (value)];
          my_friendly_assert (id != NULL_TREE, 0);
          name = IDENTIFIER_POINTER (id);
-         my_friendly_assert (name[0] == '_' && name[1] == '_', 0);
+         if (name[0] != '_' || name[1] != '_')
+           /* On some erroneous inputs, we can get here with VALUE a
+              LOOKUP_EXPR.  In that case, the NAME will be the
+              identifier for "<invalid operator>".  We must survive
+              this routine in order to issue a sensible error
+              message, so we fall through to the case below.  */
+           goto bad_value;
 
          for (i = 0; i < operands; ++i)
            {
@@ -553,6 +559,7 @@ build_overload_int (value, in_template)
             This should cause assembler errors we'll notice.  */
            
          static int n;
+       bad_value:
          sprintf (digit_buffer, " *%d", n++);
          OB_PUTCP (digit_buffer);
        }
@@ -2180,8 +2187,7 @@ do_build_copy_constructor (fndecl)
                continue;
            }
          else if ((t = TREE_TYPE (field)) != NULL_TREE
-                  && TREE_CODE (t) == UNION_TYPE
-                  && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                  && ANON_UNION_TYPE_P (t)
                   && TYPE_FIELDS (t) != NULL_TREE)
            {
              do
@@ -2190,8 +2196,7 @@ do_build_copy_constructor (fndecl)
                  field = largest_union_member (t);
                }
              while ((t = TREE_TYPE (field)) != NULL_TREE
-                    && TREE_CODE (t) == UNION_TYPE
-                    && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                    && ANON_UNION_TYPE_P (t)
                     && TYPE_FIELDS (t) != NULL_TREE);
            }
          else
@@ -2290,8 +2295,7 @@ do_build_assign_ref (fndecl)
                continue;
            }
          else if ((t = TREE_TYPE (field)) != NULL_TREE
-                  && TREE_CODE (t) == UNION_TYPE
-                  && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                  && ANON_UNION_TYPE_P (t)
                   && TYPE_FIELDS (t) != NULL_TREE)
            {
              do
@@ -2301,8 +2305,7 @@ do_build_assign_ref (fndecl)
                  field = largest_union_member (t);
                }
              while ((t = TREE_TYPE (field)) != NULL_TREE
-                    && TREE_CODE (t) == UNION_TYPE
-                    && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))
+                    && ANON_UNION_TYPE_P (t)
                     && TYPE_FIELDS (t) != NULL_TREE);
            }
          else
index d148e0dd93a59ece74e894f0a882286726048b6a..dd7060ad43fa74dadf5120726c225fc48917036d 100644 (file)
@@ -63,6 +63,7 @@ int minimal_parse_mode;
 
 int processing_specialization;
 int processing_explicit_instantiation;
+int processing_template_parmlist;
 static int template_header_count;
 
 static tree saved_trees;
@@ -115,6 +116,14 @@ static int check_cv_quals_for_unify PROTO((int, tree, tree));
 static tree tsubst_template_arg_vector PROTO((tree, tree));
 static void regenerate_decl_from_template PROTO((tree, tree));
 
+/* Nonzero if ARGVEC contains multiple levels of template arguments.  */
+#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE)           \
+  (NODE != NULL_TREE                                   \
+   && TREE_CODE (NODE) == TREE_VEC                     \
+   && TREE_VEC_LENGTH (NODE) > 0                       \
+   && TREE_VEC_ELT (NODE, 0) != NULL_TREE               \
+   && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)
+
 /* Do any processing required when DECL (a member template declaration
    using TEMPLATE_PARAMETERS as its innermost parameter list) is
    finished.  Returns the TEMPLATE_DECL corresponding to DECL, unless
@@ -388,7 +397,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
   my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
   my_friendly_assert (TREE_CODE (extra_args) == TREE_VEC, 0);
 
-  if (TREE_CODE (TREE_VEC_ELT (extra_args, 0)) == TREE_VEC)
+  if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (extra_args))
     extra_arg_depth = TREE_VEC_LENGTH (extra_args);
   else
     extra_arg_depth = 1;
@@ -411,7 +420,7 @@ complete_template_args (tmpl, extra_args, unbound_only)
             TEMPLATE_DECL with DECL_TEMPLATE_INFO.  DECL_TI_ARGS is
             all the bound template arguments.  */
          args = DECL_TI_ARGS (tmpl);
-         if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
+         if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
            depth = 1;
          else
            depth = TREE_VEC_LENGTH (args);
@@ -485,7 +494,7 @@ add_to_template_args (args, extra_args)
 {
   tree new_args;
 
-  if (TREE_CODE (TREE_VEC_ELT (args, 0)) != TREE_VEC)
+  if (!TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
     {
       new_args = make_tree_vec (2);
       TREE_VEC_ELT (new_args, 0) = args;
@@ -529,6 +538,7 @@ begin_template_parm_list ()
   pushlevel (0);
   declare_pseudo_global_level ();
   ++processing_template_decl;
+  ++processing_template_parmlist;
   note_template_header (0);
 }
 
@@ -1452,6 +1462,8 @@ end_template_parm_list (parms)
   for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
     TREE_VEC_ELT (saved_parmlist, nparms) = parm;
 
+  --processing_template_parmlist;
+
   return saved_parmlist;
 }
 
@@ -2858,9 +2870,10 @@ lookup_template_class (d1, arglist, in_decl, context)
        {
          if (context)
            push_decl_namespace (context);
-         template = 
-           maybe_get_template_decl_from_type_decl
-           (IDENTIFIER_CLASS_VALUE (d1));
+         if (current_class_type != NULL_TREE)
+           template = 
+             maybe_get_template_decl_from_type_decl
+             (IDENTIFIER_CLASS_VALUE (d1));
          if (template == NULL_TREE)
            template = lookup_name_nonclass (d1);
          if (context)
@@ -3993,7 +4006,7 @@ innermost_args (args, is_spec)
      tree args;
      int is_spec;
 {
-  if (args != NULL_TREE && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+  if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
     return TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1 - is_spec);
   return args;
 }
@@ -4189,8 +4202,7 @@ tsubst (t, args, in_decl)
          {
            tree arg = NULL_TREE;
 
-           if (TREE_VEC_ELT (args, 0) != NULL_TREE
-               && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
+           if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
              {
                levels = TREE_VEC_LENGTH (args);
                if (level <= levels)
@@ -4275,7 +4287,7 @@ tsubst (t, args, in_decl)
            break;
 
          case TEMPLATE_PARM_INDEX:
-           r = reduce_template_parm_level (t, TREE_TYPE (t), levels);
+           r = reduce_template_parm_level (t, type, levels);
            break;
           
          default:
@@ -6220,14 +6232,14 @@ unify (tparms, targs, parm, arg, strict, explicit_mask)
        /* The PARM is not one we're trying to unify.  Just check
           to see if it matches ARG.  */
        return (TREE_CODE (arg) == TREE_CODE (parm)
-               && cp_tree_equal (parm, arg)) ? 0 : 1;
+               && cp_tree_equal (parm, arg) > 0) ? 0 : 1;
 
       idx = TEMPLATE_PARM_IDX (parm);
       targ = TREE_VEC_ELT (targs, idx);
 
       if (targ)
        {
-         int i = cp_tree_equal (targ, arg);
+         int i = (cp_tree_equal (targ, arg) > 0);
          if (i == 1)
            return 0;
          else if (i == 0)
@@ -7082,17 +7094,6 @@ instantiate_decl (d)
   lineno = DECL_SOURCE_LINE (d);
   input_filename = DECL_SOURCE_FILE (d);
 
-  /* We need to set up DECL_INITIAL regardless of pattern_defined if the
-     variable is a static const initialized in the class body.  */
-  if (TREE_CODE (d) == VAR_DECL
-      && ! DECL_INITIAL (d) && DECL_INITIAL (code_pattern))
-    {
-      pushclass (DECL_CONTEXT (d), 2);
-      DECL_INITIAL (d) = tsubst_expr (DECL_INITIAL (code_pattern), args,
-                                     tmpl);
-      cp_finish_decl (d, DECL_INITIAL (d), NULL_TREE, 0, LOOKUP_NORMAL);
-    }
-
   if (pattern_defined)
     {
       repo_template_used (d);
@@ -7123,11 +7124,17 @@ instantiate_decl (d)
       && ! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d)))
     goto out;
 
-  /* Defer all templates except inline functions used in another function.  */
-  if (! pattern_defined
-      || (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
-         && ! at_eof))
-    {
+  if (TREE_CODE (d) == VAR_DECL 
+      && DECL_INITIAL (d) == NULL_TREE
+      && DECL_INITIAL (code_pattern) != NULL_TREE)
+    /* We need to set up DECL_INITIAL regardless of pattern_defined if
+        the variable is a static const initialized in the class body.  */;
+  else if (! pattern_defined
+          || (! (TREE_CODE (d) == FUNCTION_DECL && DECL_INLINE (d) && nested)
+              && ! at_eof))
+    {
+      /* Defer all templates except inline functions used in another
+         function.  */
       lineno = line;
       input_filename = file;
 
index 1a779138f38094f5c679afc70ecfa4264b4b9c98..c0db0572ee506a530fe54c6c68cd80ff5b50cd1c 100644 (file)
@@ -969,8 +969,7 @@ compute_access (basetype_path, field)
   /* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT
      slot set to the union type rather than the record type containing
      the anonymous union.  */
-  if (context && TREE_CODE (context) == UNION_TYPE
-      && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
+  if (context && ANON_UNION_TYPE_P (context))
     context = TYPE_CONTEXT (context);
 
   /* Virtual function tables are never private.  But we should know that
index 135bbd1f61bfb33a040dba06f075bfbbd72721b7..63b2adc2f3b450c480a8d2d345896dea8bf61524 100644 (file)
@@ -2065,8 +2065,8 @@ build_component_ref (datum, component, basetype_path, protect)
     {
       tree context = DECL_FIELD_CONTEXT (field);
       tree base = context;
-      while (base != basetype && TYPE_NAME (base)
-            && ANON_AGGRNAME_P (TYPE_IDENTIFIER (base)))
+      while (!comptypes (base, basetype,1) && TYPE_NAME (base)
+            && ANON_UNION_TYPE_P (base))
        {
          base = TYPE_CONTEXT (base);
        }
@@ -2096,7 +2096,7 @@ build_component_ref (datum, component, basetype_path, protect)
       basetype = base;
  
       /* Handle things from anon unions here...  */
-      if (TYPE_NAME (context) && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context)))
+      if (TYPE_NAME (context) && ANON_UNION_TYPE_P (context))
        {
          tree subfield = lookup_anon_field (basetype, context);
          tree subdatum = build_component_ref (datum, subfield,
diff --git a/gcc/testsuite/g++.old-deja/g++.other/typedef1.C b/gcc/testsuite/g++.old-deja/g++.other/typedef1.C
new file mode 100644 (file)
index 0000000..d447729
--- /dev/null
@@ -0,0 +1,13 @@
+// Build don't link:
+
+typedef const struct {
+   int x;
+} Test;
+
+void foo(Test);
+
+void foo(Test t)
+{
+  t.x = 0; // ERROR - assignment of read-only member
+  return;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash5.C b/gcc/testsuite/g++.old-deja/g++.pt/crash5.C
new file mode 100644 (file)
index 0000000..786cdf2
--- /dev/null
@@ -0,0 +1,12 @@
+// Build don't link:
+
+template <class T, int i>
+struct K {
+       void f();
+};
+
+template <class T>
+void
+K<T, i>::f()
+{ // ERROR - template parameters
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/memtemp75.C b/gcc/testsuite/g++.old-deja/g++.pt/memtemp75.C
new file mode 100644 (file)
index 0000000..4ff38b6
--- /dev/null
@@ -0,0 +1,25 @@
+// Build don't link:
+
+void
+print(const int& i)
+{
+}
+
+template<class A>
+class bar
+{
+public:        
+  template<void (*B)(const A& a)>
+  void doit(const A& a)
+    {
+      B(a);
+    }
+};
+
+
+int
+main()
+{
+  bar<int>     b;
+  b.template doit<print>(2);
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec18.C b/gcc/testsuite/g++.old-deja/g++.pt/spec18.C
new file mode 100644 (file)
index 0000000..d7d034d
--- /dev/null
@@ -0,0 +1,30 @@
+// Build don't link:
+
+template<class A, class B>
+void foo(const A& a, const B& b)
+{
+}
+
+template<class A, class B>
+void foo(const A& a, const int& b)
+{
+}
+
+template<class A*, class B>
+void foo(const A*& a, const B& b)
+{
+}
+
+template<>
+void foo(const int&, const double&)
+{
+}
+
+
+int
+main()
+{
+  foo("98239", 23);
+  foo(232, 1.022);
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/static2.C b/gcc/testsuite/g++.old-deja/g++.pt/static2.C
new file mode 100644 (file)
index 0000000..5060cfd
--- /dev/null
@@ -0,0 +1,21 @@
+// Build don't link:
+
+template <class A>
+class TEST
+{
+public:
+  TEST (A) {}
+};
+
+template <class A>
+class TEST2
+{
+  static A i;
+};
+
+template <class A>
+A TEST2 <A>::i (0);
+
+TEST2 <TEST <int> > a;
+
+template class TEST2 <TEST <int> >;
This page took 0.102128 seconds and 5 git commands to generate.