Commit 8ca4bf25 by Mark Mitchell Committed by Mark Mitchell

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
parent f05c19d1
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
......
......@@ -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);
......
......@@ -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);
......
......@@ -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;
}
}
......
......@@ -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)
......
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,
// PR c++/23694
extern "C" struct A
{
friend void foo(int) {} // { dg-error "declaration" }
friend void foo() {} // { dg-error "foo" }
};
// PR c++/23307
class A
{
template<class R>
static void f(X&); // { dg-error "" }
inline void A::f<void>(X&); // { dg-error "f|expected" }
};
// 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);
// PR c++/22180
struct A {};
template<typename T> void foo()
{
T::~T(); // { dg-error "member" }
}
template void foo<A>(); // { dg-error "instantiated" }
// 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);
}
// PR c++/22352
template <class A>
class s
{
typedef int d;
template <class s, typename s::d>
friend class t;
};
s<int> t1;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment