cxx_pretty_printer::type_id do not treat pointer to pointer to member correctly. this patch handle pointer to pointer to member according to C++ standard 11.3.3.
I don't have write access to gcc. Bootstrapped/regtested on x86_64-linux Signed-off-by: Zhouyi Zhou <zhouzho...@gmail.com> 2018-12-04 Zhouyi Zhou <zhouzho...@gmail.com> PR c++/88291 * cxx-pretty-print.c (type_id): treat pointer to pointer to member by strip out the pointee, print the type specifier of pointee, then print the rest by calling pp_cxx_ptr_operator. * g++.dg/pr88348.C: New test. --- diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index b79ff51..106e6af 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -1829,6 +1829,27 @@ cxx_pretty_printer::type_id (tree t) pp_cxx_ws_string (this, "..."); break; + case POINTER_TYPE: + { + tree pointee = strip_pointer_operator(TREE_TYPE(t)); + /* 11.3.3 */ + if (TREE_CODE(pointee) == RECORD_TYPE && + TYPE_PTRMEMFUNC_P(pointee)) { + tree pfm = TYPE_PTRMEMFUNC_FN_TYPE (pointee); + pp_cxx_type_specifier_seq (this, TREE_TYPE (TREE_TYPE (pfm))); + pp_cxx_whitespace (this); + pp_cxx_ptr_operator(this, t); + break; + } else if (TREE_CODE(pointee) == OFFSET_TYPE && + TYPE_PTRMEM_P(pointee)) { + pp_cxx_type_specifier_seq (this, TYPE_PTRMEM_POINTED_TO_TYPE(pointee)); + pp_cxx_whitespace (this); + pp_cxx_ptr_operator(this, t); + break; + } + } + /* fall through */ + default: c_pretty_printer::type_id (t); break; diff --git a/gcc/testsuite/g++.dg/pr88348.C b/gcc/testsuite/g++.dg/pr88348.C new file mode 100644 index 0000000..5713f49 --- /dev/null +++ b/gcc/testsuite/g++.dg/pr88348.C @@ -0,0 +1,16 @@ +// { dg-do compile { target c++11 } } + +void* operator new (__SIZE_TYPE__, void *p) { return p; } + +struct Z { + void f(int = 0) const; + int speed; +}; + +template <class T> struct helper {}; + +typedef void (Z::***QF)(int) const; +typedef int Z::***pSpeed; + +template <class T> void check1( helper<new QF> * ) { } // { dg-error "is not a constant expression|type/value mismatch" } +template <class T> void check2( helper<new pSpeed> * ) { } // { dg-error "is not a constant expression|type/value mismatch" }