From a6b9f513eee5543f78ab4356e70dd95be1c2a78e Mon Sep 17 00:00:00 2001 From: jason Date: Fri, 19 Jun 2015 18:15:36 +0000 Subject: [PATCH] PR c++/65880 * decl.c (build_ptrmemfunc_type): Check TYPE_GET_PTRMEMFUNC_TYPE after cv-qualifiers. * typeck.c (merge_types): build_ptrmemfunc_type before applying quals and attributes. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@224678 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 6 ++++ gcc/cp/decl.c | 14 ++++---- gcc/cp/typeck.c | 9 ++--- gcc/testsuite/g++.dg/overload/pmf3.C | 70 ++++++++++++++++++++++++++++++++++++ 4 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 gcc/testsuite/g++.dg/overload/pmf3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2f5e0fa..7d42381 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,11 @@ 2015-06-19 Jason Merrill + PR c++/65880 + * decl.c (build_ptrmemfunc_type): Check TYPE_GET_PTRMEMFUNC_TYPE after + cv-qualifiers. + * typeck.c (merge_types): build_ptrmemfunc_type before applying + quals and attributes. + PR c++/65973 * constexpr.c (build_constexpr_constructor_member_initializers): Handle an empty STATEMENT_LIST. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index c102a4e..515c2d3 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -8224,13 +8224,6 @@ build_ptrmemfunc_type (tree type) if (type == error_mark_node) return type; - /* If a canonical type already exists for this type, use it. We use - this method instead of type_hash_canon, because it only does a - simple equality check on the list of field members. */ - - if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type))) - return t; - /* Make sure that we always have the unqualified pointer-to-member type first. */ if (cp_cv_quals quals = cp_type_quals (type)) @@ -8239,6 +8232,13 @@ build_ptrmemfunc_type (tree type) return cp_build_qualified_type (unqual, quals); } + /* If a canonical type already exists for this type, use it. We use + this method instead of type_hash_canon, because it only does a + simple equality check on the list of field members. */ + + if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type))) + return t; + t = make_node (RECORD_TYPE); /* Let the front end know this is a pointer to member function. */ diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index c33ffd5..22fbb6e 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -786,15 +786,16 @@ merge_types (tree t1, tree t2) int quals = cp_type_quals (t1); if (code1 == POINTER_TYPE) - t1 = build_pointer_type (target); + { + t1 = build_pointer_type (target); + if (TREE_CODE (target) == METHOD_TYPE) + t1 = build_ptrmemfunc_type (t1); + } else t1 = cp_build_reference_type (target, TYPE_REF_IS_RVALUE (t1)); t1 = build_type_attribute_variant (t1, attributes); t1 = cp_build_qualified_type (t1, quals); - if (TREE_CODE (target) == METHOD_TYPE) - t1 = build_ptrmemfunc_type (t1); - return t1; } diff --git a/gcc/testsuite/g++.dg/overload/pmf3.C b/gcc/testsuite/g++.dg/overload/pmf3.C new file mode 100644 index 0000000..a71f554 --- /dev/null +++ b/gcc/testsuite/g++.dg/overload/pmf3.C @@ -0,0 +1,70 @@ +// PR c++/65880 + +class Test +{ + public: + Test(); + ~Test(); + + bool barl(void); + + private: + bool fool(bool (Test::* const *fms)(void)); + bool foo(void); + bool bar(void); +}; + +Test::Test() +{ +} + +Test::~Test() +{ +} + +bool Test::fool(bool (Test::* const *fms)(void)) +{ + bool retval = false; + + int i = 0; + bool (Test::*f)(void) = fms[i++]; + + while (f) { + retval = (this->*f)(); + if (retval) break; + f = fms[i++]; + } + + return retval; +} + + +bool Test::barl(void) +{ + static bool (Test::* const fms[])(void) = { + &Test::foo, + &Test::bar, + 0 + }; + + + + return fool(fms); +} + + +bool Test::foo(void) +{ + return false; +} + +bool Test::bar(void) +{ + return true; +} + +int main(int argc, const char *argv[]) +{ + Test t; + return t.barl(); +} -- 2.7.4