Hi again,

On 08/23/2014 09:16 AM, Paolo Carlini wrote:
.. on the other hand, the below is a case which my patchlet, which simply tracks pointers, does *not* handle correctly:

struct B { };
template <class T> struct A { };
A<void(B::*)()const>*p = 42;

should be fixable by complicating a bit the tracking, telling apart member pointers.
Thus I finished testing the below. I separated to a new pr34938-2.C all the cases which 4.9 is already getting right and on which we don't want to regress.

As you can see, in order to handle correctly snippets like the above in pr34938-2.C, I added to the pointer check a check TREE_CODE (t) == FUNCTION_TYPE, close to the original idea... For a while that made me a little nervous because I was afraid that we would not print the attribute for member function pointers when we should, but in fact, as we ignore it for typedefs of such types (as I reported a couple of messages ago), we also appear to drop to the floor when no typedefs are involved, thus, eg we simply accept:

struct A { template<int> void foo(); };

template<void (A::*)() __attribute((noreturn))> void bar();

fptr f1 = bar< &A::foo<0> >;

and if we butcher it a little bit to force an error message (eg, we change A::foo to be const) there is no trace of the attribute in the error message anyway. Thus I *think* that given our current status elsewhere at least, we are fine.

Thanks,
Paolo.

////////////////////////
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h        (revision 214396)
+++ cp/cp-tree.h        (working copy)
@@ -4728,7 +4728,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T
    TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS: do not omit template arguments
        identical to their defaults.
    TFF_NO_TEMPLATE_BINDINGS: do not print information about the template
-       arguments for a function template specialization.  */
+       arguments for a function template specialization.
+   TFF_POINTER: we are printing a pointer type.  */
 
 #define TFF_PLAIN_IDENTIFIER                   (0)
 #define TFF_SCOPE                              (1)
@@ -4745,6 +4746,7 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, T
 #define TFF_UNQUALIFIED_NAME                   (1 << 11)
 #define TFF_NO_OMIT_DEFAULT_TEMPLATE_ARGUMENTS (1 << 12)
 #define TFF_NO_TEMPLATE_BINDINGS               (1 << 13)
+#define TFF_POINTER                            (1 << 14)
 
 /* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM
    node.  */
Index: cp/cxx-pretty-print.h
===================================================================
--- cp/cxx-pretty-print.h       (revision 214396)
+++ cp/cxx-pretty-print.h       (working copy)
@@ -59,8 +59,8 @@ struct cxx_pretty_printer : c_pretty_printer
 
 #define pp_cxx_cv_qualifier_seq(PP, T)   \
    pp_c_type_qualifier_list (PP, T)
-#define pp_cxx_cv_qualifiers(PP, CV)   \
-   pp_c_cv_qualifiers (PP, CV, false)
+#define pp_cxx_cv_qualifiers(PP, CV, FT) \
+   pp_c_cv_qualifiers (PP, CV, FT)
 
 #define pp_cxx_whitespace(PP)          pp_c_whitespace (PP)
 #define pp_cxx_left_paren(PP)          pp_c_left_paren (PP)
Index: cp/error.c
===================================================================
--- cp/error.c  (revision 214396)
+++ cp/error.c  (working copy)
@@ -820,6 +820,8 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t,
       if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE
          || TREE_CODE (TREE_TYPE (t)) == FUNCTION_TYPE)
        pp_cxx_right_paren (pp);
+      if (TREE_CODE (t) == POINTER_TYPE)
+       flags |= TFF_POINTER;
       dump_type_suffix (pp, TREE_TYPE (t), flags);
       break;
 
@@ -839,7 +841,9 @@ dump_type_suffix (cxx_pretty_printer *pp, tree t,
        dump_parameters (pp, arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
 
        pp->padding = pp_before;
-       pp_cxx_cv_qualifiers (pp, type_memfn_quals (t));
+       pp_cxx_cv_qualifiers (pp, type_memfn_quals (t),
+                             TREE_CODE (t) == FUNCTION_TYPE
+                             && (flags & TFF_POINTER));
        dump_ref_qualifier (pp, t, flags);
        dump_exception_spec (pp, TYPE_RAISES_EXCEPTIONS (t), flags);
        dump_type_suffix (pp, TREE_TYPE (t), flags);
Index: testsuite/g++.dg/template/pr34938-1.C
===================================================================
--- testsuite/g++.dg/template/pr34938-1.C       (revision 0)
+++ testsuite/g++.dg/template/pr34938-1.C       (working copy)
@@ -0,0 +1,7 @@
+// PR c++/34938
+
+typedef void (*fptr)() __attribute((noreturn)); 
+template<int>  void foo();
+template<fptr> void bar();
+
+fptr f = bar< foo<0> >;   // { dg-error "noreturn" }
Index: testsuite/g++.dg/template/pr34938-2.C
===================================================================
--- testsuite/g++.dg/template/pr34938-2.C       (revision 0)
+++ testsuite/g++.dg/template/pr34938-2.C       (working copy)
@@ -0,0 +1,10 @@
+// PR c++/34938
+
+template <class T> struct A { };
+struct B { };
+
+A<void()const>* p1 = 42;           // { dg-error "void\\(\\) const" }
+A<void(B::*)()const>* p2 = 42;     // { dg-error "void \\(B::\\*\\)\\(\\) 
const" }
+
+A<void()volatile>* p3 = 42;        // { dg-error "void\\(\\) volatile" }
+A<void(B::*)()volatile>* p4 = 42;  // { dg-error "void \\(B::\\*\\)\\(\\) 
volatile" }

Reply via email to