Commit 0861bec8 by Jason Merrill Committed by Jason Merrill

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
parent 4e856798
...@@ -792,6 +792,11 @@ Driver Undocumented ...@@ -792,6 +792,11 @@ Driver Undocumented
; 7: The version of the ABI that treats nullptr_t as a builtin type and ; 7: The version of the ABI that treats nullptr_t as a builtin type and
; corrects the mangling of lambdas in default argument scope. ; corrects the mangling of lambdas in default argument scope.
; First selectable in G++ 4.8. ; 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 ; Additional positive integers will be assigned as new versions of
; the ABI become the default version of the ABI. ; the ABI become the default version of the ABI.
fabi-version= fabi-version=
......
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> 2013-04-03 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/56815 PR c++/56815
......
...@@ -1897,7 +1897,15 @@ write_type (tree type) ...@@ -1897,7 +1897,15 @@ write_type (tree type)
tree t = TYPE_MAIN_VARIANT (type); tree t = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (t) == FUNCTION_TYPE if (TREE_CODE (t) == FUNCTION_TYPE
|| TREE_CODE (t) == METHOD_TYPE) || TREE_CODE (t) == METHOD_TYPE)
{
t = build_ref_qualified_type (t, type_memfn_rqual (type)); 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); write_type (t);
} }
else if (TREE_CODE (type) == ARRAY_TYPE) else if (TREE_CODE (type) == ARRAY_TYPE)
......
// 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> *){}
// 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> *){}
2013-04-03 Jason Merrill <jason@redhat.com> 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. Demangle C++11 ref-qualifier.
* cp-demangle.c (d_ref_qualifier): New. * cp-demangle.c (d_ref_qualifier): New.
(d_nested_name, d_function_type): Use it. (d_nested_name, d_function_type): Use it.
......
...@@ -2198,8 +2198,16 @@ cplus_demangle_type (struct d_info *di) ...@@ -2198,8 +2198,16 @@ cplus_demangle_type (struct d_info *di)
pret = d_cv_qualifiers (di, &ret, 0); pret = d_cv_qualifiers (di, &ret, 0);
if (pret == NULL) if (pret == NULL)
return NULL; return NULL;
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); *pret = cplus_demangle_type (di);
if (! *pret) if (!*pret)
return NULL; return NULL;
if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS if ((*pret)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS
|| (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS) || (*pret)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)
...@@ -2739,53 +2747,32 @@ d_pointer_to_member_type (struct d_info *di) ...@@ -2739,53 +2747,32 @@ d_pointer_to_member_type (struct d_info *di)
{ {
struct demangle_component *cl; struct demangle_component *cl;
struct demangle_component *mem; struct demangle_component *mem;
struct demangle_component **pmem;
if (! d_check_char (di, 'M')) if (! d_check_char (di, 'M'))
return NULL; return NULL;
cl = cplus_demangle_type (di); cl = cplus_demangle_type (di);
if (cl == NULL)
/* 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)
return NULL; return NULL;
if (pmem != &mem /* The ABI says, "The type of a non-static member function is considered
&& ((*pmem)->type == DEMANGLE_COMPONENT_RVALUE_REFERENCE_THIS to be different, for the purposes of substitution, from the type of a
|| (*pmem)->type == DEMANGLE_COMPONENT_REFERENCE_THIS)) namespace-scope or static member function whose type appears
{ similar. The types of two non-static member functions are considered
/* Move the ref-qualifier outside the cv-qualifiers so that to be different, for the purposes of substitution, if the functions
they are printed in the right order. */ are members of different classes. In other words, for the purposes of
struct demangle_component *fn = d_left (*pmem); substitution, the class of which the function is a member is
d_left (*pmem) = mem; considered part of the type of function."
mem = *pmem;
*pmem = fn; 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
if (pmem != &mem && (*pmem)->type != DEMANGLE_COMPONENT_FUNCTION_TYPE) function type will never be used in a substitution, so putting the
{ wrong type in the substitution table is harmless. */
if (! d_add_substitution (di, mem))
mem = cplus_demangle_type (di);
if (mem == NULL)
return NULL; return NULL;
}
return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem); return d_make_comp (di, DEMANGLE_COMPONENT_PTRMEM_TYPE, cl, mem);
} }
......
...@@ -4273,8 +4273,8 @@ foo ...@@ -4273,8 +4273,8 @@ foo
# #
--format=gnu-v3 --no-params --format=gnu-v3 --no-params
_Z1fIKFvvES0_Evv _Z1fIKFvvES0_Evv
void f<void () const, void ()>() void f<void () const, void () const>()
f<void () const, void ()> f<void () const, void () const>
# #
--format=gnu-v3 --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_ _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_
......
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