PR c++/87145 - bogus error converting class type in template arg list.
authorMarek Polacek <polacek@redhat.com>
Fri, 5 Apr 2019 21:22:40 +0000 (21:22 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Fri, 5 Apr 2019 21:22:40 +0000 (21:22 +0000)
* pt.c (convert_nontype_argument): Don't call
build_converted_constant_expr if it could involve calling a conversion
function with a instantiation-dependent constructor as its argument.

* g++.dg/cpp0x/constexpr-conv3.C: New test.
* g++.dg/cpp0x/constexpr-conv4.C: New test.

From-SVN: r270178

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-conv3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/constexpr-conv4.C [new file with mode: 0644]

index 17c9aa712aa65fa938fa9b8d03820f0ecc3ef3d4..f766f476f10fb4aca9584fc6d147907ebaa92aa3 100644 (file)
@@ -1,3 +1,10 @@
+2019-04-05  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/87145 - bogus error converting class type in template arg list.
+       * pt.c (convert_nontype_argument): Don't call
+       build_converted_constant_expr if it could involve calling a conversion
+       function with a instantiation-dependent constructor as its argument.
+
 2019-04-05  Martin Sebor  <msebor@redhat.com>
 
        PR bootstrap/89980
index 40d954d1e8a37451518bb80d4b8f73ea9f798bad..f8001317bda58bef38b8556d77c82bbe4a3f64f2 100644 (file)
@@ -6837,6 +6837,19 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
       else if (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
               || cxx_dialect >= cxx17)
        {
+         /* Calling build_converted_constant_expr might create a call to
+            a conversion function with a value-dependent argument, which
+            could invoke taking the address of a temporary representing
+            the result of the conversion.  */
+         if (COMPOUND_LITERAL_P (expr)
+             && CONSTRUCTOR_IS_DEPENDENT (expr)
+             && MAYBE_CLASS_TYPE_P (expr_type)
+             && TYPE_HAS_CONVERSION (expr_type))
+           {
+             expr = build1 (IMPLICIT_CONV_EXPR, type, expr);
+             IMPLICIT_CONV_EXPR_NONTYPE_ARG (expr) = true;
+             return expr;
+           }
          /* C++17: A template-argument for a non-type template-parameter shall
             be a converted constant expression (8.20) of the type of the
             template-parameter.  */
index dc6f911fc4ff55772a361b6a24522229935652ae..b854b57507701a402679dbab2b5bc819c663d191 100644 (file)
@@ -1,3 +1,9 @@
+2019-04-05  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/87145 - bogus error converting class type in template arg list.
+       * g++.dg/cpp0x/constexpr-conv3.C: New test.
+       * g++.dg/cpp0x/constexpr-conv4.C: New test.
+
 2019-04-05  Martin Sebor  <msebor@redhat.com>
 
        PR bootstrap/89980
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-conv3.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-conv3.C
new file mode 100644 (file)
index 0000000..3f47c58
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/87145
+// { dg-do compile { target c++11 } }
+
+template<typename T, T t> struct integral_constant {
+  static constexpr T value = t;
+};
+
+enum class Enum : unsigned {};
+
+struct Pod {
+  unsigned val;
+
+  constexpr operator Enum() const {
+    return static_cast<Enum>(val);
+  }
+};
+
+template<unsigned N>
+constexpr void foo() {
+  using Foo = integral_constant<Enum, Pod{N}>;
+}
+
+int main() {
+  foo<2>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-conv4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-conv4.C
new file mode 100644 (file)
index 0000000..f4e3f00
--- /dev/null
@@ -0,0 +1,25 @@
+// PR c++/87145
+// { dg-do compile { target c++11 } }
+
+struct S {
+  int val;
+
+  constexpr operator int() const {
+    return static_cast<int>(val);
+  }
+};
+
+template<int N>
+struct F { };
+
+template<unsigned N>
+constexpr void foo() {
+  F<int{N}> f;
+  F<S{N}> f2;
+}
+
+int
+main()
+{
+  foo<2>();
+}