mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-23 07:00:27 +08:00
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:
parent
7ac8318c2d
commit
3c3905fc17
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
40
gcc/testsuite/g++.dg/abi/regparm1.C
Normal file
40
gcc/testsuite/g++.dg/abi/regparm1.C
Normal 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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user