diff options
author | Jason Merrill <jason@redhat.com> | 2009-03-04 13:42:17 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2009-03-04 13:42:17 -0500 |
commit | 1cb801bc76b8a0fca94513bdd5d57da167b06dee (patch) | |
tree | 4b043a137dad400926339308b7bbd08a4d533f53 | |
parent | f017bf5e2d08214435620cd9644a2679782cba47 (diff) | |
download | gcc-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/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cp/class.c | 3 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 24 | ||||
-rw-r--r-- | gcc/cp/parser.c | 66 | ||||
-rw-r--r-- | gcc/cp/pt.c | 12 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/dependent-name5.C | 45 |
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; +}; |