aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-11-16 18:29:25 -0500
committerJason Merrill <jason@gcc.gnu.org>2009-11-16 18:29:25 -0500
commit5a080ad7b0dc031e2b2c7f49fdb0ebf7d3d35514 (patch)
treed01fd61cab03b29407d10ef9f75bd71d4bae928a /gcc/cp
parent87213cd4965fb065bf1e57f6acd34df1695fedc0 (diff)
downloadgcc-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/ChangeLog19
-rw-r--r--gcc/cp/decl.c18
-rw-r--r--gcc/cp/error.c3
-rw-r--r--gcc/cp/parser.c16
-rw-r--r--gcc/cp/pt.c46
-rw-r--r--gcc/cp/search.c24
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