re PR c++/49107 ([C++0x][4.7 Regression] incomplete type regression with std::pair)
authorJason Merrill <jason@redhat.com>
Wed, 8 Jun 2011 21:35:02 +0000 (17:35 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 8 Jun 2011 21:35:02 +0000 (17:35 -0400)
PR c++/49107
* cp-tree.def (DEFERRED_NOEXCEPT): New.
* cp-tree.h (struct tree_deferred_noexcept): New.
(DEFERRED_NOEXCEPT_PATTERN, DEFERRED_NOEXCEPT_ARGS): New.
(DEFERRED_NOEXCEPT_SPEC_P): New.
(enum cp_tree_node_structure_enum): Add TS_CP_DEFERRED_NOEXCEPT.
(union lang_tree_node): Add tree_deferred_noexcept.
(maybe_instantiate_noexcept): Declare.
* cp-objcp-common.c (cp_tree_size): Handle DEFERRED_NOEXCEPT.
* error.c (dump_exception_spec): Likewise.
* cxx-pretty-print.c (pp_cxx_exception_specification): Likewise.
* ptree.c (cxx_print_xnode): Likewise.
* tree.c (cp_tree_equal): Likewise.
* decl.c (cp_tree_node_structure): Likewise.
(duplicate_decls): Call maybe_instantiate_noexcept.
* except.c (build_noexcept_spec): Handle DEFERRED_NOEXCEPT.
(nothrow_spec_p, type_noexcept_p, type_throw_all_p): Check
DEFERRED_NOEXCEPT_SPEC_P.
* typeck2.c (merge_exception_specifiers): Likewise.
* decl2.c (mark_used): Call maybe_instantiate_noexcept.
* method.c (process_subob_fn, defaulted_late_check): Likewise.
* pt.c (tsubst_exception_specification): Add defer_ok parm.
Build DEFERRED_NOEXCEPT.
(maybe_instantiate_noexcept): New.
(tsubst, regenerate_decl_from_template, instantiate_decl): Adjust.
* search.c (check_final_overrider): Call maybe_instantiate_noexcept.

From-SVN: r174820

19 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-objcp-common.c
gcc/cp/cp-tree.def
gcc/cp/cp-tree.h
gcc/cp/cxx-pretty-print.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/method.c
gcc/cp/pt.c
gcc/cp/ptree.c
gcc/cp/search.c
gcc/cp/tree.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/noexcept11.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/noexcept12.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/sfinae11.C

index 5675020503fadd7af80d3d194f8930b68e001f14..2ffefaf15bab4fcac6179695c4a64d345221670e 100644 (file)
@@ -1,5 +1,32 @@
 2011-06-08  Jason Merrill  <jason@redhat.com>
 
+       PR c++/49107
+       * cp-tree.def (DEFERRED_NOEXCEPT): New.
+       * cp-tree.h (struct tree_deferred_noexcept): New.
+       (DEFERRED_NOEXCEPT_PATTERN, DEFERRED_NOEXCEPT_ARGS): New.
+       (DEFERRED_NOEXCEPT_SPEC_P): New.
+       (enum cp_tree_node_structure_enum): Add TS_CP_DEFERRED_NOEXCEPT.
+       (union lang_tree_node): Add tree_deferred_noexcept.
+       (maybe_instantiate_noexcept): Declare.
+       * cp-objcp-common.c (cp_tree_size): Handle DEFERRED_NOEXCEPT.
+       * error.c (dump_exception_spec): Likewise.
+       * cxx-pretty-print.c (pp_cxx_exception_specification): Likewise.
+       * ptree.c (cxx_print_xnode): Likewise.
+       * tree.c (cp_tree_equal): Likewise.
+       * decl.c (cp_tree_node_structure): Likewise.
+       (duplicate_decls): Call maybe_instantiate_noexcept.
+       * except.c (build_noexcept_spec): Handle DEFERRED_NOEXCEPT.
+       (nothrow_spec_p, type_noexcept_p, type_throw_all_p): Check
+       DEFERRED_NOEXCEPT_SPEC_P.
+       * typeck2.c (merge_exception_specifiers): Likewise.
+       * decl2.c (mark_used): Call maybe_instantiate_noexcept.
+       * method.c (process_subob_fn, defaulted_late_check): Likewise.
+       * pt.c (tsubst_exception_specification): Add defer_ok parm.
+       Build DEFERRED_NOEXCEPT.
+       (maybe_instantiate_noexcept): New.
+       (tsubst, regenerate_decl_from_template, instantiate_decl): Adjust.
+       * search.c (check_final_overrider): Call maybe_instantiate_noexcept.
+
        * semantics.c (potential_constant_expression_1): Handle destructor
        call.
 
index df6b1dddd9e7bacd42132c4a2b6d807b5896c7e0..1866b81f802fd8cb3e47a560f1d2ede912fb5684 100644 (file)
@@ -79,6 +79,7 @@ cp_tree_size (enum tree_code code)
     case BASELINK:             return sizeof (struct tree_baselink);
     case TEMPLATE_PARM_INDEX:  return sizeof (template_parm_index);
     case DEFAULT_ARG:          return sizeof (struct tree_default_arg);
+    case DEFERRED_NOEXCEPT:    return sizeof (struct tree_deferred_noexcept);
     case OVERLOAD:             return sizeof (struct tree_overload);
     case STATIC_ASSERT:         return sizeof (struct tree_static_assert);
     case TYPE_ARGUMENT_PACK:
index 001ef100a13d7f7b847b678d2ec91c449ff17f89..ce1141735a7ff25b8fe06584c8e9b7d12537e08b 100644 (file)
@@ -214,6 +214,11 @@ DEFTREECODE (USING_STMT, "using_directive", tcc_statement, 1)
    parsing had occurred.  */
 DEFTREECODE (DEFAULT_ARG, "default_arg", tcc_exceptional, 0)
 
+/* An uninstantiated noexcept-specification.  DEFERRED_NOEXCEPT_PATTERN is
+   the pattern from the template, and DEFERRED_NOEXCEPT_ARGS are the
+   template arguments to substitute into the pattern when needed.  */
+DEFTREECODE (DEFERRED_NOEXCEPT, "deferred_noexcept", tcc_exceptional, 0)
+
 /* A template-id, like foo<int>.  The first operand is the template.
    The second is NULL if there are no explicit arguments, or a
    TREE_VEC of arguments.  The template will be a FUNCTION_DECL,
index 77963b246e9e994cc1c4def2cedeb98a43f1da5d..ce2af0044be5aeffba48c17b9c51b50ec5447217 100644 (file)
@@ -507,6 +507,22 @@ struct GTY (()) tree_default_arg {
   VEC(tree,gc) *instantiations;
 };
 
+
+#define DEFERRED_NOEXCEPT_PATTERN(NODE) \
+  (((struct tree_deferred_noexcept *)DEFERRED_NOEXCEPT_CHECK (NODE))->pattern)
+#define DEFERRED_NOEXCEPT_ARGS(NODE) \
+  (((struct tree_deferred_noexcept *)DEFERRED_NOEXCEPT_CHECK (NODE))->args)
+#define DEFERRED_NOEXCEPT_SPEC_P(NODE)                         \
+  ((NODE) && (TREE_PURPOSE (NODE))                             \
+   && TREE_CODE (TREE_PURPOSE (NODE)) == DEFERRED_NOEXCEPT)
+
+struct GTY (()) tree_deferred_noexcept {
+  struct tree_base base;
+  tree pattern;
+  tree args;
+};
+
+
 /* The condition associated with the static assertion.  This must be
    an integral constant expression.  */
 #define STATIC_ASSERT_CONDITION(NODE) \
@@ -693,6 +709,7 @@ enum cp_tree_node_structure_enum {
   TS_CP_BASELINK,
   TS_CP_WRAPPER,
   TS_CP_DEFAULT_ARG,
+  TS_CP_DEFERRED_NOEXCEPT,
   TS_CP_STATIC_ASSERT,
   TS_CP_ARGUMENT_PACK_SELECT,
   TS_CP_TRAIT_EXPR,
@@ -711,6 +728,7 @@ union GTY((desc ("cp_tree_node_structure (&%h)"),
   struct tree_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload;
   struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink;
   struct tree_default_arg GTY ((tag ("TS_CP_DEFAULT_ARG"))) default_arg;
+  struct tree_deferred_noexcept GTY ((tag ("TS_CP_DEFERRED_NOEXCEPT"))) deferred_noexcept;
   struct lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
   struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT"))) 
     static_assertion;
@@ -5130,6 +5148,7 @@ extern int more_specialized_fn                    (tree, tree, int);
 extern void do_decl_instantiation              (tree, tree);
 extern void do_type_instantiation              (tree, tree, tsubst_flags_t);
 extern bool always_instantiate_p               (tree);
+extern void maybe_instantiate_noexcept         (tree);
 extern tree instantiate_decl                   (tree, int, bool);
 extern int comp_template_parms                 (const_tree, const_tree);
 extern bool uses_parameter_packs                (tree);
index 2f392decf571972be03e947593cd3f09febc9955..c5f1ac02cad75daa42fa740774d679574f383bf0 100644 (file)
@@ -1446,7 +1446,10 @@ pp_cxx_exception_specification (cxx_pretty_printer *pp, tree t)
       pp_cxx_ws_string (pp, "noexcept");
       pp_cxx_whitespace (pp);
       pp_cxx_left_paren (pp);
-      pp_cxx_expression (pp, TREE_PURPOSE (ex_spec));
+      if (DEFERRED_NOEXCEPT_SPEC_P (ex_spec))
+       pp_cxx_ws_string (pp, "<uninstantiated>");
+      else
+       pp_cxx_expression (pp, TREE_PURPOSE (ex_spec));
       pp_cxx_right_paren (pp);
       return;
     }
index 30f70d9e6ee18b888753f211bd5976a2d06f4645..d7da39081541b47702c6e12bf330b8ca807be50d 100644 (file)
@@ -1784,6 +1784,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
       tree oldtype = TREE_TYPE (olddecl);
       tree newtype;
 
+      if (TREE_CODE (newdecl) == FUNCTION_DECL)
+       maybe_instantiate_noexcept (olddecl);
+
       /* Merge the data types specified in the two decls.  */
       newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
 
@@ -13665,6 +13668,7 @@ cp_tree_node_structure (union lang_tree_node * t)
   switch (TREE_CODE (&t->generic))
     {
     case DEFAULT_ARG:          return TS_CP_DEFAULT_ARG;
+    case DEFERRED_NOEXCEPT:    return TS_CP_DEFERRED_NOEXCEPT;
     case IDENTIFIER_NODE:      return TS_CP_IDENTIFIER;
     case OVERLOAD:             return TS_CP_OVERLOAD;
     case TEMPLATE_PARM_INDEX:  return TS_CP_TPI;
index 9005f7eba40d76a819a8f75f87dd6e863a8711c2..a0512cdcab21f92d896b3363d114b21482f5612f 100644 (file)
@@ -4228,6 +4228,9 @@ mark_used (tree decl)
       return;
     }
 
+  if (TREE_CODE (decl) == FUNCTION_DECL)
+    maybe_instantiate_noexcept (decl);
+
   /* Normally, we can wait until instantiation-time to synthesize DECL.
      However, if DECL is a static data member initialized with a constant
      or a constexpr function, we need it right now because a reference to
index d9652dc10efa05259b9c9c16c204bafc0d62660c..96796c206d9f70c78302a64dcc6d70d2be6e9b2a 100644 (file)
@@ -1438,7 +1438,10 @@ dump_exception_spec (tree t, int flags)
       pp_cxx_ws_string (cxx_pp, "noexcept");
       pp_cxx_whitespace (cxx_pp);
       pp_cxx_left_paren (cxx_pp);
-      dump_expr (TREE_PURPOSE (t), flags);
+      if (DEFERRED_NOEXCEPT_SPEC_P (t))
+       pp_cxx_ws_string (cxx_pp, "<uninstantiated>");
+      else
+       dump_expr (TREE_PURPOSE (t), flags);
       pp_cxx_right_paren (cxx_pp);
     }
   else if (t)
index 874f11150443a730d676d791e784aeae9143dce5..3399652241f4985a7854edb8bc2dac33a49839c1 100644 (file)
@@ -1160,6 +1160,7 @@ finish_noexcept_expr (tree expr, tsubst_flags_t complain)
 bool
 nothrow_spec_p (const_tree spec)
 {
+  gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
   if (spec == NULL_TREE
       || TREE_VALUE (spec) != NULL_TREE
       || spec == noexcept_false_spec)
@@ -1180,6 +1181,7 @@ bool
 type_noexcept_p (const_tree type)
 {
   tree spec = TYPE_RAISES_EXCEPTIONS (type);
+  gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
   if (flag_nothrow_opt)
     return nothrow_spec_p (spec);
   else
@@ -1193,6 +1195,7 @@ bool
 type_throw_all_p (const_tree type)
 {
   tree spec = TYPE_RAISES_EXCEPTIONS (type);
+  gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
   return spec == NULL_TREE || spec == noexcept_false_spec;
 }
 
@@ -1204,7 +1207,7 @@ build_noexcept_spec (tree expr, int complain)
 {
   /* This isn't part of the signature, so don't bother trying to evaluate
      it until instantiation.  */
-  if (!processing_template_decl)
+  if (!processing_template_decl && TREE_CODE (expr) != DEFERRED_NOEXCEPT)
     {
       expr = perform_implicit_conversion_flags (boolean_type_node, expr,
                                                complain,
@@ -1219,7 +1222,8 @@ build_noexcept_spec (tree expr, int complain)
     return error_mark_node;
   else
     {
-      gcc_assert (processing_template_decl || expr == error_mark_node);
+      gcc_assert (processing_template_decl || expr == error_mark_node
+                 || TREE_CODE (expr) == DEFERRED_NOEXCEPT);
       return build_tree_list (expr, NULL_TREE);
     }
 }
index cf35b4aab0080d4fa7488318ed55ddf233f9da62..918870056db9d6df9724680f26f96de218118601 100644 (file)
@@ -923,7 +923,9 @@ process_subob_fn (tree fn, bool move_p, tree *spec_p, bool *trivial_p,
 
   if (spec_p)
     {
-      tree raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
+      tree raises;
+      maybe_instantiate_noexcept (fn);
+      raises = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn));
       *spec_p = merge_exception_specifiers (*spec_p, raises);
     }
 
@@ -1558,7 +1560,9 @@ defaulted_late_check (tree fn)
      it had been implicitly declared.  */
   if (DECL_DEFAULTED_IN_CLASS_P (fn))
     {
-      tree eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
+      tree eh_spec;
+      maybe_instantiate_noexcept (fn);
+      eh_spec = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (implicit_fn));
       if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))
          && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)),
                                 eh_spec, ce_normal))
