From 1cb801bc76b8a0fca94513bdd5d57da167b06dee Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 4 Mar 2009 13:42:17 -0500 Subject: 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 From-SVN: r144618 --- gcc/cp/ChangeLog | 12 +++++++++++ gcc/cp/class.c | 3 +++ gcc/cp/cp-tree.h | 1 + gcc/cp/decl.c | 24 +++++++++++++-------- gcc/cp/parser.c | 66 ++++++++++++++++++++++++++++++-------------------------- gcc/cp/pt.c | 12 ++++++++++- 6 files changed, 77 insertions(+), 41 deletions(-) (limited to 'gcc/cp') 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 + + 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 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) -- cgit v1.1