cp-demangle.c (cplus_demangle_type): Fix function quals.

libiberty/
	* cp-demangle.c (cplus_demangle_type): Fix function quals.
	(d_pointer_to_member_type): Simplify.
gcc/cp/
	* mangle.c (write_type): When writing a function type with
	function-cv-quals, don't add the unqualified type as a
	substitution candidate.

From-SVN: r197460
This commit is contained in:
Jason Merrill 2013-04-03 20:14:00 -04:00 committed by Jason Merrill
parent 4e85679863
commit 0861bec80a
8 changed files with 76 additions and 45 deletions

View file

@ -792,6 +792,11 @@ Driver Undocumented
; 7: The version of the ABI that treats nullptr_t as a builtin type and
; corrects the mangling of lambdas in default argument scope.
; First selectable in G++ 4.8.
;
; 8: The version of the ABI that corrects the substitution behavior of
; function types with function-cv-qualifiers.
; First selectable in G++ 4.9.
;
; Additional positive integers will be assigned as new versions of
; the ABI become the default version of the ABI.
fabi-version=

View file

@ -1,3 +1,9 @@
2013-04-03 Jason Merrill <jason@redhat.com>
* mangle.c (write_type): When writing a function type with
function-cv-quals, don't add the unqualified type as a
substitution candidate.
2013-04-03 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/56815

View file

@ -1897,8 +1897,16 @@ write_type (tree type)
tree t = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (t) == FUNCTION_TYPE
|| TREE_CODE (t) == METHOD_TYPE)
t = build_ref_qualified_type (t, type_memfn_rqual (type));
write_type (t);
{
t = build_ref_qualified_type (t, type_memfn_rqual (type));
if (abi_version_at_least (8))
/* Avoid adding the unqualified function type as a substitution. */
write_function_type (t);
else
write_type (t);
}
else
write_type (t);
}
else if (TREE_CODE (type) == ARRAY_TYPE)
/* It is important not to use the TYPE_MAIN_VARIANT of TYPE here

View file

@ -0,0 +1,11 @@
// Before v8, we mistakenly treated an unqualified function type
// as a substitution candidate for a function type with function-cv-quals.
// Test for the conformant behavior.
// { dg-options -fabi-version=0 }
template <class T, class U> struct A { };
// { dg-final { scan-assembler "_Z1fP1AIKFvvEFvvEE" } }
void f (A<void()const, void()> *){}
// { dg-final { scan-assembler "_Z1gP1AIFvvEKFvvEE" } }
void g (A<void(), void()const> *){}

View file

@ -0,0 +1,11 @@
// Before v8, we mistakenly treated an unqualified function type
// as a substitution candidate for a function type with function-cv-quals.
// Test for that for backward compatibility.
// { dg-options -fabi-version=7 }
template <class T, class U> struct A { };
// { dg-final { scan-assembler "_Z1fP1AIKFvvES0_E" } }
void f (A<void()const, void()> *){}
// { dg-final { scan-assembler "_Z1gP1AIFvvEKS0_E" } }
void g (A<void(), void()const> *){}

View file

@ -1,5 +1,8 @@
2013-04-03 Jason Merrill <jason@redhat.com>
* cp-demangle.c (cplus_demangle_type): Fix function quals.
(d_pointer_to_member_type): Simplify.
Demangle C++11 ref-qualifier.
* cp-demangle.c (d_ref_qualifier): New.
(d_nested_name, d_function_type): Use it.

View file

@ -2198,8 +2198,16 @@ cplus_demangle_type (struct d_info *di)
pret = d_cv_qualifiers (di, &ret, 0);
if (pret == NULL)
return NULL;
*pret = cplus_demangle_type (di);
if (! *pret)
if (d_peek_char (di) == 'F')
{
/* cv-qualifiers before a function type apply to 'this',
so avoid adding the unqualified function type to
the substitution list. */
*pret = d_function_type (di);
}
else
*pret = cplus_demangle_type (di);
if (!*pret)
return NULL;
if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
|| (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)
@ -2739,53 +2747,32 @@ d_pointer_to_member_type (struct d_info *di)
{
struct demangle_component *cl;
struct demangle_component *mem;
struct demangle_component **pmem;
if (! d_check_char (di, 'M'))
return NULL;
cl = cplus_demangle_type (di);
/* The ABI specifies that any type can be a substitution source, and
that M is followed by two types, and that when a CV-qualified
type is seen both the base type and the CV-qualified types are
substitution sources. The ABI also specifies that for a pointer
to a CV-qualified member function, the qualifiers are attached to
the second type. Given the grammar, a plain reading of the ABI
suggests that both the CV-qualified member function and the
non-qualified member function are substitution sources. However,
g++ does not work that way. g++ treats only the CV-qualified
member function as a substitution source. FIXME. So to work
with g++, we need to pull off the CV-qualifiers here, in order to
avoid calling add_substitution() in cplus_demangle_type(). But
for a CV-qualified member which is not a function, g++ does
follow the ABI, so we need to handle that case here by calling
d_add_substitution ourselves. */
pmem = d_cv_qualifiers (di, &mem, 1);
if (pmem == NULL)
return NULL;
*pmem = cplus_demangle_type (di);
if (*pmem == NULL)
if (cl == NULL)
return NULL;
if (pmem != &mem
&& ((*pmem)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
|| (*pmem)->type == DEMANGLE_COMPONENT_REFERENCE_THIS))
{
/* Move the ref-qualifier outside the cv-qualifiers so that
they are printed in the right order. */
struct demangle_component *fn = d_left (*pmem);
d_left (*pmem) = mem;
mem = *pmem;
*pmem = fn;
}
/* The ABI says, "The type of a non-static member function is considered
to be different, for the purposes of substitution, from the type of a
namespace-scope or static member function whose type appears
similar. The types of two non-static member functions are considered
to be different, for the purposes of substitution, if the functions
are members of different classes. In other words, for the purposes of
substitution, the class of which the function is a member is
considered part of the type of function."
if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE)
{
if (! d_add_substitution (di, mem))
return NULL;
}
For a pointer to member function, this call to cplus_demangle_type
will end up adding a (possibly qualified) non-member function type to
the substitution table, which is not correct; however, the member
function type will never be used in a substitution, so putting the
wrong type in the substitution table is harmless. */
mem = cplus_demangle_type (di);
if (mem == NULL)
return NULL;
return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
}

