]> gcc.gnu.org Git - gcc.git/commitdiff
re PR c++/22464 (ICE on classes in template functions which attempt closure)
authorMark Mitchell <mark@codesourcery.com>
Thu, 13 Oct 2005 08:38:40 +0000 (08:38 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 13 Oct 2005 08:38:40 +0000 (08:38 +0000)
PR c++/22464
* semantics.c (finish_id_expression): Issue errors about uses of
local variables in containing functions even in templates.
PR c++/22180
* call.c (build_new_method_call): Correct pretty-printing of
destructor names.
* pt.c (tsubst_qualified_id): Recognize invalid uses of "~T" as an
identifier.
PR c++/23694
* decl.c (start_method): Return error_mark_node for errors.
PR c++/23307
* pt.c (push_template_decl_real): Complain about attempts to
declare template variables.
PR c++/22352
* pt.c (tsubst_template_parms): Set processing_template_decl while
processing the parameters.
(tsubst_decl): Set processing_template_decl when substituting into
a TEMPLATE_DECL.
PR c++/22405
* pt.c (most_specialized_instantiation): Robustify.
PR c++/22464
* g++.dg/template/crash/41.C: New test.
PR c++/22180
* g++.dg/template/crash40.C: New test.
PR c++/23694
* g++.dg/parse/friend5.C: New test.

PR c++/23307
* g++.dg/template/crash38.C: New test.

PR c++/22352
* g++.dg/template/friend38.C: New test.

PR c++/22405
* g++.dg/template/crash39.C: New test.

From-SVN: r105365

12 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/decl.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/friend5.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/crash38.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/crash39.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/crash40.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/crash41.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/friend38.C [new file with mode: 0644]

index cb4ce856bfcb14c81fa3c78452164230a582901e..4ad7a080990f9d9d682238b9644049e9255ebec9 100644 (file)
@@ -1,3 +1,31 @@
+2005-10-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/22180
+       * call.c (build_new_method_call): Correct pretty-printing of
+       destructor names.
+       * pt.c (tsubst_qualified_id): Recognize invalid uses of "~T" as an
+       identifier. 
+
+       PR c++/23694
+       * decl.c (start_method): Return error_mark_node for errors.
+
+       PR c++/23307
+       * pt.c (push_template_decl_real): Complain about attempts to
+       declare template variables.
+
+       PR c++/22352
+       * pt.c (tsubst_template_parms): Set processing_template_decl while
+       processing the parameters.
+       (tsubst_decl): Set processing_template_decl when substituting into
+       a TEMPLATE_DECL.
+
+       PR c++/22405
+       * pt.c (most_specialized_instantiation): Robustify.
+
+       PR c++/22464
+       * semantics.c (finish_id_expression): Issue errors about uses of
+       local variables in containing functions even in templates.
+
 2005-10-12  Danny Smith  <dannysmith@users.sourceforge.net>
 
        PR target/21801
index cdf70a4d9b8af7899458467b7e0de6ce9a2a1553..924760534eddf7eaac4b883ca304921f13e92b81 100644 (file)
@@ -5348,6 +5348,7 @@ build_new_method_call (tree instance, tree fns, tree args,
       tree type = build_pointer_type (basetype);
       if (!same_type_p (type, TREE_TYPE (instance_ptr)))
        instance_ptr = build_nop (type, instance_ptr);
+      name = complete_dtor_identifier;
     }
 
   class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
index b76c12dac5e55a73b5885c9232e514fef91b491e..77f316424c0c728daa41250bd2631bb229ff25b3 100644 (file)
@@ -10986,7 +10986,7 @@ start_method (cp_decl_specifier_seq *declspecs,
          && TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
        error ("%qD is already defined in class %qT", fndecl,
               DECL_CONTEXT (fndecl));
-      return void_type_node;
+      return error_mark_node;
     }
 
   check_template_shadow (fndecl);
index 6724cf49b2e6d74a5cb74cb1093eaf94aaea3f4f..0475fc8a987999bf5e33040315e1831d81af28bf 100644 (file)
@@ -2998,9 +2998,8 @@ push_template_decl_real (tree decl, bool is_friend)
              return decl;
            }
        }
-      else if ((DECL_IMPLICIT_TYPEDEF_P (decl)
-               && CLASS_TYPE_P (TREE_TYPE (decl)))
-              || (TREE_CODE (decl) == VAR_DECL && ctx && CLASS_TYPE_P (ctx)))
+      else if (DECL_IMPLICIT_TYPEDEF_P (decl)
+              && CLASS_TYPE_P (TREE_TYPE (decl)))
        /* OK */;
       else
        {
@@ -6004,6 +6003,12 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
   tree r = NULL_TREE;
   tree* new_parms;
 
+  /* When substituting into a template, we must set
+     PROCESSING_TEMPLATE_DECL as the template parameters may be
+     dependent if they are based on one-another, and the dependency
+     predicates are short-circuit outside of templates.  */
+  ++processing_template_decl;
+
   for (new_parms = &r;
        TMPL_PARMS_DEPTH (parms) > TMPL_ARGS_DEPTH (args);
        new_parms = &(TREE_CHAIN (*new_parms)),
@@ -6036,6 +6041,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
                   new_vec, NULL_TREE);
     }
 