index 61ca31c9eccddd6d5e193f27d83d39a740ac61f7..51d590ea566e1f6832f5ae06ea6da68ffd774a3b 100644 (file)
@@ -10342,7 +10342,8 @@ static tree
 tsubst_exception_specification (tree fntype,
                                tree args,
                                tsubst_flags_t complain,
-                               tree in_decl)
+                               tree in_decl,
+                               bool defer_ok)
 {
   tree specs;
   tree new_specs;
@@ -10352,9 +10353,33 @@ tsubst_exception_specification (tree fntype,
   if (specs && TREE_PURPOSE (specs))
     {
       /* A noexcept-specifier.  */
-      new_specs = tsubst_copy_and_build
-       (TREE_PURPOSE (specs), args, complain, in_decl, /*function_p=*/false,
-        /*integral_constant_expression_p=*/true);
+      tree expr = TREE_PURPOSE (specs);
+      if (expr == boolean_true_node || expr == boolean_false_node)
+       new_specs = expr;
+      else if (defer_ok)
+       {
+         /* Defer instantiation of noexcept-specifiers to avoid
+            excessive instantiations (c++/49107).  */
+         new_specs = make_node (DEFERRED_NOEXCEPT);
+         if (DEFERRED_NOEXCEPT_SPEC_P (specs))
+           {
+             /* We already partially instantiated this member template,
+                so combine the new args with the old.  */
+             DEFERRED_NOEXCEPT_PATTERN (new_specs)
+               = DEFERRED_NOEXCEPT_PATTERN (expr);
+             DEFERRED_NOEXCEPT_ARGS (new_specs)
+               = add_to_template_args (DEFERRED_NOEXCEPT_ARGS (expr), args);
+           }
+         else
+           {
+             DEFERRED_NOEXCEPT_PATTERN (new_specs) = expr;
+             DEFERRED_NOEXCEPT_ARGS (new_specs) = args;
+           }
+       }
+      else
+       new_specs = tsubst_copy_and_build
+         (expr, args, complain, in_decl, /*function_p=*/false,
+          /*integral_constant_expression_p=*/true);
       new_specs = build_noexcept_spec (new_specs, complain);
     }
   else if (specs)
@@ -10879,7 +10904,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 
        /* Substitute the exception specification.  */
        specs = tsubst_exception_specification (t, args, complain,
-                                               in_decl);
+                                               in_decl, /*defer_ok*/true);
        if (specs == error_mark_node)
          return error_mark_node;
        if (specs)
@@ -17159,7 +17184,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
        args = get_innermost_template_args (args, parms_depth);
 
       specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
-                                             args, tf_error, NULL_TREE);
+                                             args, tf_error, NULL_TREE,
+                                             /*defer_ok*/false);
       if (specs)
        TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
                                                    specs);
