This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++] template mangling fixes
Mark Mitchell <mark@codesourcery.com> writes:
Mark> If so, make those changes, and check in.
OK, I'm committing this:
---
This patch cleans up the logic for determining whether a type or decl
is a template instance, and in the process fixes a couple of bugs in
mangling of typename types and template template args (that reported
on 30 July by Larry Evans). Also removes an unneeded static variable,
and cleans up comments.
* mangle.c (DECL_TEMPLATE_ID_P): Remove.
(CLASSTYEP_TEMPLATE_ID_P): Check template info, and context when
ascertaining primaryness.
(G): Remove template_args.
(decl_is_template_id): New function.
(write_encoding): Use decl_is_template_id.
(write_name): Likewise. Handle type_decls. Get main variant of
type decls.
(write_nested_name): Likewise.
(write_prefix): Likewise.
(write_template_prefix): Likewise.
(write_special_name_constructor): Remove defunct production from
comment.
(write_bare_function_type): Remove comment about absent parameter.
(write_template_template_arg): Add missing grammar production to
comment.
Index: mangle.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/mangle.c,v
retrieving revision 1.12
diff -c -p -r1.12 mangle.c
*** mangle.c 2000/07/02 18:44:52 1.12
--- mangle.c 2000/07/30 23:33:31
***************
*** 74,90 ****
# define MANGLE_TRACE_TREE(FN, NODE)
#endif
! /* Non-zero if NODE is a template-id. */
! #define DECL_TEMPLATE_ID_P(NODE) \
! (DECL_LANG_SPECIFIC (NODE) != NULL \
! && DECL_USE_TEMPLATE (NODE) \
! && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (NODE)))
!
! /* Non-zero if NODE is a class template-id. */
! #define CLASSTYPE_TEMPLATE_ID_P(NODE) \
! (TYPE_LANG_SPECIFIC (NODE) != NULL \
! && CLASSTYPE_USE_TEMPLATE (NODE) \
! && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)))
/* Things we only need one of. This module is not reentrant. */
static struct globals
--- 74,91 ----
# define MANGLE_TRACE_TREE(FN, NODE)
#endif
! /* Non-zero if NODE is a class template-id. We can't rely on
! CLASSTYPE_USE_TEMPLATE here because of tricky bugs in the parser
! that hard to distinguish A<T> from A, where A<T> is the type as
! instantiated outside of the template, and A is the type used
! without parameters inside the template. The logic here is
! historical magic that apparently produces the right result. */
! #define CLASSTYPE_TEMPLATE_ID_P(NODE) \
! (TYPE_LANG_SPECIFIC (NODE) != NULL \
! && CLASSTYPE_TEMPLATE_INFO (NODE) != NULL \
! && (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (NODE)) \
! || (TREE_CODE (CP_DECL_CONTEXT (CLASSTYPE_TI_TEMPLATE (NODE))) \
! == FUNCTION_DECL)))
/* Things we only need one of. This module is not reentrant. */
static struct globals
*************** static struct globals
*** 92,100 ****
/* The name in which we're building the mangled name. */
struct obstack name_obstack;
- /* The current innermost template args. */
- tree template_args;
-
/* An array of the current substitution candidates, in the order
we've seen them. */
varray_type substitutions;
--- 93,98 ----
*************** integer_type_codes[itk_none] =
*** 136,141 ****
--- 134,141 ----
'y' /* itk_unsigned_long_long */
};
+ static int decl_is_template_id PARAMS ((tree, tree*));
+
/* Functions for handling substitutions. */
static inline tree canonicalize_for_substitution PARAMS ((tree));
*************** static tree mangle_special_for_type PARA
*** 228,233 ****
--- 228,277 ----
#define write_unsigned_number(NUMBER) \
write_number (NUMBER, /*unsigned_p=*/1, 10)
+ /* If DECL is a template instance, return non-zero and, if
+ TEMPLATE_INFO is non-NULL, set *TEMPLATE_INFO to its template info.
+ Otherwise return zero. */
+
+ static int
+ decl_is_template_id (decl, template_info)
+ tree decl;
+ tree* template_info;
+ {
+ if (TREE_CODE (decl) == TYPE_DECL)
+ {
+ /* TYPE_DECLs are handled specially. Look at its type to decide
+ if this is a template instantiation. */
+ tree type = TREE_TYPE (decl);
+
+ if (CLASS_TYPE_P (type) && CLASSTYPE_TEMPLATE_ID_P (type))
+ {
+ if (template_info != NULL)
+ /* For a templated TYPE_DECL, the template info is hanging
+ off the type. */
+ *template_info = CLASSTYPE_TEMPLATE_INFO (type);
+ return 1;
+ }
+ }
+ else
+ {
+ /* Check if this is a primary template. */
+ if (DECL_LANG_SPECIFIC (decl) != NULL
+ && DECL_USE_TEMPLATE (decl)
+ && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))
+ && TREE_CODE (decl) != TEMPLATE_DECL)
+ {
+ if (template_info != NULL)
+ /* For most templated decls, the template info is hanging
+ off the decl. */
+ *template_info = DECL_TEMPLATE_INFO (decl);
+ return 1;
+ }
+ }
+
+ /* It's not a template id. */
+ return 0;
+ }
+
/* Produce debugging output of current substitution candidates. */
static void
*************** write_encoding (decl)
*** 591,602 ****
{
tree fn_type;
! if (DECL_TEMPLATE_ID_P (decl))
fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL);
else
fn_type = TREE_TYPE (decl);
! write_bare_function_type (fn_type, DECL_TEMPLATE_ID_P (decl));
}
}
--- 635,646 ----
{
tree fn_type;
! if (decl_is_template_id (decl, NULL))
fn_type = get_mostly_instantiated_function_type (decl, NULL, NULL);
else
fn_type = TREE_TYPE (decl);
! write_bare_function_type (fn_type, decl_is_template_id (decl, NULL));
}
}
*************** write_name (decl)
*** 611,638 ****
{
tree context;
- context = CP_DECL_CONTEXT (decl);
-
MANGLE_TRACE_TREE ("name", decl);
! /* Decls in :: or ::std scope are treated specially. */
! if (context == global_namespace || DECL_NAMESPACE_STD_P (context))
{
! if (decl && DECL_TEMPLATE_ID_P (decl))
! {
! /* Templated decls get an <unqualified-template-name>. */
! write_unscoped_template_name (DECL_TI_TEMPLATE (decl));
! write_template_args (DECL_TI_ARGS (decl));
! }
! else if (TREE_CODE (decl) == TYPE_DECL
! && CLASSTYPE_TEMPLATE_ID_P (TREE_TYPE (decl)))
! {
! tree type;
! /* Templated decls get an <unqualified-template-name>. */
! type = TREE_TYPE (decl);
! write_unscoped_template_name (TYPE_TI_TEMPLATE (type));
! write_template_args (TYPE_TI_ARGS (type));
}
else
/* Everything else gets an <unqualified-name>. */
--- 655,684 ----
{
tree context;
MANGLE_TRACE_TREE ("name", decl);
! if (TREE_CODE (decl) == TYPE_DECL)
{
! /* In case this is a typedef, fish out the corresponding
! TYPE_DECL for the main variant. */
! decl = TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
! context = TYPE_CONTEXT (TYPE_MAIN_VARIANT (TREE_TYPE (decl)));
! }
! else
! context = (DECL_CONTEXT (decl) == NULL) ? NULL : CP_DECL_CONTEXT (decl);
! /* Decls in :: or ::std scope are treated specially. */
! if (context == NULL
! || context == global_namespace
! || DECL_NAMESPACE_STD_P (context))
! {
! tree template_info;
! /* Is this a template instance? */
! if (decl_is_template_id (decl, &template_info))
! {
! /* Yes: use <unscoped-template-name>. */
! write_unscoped_template_name (TI_TEMPLATE (template_info));
! write_template_args (TI_ARGS (template_info));
}
else
/* Everything else gets an <unqualified-name>. */
*************** static void
*** 696,701 ****
--- 742,749 ----
write_nested_name (decl)
tree decl;
{
+ tree template_info;
+
MANGLE_TRACE_TREE ("nested-name", decl);
write_char ('N');
*************** write_nested_name (decl)
*** 710,727 ****
write_char ('K');
}
! if (DECL_TEMPLATE_ID_P (decl))
{
write_template_prefix (decl);
! write_template_args (DECL_TI_ARGS (decl));
}
- else if (CLASSTYPE_TEMPLATE_ID_P (TREE_TYPE (decl)))
- {
- write_template_prefix (decl);
- write_template_args (CLASSTYPE_TI_ARGS (TREE_TYPE (decl)));
- }
else
{
write_prefix (DECL_CONTEXT (decl));
write_component (decl);
}
--- 758,773 ----
write_char ('K');
}
! /* Is this a template instance? */
! if (decl_is_template_id (decl, &template_info))
{
+ /* Yes, use <template-prefix>. */
write_template_prefix (decl);
! write_template_args (TI_ARGS (template_info));
}
else
{
+ /* No, just use <prefix> */
write_prefix (DECL_CONTEXT (decl));
write_component (decl);
}
*************** write_prefix (node)
*** 738,777 ****
tree node;
{
tree decl;
! tree type;
! tree context;
if (node == NULL
|| node == global_namespace)
return;
- MANGLE_TRACE_TREE ("prefix", node);
-
- decl = DECL_P (node) ? node : TYPE_NAME (node);
- type = DECL_P (node) ? TREE_TYPE (node) : node;
- context = CP_DECL_CONTEXT (decl);
-
if (find_substitution (node))
return;
! /* Check if this is a template-id. For a template member, the
! template info will be hanging off the decl. */
! if (DECL_TEMPLATE_ID_P (decl))
{
! write_template_prefix (decl);
! write_template_args (DECL_TI_ARGS (decl));
}
! /* For a template class, the template info will be hanging off the
! type. */
! else if (type && CLASSTYPE_TEMPLATE_ID_P (type))
{
! write_template_prefix (type);
! write_template_args (CLASSTYPE_TI_ARGS (type));
}
else
/* Not templated. */
{
! write_prefix (context);
write_component (decl);
}
--- 784,825 ----
tree node;
{
tree decl;
! /* Non-NULL if NODE represents a template-id. */
! tree template_info = NULL;
!
! MANGLE_TRACE_TREE ("prefix", node);
if (node == NULL
|| node == global_namespace)
return;
if (find_substitution (node))
return;
! if (DECL_P (node))
! /* Node is a decl. */
{
! decl = node;
! decl_is_template_id (decl, &template_info);
}
! else
! /* Node is a type. */
! {
! decl = TYPE_NAME (node);
! if (CLASSTYPE_TEMPLATE_ID_P (node))
! template_info = CLASSTYPE_TEMPLATE_INFO (node);
! }
!
! if (template_info != NULL)
! /* Templated. */
{
! write_template_prefix (decl);
! write_template_args (TI_ARGS (template_info));
}
else
/* Not templated. */
{
! write_prefix (CP_DECL_CONTEXT (decl));
write_component (decl);
}
*************** write_template_prefix (node)
*** 788,801 ****
tree decl = DECL_P (node) ? node : TYPE_NAME (node);
tree type = DECL_P (node) ? TREE_TYPE (node) : node;
tree context = CP_DECL_CONTEXT (decl);
tree template;
tree substitution;
MANGLE_TRACE_TREE ("template-prefix", node);
/* Find the template decl. */
! if (DECL_TEMPLATE_ID_P (decl))
! template = DECL_TI_TEMPLATE (decl);
else if (CLASSTYPE_TEMPLATE_ID_P (type))
template = CLASSTYPE_TI_TEMPLATE (type);
else
--- 836,850 ----
tree decl = DECL_P (node) ? node : TYPE_NAME (node);
tree type = DECL_P (node) ? TREE_TYPE (node) : node;
tree context = CP_DECL_CONTEXT (decl);
+ tree template_info;
tree template;
tree substitution;
MANGLE_TRACE_TREE ("template-prefix", node);
/* Find the template decl. */
! if (decl_is_template_id (decl, &template_info))
! template = TI_TEMPLATE (template_info);
else if (CLASSTYPE_TEMPLATE_ID_P (type))
template = CLASSTYPE_TI_TEMPLATE (type);
else
*************** write_identifier (identifier)
*** 997,1003 ****
<special-name> ::= C1 # complete object constructor
::= C2 # base object constructor
::= C3 # complete object allocating constructor
- ::= C4 # base object allocating constructor
Currently, allocating constructors are never used.
--- 1046,1051 ----
*************** write_bare_function_type (type, include_
*** 1436,1444 ****
/* Write the mangled representation of a method parameter list of
types given in PARM_LIST. If METHOD_P is non-zero, the function is
! considered a non-static method, and the this parameter is omitted.
! If VARARGS_P is non-zero, an additional token designating varargs
! is appended. */
static void
write_method_parms (parm_list, method_p)
--- 1484,1490 ----
/* Write the mangled representation of a method parameter list of
types given in PARM_LIST. If METHOD_P is non-zero, the function is
! considered a non-static method, and the this parameter is omitted. */
static void
write_method_parms (parm_list, method_p)
*************** write_template_template_arg (tree decl)
*** 1744,1749 ****
--- 1790,1796 ----
/* Non-terminal <array-type>. TYPE is an ARRAY_TYPE.
<array-type> ::= A [</dimension/ number>] _ </element/ type>
+ ::= A <expression> _ </element/ type>
"Array types encode the dimension (number of elements) and the
element type. For variable length arrays, the dimension (but not