+  --processing_template_decl;
+
   return r;
 }
 
@@ -6243,8 +6250,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        tmpl_args = DECL_CLASS_TEMPLATE_P (t)
          ? CLASSTYPE_TI_ARGS (TREE_TYPE (t))
          : DECL_TI_ARGS (DECL_TEMPLATE_RESULT (t));
+       /* Because this is a template, the arguments will still be
+          dependent, even after substitution.  If
+          PROCESSING_TEMPLATE_DECL is not set, the dependency
+          predicates will short-circuit.  */
+       ++processing_template_decl;
        full_args = tsubst_template_args (tmpl_args, args,
                                          complain, in_decl);
+       --processing_template_decl;
        if (full_args == error_mark_node)
          return error_mark_node;
 
@@ -6270,15 +6283,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
        gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
        TREE_CHAIN (r) = NULL_TREE;
 
-       DECL_CONTEXT (r)
-         = tsubst_aggr_type (DECL_CONTEXT (t), args,
-                             complain, in_decl,
-                             /*entering_scope=*/1);
        DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
 
        if (TREE_CODE (decl) == TYPE_DECL)
          {
-           tree new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+           tree new_type;
+           ++processing_template_decl;
+           new_type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+           --processing_template_decl; 
            if (new_type == error_mark_node)
              return error_mark_node;
 
@@ -6286,10 +6298,14 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            CLASSTYPE_TI_TEMPLATE (new_type) = r;
            DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
            DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
+           DECL_CONTEXT (r) = TYPE_CONTEXT (new_type);
          }
        else
          {
-           tree new_decl = tsubst (decl, args, complain, in_decl);
+           tree new_decl;
+           ++processing_template_decl;
+           new_decl = tsubst (decl, args, complain, in_decl);
+           --processing_template_decl;
            if (new_decl == error_mark_node)
              return error_mark_node;
 
@@ -6297,6 +6313,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
            DECL_TI_TEMPLATE (new_decl) = r;
            TREE_TYPE (r) = TREE_TYPE (new_decl);
            DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
+           DECL_CONTEXT (r) = DECL_CONTEXT (new_decl); 
          }
 
        SET_DECL_IMPLICIT_INSTANTIATION (r);
@@ -7662,7 +7679,12 @@ tsubst_qualified_id (tree qualified_id, tree args,
 
   if (!BASELINK_P (name) && !DECL_P (expr))
     {
-      expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
+      if (TREE_CODE (expr) == BIT_NOT_EXPR)
+       /* If this were actually a destructor call, it would have been
+          parsed as such by the parser.  */
+       expr = error_mark_node;
+      else
+       expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
       if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
                     ? DECL_TEMPLATE_RESULT (expr) : expr) == TYPE_DECL)
        {
@@ -10786,13 +10808,15 @@ most_specialized_instantiation (tree instantiations)
                        NULL_TREE, /*check_ret=*/false))
        fate++;
 
-      if (fate != 1)
+      if (fate == -1)
+       champ = fn;
+      else if (!fate)
        {
-         if (!fate)
-           /* Equally specialized, move to next function.  If there
-              is no next function, nothing's most specialized.  */
-           fn = TREE_CHAIN (fn);
-         champ = fn;
+         /* Equally specialized, move to next function.  If there
+            is no next function, nothing's most specialized.  */
+         fn = TREE_CHAIN (fn);
+         if (!fn)
+           break;
        }
     }
 