View file

@ -4273,8 +4273,8 @@ foo
#
--format=gnu-v3 --no-params
_Z1fIKFvvES0_Evv
void f<void () const, void ()>()
f<void () const, void ()>
void f<void () const, void () const>()
f<void () const, void () const>
#
--format=gnu-v3
_ZN4modc6parser8sequenceINS_9astParser13LocatedParserINS0_9ParserRefINS2_UlRNS2_16TokenParserInputEE_EEEEEINS0_14OptionalParserINS2_18ListParserTemplateILNS_6tokens5Token4TypeE4EXadL_ZNSD_Ut_13parenthesizedEEEE6ParserINS4_INS0_6ParserIS5_NS_3ast10ExpressionEEEEEEEEENSA_INS4_INS2_22OneOfKeywordsToTParserINSJ_5StyleEEEEEEENS0_14SequenceParserIS5_INS0_18ExactElementParserIS5_EENSA_ISM_EEEEENS0_14RepeatedParserINS4_INS0_15TransformParserINSU_IS5_INS4_INSP_INSJ_10Annotation12RelationshipEEEEESX_EEENS2_UlNS2_3LocES12_ONS_5MaybeISK_EEE19_EEEEELb0EEEEEENSU_INS0_17ExtractParserTypeIT_E9InputTypeEINS0_8MaybeRefIS1F_E4TypeEDpNS1I_IT0_E4TypeEEEEOS1F_DpOS1L_