Commit 1cb801bc by Jason Merrill Committed by Jason Merrill

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
parent f017bf5e
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
......
......@@ -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)
......
......@@ -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);
......
......@@ -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)
......
......@@ -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;
}
......
......@@ -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)
......
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
......
// 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;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment