aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-03-04 13:42:17 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-03-04 13:42:17 -0500
commit1cb801bc76b8a0fca94513bdd5d57da167b06dee (patch)
tree4b043a137dad400926339308b7bbd08a4d533f53
parentf017bf5e2d08214435620cd9644a2679782cba47 (diff)
downloadgcc-1cb801bc76b8a0fca94513bdd5d57da167b06dee.zip
gcc-1cb801bc76b8a0fca94513bdd5d57da167b06dee.tar.gz
gcc-1cb801bc76b8a0fca94513bdd5d57da167b06dee.tar.bz2
re PR c++/9634 ([DR224] Injected class name as qualifier should not make the name dependent)
PR c++/9634 PR c++/29469 PR c++/29607 * decl.c (make_typename_type): Do look inside currently open classes. * parser.c (cp_parser_lookup_name): Likewise. (cp_parser_template_name): Likewise. * pt.c (dependent_scope_p): New function. * cp-tree.h: Declare it. * class.c (currently_open_class): Return fast if T isn't a class. Co-Authored-By: Giovanni Bajo <giovannibajo@gcc.gnu.org> From-SVN: r144618
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/class.c3
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c24
-rw-r--r--gcc/cp/parser.c66
-rw-r--r--gcc/cp/pt.c12
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/template/dependent-name5.C45
8 files changed, 130 insertions, 41 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9d1ab5a..30034b1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2009-03-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/9634
+ PR c++/29469
+ PR c++/29607
+ * decl.c (make_typename_type): Do look inside currently open classes.
+ * parser.c (cp_parser_lookup_name): Likewise.
+ (cp_parser_template_name): Likewise.
+ * pt.c (dependent_scope_p): New function.
+ * cp-tree.h: Declare it.
+ * class.c (currently_open_class): Return fast if T isn't a class.
+
2009-02-26 H.J. Lu <hongjiu.lu@intel.com>
PR c++/37789
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 13fa990..ae89218 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -5787,6 +5787,9 @@ currently_open_class (tree t)
{
int i;
+ if (!CLASS_TYPE_P (t))
+ return false;
+
/* We start looking from 1 because entry 0 is from global scope,
and has no type. */
for (i = current_class_depth; i > 0; --i)
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 46ff922..b6bf7d4 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4594,6 +4594,7 @@ extern struct tinst_level *current_instantiation(void);
extern tree maybe_get_template_decl_from_type_decl (tree);
extern int processing_template_parmlist;
extern bool dependent_type_p (tree);
+extern bool dependent_scope_p (tree);
extern bool any_dependent_template_arguments_p (const_tree);
extern bool dependent_template_p (tree);
extern bool dependent_template_id_p (tree, tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 551764d..ddd133a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2977,12 +2977,6 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
gcc_assert (TYPE_P (context));
- /* 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 (!MAYBE_CLASS_TYPE_P (context))
{
if (complain & tf_error)
@@ -2990,11 +2984,23 @@ make_typename_type (tree context, tree name, enum tag_types tag_type,
return error_mark_node;
}
+ /* When the CONTEXT is a dependent type, NAME could refer to a
+ dependent base class of CONTEXT. But look inside it anyway
+ if CONTEXT is a currently open scope, in case it refers to a
+ member of the current instantiation or a non-dependent base;
+ lookup will stop when we hit a dependent base. */
+ if (!dependent_scope_p (context))
+ /* 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);
+ else
+ t = NULL_TREE;
+
+ if (!t && dependent_type_p (context))
+ return build_typename_type (context, name, fullname, tag_type);
+
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)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 80a767e..f07df91 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10323,7 +10323,7 @@ cp_parser_template_name (cp_parser* parser,
&& !template_keyword_p
&& parser->scope && TYPE_P (parser->scope)
&& check_dependency_p
- && dependent_type_p (parser->scope)
+ && dependent_scope_p (parser->scope)
/* Do not do this for dtors (or ctors), since they never
need the template keyword before their name. */
&& !constructor_name_p (identifier, parser->scope))
@@ -17023,35 +17023,11 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
cannot look up the name if the scope is not a class type; it
might, for example, be a template type parameter. */
dependent_p = (TYPE_P (parser->scope)
- && !(parser->in_declarator_p
- && currently_open_class (parser->scope))
- && dependent_type_p (parser->scope));
+ && dependent_scope_p (parser->scope));
if ((check_dependency || !CLASS_TYPE_P (parser->scope))
- && dependent_p)
- {
- if (tag_type)
- {
- tree type;
-
- /* The resolution to Core Issue 180 says that `struct
- A::B' should be considered a type-name, even if `A'
- is dependent. */
- type = make_typename_type (parser->scope, name, tag_type,
- /*complain=*/tf_error);
- decl = TYPE_NAME (type);
- }
- else if (is_template
- && (cp_parser_next_token_ends_template_argument_p (parser)
- || cp_lexer_next_token_is (parser->lexer,
- CPP_CLOSE_PAREN)))
- decl = make_unbound_class_template (parser->scope,
- name, NULL_TREE,
- /*complain=*/tf_error);
- else
- decl = build_qualified_name (/*type=*/NULL_TREE,
- parser->scope, name,
- is_template);
- }
+ && dependent_p)
+ /* Defer lookup. */
+ decl = error_mark_node;
else
{
tree pushed_scope = NULL_TREE;
@@ -17072,14 +17048,42 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
/*complain=*/true);
/* If we have a single function from a using decl, pull it out. */
- if (decl
- && TREE_CODE (decl) == OVERLOAD
+ if (TREE_CODE (decl) == OVERLOAD
&& !really_overloaded_fn (decl))
decl = OVL_FUNCTION (decl);
if (pushed_scope)
pop_scope (pushed_scope);
}
+
+ /* If the scope is a dependent type and either we deferred lookup or
+ we did lookup but didn't find the name, rememeber the name. */
+ if (decl == error_mark_node && TYPE_P (parser->scope)
+ && dependent_type_p (parser->scope))
+ {
+ if (tag_type)
+ {
+ tree type;
+
+ /* The resolution to Core Issue 180 says that `struct
+ A::B' should be considered a type-name, even if `A'
+ is dependent. */
+ type = make_typename_type (parser->scope, name, tag_type,
+ /*complain=*/tf_error);
+ decl = TYPE_NAME (type);
+ }
+ else if (is_template
+ && (cp_parser_next_token_ends_template_argument_p (parser)
+ || cp_lexer_next_token_is (parser->lexer,
+ CPP_CLOSE_PAREN)))
+ decl = make_unbound_class_template (parser->scope,
+ name, NULL_TREE,
+ /*complain=*/tf_error);
+ else
+ decl = build_qualified_name (/*type=*/NULL_TREE,
+ parser->scope, name,
+ is_template);
+ }
parser->qualifying_scope = parser->scope;
parser->object_scope = NULL_TREE;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index dacc868..8ae4ed5 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -16067,6 +16067,16 @@ dependent_type_p (tree type)
return TYPE_DEPENDENT_P (type);
}
+/* Returns TRUE if SCOPE is a dependent scope, in which we can't do any
+ lookup. In other words, a dependent type that is not the current
+ instantiation. */
+
+bool
+dependent_scope_p (tree scope)
+{
+ return dependent_type_p (scope) && !currently_open_class (scope);
+}
+
/* Returns TRUE if EXPRESSION is dependent, according to CRITERION. */
static bool
@@ -16088,7 +16098,7 @@ dependent_scope_ref_p (tree expression, bool criterion (tree))
An id-expression is type-dependent if it contains a
nested-name-specifier that contains a class-name that names a
dependent type. */
- /* The suggested resolution to Core Issue 2 implies that if the
+ /* The suggested resolution to Core Issue 224 implies that if the
qualifying type is the current class, then we must peek
inside it. */
if (DECL_P (name)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index e1cbbc7..97668fd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,11 @@
+2009-03-04 Jason Merrill <jason@redhat.com>
+ Giovanni Bajo <giovannibajo@gcc.gnu.org>
+
+ PR c++/9634
+ PR c++/29469
+ PR c++/29607
+ * g++.dg/template/dependent-name5.C: New test.
+
2009-03-04 Steve Ellcey <sje@cup.hp.com>
PR testsuite/39357
diff --git a/gcc/testsuite/g++.dg/template/dependent-name5.C b/gcc/testsuite/g++.dg/template/dependent-name5.C
new file mode 100644
index 0000000..681060c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dependent-name5.C
@@ -0,0 +1,45 @@
+// PR c++/9634, c++/29469, c++/29607
+// Contributed by: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
+// DR224: Make sure that a name is *truly* semantically dependent.
+
+struct D {
+ typedef int K;
+};
+
+template <typename T>
+struct A
+{
+ typedef int Bar;
+
+ template <typename>
+ struct N {};
+
+ typedef Bar type1;
+ typedef A::Bar type2;
+ typedef A<T>::Bar type3;
+ typedef A<T*>::Bar type4; // { dg-error "" }
+ typedef typename A<T*>::Bar type5;
+
+ typedef N<int> type6;
+ typedef A::N<int> type7;
+ typedef A<T>::N<int> type8;
+ typedef A<T*>::template N<int> type9; // { dg-error "" }
+ typedef typename A<T*>::template N<int> type10;
+
+ typedef D Bar2;
+ struct N2 { typedef int K; };
+
+ // Check that A::N2 is still considered dependent (because it
+ // could be specialized), while A::Bar2 (being just ::D) is not.
+ typedef A::Bar2 type11;
+ typedef type11::K k3;
+
+ typedef A::N2 type12;
+ typedef typename type12::K k2;
+ typedef type12::K k1; // { dg-error "" }
+
+ // Check that A::Bar2 is not considered dependent even if we use
+ // the typename keyword.
+ typedef typename A::Bar2 type13;
+ typedef type13::K k4;
+};