From 8ca4bf259c9e43016064c46ed853191c2ed4abd2 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Thu, 13 Oct 2005 08:38:40 +0000 Subject: [PATCH] re PR c++/22464 (ICE on classes in template functions which attempt closure) 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 --- gcc/cp/ChangeLog | 28 ++++++++++++++++ gcc/cp/call.c | 1 + gcc/cp/decl.c | 2 +- gcc/cp/pt.c | 56 +++++++++++++++++++++++--------- gcc/cp/semantics.c | 32 +++++++++--------- gcc/testsuite/ChangeLog | 20 ++++++++++++ gcc/testsuite/g++.dg/parse/friend5.C | 7 ++++ gcc/testsuite/g++.dg/template/crash38.C | 8 +++++ gcc/testsuite/g++.dg/template/crash39.C | 11 +++++++ gcc/testsuite/g++.dg/template/crash40.C | 10 ++++++ gcc/testsuite/g++.dg/template/crash41.C | 18 ++++++++++ gcc/testsuite/g++.dg/template/friend38.C | 12 +++++++ 12 files changed, 171 insertions(+), 34 deletions(-) create mode 100644 gcc/testsuite/g++.dg/parse/friend5.C create mode 100644 gcc/testsuite/g++.dg/template/crash38.C create mode 100644 gcc/testsuite/g++.dg/template/crash39.C create mode 100644 gcc/testsuite/g++.dg/template/crash40.C create mode 100644 gcc/testsuite/g++.dg/template/crash41.C create mode 100644 gcc/testsuite/g++.dg/template/friend38.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index cb4ce85..4ad7a08 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,31 @@ +2005-10-13 Mark Mitchell + + 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 PR target/21801 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index cdf70a4..9247605 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index b76c12d..77f3164 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6724cf4..0475fc8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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; } } diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 80885c5..d870fda 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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 % 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 % 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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 640cc22..1cfd961 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,23 @@ +2005-10-13 Mark Mitchell + + 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 * 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 index 0000000..5e23f45 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/friend5.C @@ -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 index 0000000..c652cc8 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash38.C @@ -0,0 +1,8 @@ +// PR c++/23307 + +class A +{ + template + static void f(X&); // { dg-error "" } + inline void A::f(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 index 0000000..ddecc17 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash39.C @@ -0,0 +1,11 @@ +// PR c++/22405 + +template void foo(T &arg) { // { dg-error "declared" } + arg+=1; +} + +template 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 index 0000000..716b4a2 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash40.C @@ -0,0 +1,10 @@ +// PR c++/22180 + +struct A {}; + +template void foo() +{ + T::~T(); // { dg-error "member" } +} + +template void foo(); // { 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 index 0000000..9a440b0 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/crash41.C @@ -0,0 +1,18 @@ +// PR c++/22464 + +template +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 index 0000000..41faf79 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/friend38.C @@ -0,0 +1,12 @@ +// PR c++/22352 + +template +class s +{ + typedef int d; + template + friend class t; +}; + +s t1; + -- 2.7.4