@@ -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;
new file mode 100644
@@ -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" }
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 <zhouzhouyi@gmail.com> 2018-12-04 Zhouyi Zhou <zhouzhouyi@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. ---