diff options
-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 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/inherit.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/template/injected1.C | 33 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.brendan/crash56.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/lookup8.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp22.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/ttp23.C | 2 |
13 files changed, 134 insertions, 45 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ce4415d3f7f..960cedc2af5 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 73bf995714f..851edeb5251 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 f4232075119..7266d8872d5 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 3a4b409e738..576842641fe 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 4ca94d6a895..9c82e3c19a5 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 3adf9e0a1ab..3e9bec011ff 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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 42702ebd9d5..6b3e48cbdac 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2009-11-16 Jason Merrill <jason@redhat.com> + + PR c++/13950 + * g++.dg/template/injected1.C: New. + * g++.dg/template/inherit.C: Adjust. + * g++.old-deja/g++.brendan/crash56.C: Adjust. + * g++.old-deja/g++.pt/lookup8.C: Adjust. + * g++.old-deja/g++.pt/ttp22.C: Adjust. + * g++.old-deja/g++.pt/ttp23.C: Adjust. + 2009-11-16 Paolo Carlini <paolo.carlini@oracle.com> PR c++/42055 diff --git a/gcc/testsuite/g++.dg/template/inherit.C b/gcc/testsuite/g++.dg/template/inherit.C index bc20345fa0a..43af3cfc5ac 100644 --- a/gcc/testsuite/g++.dg/template/inherit.C +++ b/gcc/testsuite/g++.dg/template/inherit.C @@ -9,5 +9,5 @@ struct Z : X<int> { }; int main() { Z z; - z.X::f(); // { dg-error "template parameters" "" } + z.X::f(); } diff --git a/gcc/testsuite/g++.dg/template/injected1.C b/gcc/testsuite/g++.dg/template/injected1.C new file mode 100644 index 00000000000..81873b498f9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/injected1.C @@ -0,0 +1,33 @@ +// PR c++/13950, DR 176 + +template <class T> struct Base { }; // { dg-error "" } candidate + +struct D1: Base<void> +{ + D1::Base* p1; + D1::Base<double>* p2; + Base *p3; + Base<double>* p4; +}; + +struct D2: Base<void>, Base<void*> +{ + D2::Base* p1; // { dg-error "" } + D2::Base<double>* p2; + Base *p3; // { dg-error "" } + Base<double>* p4; +}; + +template <class T> +struct D3: Base<T> { + typename D3::Base* p1; + typename D3::template Base<double>* p2; +}; +template struct D3<void>; + +template <class T> +struct D4: Base<T>, Base<T*> { + typename D4::Base* p1; // { dg-error "" } + typename D4::template Base<double>* p2; +}; +template struct D4<void>; // { dg-message "instantiated" } diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C index dcb89dc9e48..0932ca46659 100644 --- a/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C +++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash56.C @@ -342,7 +342,7 @@ operator>=(const SetLD<T>& a, const SetLD<T>& b) { return ! (a < b); } class String { }; class IcaseString: public String { }; -template <> class SetLD< IcaseString >: public SetLD< String > { public: SetLD (): SetLD< String >() { }; SetLD (const ListD< IcaseString >& other): SetLD< String >() { ListD< IcaseString >::Vix x; for (other.first(x); 0 != x; other.next(x)) add(other(x)); }; SetLD (const SetLD & other): SetLD< String >(other) { }; const IcaseString & operator()(const Vix& x) const { return ( IcaseString &) SetLD< String >::operator()(x); } }; typedef SetLD< String > SetLD_String_IcaseString_old_tmp99; typedef SetLD< IcaseString > SetLD_String_IcaseString_new_tmp99; +template <> class SetLD< IcaseString >: public SetLD< String > { public: SetLD (): SetLD< String >() { }; SetLD (const ::ListD< IcaseString >& other): SetLD< String >() { ::ListD< IcaseString >::Vix x; for (other.first(x); 0 != x; other.next(x)) add(other(x)); }; SetLD (const SetLD & other): SetLD< String >(other) { }; const IcaseString & operator()(const Vix& x) const { return ( IcaseString &) SetLD< String >::operator()(x); } }; typedef SetLD< String > SetLD_String_IcaseString_old_tmp99; typedef SetLD< IcaseString > SetLD_String_IcaseString_new_tmp99; inline int operator== (const SetLD_String_IcaseString_new_tmp99& a, const SetLD_String_IcaseString_new_tmp99& b) // { dg-message "operator==" } { const SetLD_String_IcaseString_old_tmp99& oa = a; diff --git a/gcc/testsuite/g++.old-deja/g++.pt/lookup8.C b/gcc/testsuite/g++.old-deja/g++.pt/lookup8.C index 2c6df5583b9..1662f68c7b6 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/lookup8.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/lookup8.C @@ -11,5 +11,5 @@ class Y : public X<int> void Y::f() { - X x; // { dg-error "" } X is not a type. + X x; } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp22.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp22.C index 01f08c0dbbe..de3334e79e6 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ttp22.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp22.C @@ -24,7 +24,7 @@ template<template<class> class DD,class EE> int C<DD,EE>::f() class E : C<D,int> { public: - int f() { return C<D,int>::f(); } + int f() { return C< ::D,int>::f(); } }; int main() diff --git a/gcc/testsuite/g++.old-deja/g++.pt/ttp23.C b/gcc/testsuite/g++.old-deja/g++.pt/ttp23.C index 8db7f386a03..051a3f33036 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/ttp23.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/ttp23.C @@ -24,7 +24,7 @@ template<template<class> class E,class D> int C<E,D>::f() class E : C<D,int> { public: - int f() { return C<D,int>::f(); } + int f() { return C< ::D,int>::f(); } }; int main() |