@@ -17324,6 +17350,46 @@ always_instantiate_p (tree decl)
              && decl_maybe_constant_var_p (decl)));
 }
 
+/* If FN has a noexcept-specifier that hasn't been instantiated yet,
+   instantiate it now, modifying TREE_TYPE (fn).  */
+
+void
+maybe_instantiate_noexcept (tree fn)
+{
+  tree fntype = TREE_TYPE (fn);
+  tree spec = TYPE_RAISES_EXCEPTIONS (fntype);
+  tree noex = NULL_TREE;
+  location_t saved_loc = input_location;
+  tree clone;
+
+  if (!DEFERRED_NOEXCEPT_SPEC_P (spec))
+    return;
+  noex = TREE_PURPOSE (spec);
+
+  push_tinst_level (fn);
+  push_access_scope (fn);
+  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);
+  input_location = saved_loc;
+  pop_access_scope (fn);
+  pop_tinst_level ();
+  spec = build_noexcept_spec (noex, tf_warning_or_error);
+  if (spec == error_mark_node)
+    spec = noexcept_false_spec;
+  TREE_TYPE (fn) = build_exception_variant (fntype, spec);
+
+  FOR_EACH_CLONE (clone, fn)
+    {
+      if (TREE_TYPE (clone) == fntype)
+       TREE_TYPE (clone) = TREE_TYPE (fn);
+      else
+       TREE_TYPE (clone) = build_exception_variant (TREE_TYPE (clone), spec);
+    }
+}
+
 /* Produce the definition of D, a _DECL generated from a template.  If
    DEFER_OK is nonzero, then we don't have to actually do the
    instantiation now; we just have to do it sometime.  Normally it is
@@ -17460,6 +17526,9 @@ instantiate_decl (tree d, int defer_ok,
       SET_DECL_IMPLICIT_INSTANTIATION (d);
     }
 
+  if (TREE_CODE (d) == FUNCTION_DECL)
+    maybe_instantiate_noexcept (d);
+
   /* Recheck the substitutions to obtain any warning messages
      about ignoring cv qualifiers.  Don't do this for artificial decls,
      as it breaks the context-sensitive substitution for lambda op(). */
