PR c++/88294 - ICE with non-constant noexcept-specifier.
authorMarek Polacek <polacek@redhat.com>
Sat, 23 Feb 2019 14:05:31 +0000 (14:05 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Sat, 23 Feb 2019 14:05:31 +0000 (14:05 +0000)
* pt.c (maybe_instantiate_noexcept): Set up the list of local
specializations.  Set current_class_{ptr,ref}.

* g++.dg/cpp0x/noexcept34.C: New test.
* g++.dg/cpp0x/noexcept35.C: New test.

From-SVN: r269158

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/noexcept34.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/noexcept35.C [new file with mode: 0644]

index 2a5056ad4af00049f8a3df96334940bdd1dbe489..2da2e3d60dc3009149844ff04679895cf8cda68c 100644 (file)
@@ -1,3 +1,9 @@
+2019-02-23  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/88294 - ICE with non-constant noexcept-specifier.
+       * pt.c (maybe_instantiate_noexcept): Set up the list of local
+       specializations.  Set current_class_{ptr,ref}.
+
 2019-02-22  David Malcolm  <dmalcolm@redhat.com>
 
        PR c++/89390
index 42dd095a6b010ba63bd2f14d1084568886465dfe..d678e27807810a2353a6f3ebdbc60ff79a953025 100644 (file)
@@ -24203,12 +24203,39 @@ maybe_instantiate_noexcept (tree fn, tsubst_flags_t complain)
          push_access_scope (fn);
          push_deferring_access_checks (dk_no_deferred);
          input_location = DECL_SOURCE_LOCATION (fn);
-         noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
-                                       DEFERRED_NOEXCEPT_ARGS (noex),
-                                       tf_warning_or_error, fn,
-                                       /*function_p=*/false,
-                                       /*integral_constant_expression_p=*/true);
-         spec = build_noexcept_spec (noex, tf_warning_or_error);
+
+         /* A new stack interferes with pop_access_scope.  */
+         {
+           /* Set up the list of local specializations.  */
+           local_specialization_stack lss (lss_copy);
+
+           tree save_ccp = current_class_ptr;
+           tree save_ccr = current_class_ref;
+           /* If needed, set current_class_ptr for the benefit of
+              tsubst_copy/PARM_DECL.  */
+           tree tdecl = DECL_TEMPLATE_RESULT (DECL_TI_TEMPLATE (fn));
+           if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tdecl))
+             {
+               tree this_parm = DECL_ARGUMENTS (tdecl);
+               current_class_ptr = NULL_TREE;
+               current_class_ref = cp_build_fold_indirect_ref (this_parm);
+               current_class_ptr = this_parm;
+             }
+
+           /* Create substitution entries for the parameters.  */
+           register_parameter_specializations (tdecl, fn);
+
+           /* Do deferred instantiation of the noexcept-specifier.  */
+           noex = tsubst_copy_and_build (DEFERRED_NOEXCEPT_PATTERN (noex),
+                                         DEFERRED_NOEXCEPT_ARGS (noex),
+                                         tf_warning_or_error, fn,
+                                         /*function_p=*/false,
+                                         /*i_c_e_p=*/true);
+           current_class_ptr = save_ccp;
+           current_class_ref = save_ccr;
+           spec = build_noexcept_spec (noex, tf_warning_or_error);
+         }
+
          pop_deferring_access_checks ();
          pop_access_scope (fn);
          pop_tinst_level ();
index cc5a87d5cc7213dd22eea4ac82f8b3840cd74c40..da4aa85aa412758a526ef6aea128b31cf283a35a 100644 (file)
@@ -1,3 +1,9 @@
+2019-02-23  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/88294 - ICE with non-constant noexcept-specifier.
+       * g++.dg/cpp0x/noexcept34.C: New test.
+       * g++.dg/cpp0x/noexcept35.C: New test.
+
 2019-02-23  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/88117
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept34.C b/gcc/testsuite/g++.dg/cpp0x/noexcept34.C
new file mode 100644 (file)
index 0000000..dce3565
--- /dev/null
@@ -0,0 +1,29 @@
+// PR c++/88294
+// { dg-do compile { target c++11 } }
+
+constexpr int foo (bool b) { return b; }
+
+template<typename> struct A
+{
+  constexpr int f () { return 0; }
+  bool b = true;
+  void g () noexcept (f()) { } // { dg-error "use of parameter" }
+  void g2 () noexcept (this->f()) { } // { dg-error "use of parameter" }
+  void g3 () noexcept (b) { } // { dg-error "use of .this. in a constant expression|use of parameter" }
+  void g4 (int i) noexcept (i) { } // { dg-error "use of parameter" }
+  void g5 () noexcept (A::f()) { } // { dg-error "use of parameter" }
+  void g6 () noexcept (foo(b)) { } // { dg-error "use of .this. in a constant expression|use of parameter" }
+  void g7 () noexcept (int{f()}) { } // { dg-error "use of parameter" }
+};
+
+int main ()
+{
+  A<int> a;
+  a.g ();
+  a.g2 ();
+  a.g3 ();
+  a.g4 (1);
+  a.g5 ();
+  a.g6 ();
+  a.g7 ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept35.C b/gcc/testsuite/g++.dg/cpp0x/noexcept35.C
new file mode 100644 (file)
index 0000000..8606b1a
--- /dev/null
@@ -0,0 +1,21 @@
+// { dg-do compile { target c++11 } }
+
+template <typename _Tp, _Tp __v> struct A { static constexpr _Tp value = __v; };
+typedef A<bool, false> false_type;
+struct is_same : false_type {};
+template <bool> struct enable_if;
+template <typename> using __remove_cvref_t = int;
+template <typename _Tp> class reference_wrapper {
+  static _Tp _S_fun();
+  template <typename _Up, typename = __remove_cvref_t<_Up>>
+  using __not_same = enable_if<is_same::value>;
+
+public:
+  template <typename _Up, typename = __not_same<_Up>>
+  reference_wrapper(_Up) noexcept(noexcept(reference_wrapper::_S_fun));
+};
+
+reference_wrapper<int> fn1() {
+  int __t = 10;
+  return __t;
+}