class.c (resolve_address_of_overloaded_function): Do conversion to correct type here, rather than ...
* class.c (resolve_address_of_overloaded_function): Do conversion to correct type here, rather than ... (instantiate_type): Here. * cp-tree.h (DECL_TEMPLATE_PARM_P): New macro. (DECL_TEMPLATE_TEMPLATE_PARM_P): Use it. (decl_template_parm_p): Remove. * decl.c (pushdecl): Don't set DECL_CONTEXT for a template paramter. * lex.c (do_identifier): Use DECL_TEMPLATE_PARM_P. (push_inline_template_parms_recursive): Set it. (decl_template_parm_p): Remove. (check_template_shadow): Use DECL_TEMPLATE_PARM_P. (process_template_parm): Set it. From-SVN: r24344
This commit is contained in:
parent
05c32e169c
commit
50714e797c
|
@ -1,3 +1,20 @@
|
||||||
|
1998-12-16 Mark Mitchell <mark@markmitchell.com>
|
||||||
|
|
||||||
|
* class.c (resolve_address_of_overloaded_function): Do conversion
|
||||||
|
to correct type here, rather than ...
|
||||||
|
(instantiate_type): Here.
|
||||||
|
|
||||||
|
* cp-tree.h (DECL_TEMPLATE_PARM_P): New macro.
|
||||||
|
(DECL_TEMPLATE_TEMPLATE_PARM_P): Use it.
|
||||||
|
(decl_template_parm_p): Remove.
|
||||||
|
* decl.c (pushdecl): Don't set DECL_CONTEXT for a template
|
||||||
|
paramter.
|
||||||
|
* lex.c (do_identifier): Use DECL_TEMPLATE_PARM_P.
|
||||||
|
(push_inline_template_parms_recursive): Set it.
|
||||||
|
(decl_template_parm_p): Remove.
|
||||||
|
(check_template_shadow): Use DECL_TEMPLATE_PARM_P.
|
||||||
|
(process_template_parm): Set it.
|
||||||
|
|
||||||
Wed Dec 16 16:33:58 1998 Dave Brolley <brolley@cygnus.com>
|
Wed Dec 16 16:33:58 1998 Dave Brolley <brolley@cygnus.com>
|
||||||
|
|
||||||
* lang-specs.h (default_compilers): Pass -MD, -MMD and -MG to cc1plus
|
* lang-specs.h (default_compilers): Pass -MD, -MMD and -MG to cc1plus
|
||||||
|
|
|
@ -5025,6 +5025,7 @@ resolve_address_of_overloaded_function (target_type,
|
||||||
are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
|
are the TREE_PURPOSE, not the TREE_VALUE, in this list, for easy
|
||||||
interoperability with most_specialized_instantiation. */
|
interoperability with most_specialized_instantiation. */
|
||||||
tree matches = NULL_TREE;
|
tree matches = NULL_TREE;
|
||||||
|
tree fn;
|
||||||
|
|
||||||
/* By the time we get here, we should be seeing only real
|
/* By the time we get here, we should be seeing only real
|
||||||
pointer-to-member types, not the internal POINTER_TYPE to
|
pointer-to-member types, not the internal POINTER_TYPE to
|
||||||
|
@ -5212,8 +5213,20 @@ resolve_address_of_overloaded_function (target_type,
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Good, exactly one match. */
|
/* Good, exactly one match. Now, convert it to the correct type. */
|
||||||
return TREE_PURPOSE (matches);
|
fn = TREE_PURPOSE (matches);
|
||||||
|
|
||||||
|
if (TYPE_PTRFN_P (target_type) || TYPE_PTRMEMFUNC_P (target_type))
|
||||||
|
return build_unary_op (ADDR_EXPR, fn, 0);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* The target must be a REFERENCE_TYPE. Above, build_unary_op
|
||||||
|
will mark the function as addressed, but here we must do it
|
||||||
|
explicitly. */
|
||||||
|
mark_addressable (fn);
|
||||||
|
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function will instantiate the type of the expression given in
|
/* This function will instantiate the type of the expression given in
|
||||||
|
@ -5291,33 +5304,31 @@ instantiate_type (lhstype, rhs, complain)
|
||||||
case COMPONENT_REF:
|
case COMPONENT_REF:
|
||||||
{
|
{
|
||||||
tree field = TREE_OPERAND (rhs, 1);
|
tree field = TREE_OPERAND (rhs, 1);
|
||||||
if (TREE_CODE (field) == TREE_LIST)
|
tree r;
|
||||||
|
|
||||||
|
my_friendly_assert (TREE_CODE (field) == TREE_LIST, 0);
|
||||||
|
|
||||||
|
r = instantiate_type (lhstype, field, complain);
|
||||||
|
|
||||||
|
if (r != error_mark_node && TYPE_PTRMEMFUNC_P (lhstype))
|
||||||
{
|
{
|
||||||
tree function = instantiate_type (lhstype, field, complain);
|
tree t = TYPE_PTRMEMFUNC_OBJECT_TYPE (lhstype);
|
||||||
if (function == error_mark_node)
|
tree fn = TREE_VALUE (field);
|
||||||
return error_mark_node;
|
if (TREE_CODE (fn) == OVERLOAD)
|
||||||
my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 185);
|
fn = OVL_FUNCTION (fn);
|
||||||
|
if (TREE_CODE (fn) == FUNCTION_DECL)
|
||||||
if (! DECL_STATIC_FUNCTION_P (function))
|
|
||||||
{
|
{
|
||||||
tree t = TREE_TYPE (TREE_OPERAND (rhs, 0));
|
cp_error ("object-dependent reference `%E' can only be used in a call",
|
||||||
if (TYPE_MAIN_VARIANT (t) == current_class_type)
|
DECL_NAME (fn));
|
||||||
t = constructor_name (t);
|
cp_error (" to form a pointer to member function, say `&%T::%E'",
|
||||||
|
t, DECL_NAME (fn));
|
||||||
cp_error ("object-dependent reference to `%D' can only be used in a call",
|
|
||||||
function);
|
|
||||||
cp_error (" to form a pointer to member function, say `&%T::%D'",
|
|
||||||
t, DECL_NAME (function));
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
mark_used (function);
|
cp_error ("object-dependent reference can only be used in a call");
|
||||||
return function;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* I could not trigger this code. MvL */
|
return r;
|
||||||
my_friendly_abort (980326);
|
|
||||||
return rhs;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case OFFSET_REF:
|
case OFFSET_REF:
|
||||||
|
@ -5469,27 +5480,7 @@ instantiate_type (lhstype, rhs, complain)
|
||||||
return rhs;
|
return rhs;
|
||||||
|
|
||||||
case ADDR_EXPR:
|
case ADDR_EXPR:
|
||||||
{
|
return instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
|
||||||
tree fn = instantiate_type (lhstype, TREE_OPERAND (rhs, 0), complain);
|
|
||||||
if (fn == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
mark_addressable (fn);
|
|
||||||
TREE_OPERAND (rhs, 0) = fn;
|
|
||||||
TREE_CONSTANT (rhs) = staticp (fn);
|
|
||||||
if (TYPE_PTRMEMFUNC_P (lhstype))
|
|
||||||
{
|
|
||||||
/* We must use the POINTER_TYPE to METHOD_TYPE on RHS here
|
|
||||||
so that build_ptrmemfunc knows that RHS we have is not
|
|
||||||
already a pointer-to-member constant. Instead, it is
|
|
||||||
just a ADDR_EXPR over a FUNCTION_DECL. */
|
|
||||||
TREE_TYPE (rhs) = TYPE_PTRMEMFUNC_FN_TYPE (lhstype);
|
|
||||||
rhs = build_ptrmemfunc (TREE_TYPE (rhs), rhs, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
/* Here, things our simple; we have exactly what we need. */
|
|
||||||
TREE_TYPE (rhs) = lhstype;
|
|
||||||
}
|
|
||||||
return rhs;
|
|
||||||
|
|
||||||
case ENTRY_VALUE_EXPR:
|
case ENTRY_VALUE_EXPR:
|
||||||
my_friendly_abort (184);
|
my_friendly_abort (184);
|
||||||
|
|
|
@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
Usage of DECL_LANG_FLAG_?:
|
Usage of DECL_LANG_FLAG_?:
|
||||||
0: DECL_ERROR_REPORTED (in VAR_DECL).
|
0: DECL_ERROR_REPORTED (in VAR_DECL).
|
||||||
|
DECL_TEMPLATE_PARM_P (in CONST_DECL, TYPE_DECL, or TEMPLATE_DECL)
|
||||||
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
|
1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
|
||||||
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
|
DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
|
||||||
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
|
2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
|
||||||
|
@ -1832,11 +1833,12 @@ extern int flag_new_for_scope;
|
||||||
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
|
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE(NODE)
|
||||||
#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
|
#define DECL_TEMPLATE_INJECT(NODE) DECL_INITIAL(NODE)
|
||||||
|
|
||||||
/* Nonzero for TEMPLATE_DECL nodes that represents template template
|
/* Nonzero for a DECL which is actually a template parameter. */
|
||||||
parameters */
|
#define DECL_TEMPLATE_PARM_P(NODE) \
|
||||||
|
DECL_LANG_FLAG_0 (NODE)
|
||||||
|
|
||||||
#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \
|
#define DECL_TEMPLATE_TEMPLATE_PARM_P(NODE) \
|
||||||
(TREE_CODE (NODE) == TEMPLATE_DECL && TREE_TYPE (NODE) \
|
(TREE_CODE (NODE) == TEMPLATE_DECL && DECL_TEMPLATE_PARM_P (NODE))
|
||||||
&& TREE_CODE (TREE_TYPE (NODE)) == TEMPLATE_TEMPLATE_PARM)
|
|
||||||
|
|
||||||
#define DECL_FUNCTION_TEMPLATE_P(NODE) \
|
#define DECL_FUNCTION_TEMPLATE_P(NODE) \
|
||||||
(TREE_CODE (NODE) == TEMPLATE_DECL \
|
(TREE_CODE (NODE) == TEMPLATE_DECL \
|
||||||
|
@ -3070,7 +3072,6 @@ extern void do_pushlevel PROTO((void));
|
||||||
extern int is_member_template PROTO((tree));
|
extern int is_member_template PROTO((tree));
|
||||||
extern int template_parms_equal PROTO((tree, tree));
|
extern int template_parms_equal PROTO((tree, tree));
|
||||||
extern int comp_template_parms PROTO((tree, tree));
|
extern int comp_template_parms PROTO((tree, tree));
|
||||||
extern int decl_template_parm_p PROTO((tree));
|
|
||||||
extern int template_class_depth PROTO((tree));
|
extern int template_class_depth PROTO((tree));
|
||||||
extern int is_specialization_of PROTO((tree, tree));
|
extern int is_specialization_of PROTO((tree, tree));
|
||||||
extern int comp_template_args PROTO((tree, tree));
|
extern int comp_template_args PROTO((tree, tree));
|
||||||
|
|
|
@ -3514,15 +3514,23 @@ pushdecl (x)
|
||||||
register tree name = DECL_ASSEMBLER_NAME (x);
|
register tree name = DECL_ASSEMBLER_NAME (x);
|
||||||
int need_new_binding = 1;
|
int need_new_binding = 1;
|
||||||
|
|
||||||
if (current_function_decl && x != current_function_decl
|
if (DECL_TEMPLATE_PARM_P (x))
|
||||||
/* A local declaration for a function doesn't constitute nesting. */
|
/* Template parameters have no context; they are not X::T even
|
||||||
&& (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
|
when declared within a class or namespace. */
|
||||||
/* Don't change DECL_CONTEXT of virtual methods. */
|
;
|
||||||
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
|
else
|
||||||
&& !DECL_CONTEXT (x))
|
{
|
||||||
DECL_CONTEXT (x) = current_function_decl;
|
if (current_function_decl && x != current_function_decl
|
||||||
if (!DECL_CONTEXT (x))
|
/* A local declaration for a function doesn't constitute
|
||||||
DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
|
nesting. */
|
||||||
|
&& (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
|
||||||
|
/* Don't change DECL_CONTEXT of virtual methods. */
|
||||||
|
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
|
||||||
|
&& !DECL_CONTEXT (x))
|
||||||
|
DECL_CONTEXT (x) = current_function_decl;
|
||||||
|
if (!DECL_CONTEXT (x))
|
||||||
|
DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
|
||||||
|
}
|
||||||
|
|
||||||
/* Type are looked up using the DECL_NAME, as that is what the rest of the
|
/* Type are looked up using the DECL_NAME, as that is what the rest of the
|
||||||
compiler wants to use. */
|
compiler wants to use. */
|
||||||
|
|
11
gcc/cp/lex.c
11
gcc/cp/lex.c
|
@ -3051,16 +3051,7 @@ do_identifier (token, parsing, args)
|
||||||
cp_error ("enum `%D' is private", id);
|
cp_error ("enum `%D' is private", id);
|
||||||
/* protected is OK, since it's an enum of `this'. */
|
/* protected is OK, since it's an enum of `this'. */
|
||||||
}
|
}
|
||||||
if (!processing_template_decl
|
if (!processing_template_decl || DECL_TEMPLATE_PARM_P (id))
|
||||||
/* Really, if we're processing a template, we just want to
|
|
||||||
resolve template parameters, and not enumeration
|
|
||||||
constants. But, they're hard to tell apart. (Note that
|
|
||||||
a non-type template parameter may have enumeration type.)
|
|
||||||
Fortunately, there's no harm in resolving *global*
|
|
||||||
enumeration constants, since they can't depend on
|
|
||||||
template parameters. */
|
|
||||||
|| (TREE_CODE (CP_DECL_CONTEXT (id)) == NAMESPACE_DECL
|
|
||||||
&& TREE_CODE (DECL_INITIAL (id)) == TEMPLATE_PARM_INDEX))
|
|
||||||
id = DECL_INITIAL (id);
|
id = DECL_INITIAL (id);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// Build don't link:
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
struct S {
|
||||||
|
typedef T X;
|
||||||
|
|
||||||
|
class C {
|
||||||
|
typedef T X;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
template <int I>
|
||||||
|
struct S2 {
|
||||||
|
enum { A = I };
|
||||||
|
|
||||||
|
void f() {
|
||||||
|
int A;
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue