OSDN Git Service

cp:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 22 Mar 2003 15:34:41 +0000 (15:34 +0000)
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 22 Mar 2003 15:34:41 +0000 (15:34 +0000)
PR c++/9978, c++/9708
* cp-tree.h (instantiate_template): Add tsubst_flags parameter.
* call.c (add_template_candidate_real): Adjust
instantiate_template call.
* class.c (resolve_address_of_overloaded_function): Likewise.
* decl.c (build_enumerator): Set TREE_CONSTANT.
* pt.c (check_instantiated_args): New.
(push_inline_template_parms_recursive): Set TREE_CONSTANT,
TREE_READONLY.
(build_template_parm_index): Copy TREE_CONSTANT, TREE_READONLY.
(reduce_template_parm_level): Likewise.
(process_template_parm): Likewise.
(check_explicit_specialization): Adjust instantiate_template call.
(convert_template_argument): Don't check non-type argument here.
(lookup_template_class): Check them here.
(tsubst_friend_function): Adjust instantiate_template call.
(instantiate_template): Add tsubst_flags parameter, use it. Check
instantiated args.
testsuite:
PR c++/9978, c++/9708
* g++.dg/ext/vlm1.C: Adjust expected error.
* g++.dg/ext/vla2.C: New test.
* g++.dg/template/arg1.C: New test.
* g++.dg/template/arg2.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@64714 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/vla2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/ext/vlm1.C
gcc/testsuite/g++.dg/template/arg1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/arg2.C [new file with mode: 0644]

index 616078a..ecc9bda 100644 (file)
@@ -1,3 +1,24 @@
+2003-03-22  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9978, c++/9708
+       * cp-tree.h (instantiate_template): Add tsubst_flags parameter.
+       * call.c (add_template_candidate_real): Adjust
+       instantiate_template call.
+       * class.c (resolve_address_of_overloaded_function): Likewise.
+       * decl.c (build_enumerator): Set TREE_CONSTANT.
+       * pt.c (check_instantiated_args): New.
+       (push_inline_template_parms_recursive): Set TREE_CONSTANT,
+       TREE_READONLY.
+       (build_template_parm_index): Copy TREE_CONSTANT, TREE_READONLY.
+       (reduce_template_parm_level): Likewise.
+       (process_template_parm): Likewise.
+       (check_explicit_specialization): Adjust instantiate_template call.
+       (convert_template_argument): Don't check non-type argument here.
+       (lookup_template_class): Check them here.
+       (tsubst_friend_function): Adjust instantiate_template call.
+       (instantiate_template): Add tsubst_flags parameter, use it. Check
+       instantiated args.
+
 2003-03-21  Zack Weinberg  <zack@codesourcery.com>
 
        * decl.c: Update calls to shadow_warning.
index 09a0656..3d8e17f 100644 (file)
@@ -2275,7 +2275,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
   if (i != 0)
     return NULL;
 
-  fn = instantiate_template (tmpl, targs);
+  fn = instantiate_template (tmpl, targs, tf_none);
   if (fn == error_mark_node)
     return NULL;
 
index 0df87ae..e899c57 100644 (file)
@@ -5989,7 +5989,8 @@ cannot resolve overloaded function `%D' based on conversion to type `%T'",
            continue;
 
          /* Instantiate the template.  */
-         instantiation = instantiate_template (fn, targs);
+         instantiation = instantiate_template (fn, targs,
+                                               complain ? tf_error : tf_none);
          if (instantiation == error_mark_node)
            /* Instantiation failed.  */
            continue;
index 2a207a1..1c871e8 100644 (file)
@@ -4016,7 +4016,7 @@ extern tree lookup_template_class         (tree, tree, tree, tree, int, tsubst_flags_t)
 extern tree lookup_template_function            (tree, tree);
 extern int uses_template_parms                 (tree);
 extern tree instantiate_class_template         (tree);
-extern tree instantiate_template               (tree, tree);
+extern tree instantiate_template               (tree, tree, tsubst_flags_t);
 extern int fn_type_unification                  (tree, tree, tree, tree, tree, unification_kind_t, int);
 extern tree tinst_for_decl                     (void);
 extern void mark_decl_instantiated             (tree, int);
index 99898d0..4756cdc 100644 (file)
@@ -13286,8 +13286,8 @@ build_enumerator (tree name, tree value, tree enumtype)
     decl = build_decl (CONST_DECL, name, type);
 
   DECL_CONTEXT (decl) = FROB_CONTEXT (context);
+  TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
   DECL_INITIAL (decl) = value;
-  TREE_READONLY (decl) = 1;
 
   if (context && context == current_class_type)
     /* In something like `struct S { enum E { i = 7 }; };' we put `i'
index 8523c96..aa9a2c7 100644 (file)
@@ -110,6 +110,7 @@ static tree coerce_template_parms PARAMS ((tree, tree, tree,
 static void tsubst_enum        PARAMS ((tree, tree, tree));
 static tree add_to_template_args PARAMS ((tree, tree));
 static tree add_outermost_template_args PARAMS ((tree, tree));
+static bool check_instantiated_args PARAMS ((tree, tree, tsubst_flags_t));
 static int maybe_adjust_types_for_deduction PARAMS ((unification_kind_t, tree*,
                                                     tree*)); 
 static int  type_unification_real PARAMS ((tree, tree, tree, tree,
@@ -429,6 +430,7 @@ push_inline_template_parms_recursive (parmlist, levels)
            tree decl = build_decl (CONST_DECL, DECL_NAME (parm),
                                    TREE_TYPE (parm));
            DECL_ARTIFICIAL (decl) = 1;
+           TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
            DECL_INITIAL (decl) = DECL_INITIAL (parm);
            SET_DECL_TEMPLATE_PARM_P (decl);
            pushdecl (decl);
@@ -1839,7 +1841,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
                  targs = new_targs;
                }
                  
-             return instantiate_template (tmpl, targs);
+             return instantiate_template (tmpl, targs, tf_error);
            }
 
          /* If this is a specialization of a member template of a
@@ -2050,6 +2052,8 @@ build_template_parm_index (index, level, orig_level, decl, type)
   TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
   TEMPLATE_PARM_DECL (t) = decl;
   TREE_TYPE (t) = type;
+  TREE_CONSTANT (t) = TREE_CONSTANT (decl);
+  TREE_READONLY (t) = TREE_READONLY (decl);
 
   return t;
 }
@@ -2069,20 +2073,21 @@ reduce_template_parm_level (index, type, levels)
       || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index))
          != TEMPLATE_PARM_LEVEL (index) - levels))
     {
-      tree decl 
-       = build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)),
-                     DECL_NAME (TEMPLATE_PARM_DECL (index)),
-                     type);
-      tree t
-       = build_template_parm_index (TEMPLATE_PARM_IDX (index),
+      tree orig_decl = TEMPLATE_PARM_DECL (index);
+      tree decl, t;
+      
+      decl = build_decl (TREE_CODE (orig_decl), DECL_NAME (orig_decl), type);
+      TREE_CONSTANT (decl) = TREE_CONSTANT (orig_decl);
+      TREE_READONLY (decl) = TREE_READONLY (orig_decl);
+      DECL_ARTIFICIAL (decl) = 1;
+      SET_DECL_TEMPLATE_PARM_P (decl);
+      
+      t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
                                     TEMPLATE_PARM_LEVEL (index) - levels,
                                     TEMPLATE_PARM_ORIG_LEVEL (index),
                                     decl, type);
       TEMPLATE_PARM_DESCENDANTS (index) = t;
 
-      DECL_ARTIFICIAL (decl) = 1;
-      SET_DECL_TEMPLATE_PARM_P (decl);
-
       /* Template template parameters need this.  */
       DECL_TEMPLATE_PARMS (decl)
        = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index));
@@ -2137,10 +2142,11 @@ process_template_parm (list, next)
       TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm));
 
       /* A template parameter is not modifiable.  */
-      TREE_READONLY (parm) = 1;
+      TREE_READONLY (parm) = TREE_CONSTANT (parm) = 1;
       if (invalid_nontype_parm_type_p (TREE_TYPE (parm), 1))
         TREE_TYPE (parm) = void_type_node;
       decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm));
+      TREE_CONSTANT (decl) = TREE_READONLY (decl) = 1;
       DECL_INITIAL (parm) = DECL_INITIAL (decl) 
        = build_template_parm_index (idx, processing_template_decl,
                                     processing_template_decl,
@@ -3632,39 +3638,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
            }
        }
       else
