re PR c++/9381 (attribute on member function pointer have no effect)

PR c++/9381
	* decl2.c (build_memfn_type): Preserve attributes.
	(cp_reconstruct_complex_type): Likewise.
	(maybe_retrofit_in_chrg): Likewise.
	* call.c (standard_conversion): Use build_memfn_type.
	* pt.c (tsubst): Likewise.
	* decl.c (build_ptrmem_type): Likewise
	(check_function_type): Preserve attributes.
	* tree.c (cp_build_type_attribute_variant): Propagate exception
	specs on METHOD_TYPE, too.
	(strip_typedefs): Preserve exception specs and attributes.

From-SVN: r153977
This commit is contained in:
Jason Merrill 2009-11-06 16:18:35 -05:00 committed by Jason Merrill
parent 7ac8318c2d
commit 3c3905fc17
9 changed files with 93 additions and 24 deletions

View File

@ -1,3 +1,17 @@
2009-11-06 Jason Merrill <jason@redhat.com>
PR c++/9381
* decl2.c (build_memfn_type): Preserve attributes.
(cp_reconstruct_complex_type): Likewise.
(maybe_retrofit_in_chrg): Likewise.
* call.c (standard_conversion): Use build_memfn_type.
* pt.c (tsubst): Likewise.
* decl.c (build_ptrmem_type): Likewise
(check_function_type): Preserve attributes.
* tree.c (cp_build_type_attribute_variant): Propagate exception
specs on METHOD_TYPE, too.
(strip_typedefs): Preserve exception specs and attributes.
2009-11-06 Andrew Pinski <andrew_pinski@playstation.sony.com>
PR c++/41536

View File

@ -896,10 +896,7 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
|| cp_type_quals (fbase) != cp_type_quals (tbase))
return NULL;
from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
from = build_method_type_directly (from,
TREE_TYPE (fromfn),
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
from = build_memfn_type (fromfn, tbase, cp_type_quals (tbase));
from = build_ptrmemfunc_type (build_pointer_type (from));
conv = build_conv (ck_pmem, from, conv);
conv->base_p = true;

View File

@ -4104,6 +4104,7 @@ adjust_clone_args (tree decl)
/* A default parameter has been added. Adjust the
clone's parameters. */
tree exceptions = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (clone));
tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (clone));
tree basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (clone));
tree type;
@ -4121,6 +4122,8 @@ adjust_clone_args (tree decl)
clone_parms);
if (exceptions)
type = build_exception_variant (type, exceptions);
if (attrs)
type = cp_build_type_attribute_variant (type, attrs);
TREE_TYPE (clone) = type;
clone_parms = NULL_TREE;

View File

@ -7170,16 +7170,9 @@ build_ptrmem_type (tree class_type, tree member_type)
{
if (TREE_CODE (member_type) == METHOD_TYPE)
{
tree arg_types;
arg_types = TYPE_ARG_TYPES (member_type);
class_type = (cp_build_qualified_type
(class_type,
cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)))));
member_type
= build_method_type_directly (class_type,
TREE_TYPE (member_type),
TREE_CHAIN (arg_types));
tree arg_types = TYPE_ARG_TYPES (member_type);
cp_cv_quals quals = cp_type_quals (TREE_TYPE (TREE_VALUE (arg_types)));
member_type = build_memfn_type (member_type, class_type, quals);
return build_ptrmemfunc_type (build_pointer_type (member_type));
}
else
@ -11551,7 +11544,7 @@ lookup_enumerator (tree enumtype, tree name)
}
/* We're defining DECL. Make sure that it's type is OK. */
/* We're defining DECL. Make sure that its type is OK. */
static void
check_function_type (tree decl, tree current_function_parms)
@ -11585,9 +11578,12 @@ check_function_type (tree decl, tree current_function_parms)
TREE_CHAIN (args));
else
fntype = build_function_type (void_type_node, args);
TREE_TYPE (decl)
fntype
= build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)));
fntype = (cp_build_type_attribute_variant
(fntype, TYPE_ATTRIBUTES (TREE_TYPE (decl))));
TREE_TYPE (decl) = fntype;
}
else
abstract_virtuals_error (decl, TREE_TYPE (fntype));

View File