index 80885c564a75183e19315a7957cba3145a12300f..d870fda6ba2c12ba5ac5871834b41412ec2a575d 100644 (file)
@@ -2459,6 +2459,21 @@ finish_id_expression (tree id_expression,
         was entirely defined.  */
       if (!scope && decl != error_mark_node)
        maybe_note_name_used_in_class (id_expression, decl);
+
+      /* Disallow uses of local variables from containing functions.  */
+      if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
+       {
+         tree context = decl_function_context (decl);
+         if (context != NULL_TREE && context != current_function_decl
+             && ! TREE_STATIC (decl))
+           {
+             error (TREE_CODE (decl) == VAR_DECL
+                    ? "use of %<auto%> variable from containing function"
+                    : "use of parameter from containing function");
+             error ("  %q+#D declared here", decl);
+             return error_mark_node;
+           }
+       }
     }
 
   /* If we didn't find anything, or what we found was a type,
@@ -2730,23 +2745,6 @@ finish_id_expression (tree id_expression,
        }
       else
        {
-         if (TREE_CODE (decl) == VAR_DECL
-             || TREE_CODE (decl) == PARM_DECL
-             || TREE_CODE (decl) == RESULT_DECL)
-           {
-             tree context = decl_function_context (decl);
-
-             if (context != NULL_TREE && context != current_function_decl
-                 && ! TREE_STATIC (decl))
-               {
-                 error (TREE_CODE (decl) == VAR_DECL
-                        ? "use of %<auto%> variable from containing function"
-                        : "use of parameter from containing function");
-                 error ("  %q+#D declared here", decl);
-                 return error_mark_node;
-               }
-           }
-
          if (DECL_P (decl) && DECL_NONLOCAL (decl)
              && DECL_CLASS_SCOPE_P (decl)
              && DECL_CONTEXT (decl) != current_class_type)
index 640cc223a36f89b7a0584e6781f4ad44993081d9..1cfd961196f822b466f131a6f9491391ebac11a5 100644 (file)
@@ -1,3 +1,23 @@
+2005-10-13  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/22464
+       * g++.dg/template/crash/41.C: New test.
+
+       PR c++/22180
+       * g++.dg/template/crash40.C: New test.
+
+       PR c++/23694
+       * g++.dg/parse/friend5.C: New test.
+       
+       PR c++/23307
+       * g++.dg/template/crash38.C: New test.
+       
+       PR c++/22352
+       * g++.dg/template/friend38.C: New test.
+       
+       PR c++/22405
+       * g++.dg/template/crash39.C: New test.
+       
 2005-10-13  Hans-Peter Nilsson  <hp@bitrange.com>
 
        * gcc.dg/debug/dwarf2/dwarf-char1.c,
diff --git a/gcc/testsuite/g++.dg/parse/friend5.C b/gcc/testsuite/g++.dg/parse/friend5.C
new file mode 100644 (file)
index 0000000..5e23f45
--- /dev/null
@@ -0,0 +1,7 @@
+// PR c++/23694
+extern "C" struct A
+{
+  friend void foo(int) {} // { dg-error "declaration" }
+  friend void foo() {} // { dg-error "foo" }
+};
diff --git a/gcc/testsuite/g++.dg/template/crash38.C b/gcc/testsuite/g++.dg/template/crash38.C
new file mode 100644 (file)
index 0000000..c652cc8
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/23307
+
+class A
+{
+  template<class R>
+  static void f(X&); // { dg-error "" }
+  inline void A::f<void>(X&); // { dg-error "f|expected" }
+};
diff --git a/gcc/testsuite/g++.dg/template/crash39.C b/gcc/testsuite/g++.dg/template/crash39.C
new file mode 100644 (file)
index 0000000..ddecc17
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/22405
+
+template <typename T> void foo(T &arg) { // { dg-error "declared" }
+  arg+=1;
+}
+
+template <typename T> void foo(T &arg) { // { dg-error "redefinition" }
+  arg+=2;
+}
+
+template void foo(float &arg);
diff --git a/gcc/testsuite/g++.dg/template/crash40.C b/gcc/testsuite/g++.dg/template/crash40.C
new file mode 100644 (file)
index 0000000..716b4a2
--- /dev/null
@@ -0,0 +1,10 @@
+// PR c++/22180
+
+struct A {};
+
+template<typename T> void foo()
+{
+  T::~T(); // { dg-error "member" }
+}
+
+template void foo<A>(); // { dg-error "instantiated" }
diff --git a/gcc/testsuite/g++.dg/template/crash41.C b/gcc/testsuite/g++.dg/template/crash41.C
new file mode 100644 (file)
index 0000000..9a440b0
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/22464
+
+template<typename T>
+void do_something(const T* A) // { dg-error "declared" }
+{ 
+  struct helper_t{ 
+    helper_t() {  
+      A[0]; // { dg-error "use" }
+    }
+  } helper;
+}
+
+void sub1() {
+  double A[7];
+  do_something (A);
+}
+
+  
diff --git a/gcc/testsuite/g++.dg/template/friend38.C b/gcc/testsuite/g++.dg/template/friend38.C
new file mode 100644 (file)
index 0000000..41faf79
--- /dev/null
@@ -0,0 +1,12 @@
+// PR c++/22352
+
+template <class A>
+class s
+{
+  typedef int d;
+  template <class s, typename s::d>
+  friend class t;
+};
+
+s<int> t1;
+
This page took 0.115816 seconds and 5 git commands to generate.