Commit ca90f3e1 by Mark Mitchell Committed by Mark Mitchell

re PR c++/11105 ([3.3/3.4 regression of sorts] ICE in mangle_conv_op_name_for_type)

	PR c++/11105
	* cp-tree.h (DECL_CONV_FN_TYPE): New method.
	* mangle.c (struct globals): Remove internal_mangling_p.
	(write_unqualified_name): Use DECL_CONV_FN_TYPE.
	(write_template_parm): Don't write out the level number.
	(conv_type_names): New variable.
	(hash_type): New function.
	(compare_type): Likewise.
	(mangle_conv_op_name_for_type): Don't try to mangle conversion
	operator names.
	* search.c (lookup_conversion_operator): New function.
	(lookup_fnfields_1): Use it.

	PR c++/11105
	* g++.dg/abi/conv1.C: Remove it.
	* g++.dg/template/conv7.C: New test.
	* g++.dg/template/conv8.C: Likewise.
	* g++.old-deja/g++.ext/pretty2.C: Do not test __FUNCTION__ for a
	conversion operator.

From-SVN: r68095
parent 8207b189
2003-06-17 Mark Mitchell <mark@codesourcery.com>
PR c++/11105
* cp-tree.h (DECL_CONV_FN_TYPE): New method.
* mangle.c (struct globals): Remove internal_mangling_p.
(write_unqualified_name): Use DECL_CONV_FN_TYPE.
(write_template_parm): Don't write out the level number.
(conv_type_names): New variable.
(hash_type): New function.
(compare_type): Likewise.
(mangle_conv_op_name_for_type): Don't try to mangle conversion
operator names.
* search.c (lookup_conversion_operator): New function.
(lookup_fnfields_1): Use it.
2003-06-17 Andreas Jaeger <aj@suse.de>
* except.c: Remove duplicate declaration of push_eh_cleanup.
......
......@@ -1856,6 +1856,11 @@ struct lang_decl GTY(())
#define DECL_CONV_FN_P(NODE) \
(IDENTIFIER_TYPENAME_P (DECL_NAME (NODE)))
/* If FN is a conversion operator, the type to which it converts.
Otherwise, NULL_TREE. */
#define DECL_CONV_FN_TYPE(FN) \
(DECL_CONV_FN_P (FN) ? TREE_TYPE (DECL_NAME (FN)) : NULL_TREE)
/* Nonzero if NODE, which is a TEMPLATE_DECL, is a template
conversion operator to a type dependent on the innermost template
args. */
......
......@@ -102,11 +102,6 @@ static struct globals
/* The entity that is being mangled. */
tree entity;
/* We are mangling an internal symbol. It is important to keep those
involving template parmeters distinct by distinguishing their level
and, for non-type parms, their type. */
bool internal_mangling_p;
/* True if the mangling will be different in a future version of the
ABI. */
bool need_abi_warning;
......@@ -1006,7 +1001,7 @@ write_unqualified_name (const tree decl)
type = TREE_TYPE (fn_type);
}
else
type = TREE_TYPE (DECL_NAME (decl));
type = DECL_CONV_FN_TYPE (decl);
write_conversion_operator_name (type);
}
else if (DECL_OVERLOADED_OPERATOR_P (decl))
......@@ -2250,15 +2245,6 @@ write_template_param (const tree parm)
if (parm_index > 0)
write_unsigned_number (parm_index - 1);
write_char ('_');
if (G.internal_mangling_p)
{
if (parm_level > 0)
write_unsigned_number (parm_level - 1);
write_char ('_');
if (parm_type)
write_type (parm_type);
write_char ('_');
}
}
/* <template-template-param>
......@@ -2600,6 +2586,28 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
return get_identifier (result);
}
/* This hash table maps TYPEs to the IDENTIFIER for a conversion
operator to TYPE. The nodes are TREE_LISTs whose TREE_PURPOSE is
the TYPE and whose TREE_VALUE is the IDENTIFIER. */
static GTY ((param_is (union tree_node))) htab_t conv_type_names;
/* Hash a node (VAL1) in the table. */
static hashval_t
hash_type (const void *val)
{
return htab_hash_pointer (TREE_PURPOSE (*((tree *) val)));
}
/* Compare VAL1 (a node in the table) with VAL2 (a TYPE). */
static int
compare_type (const void *val1, const void *val2)
{
return TREE_PURPOSE ((tree) val1) == (tree) val2;
}
/* Return an identifier for the mangled unqualified name for a
conversion operator to TYPE. This mangling is not specified by the
ABI spec; it is only used internally. */
......@@ -2607,33 +2615,22 @@ mangle_thunk (tree fn_decl, const int this_adjusting, tree fixed_offset,
tree
mangle_conv_op_name_for_type (const tree type)
{
void **slot;
tree identifier;
const char *mangled_type;
char *op_name;
/* Build the internal mangling for TYPE. */
G.internal_mangling_p = true;
mangled_type = mangle_type_string (type);
G.internal_mangling_p = false;
/* Allocate a temporary buffer for the complete name. */
op_name = concat ("operator ", mangled_type, NULL);
/* Find or create an identifier. */
identifier = get_identifier (op_name);
/* Done with the temporary buffer. */
free (op_name);
/* It had better be a unique mangling for the type. */
if (IDENTIFIER_TYPENAME_P (identifier)
&& !same_type_p (type, TREE_TYPE (identifier)))
{
/* In G++ 3.2, the name mangling scheme was ambiguous. In later
versions of the ABI, this problem has been fixed. */
if (abi_version_at_least (2))
abort ();
error ("due to a defect in the G++ 3.2 ABI, G++ has assigned the "
"same mangled name to two different types");
}
char buffer[64];
if (conv_type_names == NULL)
conv_type_names = htab_create_ggc (31, &hash_type, &compare_type, NULL);
slot = htab_find_slot_with_hash (conv_type_names, type,
htab_hash_pointer (type), INSERT);
if (*slot)
return TREE_VALUE ((tree) *slot);
/* Create a unique name corresponding to TYPE. */
sprintf (buffer, "operator %d\n", htab_elements (conv_type_names));
identifier = get_identifier (buffer);
*slot = build_tree_list (type, identifier);
/* Set bits on the identifier so we know later it's a conversion. */
IDENTIFIER_OPNAME_P (identifier) = 1;
......
......@@ -1338,22 +1338,84 @@ lookup_fnfields (tree xbasetype, tree name, int protect)
return rval;
}
/* Return the index in the CLASSTYPE_METHOD_VEC for CLASS_TYPE
corresponding to "operator TYPE ()", or -1 if there is no such
operator. Only CLASS_TYPE itself is searched; this routine does
not scan the base classes of CLASS_TYPE. */
static int
lookup_conversion_operator (tree class_type, tree type)
{
int pass;
int i;
tree methods = CLASSTYPE_METHOD_VEC (class_type);
for (pass = 0; pass < 2; ++pass)
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
i < TREE_VEC_LENGTH (methods);
++i)
{
tree fn = TREE_VEC_ELT (methods, i);
/* The size of the vector may have some unused slots at the
end. */
if (!fn)
break;
/* All the conversion operators come near the beginning of the
class. Therefore, if FN is not a conversion operator, there
is no matching conversion operator in CLASS_TYPE. */
fn = OVL_CURRENT (fn);
if (!DECL_CONV_FN_P (fn))
break;
if (pass == 0)
{
/* On the first pass we only consider exact matches. If
the types match, this slot is the one where the right
conversion operators can be found. */
if (TREE_CODE (fn) != TEMPLATE_DECL
&& same_type_p (DECL_CONV_FN_TYPE (fn), type))
return i;
}
else
{
/* On the second pass we look for template conversion
operators. It may be possible to instantiate the
template to get the type desired. All of the template
conversion operators share a slot. By looking for
templates second we ensure that specializations are
preferred over templates. */
if (TREE_CODE (fn) == TEMPLATE_DECL)
return i;
}
}
return -1;
}
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 is no such field exists. */
int
lookup_fnfields_1 (tree type, tree name)
{
tree method_vec = (CLASS_TYPE_P (type)
? CLASSTYPE_METHOD_VEC (type)
: NULL_TREE);
if (method_vec != 0)
{
register int i;
register tree *methods = &TREE_VEC_ELT (method_vec, 0);
int len = TREE_VEC_LENGTH (method_vec);
tree method_vec;
tree *methods;
tree tmp;
int i;
int len;
if (!CLASS_TYPE_P (type))
return -1;
method_vec = CLASSTYPE_METHOD_VEC (type);
if (!method_vec)
return -1;
methods = &TREE_VEC_ELT (method_vec, 0);
len = TREE_VEC_LENGTH (method_vec);
#ifdef GATHER_STATISTICS
n_calls_lookup_fnfields_1++;
......@@ -1367,25 +1429,19 @@ lookup_fnfields_1 (tree type, tree name)
if (name == dtor_identifier)
return (methods[CLASSTYPE_DESTRUCTOR_SLOT]
? CLASSTYPE_DESTRUCTOR_SLOT : -1);
if (IDENTIFIER_TYPENAME_P (name))
return lookup_conversion_operator (type, TREE_TYPE (name));
for (i = CLASSTYPE_FIRST_CONVERSION_SLOT;
i < len && methods[i];
++i)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
tmp = OVL_CURRENT (methods[i]);
if (DECL_NAME (tmp) == name)
return i;
/* Skip the conversion operators. */
i = CLASSTYPE_FIRST_CONVERSION_SLOT;
while (i < len && methods[i] && DECL_CONV_FN_P (OVL_CURRENT (methods[i])))
i++;
/* If the type is complete and we're past the conversion ops,
switch to binary search. */
if (! DECL_CONV_FN_P (tmp)
&& COMPLETE_TYPE_P (type))
/* If the type is complete, use binary search. */
if (COMPLETE_TYPE_P (type))
{
int lo = i + 1, hi = len;
int lo = i;
int hi = len;
while (lo < hi)
{
......@@ -1396,10 +1452,9 @@ lookup_fnfields_1 (tree type, tree name)
#endif /* GATHER_STATISTICS */
tmp = methods[i];
/* This slot may be empty; we allocate more slots
than we need. In that case, the entry we're
looking for is closer to the beginning of the
list. */
/* This slot may be empty; we allocate more slots than we
need. In that case, the entry we're looking for is
closer to the beginning of the list. */
if (tmp)
tmp = DECL_NAME (OVL_CURRENT (tmp));
if (!tmp || tmp > name)
......@@ -1409,28 +1464,18 @@ lookup_fnfields_1 (tree type, tree name)
else
return i;
}
break;
}
}
/* If we didn't find it, it might have been a template
conversion operator to a templated type. If there are any,
such template conversion operators will all be overloaded on
the first conversion slot. (Note that we don't look for this
case above so that we will always find specializations
first.) */
if (IDENTIFIER_TYPENAME_P (name))
{
i = CLASSTYPE_FIRST_CONVERSION_SLOT;
if (i < len && methods[i])
else
for (; i < len && methods[i]; ++i)
{
#ifdef GATHER_STATISTICS
n_outer_fields_searched++;
#endif /* GATHER_STATISTICS */
tmp = OVL_CURRENT (methods[i]);
if (TREE_CODE (tmp) == TEMPLATE_DECL
&& DECL_TEMPLATE_CONV_FN_P (tmp))
if (DECL_NAME (tmp) == name)
return i;
}
}
}
return -1;
}
......
2003-06-17 Mark Mitchell <mark@codesourcery.com>
PR c++/11105
* g++.dg/abi/conv1.C: Remove it.
* g++.dg/template/conv7.C: New test.
* g++.dg/template/conv8.C: Likewise.
* g++.old-deja/g++.ext/pretty2.C: Do not test __FUNCTION__ for a
conversion operator.
2003-06-17 Janis Johnson <janis187@us.ibm.com>
* gcc.dg/compat/compat-common.h (DEBUG_INIT): New.
......
// { dg-options "-fabi-version=1" }
template<class T1>
struct A {
typedef typename T1::X X;
operator X() const;
};
template <class T0, class T1 >
struct B {
typedef typename T1::X X;
operator X() const; // { dg-error "" }
};
// { dg-options "-fabi-version=0" }
template <typename T> struct S {
struct I{};
operator I* ();
};
template <typename T> struct S2 : S<T> {
operator typename S<T>::I* ();
};
template struct S2<int>;
// { dg-options "-fabi-version=1" }
template <typename T> struct S {
struct I{};
operator I* ();
};
template <typename T> struct S2 : S<T> {
operator typename S<T>::I* ();
};
template struct S2<int>;
// { dg-do run }
// Copyright (C) 1999, 2000 Free Software Foundation, Inc.
// Copyright (C) 1999, 2000, 2003 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 21 Nov 1999 <nathan@acm.org>
// make sure __FUNCTION__ and __PRETTY_FUNCTION__ work in member functions
......@@ -68,8 +68,6 @@ X::operator int ()
printf ("__FUNCTION__ %s\n", function);
printf ("__PRETTY_FUNCTION__ %s\n", pretty);
if (strcmp (function, "operator i"))
bad = true;
if (strcmp (pretty, "X::operator int()"))
bad = true;
return 0;
......
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