aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2005-10-13 08:38:40 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2005-10-13 08:38:40 +0000
commit8ca4bf259c9e43016064c46ed853191c2ed4abd2 (patch)
tree47e3bf1306fadcd49657cf8f43c314aa5076aa1f /gcc
parentf05c19d12690c180c75cea2f10cdfc853da8060c (diff)
downloadgcc-8ca4bf259c9e43016064c46ed853191c2ed4abd2.zip
gcc-8ca4bf259c9e43016064c46ed853191c2ed4abd2.tar.gz
gcc-8ca4bf259c9e43016064c46ed853191c2ed4abd2.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog28
-rw-r--r--gcc/cp/call.c1
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/pt.c56
-rw-r--r--gcc/cp/semantics.c32
-rw-r--r--gcc/testsuite/ChangeLog20
-rw-r--r--gcc/testsuite/g++.dg/parse/friend5.C7
-rw-r--r--gcc/testsuite/g++.dg/template/crash38.C8
-rw-r--r--gcc/testsuite/g++.dg/template/crash39.C11
-rw-r--r--gcc/testsuite/g++.dg/template/crash40.C10
-rw-r--r--gcc/testsuite/g++.dg/template/crash41.C18
-rw-r--r--gcc/testsuite/g++.dg/template/friend38.C12
12 files changed, 171 insertions, 34 deletions
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 <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
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 %<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)
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 <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
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<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
index 0000000..ddecc17
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash39.C
@@ -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
index 0000000..716b4a2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash40.C
@@ -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
index 0000000..9a440b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/crash41.C
@@ -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
index 0000000..41faf79
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/friend38.C
@@ -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;
+