diff options
author | Jason Merrill <jason@redhat.com> | 2009-11-16 18:29:25 -0500 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2009-11-16 18:29:25 -0500 |
commit | 5a080ad7b0dc031e2b2c7f49fdb0ebf7d3d35514 (patch) | |
tree | d01fd61cab03b29407d10ef9f75bd71d4bae928a /gcc/cp | |
parent | 87213cd4965fb065bf1e57f6acd34df1695fedc0 (diff) | |
download | gcc-5a080ad7b0dc031e2b2c7f49fdb0ebf7d3d35514.zip gcc-5a080ad7b0dc031e2b2c7f49fdb0ebf7d3d35514.tar.gz gcc-5a080ad7b0dc031e2b2c7f49fdb0ebf7d3d35514.tar.bz2 |
PR c++/13950, DR 176
PR c++/13950, DR 176
* search.c (lookup_field_r): Allow lookup to find the
injected-class-name from a template base.
(template_self_reference_p): Remove.
* decl.c (make_typename_type): Diagnose ambiguity. Use
maybe_get_template_decl_from_type_decl.
* parser.c (cp_parser_template_name): Pass true to is_template
rather than use maybe_get_template_decl_from_type_decl.
(cp_parser_lookup_name): Use maybe_get_template_decl_from_type_decl.
* pt.c (maybe_get_template_decl_from_type_decl): Handle ambiguity.
Use DECL_SELF_REFERENCE_P.
* parser.c (cp_parser_parse_and_diagnose_invalid_type_name):
Avoid duplicate ambiguity error.
* error.c (dump_decl): Don't say "typedef" for injected-class-name.
* pt.c (convert_template_argument): Tweak logic.
From-SVN: r154223
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 19 | ||||
-rw-r--r-- | gcc/cp/decl.c | 18 | ||||
-rw-r--r-- | gcc/cp/error.c | 3 | ||||
-rw-r--r-- | gcc/cp/parser.c | 16 | ||||
-rw-r--r-- | gcc/cp/pt.c | 46 | ||||
-rw-r--r-- | gcc/cp/search.c | 24 |
6 files changed, 86 insertions, 40 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ce4415d..960cedc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +2009-11-16 Jason Merrill <jason@redhat.com> + + PR c++/13950, DR 176 + * search.c (lookup_field_r): Allow lookup to find the + injected-class-name from a template base. + (template_self_reference_p): Remove. + * decl.c (make_typename_type): Diagnose ambiguity. Use + maybe_get_template_decl_from_type_decl. + * parser.c (cp_parser_template_name): Pass true to is_template + rather than use maybe_get_template_decl_from_type_decl. + (cp_parser_lookup_name): Use maybe_get_template_decl_from_type_decl. + * pt.c (maybe_get_template_decl_from_type_decl): Handle ambiguity. + Use DECL_SELF_REFERENCE_P. + + * parser.c (cp_parser_parse_and_diagnose_invalid_type_name): + Avoid duplicate ambiguity error. + * error.c (dump_decl): Don't say "typedef" for injected-class-name. + * pt.c (convert_template_argument): Tweak logic. + 2009-11-16 Paolo Carlini <paolo.carlini@oracle.com> PR c++/42055 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 73bf995..851edeb 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3040,11 +3040,11 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, 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); + t = lookup_field (context, name, 2, /*want_type=*/true); else t = NULL_TREE; - if (!t && dependent_type_p (context)) + if ((!t || TREE_CODE (t) == TREE_LIST) && dependent_type_p (context)) return build_typename_type (context, name, fullname, tag_type); want_template = TREE_CODE (fullname) == TEMPLATE_ID_EXPR; @@ -3057,6 +3057,20 @@ make_typename_type (tree context, tree name, enum tag_types tag_type, return error_mark_node; } + /* Pull out the template from an injected-class-name (or multiple). */ + if (want_template) + t = maybe_get_template_decl_from_type_decl (t); + + if (TREE_CODE (t) == TREE_LIST) + { + if (complain & tf_error) + { + error ("lookup of %qT in %qT is ambiguous", name, context); + print_candidates (t); + } + return error_mark_node; + } + if (want_template && !DECL_CLASS_TEMPLATE_P (t)) { if (complain & tf_error) diff --git a/gcc/cp/error.c b/gcc/cp/error.c index f423207..7266d88 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -908,7 +908,8 @@ dump_decl (tree t, int flags) dump_type (TREE_TYPE (t), flags); break; } - if (flags & TFF_DECL_SPECIFIERS) + if ((flags & TFF_DECL_SPECIFIERS) + && !DECL_SELF_REFERENCE_P (t)) pp_cxx_ws_string (cxx_pp, "typedef"); dump_simple_decl (t, DECL_ORIGINAL_TYPE (t) ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 3a4b409..57684264 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -2430,6 +2430,14 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) tree id; cp_token *token = cp_lexer_peek_token (parser->lexer); + /* Avoid duplicate error about ambiguous lookup. */ + if (token->type == CPP_NESTED_NAME_SPECIFIER) + { + cp_token *next = cp_lexer_peek_nth_token (parser->lexer, 2); + if (next->type == CPP_NAME && next->ambiguous_p) + goto out; + } + cp_parser_parse_tentatively (parser); id = cp_parser_id_expression (parser, /*template_keyword_p=*/false, @@ -2451,6 +2459,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser) /* Emit a diagnostic for the invalid type. */ cp_parser_diagnose_invalid_type_name (parser, parser->scope, id, token->location); + out: /* If we aren't in the middle of a declarator (i.e. in a parameter-declaration-clause), skip to the end of the declaration; there's no point in trying to process it. */ @@ -11086,12 +11095,11 @@ cp_parser_template_name (cp_parser* parser, /* Look up the name. */ decl = cp_parser_lookup_name (parser, identifier, none_type, - /*is_template=*/false, + /*is_template=*/true, /*is_namespace=*/false, check_dependency_p, /*ambiguous_decls=*/NULL, token->location); - decl = maybe_get_template_decl_from_type_decl (decl); /* If DECL is a template, then the name was a template-name. */ if (TREE_CODE (decl) == TEMPLATE_DECL) @@ -18045,6 +18053,10 @@ cp_parser_lookup_name (cp_parser *parser, tree name, if (!decl || decl == error_mark_node) return error_mark_node; + /* Pull out the template from an injected-class-name (or multiple). */ + if (is_template) + decl = maybe_get_template_decl_from_type_decl (decl); + /* If it's a TREE_LIST, the result of the lookup was ambiguous. */ if (TREE_CODE (decl) == TREE_LIST) { diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 4ca94d6..9c82e3c 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5451,7 +5451,7 @@ convert_template_argument (tree parm, complain, in_decl, args)) { - val = orig_arg; + val = arg; /* TEMPLATE_TEMPLATE_PARM node is preferred over TEMPLATE_DECL. */ @@ -5459,12 +5459,8 @@ convert_template_argument (tree parm, { if (DECL_TEMPLATE_TEMPLATE_PARM_P (val)) val = TREE_TYPE (val); - else if (TREE_CODE (val) == TYPE_PACK_EXPANSION - && DECL_TEMPLATE_TEMPLATE_PARM_P (arg)) - { - val = TREE_TYPE (arg); - val = make_pack_expansion (val); - } + if (TREE_CODE (orig_arg) == TYPE_PACK_EXPANSION) + val = make_pack_expansion (val); } } else @@ -5990,15 +5986,43 @@ lookup_template_function (tree fns, tree arglist) TEMPLATE_DECL. If DECL is a TYPE_DECL for current_class_type, or one of its enclosing classes, and that type is a template, return the associated TEMPLATE_DECL. Otherwise, the original - DECL is returned. */ + DECL is returned. + + Also handle the case when DECL is a TREE_LIST of ambiguous + injected-class-names from different bases. */ tree maybe_get_template_decl_from_type_decl (tree decl) { + if (decl == NULL_TREE) + return decl; + + /* DR 176: A lookup that finds an injected-class-name (10.2 + [class.member.lookup]) can result in an ambiguity in certain cases + (for example, if it is found in more than one base class). If all of + the injected-class-names that are found refer to specializations of + the same class template, and if the name is followed by a + template-argument-list, the reference refers to the class template + itself and not a specialization thereof, and is not ambiguous. */ + if (TREE_CODE (decl) == TREE_LIST) + { + tree t, tmpl = NULL_TREE; + for (t = decl; t; t = TREE_CHAIN (t)) + { + tree elt = maybe_get_template_decl_from_type_decl (TREE_VALUE (t)); + if (!tmpl) + tmpl = elt; + else if (tmpl != elt) + break; + } + if (tmpl && t == NULL_TREE) + return tmpl; + else + return decl; + } + return (decl != NULL_TREE - && TREE_CODE (decl) == TYPE_DECL - && DECL_ARTIFICIAL (decl) - && CLASS_TYPE_P (TREE_TYPE (decl)) + && DECL_SELF_REFERENCE_P (decl) && CLASSTYPE_TEMPLATE_INFO (TREE_TYPE (decl))) ? CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl)) : decl; } diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 3adf9e0..3e9bec0 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -63,7 +63,6 @@ static tree dfs_access_in_type (tree, void *); static access_kind access_in_type (tree, tree); static int protected_accessible_p (tree, tree, tree); static int friend_accessible_p (tree, tree, tree); -static int template_self_reference_p (tree, tree); static tree dfs_get_pure_virtuals (tree, void *); @@ -955,24 +954,6 @@ struct lookup_field_info { const char *errstr; }; -/* Within the scope of a template class, you can refer to the to the - current specialization with the name of the template itself. For - example: - - template <typename T> struct S { S* sp; } - - Returns nonzero if DECL is such a declaration in a class TYPE. */ - -static int -template_self_reference_p (tree type, tree decl) -{ - return (CLASSTYPE_USE_TEMPLATE (type) - && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)) - && TREE_CODE (decl) == TYPE_DECL - && DECL_ARTIFICIAL (decl) - && DECL_NAME (decl) == constructor_name (type)); -} - /* Nonzero for a class member means that it is shared between all objects of that class. @@ -1092,11 +1073,6 @@ lookup_field_r (tree binfo, void *data) } } - /* You must name a template base class with a template-id. */ - if (!same_type_p (type, lfi->type) - && template_self_reference_p (type, nval)) - goto done; - /* If the lookup already found a match, and the new value doesn't hide the old one, we might have an ambiguity. */ if (lfi->rval_binfo |