@@ -17477,7 +17546,7 @@ instantiate_decl (tree d, int defer_ok,
        {
          tsubst (DECL_ARGUMENTS (gen), gen_args, tf_warning_or_error, d);
           tsubst_exception_specification (type, gen_args, tf_warning_or_error,
-                                          d);
+                                          d, /*defer_ok*/true);
          /* Don't simply tsubst the function type, as that will give
             duplicate warnings about poor parameter qualifications.
             The function arguments are the same as the decl_arguments
index 5c9626e768956b6f0c9854dbc6963ae564bd588a..fb05e13604506414f3928b25c60c34e2588e5bdd 100644 (file)
@@ -227,6 +227,10 @@ cxx_print_xnode (FILE *file, tree node, int indent)
       indent_to (file, indent + 3);
       fprintf (file, "index %d", ARGUMENT_PACK_SELECT_INDEX (node));
       break;
+    case DEFERRED_NOEXCEPT:
+      print_node (file, "pattern", DEFERRED_NOEXCEPT_PATTERN (node), indent+4);
+      print_node (file, "args", DEFERRED_NOEXCEPT_ARGS (node), indent+4);
+      break;
     default:
       break;
     }
index cf0b1a0a7e01326e3b2a23597277bb8c5f3db459..97f593cfb392fcd2210c345676c6d32704d49291 100644 (file)
@@ -1803,8 +1803,8 @@ check_final_overrider (tree overrider, tree basefn)
   tree base_type = TREE_TYPE (basefn);
   tree over_return = TREE_TYPE (over_type);
   tree base_return = TREE_TYPE (base_type);
-  tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
-  tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
+  tree over_throw, base_throw;
+
   int fail = 0;
 
   if (DECL_INVALID_OVERRIDER_P (overrider))
@@ -1888,6 +1888,11 @@ check_final_overrider (tree overrider, tree basefn)
     }
 
   /* Check throw specifier is at least as strict.  */
+  maybe_instantiate_noexcept (basefn);
+  maybe_instantiate_noexcept (overrider);
+  base_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (basefn));
+  over_throw = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (overrider));
+
   if (!comp_except_specs (base_throw, over_throw, ce_derived))
     {
       error ("looser throw specifier for %q+#F", overrider);
index 025fe2d1d1f011add40e174b71f1a305e79c238e..5b988e9e0a1c7eee6af02e6c08e7149468e41f29 100644 (file)
@@ -2340,6 +2340,13 @@ cp_tree_equal (tree t1, tree t2)
       /* Now compare operands as usual.  */
       break;
 
+    case DEFERRED_NOEXCEPT:
+      return (cp_tree_equal (DEFERRED_NOEXCEPT_PATTERN (t1),
+                            DEFERRED_NOEXCEPT_PATTERN (t2))
+             && comp_template_args (DEFERRED_NOEXCEPT_ARGS (t1),
+                                    DEFERRED_NOEXCEPT_ARGS (t2)));
+      break;
+
     default:
       break;
     }
