aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog14
-rw-r--r--gcc/cp/call.c5
-rw-r--r--gcc/cp/class.c3
-rw-r--r--gcc/cp/decl.c20
-rw-r--r--gcc/cp/decl2.c14
-rw-r--r--gcc/cp/pt.c7
-rw-r--r--gcc/cp/tree.c9
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/abi/regparm1.C40
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;
+}