]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Core DR 342 PR c++/48582
authorJason Merrill <jason@redhat.com>
Sun, 28 Aug 2011 15:38:29 +0000 (11:38 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Sun, 28 Aug 2011 15:38:29 +0000 (11:38 -0400)
Core DR 342
PR c++/48582
* pt.c (check_valid_ptrmem_cst_expr): A null member pointer value
is valid in C++11.
(convert_nontype_argument): Likewise.  Implicitly convert nullptr
and do constant folding.
* mangle.c (write_template_arg_literal): Mangle null member
pointer values as 0.
* call.c (null_member_pointer_value_p): New.
* cp-tree.h: Declare it.

From-SVN: r178144

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/abi/mangle50.C [new file with mode: 0644]

index 10e64ef7f35dae121480d8238829bd83ab381949..2e0d6ab93050992c02f091c8fce9a11f9298f926 100644 (file)
@@ -1,3 +1,16 @@
+2011-08-26  Jason Merrill  <jason@redhat.com>
+
+       Core DR 342
+       PR c++/48582
+       * pt.c (check_valid_ptrmem_cst_expr): A null member pointer value
+       is valid in C++11.
+       (convert_nontype_argument): Likewise.  Implicitly convert nullptr
+       and do constant folding.
+       * mangle.c (write_template_arg_literal): Mangle null member
+       pointer values as 0.
+       * call.c (null_member_pointer_value_p): New.
+       * cp-tree.h: Declare it.
+
 2011-08-25  Jason Merrill  <jason@redhat.com>
 
        * call.c (convert_like_real): Remove redundant complain checks.
index dc3582414f57dd845ef139bfcc2c287c43f97d6f..84212603b1ab5f5f1bb14858e42f8f6518dc43a4 100644 (file)
@@ -553,6 +553,23 @@ null_ptr_cst_p (tree t)
   return false;
 }
 
+/* Returns true iff T is a null member pointer value (4.11).  */
+
+bool
+null_member_pointer_value_p (tree t)
+{
+  tree type = TREE_TYPE (t);
+  if (!type)
+    return false;
+  else if (TYPE_PTRMEMFUNC_P (type))
+    return (TREE_CODE (t) == CONSTRUCTOR
+           && integer_zerop (CONSTRUCTOR_ELT (t, 0)->value));
+  else if (TYPE_PTRMEM_P (type))
+    return integer_all_onesp (t);
+  else
+    return false;
+}
+
 /* Returns nonzero if PARMLIST consists of only default parms,
    ellipsis, and/or undeduced parameter packs.  */
 
index 859594393979bdc5bb0c653b846835720166bd56..d1256424defd3a0272931d00244264d27e14b719 100644 (file)
@@ -4722,6 +4722,7 @@ extern tree build_addr_func                       (tree);
 extern tree build_call_a                       (tree, int, tree*);
 extern tree build_call_n                       (tree, int, ...);
 extern bool null_ptr_cst_p                     (tree);
+extern bool null_member_pointer_value_p                (tree);
 extern bool sufficient_parms_p                 (const_tree);
 extern tree type_decays_to                     (tree);
 extern tree build_user_type_conversion         (tree, tree, int);
index 4c7cc79d4e34b892387c4dc370508339f12dfc35..1fcd999e5850d598ce7d15446891ceedf8bc3293 100644 (file)
@@ -2762,29 +2762,34 @@ write_template_arg_literal (const tree value)
   write_char ('L');
   write_type (TREE_TYPE (value));
 
-  switch (TREE_CODE (value))
-    {
-    case CONST_DECL:
-      write_integer_cst (DECL_INITIAL (value));
-      break;
+  /* Write a null member pointer value as (type)0, regardless of its
+     real representation.  */
+  if (null_member_pointer_value_p (value))
+    write_integer_cst (integer_zero_node);
+  else
+    switch (TREE_CODE (value))
+      {
+      case CONST_DECL:
+       write_integer_cst (DECL_INITIAL (value));
+       break;
 
-    case INTEGER_CST:
-      gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
-                 || integer_zerop (value) || integer_onep (value));
-      write_integer_cst (value);
-      break;
+      case INTEGER_CST:
+       gcc_assert (!same_type_p (TREE_TYPE (value), boolean_type_node)
+                   || integer_zerop (value) || integer_onep (value));
+       write_integer_cst (value);
+       break;
 
-    case REAL_CST:
-      write_real_cst (value);
-      break;
+      case REAL_CST:
+       write_real_cst (value);
+       break;
 
-    case STRING_CST:
-      sorry ("string literal in function template signature");
-      break;
+      case STRING_CST:
+       sorry ("string literal in function template signature");
+       break;
 
-    default:
-      gcc_unreachable ();
-    }
+      default:
+       gcc_unreachable ();
+      }
 
   write_char ('E');
 }