index 4d5c21ad5f32d6c3dc9e40b0ba46ced3c3f38d27..f291393d9c8b9b3adeeaf65aae2c41a872436592 100644 (file)
@@ -1769,10 +1769,15 @@ merge_exception_specifiers (tree list, tree add)
     return list;
   else if (!add || add == noexcept_false_spec)
     return add;
+
+  /* We need to instantiate deferred noexcept before we get here.  */
+  gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (list)
+             && !DEFERRED_NOEXCEPT_SPEC_P (add));
+
   /* For merging noexcept(true) and throw(), take the more recent one (LIST).
      Any other noexcept-spec should only be merged with an equivalent one.
      So the !TREE_VALUE code below is correct for all cases.  */
-  else if (!TREE_VALUE (add))
+  if (!TREE_VALUE (add))
     return list;
   else if (!TREE_VALUE (list))
     return add;
index ebdb7ebe5dec00bd561e48a568bfe0d36b155f3b..465d22a3d596f6ca2537911efca1b8d6d7edd54a 100644 (file)
@@ -1,3 +1,9 @@
+2011-06-08  Jason Merrill  <jason@redhat.com>
+
+       * g++.dg/cpp0x/noexcept11.C: New.
+       * g++.dg/cpp0x/noexcept12.C: New.
+       * g++.dg/cpp0x/sfinae11.C: Adjust.
+
 2011-06-08  Jakub Jelinek  <jakub@redhat.com>
 
        PR testsuite/49323
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept11.C b/gcc/testsuite/g++.dg/cpp0x/noexcept11.C
new file mode 100644 (file)
index 0000000..b7c64a6
--- /dev/null
@@ -0,0 +1,53 @@
+// PR c++/49107
+// { dg-options -std=c++0x }
+
+template<typename _Tp>
+_Tp declval() noexcept;
+
+template<typename _Tp , typename = decltype(_Tp(declval<_Tp&&>()))>
+struct trait
+{
+  static const bool value=true;
+};
+
+template<class _T2>
+struct pair
+{
+  _T2 second;
+  void swap(pair& __p)
+    noexcept(trait<_T2>::value);
+};
+
+template < class R_ >
+struct Main
+{
+  Main() {}
+  Main(const typename R_::Sub1T& r) ;
+  Main(const typename R_::Sub2T& l) ;
+};
+
+template < class R_ >
+class Sub1
+{
+  typedef pair<typename R_::MainT> Rep;
+  Rep base;
+};
+
+template < class R_ >
+struct Sub2
+{
+  typedef pair<typename R_::MainT> Rep;
+  Rep base;
+};
+
+struct Kernel
+{
+  typedef Main<Kernel> MainT;
+  typedef Sub1<Kernel> Sub1T;
+  typedef Sub2<Kernel> Sub2T;
+};
+
+Main<Kernel> f()
+{
+  return Main<Kernel> ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept12.C b/gcc/testsuite/g++.dg/cpp0x/noexcept12.C
new file mode 100644 (file)
index 0000000..1fd1b03
--- /dev/null
@@ -0,0 +1,11 @@
+// Test that we handle merging with deferred noexcept.
+// { dg-options -std=c++0x }
+
+template <class U>
+struct O
+{
+  template <class T>
+  void f() noexcept(noexcept(T()));
+};
+
+template<> template<> void O<int>::f<int>() noexcept { }
index a3ffc34f9a3277069d6f9fbd331b1b5b0253c05e..117b08bb623dec3bc150449f5c3006648e6e2782 100644 (file)
@@ -6,7 +6,7 @@ template<class T>
 T&& declval() noexcept;
 
 template< class T >
-inline void f1( T& x ) noexcept( noexcept( declval<T&>().foo() ) )
+inline void f1( T& x ) noexcept( noexcept( declval<T&>().foo() ) ) // { dg-error "Z" }
 {
   x.foo();
 }
@@ -21,7 +21,7 @@ inline void f2( T& x ) noexcept( Noexcept )
 
 // a common and trivial mistake
 template< class T >
-inline void f3( T& x ) noexcept( declval<T&>().foo() )
+inline void f3( T& x ) noexcept( declval<T&>().foo() ) // { dg-error "Z" }
 {
   x.foo();
 }
@@ -50,7 +50,7 @@ int main()
   static_assert(  noexcept( f2(y) ), "OK." );
   // static_assert(  noexcept( f3(y) ), "shall be ill-formed(OK)." );
 
-  static_assert(  noexcept( f1(z) ), "shall be ill-formed." ); // { dg-error "no match" }
+  noexcept( f1(z) );           // { dg-message "required" }
   static_assert(  noexcept( f2(z) ), "shall be ill-formed." ); // { dg-error "no match" }
-  static_assert( !noexcept( f3(z) ), "shall be ill-formed." ); // { dg-error "no match" }
+  noexcept( f3(z) );           // { dg-message "required" }
 }