From 1026172832d7175b52ee0ddf5ef17d7f5b803e2e Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 8 Jun 2011 17:35:02 -0400 Subject: [PATCH] re PR c++/49107 ([C++0x][4.7 Regression] incomplete type regression with std::pair) 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 --- gcc/cp/ChangeLog | 27 +++++++++++ gcc/cp/cp-objcp-common.c | 1 + gcc/cp/cp-tree.def | 5 ++ gcc/cp/cp-tree.h | 19 ++++++++ gcc/cp/cxx-pretty-print.c | 5 +- gcc/cp/decl.c | 4 ++ gcc/cp/decl2.c | 3 ++ gcc/cp/error.c | 5 +- gcc/cp/except.c | 8 +++- gcc/cp/method.c | 8 +++- gcc/cp/pt.c | 83 ++++++++++++++++++++++++++++++--- gcc/cp/ptree.c | 4 ++ gcc/cp/search.c | 9 +++- gcc/cp/tree.c | 7 +++ gcc/cp/typeck2.c | 7 ++- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/cpp0x/noexcept11.C | 53 +++++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/noexcept12.C | 11 +++++ gcc/testsuite/g++.dg/cpp0x/sfinae11.C | 8 ++-- 19 files changed, 253 insertions(+), 20 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept11.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/noexcept12.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5675020..2ffefaf 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,32 @@ 2011-06-08 Jason Merrill + 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. diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c index df6b1dd..1866b81 100644 --- a/gcc/cp/cp-objcp-common.c +++ b/gcc/cp/cp-objcp-common.c @@ -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: diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def index 001ef10..ce11417 100644 --- a/gcc/cp/cp-tree.def +++ b/gcc/cp/cp-tree.def @@ -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. 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, diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 77963b2..ce2af00 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c index 2f392de..c5f1ac0 100644 --- a/gcc/cp/cxx-pretty-print.c +++ b/gcc/cp/cxx-pretty-print.c @@ -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, ""); + else + pp_cxx_expression (pp, TREE_PURPOSE (ex_spec)); pp_cxx_right_paren (pp); return; } diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 30f70d9..d7da390 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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; diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 9005f7e..a0512cd 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 diff --git a/gcc/cp/error.c b/gcc/cp/error.c index d9652dc..96796c2 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -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, ""); + else + dump_expr (TREE_PURPOSE (t), flags); pp_cxx_right_paren (cxx_pp); } else if (t) diff --git a/gcc/cp/except.c b/gcc/cp/except.c index 874f111..3399652 100644 --- a/gcc/cp/except.c +++ b/gcc/cp/except.c @@ -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); } } diff --git a/gcc/cp/method.c b/gcc/cp/method.c index cf35b4a..9188700 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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)) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 61ca31c..51d590e 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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 diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c index 5c9626e..fb05e13 100644 --- a/gcc/cp/ptree.c +++ b/gcc/cp/ptree.c @@ -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; } diff --git a/gcc/cp/search.c b/gcc/cp/search.c index cf0b1a0..97f593c 100644 --- a/gcc/cp/search.c +++ b/gcc/cp/search.c @@ -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); diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 025fe2d..5b988e9 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -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; } diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 4d5c21a..f291393 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index ebdb7eb..465d22a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2011-06-08 Jason Merrill + + * g++.dg/cpp0x/noexcept11.C: New. + * g++.dg/cpp0x/noexcept12.C: New. + * g++.dg/cpp0x/sfinae11.C: Adjust. + 2011-06-08 Jakub Jelinek 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 index 0000000..b7c64a6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept11.C @@ -0,0 +1,53 @@ +// PR c++/49107 +// { dg-options -std=c++0x } + +template +_Tp declval() noexcept; + +template()))> +struct trait +{ + static const bool value=true; +}; + +template +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 Rep; + Rep base; +}; + +template < class R_ > +struct Sub2 +{ + typedef pair Rep; + Rep base; +}; + +struct Kernel +{ + typedef Main MainT; + typedef Sub1 Sub1T; + typedef Sub2 Sub2T; +}; + +Main f() +{ + return Main (); +} diff --git a/gcc/testsuite/g++.dg/cpp0x/noexcept12.C b/gcc/testsuite/g++.dg/cpp0x/noexcept12.C new file mode 100644 index 0000000..1fd1b03 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/noexcept12.C @@ -0,0 +1,11 @@ +// Test that we handle merging with deferred noexcept. +// { dg-options -std=c++0x } + +template +struct O +{ + template + void f() noexcept(noexcept(T())); +}; + +template<> template<> void O::f() noexcept { } diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C index a3ffc34..117b08b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/sfinae11.C +++ b/gcc/testsuite/g++.dg/cpp0x/sfinae11.C @@ -6,7 +6,7 @@ template T&& declval() noexcept; template< class T > -inline void f1( T& x ) noexcept( noexcept( declval().foo() ) ) +inline void f1( T& x ) noexcept( noexcept( declval().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().foo() ) +inline void f3( T& x ) noexcept( declval().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" } } -- 2.7.4