From: Jason Merrill Date: Fri, 19 Jun 2015 18:15:36 +0000 (-0400) Subject: re PR c++/65880 (Member function issue with argument "pointer to const array of membe... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=62245e6f7ed68c9c387418827612d719fdc63830;p=gcc.git re PR c++/65880 (Member function issue with argument "pointer to const array of member function pointers") 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. From-SVN: r224678 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 2f5e0fa8c12..7d42381a474 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 c102a4ee717..515c2d33e10 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 c33ffd57a0b..22fbb6e2389 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 00000000000..a71f554441b --- /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(); +}