diff options
-rw-r--r-- | gcc/cp/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/cp/call.c | 5 | ||||
-rw-r--r-- | gcc/cp/class.c | 3 | ||||
-rw-r--r-- | gcc/cp/decl.c | 20 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 14 | ||||
-rw-r--r-- | gcc/cp/pt.c | 7 | ||||
-rw-r--r-- | gcc/cp/tree.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/abi/regparm1.C | 40 |
9 files changed, 93 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 6d7fd34..36f7255 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -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 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0979f3a..1aebaac 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 4020144..c798ba2 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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; diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 97f1ac1f..5e2f85f 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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)); diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index dbb9fb4..53f66ad 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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)); } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 75180ea..dd453c5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index b79093a..5aea55e 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bf74370..be66e31 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/g++.dg/abi/regparm1.C b/gcc/testsuite/g++.dg/abi/regparm1.C new file mode 100644 index 0000000..a83c477 --- /dev/null +++ b/gcc/testsuite/g++.dg/abi/regparm1.C @@ -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; +} |