-       {
-         val = groktypename (arg);
-         if (! processing_template_decl)
-           {
-             /* [basic.link]: A name with no linkage (notably, the
-                name of a class or enumeration declared in a local
-                scope) shall not be used to declare an entity with
-                linkage.  This implies that names with no linkage
-                cannot be used as template arguments.  */
-             tree t = no_linkage_check (val);
-             if (t)
-               {
-                 if (TYPE_ANONYMOUS_P (t))
-                   pedwarn
-                     ("template-argument `%T' uses anonymous type", val);
-                 else
-                   error
-                     ("template-argument `%T' uses local type `%T'",
-                      val, t);
-                 return error_mark_node;
-               }
-
-             /* In order to avoid all sorts of complications, we do
-                not allow variably-modified types as template
-                arguments.  */
-             if (variably_modified_type_p (val))
-               {
-                 error ("template-argument `%T' is a variably modified type",
-                        val);
-                 return error_mark_node;
-               }
-           }
-       }
+       val = groktypename (arg);
     }
   else
     {
@@ -3704,9 +3678,7 @@ convert_template_argument (parm, arg, args, complain, i, in_decl)
 /* Convert all template arguments to their appropriate types, and
    return a vector containing the innermost resulting template
    arguments.  If any error occurs, return error_mark_node. Error and
-   warning messages are issued under control of COMPLAIN.  Some error
-   messages are issued even if COMPLAIN is zero; for instance, if a
-   template argument is composed from a local class.
+   warning messages are issued under control of COMPLAIN.
 
    If REQUIRE_ALL_ARGUMENTS is nonzero, all arguments must be
    provided in ARGLIST, or else trailing parameters must have default
@@ -4207,7 +4179,9 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
 
       arglist2 = coerce_template_parms (parmlist, arglist, template,
                                         complain, /*require_all_args=*/1);
-      if (arglist2 == error_mark_node)
+      if (arglist2 == error_mark_node
+         || (!processing_template_decl
+             && check_instantiated_args (template, arglist2, complain)))
         POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
       parm = bind_template_template_parm (TREE_TYPE (template), arglist2);
@@ -4296,7 +4270,11 @@ lookup_template_class (d1, arglist, in_decl, context, entering_scope, complain)
                                   template,
                                   complain, /*require_all_args=*/1);
 
-      if (arglist == error_mark_node)
+      if (arglist == error_mark_node
+         || (!processing_template_decl
+             && check_instantiated_args (template,
+                                         INNERMOST_TEMPLATE_ARGS (arglist),
+                                         complain)))
        /* We were unable to bind the arguments.  */
        POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
 
@@ -4919,7 +4897,7 @@ tsubst_friend_function (decl, args)
       tmpl = determine_specialization (template_id, new_friend,
                                       &new_args, 
                                       /*need_member_template=*/0);
-      new_friend = instantiate_template (tmpl, new_args);
+      new_friend = instantiate_template (tmpl, new_args, tf_error);
       goto done;
     }
 
@@ -8394,18 +8372,78 @@ tsubst_copy_and_build (t, args, complain, in_decl)
     }
 }
 
+/* Verify that the instantiated ARGS are valid. For type arguments,
+   make sure that the type's linkage is ok. For non-type arguments,
+   make sure they are constants if they are integral or enumarations.
+   Emit an error under control of COMPLAIN, and return TRUE on error. */
+
+static bool
+check_instantiated_args (tmpl, args, complain)
+     tree tmpl, args;
+     tsubst_flags_t complain;
+{
+  int ix, len = DECL_NTPARMS (tmpl);
+  bool result = false;
+
+  for (ix = 0; ix != len; ix++)
+    {
+      tree t = TREE_VEC_ELT (args, ix);
+      
+      if (TYPE_P (t))
+       {
+         /* [basic.link]: A name with no linkage (notably, the name
+            of a class or enumeration declared in a local scope)
+            shall not be used to declare an entity with linkage.
+            This implies that names with no linkage cannot be used as
+            template arguments.  */
+         tree nt = no_linkage_check (t);
+
+         if (nt)
+           {
+             if (!(complain & tf_error))
+               /*OK*/;
+             else if (TYPE_ANONYMOUS_P (nt))
+               error ("`%T' uses anonymous type", t);
+             else
+               error ("`%T' uses local type `%T'", t, nt);
+             result = true;
+           }
+         /* In order to avoid all sorts of complications, we do not
+            allow variably-modified types as template arguments.  */
+         else if (variably_modified_type_p (t))
+           {
+             if (complain & tf_error)
+               error ("`%T' is a variably modified type", t);
+             result = true;
+           }
+       }
+      /* A non-type argument of integral or enumerated type must be a
+        constant.  */
+      else if (TREE_TYPE (t)
+              && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
+              && !TREE_CONSTANT (t))
+       {
+         if (complain & tf_error)
+           error ("integral expression `%E' is not constant", t);
+         result = true;
+       }
+    }
+  if (result && complain & tf_error)
+    error ("  trying to instantiate `%D'", tmpl);
+  return result;
+}
+
 /* Instantiate the indicated variable or function template TMPL with
    the template arguments in TARG_PTR.  */
 
 tree
-instantiate_template (tmpl, targ_ptr)
+instantiate_template (tmpl, targ_ptr, complain)
      tree tmpl, targ_ptr;
