PATCH: PRs 22464, 22180, 23694, 23307, 22352, 22405
Mark Mitchell
mark@codesourcery.com
Thu Oct 13 08:39:00 GMT 2005
This patch fixes some ICE regressions in the C++ front end:
PR 22464: We were getting confused when a member function of a local
class, nested within a member function of a template class, referred
to a parameter of the containing function. That's not legal -- but we
weren't issuing the diagnostic at template-parse time. By doing it at
that point, we avoid the crash. (There's no problem with
multiple diagnostics at declaration and instantiation time because we
use error_mark_node to represent the erroneous expression.)
PR 22180: "T::~T()" is not a valid call to a destructor, if "T" is a
template type parameter. (You can say "this->T::~T()", but that's
different.) We weren't considering that case, and ICEd. (I also
noticed we weren't printing destructor names correctly in
build_new_method_call; fixed that.)
PR 23694: For some reason, G++ historically used void_type_node in
some places where it meant error_mark_node. That's a recipe for ICEs;
this patch fixes one such place.
PR 23307: We were trying to cope with template declarations of static
data members. Those aren't valid, and by issuing the error sooner we
avoid the ICE.
PR 22352: Template parameters for a member template in a template
class may still be dependent, even after substituting for parametmers
in the contaiing class, so we need to make sure
processing_template_decl is set, thereby making our dependency
predicates work.
PR 22405: Minor logic bug; the author of the code forgot that the
third expression in a for loop is executed before the second.
Tested on x86_64-unknown-linux-gnu.
--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com
2005-10-13 Mark Mitchell <mark@codesourcery.com>
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.
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.
Index: gcc/cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.556
diff -c -5 -p -r1.556 call.c
*** gcc/cp/call.c 11 Oct 2005 20:58:44 -0000 1.556
--- gcc/cp/call.c 13 Oct 2005 07:50:38 -0000
*************** build_new_method_call (tree instance, tr
*** 5341,5350 ****
--- 5341,5351 ----
if (DECL_DESTRUCTOR_P (fn))
{
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);
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1431
diff -c -5 -p -r1.1431 decl.c
*** gcc/cp/decl.c 10 Oct 2005 14:41:49 -0000 1.1431
--- gcc/cp/decl.c 13 Oct 2005 07:50:40 -0000
*************** start_method (cp_decl_specifier_seq *dec
*** 10989,10999 ****
{
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
error ("%qD is already defined in class %qT", fndecl,
DECL_CONTEXT (fndecl));
! return void_type_node;
}
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
--- 10989,10999 ----
{
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
error ("%qD is already defined in class %qT", fndecl,
DECL_CONTEXT (fndecl));
! return error_mark_node;
}
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
Index: gcc/cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.1043
diff -c -5 -p -r1.1043 pt.c
*** gcc/cp/pt.c 11 Oct 2005 06:26:04 -0000 1.1043
--- gcc/cp/pt.c 13 Oct 2005 07:50:41 -0000
*************** push_template_decl_real (tree decl, bool
*** 2996,3008 ****
have two or more parameters. */
error ("invalid template declaration of %qD", decl);
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)))
/* OK */;
else
{
error ("template declaration of %q#D", decl);
return error_mark_node;
--- 2996,3007 ----
have two or more parameters. */
error ("invalid template declaration of %qD", decl);
return decl;
}
}
! else if (DECL_IMPLICIT_TYPEDEF_P (decl)
! && CLASS_TYPE_P (TREE_TYPE (decl)))
/* OK */;
else
{
error ("template declaration of %q#D", decl);
return error_mark_node;
*************** static tree
*** 6000,6009 ****
--- 5999,6014 ----
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)),
parms = TREE_CHAIN (parms))
{
*************** tsubst_template_parms (tree parms, tree
*** 6032,6041 ****
--- 6037,6048 ----
tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
- TMPL_ARGS_DEPTH (args)),
new_vec, NULL_TREE);
}
+ --processing_template_decl;
+
return r;
}
/* Substitute the ARGS into the indicated aggregate (or enumeration)
type T. If T is not an aggregate or enumeration type, it is
*************** tsubst_decl (tree t, tree args, tsubst_f
*** 6239,6250 ****
--- 6246,6263 ----
full args contain the tsubst'd args for the context,
plus the innermost args from the template decl. */
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;
/* tsubst_template_args doesn't copy the vector if
nothing changed. But, *something* should have
*************** tsubst_decl (tree t, tree args, tsubst_f
*** 6266,6302 ****
than the old one. */
r = copy_decl (t);
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);
if (new_type == error_mark_node)
return error_mark_node;
TREE_TYPE (r) = new_type;
CLASSTYPE_TI_TEMPLATE (new_type) = r;
DECL_TEMPLATE_RESULT (r) = TYPE_MAIN_DECL (new_type);
DECL_TI_ARGS (r) = CLASSTYPE_TI_ARGS (new_type);
}
else
{
! tree new_decl = tsubst (decl, args, complain, in_decl);
if (new_decl == error_mark_node)
return error_mark_node;
DECL_TEMPLATE_RESULT (r) = new_decl;
DECL_TI_TEMPLATE (new_decl) = r;
TREE_TYPE (r) = TREE_TYPE (new_decl);
DECL_TI_ARGS (r) = DECL_TI_ARGS (new_decl);
}
SET_DECL_IMPLICIT_INSTANTIATION (r);
DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
--- 6279,6319 ----
than the old one. */
r = copy_decl (t);
gcc_assert (DECL_LANG_SPECIFIC (r) != 0);
TREE_CHAIN (r) = NULL_TREE;
DECL_TEMPLATE_INFO (r) = build_tree_list (t, args);
if (TREE_CODE (decl) == TYPE_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;
TREE_TYPE (r) = new_type;
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;
! ++processing_template_decl;
! new_decl = tsubst (decl, args, complain, in_decl);
! --processing_template_decl;
if (new_decl == error_mark_node)
return error_mark_node;
DECL_TEMPLATE_RESULT (r) = new_decl;
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);
DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;
DECL_TEMPLATE_SPECIALIZATIONS (r) = NULL_TREE;
*************** tsubst_qualified_id (tree qualified_id,
*** 7658,7668 ****
if (dependent_type_p (scope))
return build_nt (SCOPE_REF, scope, expr);
if (!BASELINK_P (name) && !DECL_P (expr))
{
! 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)
{
if (complain & tf_error)
{
--- 7675,7690 ----
if (dependent_type_p (scope))
return build_nt (SCOPE_REF, scope, expr);
if (!BASELINK_P (name) && !DECL_P (expr))
{
! 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)
{
if (complain & tf_error)
{
*************** most_specialized_instantiation (tree ins
*** 10782,10798 ****
if (get_bindings (TREE_VALUE (fn),
DECL_TEMPLATE_RESULT (TREE_VALUE (champ)),
NULL_TREE, /*check_ret=*/false))
fate++;
! if (fate != 1)
! {
! if (!fate)
! /* Equally specialized, move to next function. If there
! is no next function, nothing's most specialized. */
! fn = TREE_CHAIN (fn);
! champ = fn;
}
}
if (champ)
/* Now verify that champ is better than everything earlier in the
--- 10804,10822 ----
if (get_bindings (TREE_VALUE (fn),
DECL_TEMPLATE_RESULT (TREE_VALUE (champ)),
NULL_TREE, /*check_ret=*/false))
fate++;
! if (fate == -1)
! champ = fn;
! else if (!fate)
! {
! /* Equally specialized, move to next function. If there
! is no next function, nothing's most specialized. */
! fn = TREE_CHAIN (fn);
! if (!fn)
! break;
}
}
if (champ)
/* Now verify that champ is better than everything earlier in the
Index: gcc/cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.491
diff -c -5 -p -r1.491 semantics.c
*** gcc/cp/semantics.c 5 Oct 2005 12:17:13 -0000 1.491
--- gcc/cp/semantics.c 13 Oct 2005 07:50:41 -0000
*************** finish_id_expression (tree id_expression
*** 2457,2466 ****
--- 2457,2481 ----
the current class so that we can check later to see if
the meaning would have been different after the class
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,
then this wasn't really an id-expression. */
if (TREE_CODE (decl) == TEMPLATE_DECL
*************** finish_id_expression (tree id_expression
*** 2728,2754 ****
return finish_class_member_access_expr (decl, 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)
{
tree path;
--- 2743,2752 ----
Index: gcc/testsuite/g++.dg/parse/friend5.C
===================================================================
RCS file: gcc/testsuite/g++.dg/parse/friend5.C
diff -N gcc/testsuite/g++.dg/parse/friend5.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/parse/friend5.C 13 Oct 2005 07:50:42 -0000
***************
*** 0 ****
--- 1,7 ----
+ // PR c++/23694
+
+ extern "C" struct A
+ {
+ friend void foo(int) {} // { dg-error "declaration" }
+ friend void foo() {} // { dg-error "foo" }
+ };
Index: gcc/testsuite/g++.dg/template/crash38.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/crash38.C
diff -N gcc/testsuite/g++.dg/template/crash38.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/crash38.C 13 Oct 2005 07:50:42 -0000
***************
*** 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" }
+ };
Index: gcc/testsuite/g++.dg/template/crash39.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/crash39.C
diff -N gcc/testsuite/g++.dg/template/crash39.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/crash39.C 13 Oct 2005 07:50:42 -0000
***************
*** 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);
Index: gcc/testsuite/g++.dg/template/crash40.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/crash40.C
diff -N gcc/testsuite/g++.dg/template/crash40.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/crash40.C 13 Oct 2005 07:50:42 -0000
***************
*** 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" }
Index: gcc/testsuite/g++.dg/template/crash41.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/crash41.C
diff -N gcc/testsuite/g++.dg/template/crash41.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/crash41.C 13 Oct 2005 07:50:42 -0000
***************
*** 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);
+ }
+
+
Index: gcc/testsuite/g++.dg/template/friend38.C
===================================================================
RCS file: gcc/testsuite/g++.dg/template/friend38.C
diff -N gcc/testsuite/g++.dg/template/friend38.C
*** /dev/null 1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/template/friend38.C 13 Oct 2005 07:50:42 -0000
***************
*** 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;
+
More information about the Gcc-patches
mailing list