@ -114,20 +114,27 @@ tree
build_memfn_type (tree fntype, tree ctype, cp_cv_quals quals)
{
tree raises;
tree attrs;
int type_quals;
if (fntype == error_mark_node || ctype == error_mark_node)
return error_mark_node;
gcc_assert (TREE_CODE (fntype) == FUNCTION_TYPE
|| TREE_CODE (fntype) == METHOD_TYPE);
type_quals = quals & ~TYPE_QUAL_RESTRICT;
ctype = cp_build_qualified_type (ctype, type_quals);
raises = TYPE_RAISES_EXCEPTIONS (fntype);
attrs = TYPE_ATTRIBUTES (fntype);
fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
: TYPE_ARG_TYPES (fntype)));
raises = TYPE_RAISES_EXCEPTIONS (fntype);
if (raises)
fntype = build_exception_variant (fntype, raises);
if (attrs)
fntype = cp_build_type_attribute_variant (fntype, attrs);
return fntype;
}
@ -237,6 +244,9 @@ maybe_retrofit_in_chrg (tree fn)
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
fntype = build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
if (TYPE_ATTRIBUTES (TREE_TYPE (fn)))
fntype = (cp_build_type_attribute_variant
(fntype, TYPE_ATTRIBUTES (TREE_TYPE (fn))));
TREE_TYPE (fn) = fntype;
/* Now we've got the in-charge parameter. */
@ -1219,6 +1229,8 @@ cp_reconstruct_complex_type (tree type, tree bottom)
else
return bottom;
if (TYPE_ATTRIBUTES (type))
outer = cp_build_type_attribute_variant (outer, TYPE_ATTRIBUTES (type));
return cp_build_qualified_type (outer, TYPE_QUALS (type));
}

View File

@ -10015,13 +10015,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
/* The type of the implicit object parameter gets its
cv-qualifiers from the FUNCTION_TYPE. */
tree method_type;
tree this_type = cp_build_qualified_type (TYPE_MAIN_VARIANT (r),
cp_type_quals (type));
tree memptr;
method_type = build_method_type_directly (this_type,
TREE_TYPE (type),
TYPE_ARG_TYPES (type));
tree method_type = build_memfn_type (type, r, cp_type_quals (type));
memptr = build_ptrmemfunc_type (build_pointer_type (method_type));
return cp_build_qualified_type_real (memptr, cp_type_quals (t),
complain);

View File

@ -1050,6 +1050,10 @@ strip_typedefs (tree t)
else
result = build_function_type (type,
arg_types);
if (TYPE_RAISES_EXCEPTIONS (t))
result = build_exception_variant (result,
TYPE_RAISES_EXCEPTIONS (t));
}
break;
default:
@ -1058,6 +1062,8 @@ strip_typedefs (tree t)
if (!result)
result = TYPE_MAIN_VARIANT (t);
if (TYPE_ATTRIBUTES (t))
result = cp_build_type_attribute_variant (result, TYPE_ATTRIBUTES (t));
return cp_build_qualified_type (result, cp_type_quals (t));
}
@ -2609,7 +2615,8 @@ cp_build_type_attribute_variant (tree type, tree attributes)
tree new_type;
new_type = build_type_attribute_variant (type, attributes);
if (TREE_CODE (new_type) == FUNCTION_TYPE
if ((TREE_CODE (new_type) == FUNCTION_TYPE
|| TREE_CODE (new_type) == METHOD_TYPE)
&& (TYPE_RAISES_EXCEPTIONS (new_type)
!= TYPE_RAISES_EXCEPTIONS (type)))
new_type = build_exception_variant (new_type,

View File

@ -1,3 +1,8 @@
2009-11-06 Jason Merrill <jason@redhat.com>
PR c++/9381
* g++.dg/abi/regparm1.C: New.
2009-11-06 Basile Starynkevitch <basile@starynkevitch.net>
* g++.dg/plugin/pragma_plugin-test-1.C: new testcase for

View File

@ -0,0 +1,40 @@
// PR c++/29911 (9381)
// { dg-options -std=c++0x }
// { dg-do run { target i?86-*-* x86_64-*-* } }
extern "C" int printf(const char *, ...);
void *save_this;
int *save_addr1, *save_addr2;
struct Base
{
__attribute((regparm(3))) void
set(int *addr1, int *addr2)
{
if (this != save_this)
printf("error! this == %p, should be %p\n", this, save_this);
if (addr1 != save_addr1)
printf("error! addr1 == %p, should be %p\n", addr1, save_addr1);
if (addr2 != save_addr2)
printf("error! addr2 == %p, should be %p\n", addr2, save_addr1);
}
};
int main()
{
void (__attribute((regparm(3))) Base::* pfm)(int *, int *) = &Base::set;
__typeof (&Base::set) pfm2 = &Base::set;
decltype (&Base::set) pfm3 = &Base::set;
auto pfm4 = &Base::set;
Base obj; save_this = &obj;
int x, y; save_addr1 = &x; save_addr2 = &y;
(obj.* pfm) (&x, &y);
(obj.* pfm2) (&x, &y);
(obj.* pfm3) (&x, &y);
(obj.* pfm4) (&x, &y);
return 0;
}