@@ -2845,7 +2850,8 @@ write_template_arg (tree node)
     /* A template appearing as a template arg is a template template arg.  */
     write_template_template_arg (node);
   else if ((TREE_CODE_CLASS (code) == tcc_constant && code != PTRMEM_CST)
-          || (abi_version_at_least (2) && code == CONST_DECL))
+          || (abi_version_at_least (2) && code == CONST_DECL)
+          || null_member_pointer_value_p (node))
     write_template_arg_literal (node);
   else if (DECL_P (node))
     {
index 3c6b2c54a99bc4c53dd64523ebfb005da5f42438..1f43ff1fbf0376f220c5690a31796abbed123688 100644 (file)
@@ -5240,6 +5240,8 @@ check_valid_ptrmem_cst_expr (tree type, tree expr,
   STRIP_NOPS (expr);
   if (expr && (null_ptr_cst_p (expr) || TREE_CODE (expr) == PTRMEM_CST))
     return true;
+  if (cxx_dialect >= cxx0x && null_member_pointer_value_p (expr))
+    return true;
   if (complain & tf_error)
     {
       error ("%qE is not a valid template argument for type %qT",
@@ -5550,6 +5552,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
   else
     expr = mark_rvalue_use (expr);
 
+  /* 14.3.2/5: The null pointer{,-to-member} conversion is applied
+     to a non-type argument of "nullptr".  */
+  if (expr == nullptr_node
+      && (TYPE_PTR_P (type) || TYPE_PTR_TO_MEMBER_P (type)))
+    expr = convert (type, expr);
+
+  /* In C++11, non-type template arguments can be arbitrary constant
+     expressions.  But don't fold a PTRMEM_CST to a CONSTRUCTOR yet.  */
+  if (cxx_dialect >= cxx0x && TREE_CODE (expr) != PTRMEM_CST)
+    expr = maybe_constant_value (expr);
+
   /* HACK: Due to double coercion, we can get a
      NOP_EXPR<REFERENCE_TYPE>(ADDR_EXPR<POINTER_TYPE> (arg)) here,
      which is the tree that we built on the first call (see
@@ -5658,6 +5671,8 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
       if (DECL_P (expr) && DECL_TEMPLATE_PARM_P (expr))
        /* Non-type template parameters are OK.  */
        ;
+      else if (cxx_dialect >= cxx0x && integer_zerop (expr))
+       /* Null pointer values are OK in C++11.  */;
       else if (TREE_CODE (expr) != ADDR_EXPR
               && TREE_CODE (expr_type) != ARRAY_TYPE)
        {
@@ -5785,6 +5800,10 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
            return error_mark_node;
        }
 
+      if (cxx_dialect >= cxx0x && integer_zerop (expr))
+       /* Null pointer values are OK in C++11.  */
+       return perform_qualification_conversions (type, expr);
+
       expr = convert_nontype_argument_function (type, expr);
       if (!expr || expr == error_mark_node)
        return expr;
index 34816571d37ceeb63dec251fe23ed1f787e71949..03a45a4ee07b111081999a4b1b59525d4b6f6974 100644 (file)
@@ -1,3 +1,9 @@
+2011-08-26  Jason Merrill  <jason@redhat.com>
+
+       Core DR 342
+       PR c++/48582
+       * g++.dg/abi/mangle50.C: New.
+
 2011-08-27  Uros Bizjak  <ubizjak@gmail.com>
 
        PR target/50202
diff --git a/gcc/testsuite/g++.dg/abi/mangle50.C b/gcc/testsuite/g++.dg/abi/mangle50.C
new file mode 100644 (file)
index 0000000..df7afb9
--- /dev/null
@@ -0,0 +1,25 @@
+// DR 342, PR c++/48582
+// { dg-options -std=c++0x }
+
+struct A;
+template < void * = nullptr > void f() { }
+template < void (A::*)() = nullptr > void g() { }
+template < int A::* = nullptr > void h() { }
+
+int main()
+{
+  // { dg-final { scan-assembler "_Z1fILPv0EEvv" } }
+  f();
+  f<nullptr>();
+
+  // { dg-final { scan-assembler "_Z1gILM1AFvvE0EEvv" } }
+  g();
+  g<nullptr>();
+
+  // { dg-final { scan-assembler "_Z1fILPv0EEvv" } }
+  h();
+  h<nullptr>();
+
+  constexpr void * ptr = nullptr;
+  f<ptr>();
+}