+     tsubst_flags_t complain;
 {
   tree fndecl;
   tree gen_tmpl;
   tree spec;
-  int i, len;
-  tree inner_args;
 
   if (tmpl == error_mark_node)
     return error_mark_node;
@@ -8415,7 +8453,8 @@ instantiate_template (tmpl, targ_ptr)
   /* If this function is a clone, handle it specially.  */
   if (DECL_CLONED_FUNCTION_P (tmpl))
     {
-      tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr);
+      tree spec = instantiate_template (DECL_CLONED_FUNCTION (tmpl), targ_ptr,
+                                       complain);
       tree clone;
       
       /* Look for the clone.  */
@@ -8449,34 +8488,20 @@ instantiate_template (tmpl, targ_ptr)
        return spec;
     }
 
-  len = DECL_NTPARMS (gen_tmpl);
-  inner_args = INNERMOST_TEMPLATE_ARGS (targ_ptr);
-  i = len;
-  while (i--)
-    {
-      tree t = TREE_VEC_ELT (inner_args, i);
-      if (TYPE_P (t))
-       {
-         tree nt = target_type (t);
-         if (IS_AGGR_TYPE (nt) && decl_function_context (TYPE_MAIN_DECL (nt)))
-           {
-             error ("type `%T' composed from a local class is not a valid template-argument", t);
-             error ("  trying to instantiate `%D'", gen_tmpl);
-             return error_mark_node;
-           }
-       }
-    }
-
+  if (check_instantiated_args (gen_tmpl, INNERMOST_TEMPLATE_ARGS (targ_ptr),
+                              complain))
+    return error_mark_node;
+  
   /* Make sure that we can see identifiers, and compute access
      correctly.  The desired FUNCTION_DECL for FNDECL may or may not be
      created earlier.  Let push_access_scope_real figure that out.  */
   push_access_scope_real
     (gen_tmpl, targ_ptr, tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr, 
-                                tf_error, gen_tmpl));
+                                complain, gen_tmpl));
 
   /* substitute template parameters */
   fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
-                  targ_ptr, tf_error, gen_tmpl);
+                  targ_ptr, complain, gen_tmpl);
 
   pop_access_scope (gen_tmpl);
 
index 25baba3..901d52b 100644 (file)
@@ -1,3 +1,11 @@
+2003-03-22  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/9978, c++/9708
+       * g++.dg/ext/vlm1.C: Adjust expected error.
+       * g++.dg/ext/vla2.C: New test.
+       * g++.dg/template/arg1.C: New test.
+       * g++.dg/template/arg2.C: New test.
+
 2003-03-22  Bud Davis  <bdavis9659@comcast.net>
 
        * g77.f-torture/execute/select.f: New test.
diff --git a/gcc/testsuite/g++.dg/ext/vla2.C b/gcc/testsuite/g++.dg/ext/vla2.C
new file mode 100644 (file)
index 0000000..c17dc86
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do compile }
+// { dg-options "" }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 21 Mar 2003 <nathan@codesourcery.com>
+
+// PR 9708. We unified a VLA size as a constant. Then issued bogus
+// errors.
+
+template <unsigned int N>
+char* begin(char (&a) [N] );
+
+void bar(int i)
+{
+  char d[i] ;
+  
+  begin(d);  // { dg-error "no matching function" "" }
+}
index 61628e6..13f6702 100644 (file)
@@ -4,7 +4,7 @@ template <class T> struct A {};
  
 struct B {
   static const int s;
-  A<int[s]> a; // { dg-error "variably modified|no type" }
+  A<int[s]> a; // { dg-error "variably modified|no type|trying to instantiate" }
 };
  
 const int B::s=16;
diff --git a/gcc/testsuite/g++.dg/template/arg1.C b/gcc/testsuite/g++.dg/template/arg1.C
new file mode 100644 (file)
index 0000000..f7a8b31
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 21 Mar 2003 <nathan@codesourcery.com>
+
+// PR 9978. We rejected a constant expression.
+  
+enum { val = 1 };
+
+template <class T>
+struct Bar
+{
+  static const int A = val;
+  static const int B = A + 1;
+};
diff --git a/gcc/testsuite/g++.dg/template/arg2.C b/gcc/testsuite/g++.dg/template/arg2.C
new file mode 100644 (file)
index 0000000..5a4ff27
--- /dev/null
@@ -0,0 +1,14 @@
+// { dg-do compile }
+
+// Copyright (C) 2003 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 21 Mar 2003 <nathan@codesourcery.com>
+
+// PR 9708. We accepted a local class
+
+template <typename T> class X {};
+
+void fn ()
+{
+  class L {};
+  X<L> f; // { dg-error "uses local type|trying to instantiate|expected" "" }
+}