Implement N4268, Do constant evaluation of all non-type template args.
authorJason Merrill <jason@redhat.com>
Tue, 20 Oct 2015 02:48:51 +0000 (22:48 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 20 Oct 2015 02:48:51 +0000 (22:48 -0400)
gcc/c-family/
* c-cppbuiltin.c (c_cpp_builtins): Define
__cpp_nontype_template_args.
gcc/cp/
* parser.c (cp_parser_template_argument): For C++1z just parse a
constant-expression.
* pt.c (convert_nontype_argument): For C++1z always call
maybe_constant_value.

From-SVN: r229019

gcc/c-family/ChangeLog
gcc/c-family/c-cppbuiltin.c
gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1z/nontype1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/nontype2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/nontype3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp1z/nontype3a.C [new file with mode: 0644]

index abcba2910dcfb38bb6df16e1ab1c487c75f5c944..46a6d749ed6789b7a9714ffbb59c79208c77c851 100644 (file)
@@ -1,3 +1,8 @@
+2015-10-19  Jason Merrill  <jason@redhat.com>
+
+       * c-cppbuiltin.c (c_cpp_builtins): Define
+       __cpp_nontype_template_args.
+
 2015-10-19  Jason Merrill  <jason@redhat.com>
 
        * c-cppbuiltin.c (c_cpp_builtins): Define
index cd6fd51ba2f2d0566b3114ab45f49f4bfa6b1010..c6c3d6b0116c3bb8ca7b4b546c4f34a18693f12d 100644 (file)
@@ -876,6 +876,7 @@ c_cpp_builtins (cpp_reader *pfile)
          cpp_define (pfile, "__cpp_enumerator_attributes=201411");
          cpp_define (pfile, "__cpp_nested_namespace_definitions=201411");
          cpp_define (pfile, "__cpp_fold_expressions=201411");
+         cpp_define (pfile, "__cpp_nontype_template_args=201411");
        }
       if (flag_concepts)
        /* Use a value smaller than the 201507 specified in
index 6bc52c360804f36a98c1eeaed4289f4bc9eb4cb4..842426b5f2d46f01ea4ebe4e478551695554542a 100644 (file)
@@ -1,5 +1,11 @@
 2015-10-19  Jason Merrill  <jason@redhat.com>
 
+       Implement N4268, Do constant evaluation of all non-type template args.
+       * parser.c (cp_parser_template_argument): For C++1z just parse a
+       constant-expression.
+       * pt.c (convert_nontype_argument): For C++1z always call
+       maybe_constant_value.
+
        * constexpr.c (cxx_eval_constant_expression): Expand PTRMEM_CST
        only when necessary.
        (cxx_eval_component_reference): Like here.
index 435757d3fa1c3f85f9fba4b4d29029e349a91bb1..f07a5e49532d62a000e53ba63fbd3024600b792a 100644 (file)
@@ -14977,8 +14977,12 @@ cp_parser_template_argument (cp_parser* parser)
        warn_deprecated_use (argument, NULL_TREE);
       return argument;
     }
-  /* It must be a non-type argument.  There permitted cases are given
-     in [temp.arg.nontype]:
+  /* It must be a non-type argument.  In C++17 any constant-expression is
+     allowed.  */
+  if (cxx_dialect > cxx14)
+    goto general_expr;
+
+  /* Otherwise, the permitted cases are given in [temp.arg.nontype]:
 
      -- an integral constant-expression of integral or enumeration
        type; or
@@ -15090,6 +15094,7 @@ cp_parser_template_argument (cp_parser* parser)
       return error_mark_node;
     }
 
+ general_expr:
   /* If the argument wasn't successfully parsed as a type-id followed
      by '>>', the argument can only be a constant expression now.
      Otherwise, we try parsing the constant-expression tentatively,
index 14a5ddd9bb395db5ebc5f03424220fb0600a0d6f..142245ad8e0c8a2d377a3d28622b239f9850e81d 100644 (file)
@@ -6233,6 +6233,17 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
           CONSTRUCTOR.  */;
       else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
        expr = maybe_constant_value (expr);
+      else if (cxx_dialect >= cxx1z)
+       {
+         if (TREE_CODE (type) != REFERENCE_TYPE)
+           expr = maybe_constant_value (expr);
+         else if (REFERENCE_REF_P (expr))
+           {
+             expr = TREE_OPERAND (expr, 0);
+             expr = maybe_constant_value (expr);
+             expr = convert_from_reference (expr);
+           }
+       }
       else if (TYPE_PTR_OR_PTRMEM_P (type))
        {
          tree folded = maybe_constant_value (expr);
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype1.C b/gcc/testsuite/g++.dg/cpp1z/nontype1.C
new file mode 100644 (file)
index 0000000..bb46a99
--- /dev/null
@@ -0,0 +1,25 @@
+// { dg-options -std=c++1z }
+
+struct S { int m; static int s; } s;
+
+struct T: S { };
+
+template<int* p> class X { };
+template<const int S::*> class M {};
+template<const S&> class SP {};
+
+constexpr int *p = &S::s;
+constexpr int S::*sp = &T::m;
+constexpr S& sr = s;
+constexpr S& sf() { return s; }
+
+// { dg-final { scan-assembler "_Z1g1XIXadL_ZN1S1sEEEE" } }
+void g (X<&s.s>) { }
+// { dg-final { scan-assembler "_Z1f1XIXadL_ZN1S1sEEEE" } }
+void f (X<p>) { }
+// { dg-final { scan-assembler "_Z1f1MIXadL_ZN1S1mEEEE" } }
+void f (M<sp>) {}
+// { dg-final { scan-assembler "_Z1f2SPIL_Z1sEE" } }
+void f (SP<sr>) {}
+// { dg-final { scan-assembler "_Z1g2SPIL_Z1sEE" } }
+void g (SP<sf()>) {}
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype2.C b/gcc/testsuite/g++.dg/cpp1z/nontype2.C
new file mode 100644 (file)
index 0000000..e489476
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-options -std=c++1z }
+
+#include <typeinfo>
+
+struct S { int m; static int s; } s;
+
+template<int* p> class X { };
+template<const char *s> class Y {};
+template<const std::type_info &> class Z {};
+
+X<&s.m> x7;                    // { dg-error "" }
+Y<"foo"> y1;                   // { dg-error "string literal" }
+Z<typeid(p)> z1;               // { dg-error "" }
+
+void f()
+{
+  Y<__func__> y;               // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype3.C b/gcc/testsuite/g++.dg/cpp1z/nontype3.C
new file mode 100644 (file)
index 0000000..886d7a5
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++1z" }
+
+#ifndef __cpp_nontype_template_args
+#error __cpp_nontype_template_args not defined
+#endif
+
+#if __cpp_nontype_template_args != 201411
+#error Wrong value for __cpp_nontype_template_args
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/nontype3a.C b/gcc/testsuite/g++.dg/cpp1z/nontype3a.C
new file mode 100644 (file)
index 0000000..a253d6b
--- /dev/null
@@ -0,0 +1,5 @@
+// This macro should not be defined without -std=c++1z.
+
+#ifdef __cpp_nontype_template_args
+#error __cpp_nontype_template_args defined
+#endif