aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2006-08-25 16:56:07 +0000
committerNathan Sidwell <nathan@codesourcery.com>2006-08-25 16:56:07 +0000
commit78a6c3ade8cb0b987be2fff20d42526906967209 (patch)
tree1975a26da88ae00800dc1b09ba8808327325e61d
parentfb873b52064003d1a7cb9eab5bd86d9a5830a679 (diff)
cp/
PR c++/27787 * decl.c (make_typename_type): Only try and resolve it when context is not dependent. Refactor. * decl2.c (check_classfn): Push to class scope before looking for the function. testsuite/ PR c++/27787 * g++.dg/template/typename10.C: New. * g++.dg/template/lookup4.C: Remove bogus error marker. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@116409 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/decl.c111
-rw-r--r--gcc/cp/decl2.c21
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/template/lookup4.C2
-rw-r--r--gcc/testsuite/g++.dg/template/typename10.C24
6 files changed, 104 insertions, 68 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c3bb4f32614..629ba67d3f0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2006-08-25 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/27787
+ * decl.c (make_typename_type): Only try and resolve it when
+ context is not dependent. Refactor.
+ * decl2.c (check_classfn): Push to class scope before looking for
+ the function.
+
2006-08-24 Danny Smith <dannysmith@users.sourceforge.net>
PR driver/28528
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index f45459603ad..8ba2a13578a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2779,6 +2779,8 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
tsubst_flags_t complain)
{
tree fullname;
+ tree t;
+ bool want_template;
if (name == error_mark_node
|| context == NULL_TREE
@@ -2816,73 +2818,60 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
gcc_assert (TYPE_P (context));
- if (!dependent_type_p (context)
- || currently_open_class (context))
- {
- if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
- {
- tree tmpl = NULL_TREE;
- if (IS_AGGR_TYPE (context))
- tmpl = lookup_field (context, name, 0, false);
- if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
- {
- if (complain & tf_error)
- error ("no class template named %q#T in %q#T",
- name, context);
- return error_mark_node;
- }
-
- if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
-
- return lookup_template_class (tmpl,
- TREE_OPERAND (fullname, 1),
- NULL_TREE, context,
- /*entering_scope=*/0,
- tf_warning_or_error | tf_user);
- }
- else
- {
- tree t;
+ /* When the CONTEXT is a dependent type, NAME could refer to a
+ dependent base class of CONTEXT. So we cannot peek inside it,
+ even if CONTEXT is a currently open scope. */
+ if (dependent_type_p (context))
+ return build_typename_type (context, name, fullname, tag_type);
- if (!IS_AGGR_TYPE (context))
- {
- if (complain & tf_error)
- error ("no type named %q#T in %q#T", name, context);
- return error_mark_node;
- }
-
- t = lookup_field (context, name, 0, true);
- if (t)
- {
- if (TREE_CODE (t) != TYPE_DECL)
- {
- if (complain & tf_error)
- error ("no type named %q#T in %q#T", name, context);
- return error_mark_node;
- }
-
- if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), t);
-
- if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
- t = TREE_TYPE (t);
-
- return t;
- }
- }
+ if (!IS_AGGR_TYPE (context))
+ {
+ if (complain & tf_error)
+ error ("%q#T is not a class", context);
+ return error_mark_node;
}
-
- /* If the CONTEXT is not a template type, then either the field is
- there now or its never going to be. */
- if (!dependent_type_p (context))
+
+ want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR;
+
+ /* We should only set WANT_TYPE when we're a nested typename type.
+ Then we can give better diagnostics if we find a non-type. */
+ t = lookup_field (context, name, 0, /*want_type=*/true);
+ if (!t)
{
if (complain & tf_error)
- error ("no type named %q#T in %q#T", name, context);
+ error (want_template ? "no class template named %q#T in %q#T"
+ : "no type named %q#T in %q#T", name, context);
return error_mark_node;
}
-
- return build_typename_type (context, name, fullname, tag_type);
+
+ if (want_template && !DECL_CLASS_TEMPLATE_P (t))
+ {
+ if (complain & tf_error)
+ error ("%<typename %T::%D%> names %q#T, which is not a class template",
+ context, name, t);
+ return error_mark_node;
+ }
+ if (!want_template && TREE_CODE (t) != TYPE_DECL)
+ {
+ if (complain & tf_error)
+ error ("%<typename %T::%D%> names %q#T, which is not a type",
+ context, name, t);
+ return error_mark_node;
+ }
+
+ if (complain & tf_error)
+ perform_or_defer_access_check (TYPE_BINFO (context), t);
+
+ if (want_template)
+ return lookup_template_class (t, TREE_OPERAND (fullname, 1),
+ NULL_TREE, context,
+ /*entering_scope=*/0,
+ tf_warning_or_error | tf_user);
+
+ if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
+ t = TREE_TYPE (t);
+
+ return t;
}
/* Resolve `CONTEXT::template NAME'. Returns a TEMPLATE_DECL if the name
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 0de2756620e..db1e9179a2b 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -553,7 +553,8 @@ check_classfn (tree ctype, tree function, tree template_parms)
{
int ix;
bool is_template;
-
+ tree pushed_scope;
+
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
@@ -583,16 +584,18 @@ check_classfn (tree ctype, tree function, tree template_parms)
/* OK, is this a definition of a member template? */
is_template = (template_parms != NULL_TREE);
+ /* We must enter the scope here, because conversion operators are
+ named by target type, and type equivalence relies on typenames
+ resolving within the scope of CTYPE. */
+ pushed_scope = push_scope (ctype);
ix = class_method_index_for_fn (complete_type (ctype), function);
if (ix >= 0)
{
VEC(tree,gc) *methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
- tree pushed_scope;
const char *format = NULL;
- pushed_scope = push_scope (ctype);
for (fndecls = VEC_index (tree, methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
@@ -631,10 +634,13 @@ check_classfn (tree ctype, tree function, tree template_parms)
== DECL_TI_TEMPLATE (fndecl))))
break;
}
- if (pushed_scope)
- pop_scope (pushed_scope);
if (fndecls)
- return OVL_CURRENT (fndecls);
+ {
+ if (pushed_scope)
+ pop_scope (pushed_scope);
+ return OVL_CURRENT (fndecls);
+ }
+
error ("prototype for %q#D does not match any in class %qT",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
@@ -682,6 +688,9 @@ check_classfn (tree ctype, tree function, tree template_parms)
properly within the class. */
if (COMPLETE_TYPE_P (ctype))
add_method (ctype, function, NULL_TREE);
+
+ if (pushed_scope)
+ pop_scope (pushed_scope);
return NULL_TREE;
}
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 2a1485c2da3..8e9e60a35ae 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2006-08-25 Nathan Sidwell <nathan@codesourcery.com>
+
+ PR c++/27787
+ * g++.dg/template/typename10.C: New.
+ * g++.dg/template/lookup4.C: Remove bogus error marker.
+
2006-08-25 Richard Guenther <rguenther@suse.de>
PR testsuite/28829
diff --git a/gcc/testsuite/g++.dg/template/lookup4.C b/gcc/testsuite/g++.dg/template/lookup4.C
index d64006133c3..3bd73a34e60 100644
--- a/gcc/testsuite/g++.dg/template/lookup4.C
+++ b/gcc/testsuite/g++.dg/template/lookup4.C
@@ -2,5 +2,5 @@
template <class T> struct Base {};
template <class T> struct Derived: public Base<T> {
- typename Derived::template Base<double>* p1; // { dg-error "" }
+ typename Derived::template Base<double>* p1;
};
diff --git a/gcc/testsuite/g++.dg/template/typename10.C b/gcc/testsuite/g++.dg/template/typename10.C
new file mode 100644
index 00000000000..f6f9931dfaf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typename10.C
@@ -0,0 +1,24 @@
+// { dg-do compile }
+
+// Copyright (C) 2006 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 25 Aug 2006 <nathan@codesourcery.com>
+
+// Origin: Tobias Schwinger <tschwinger@neoscientists.org>
+// PR 27787. Too eager to resolve a typename
+
+template<typename X>
+struct x
+{
+ template<typename Y>
+ struct y
+ {
+ typedef Y type;
+ };
+};
+
+template<typename A>
+struct a : x<A>
+{
+ template<typename B>
+ typename a::template y<B>::type f(B);
+};