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
This commit is contained in:
parent
535fb6eb20
commit
1026172832
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1446,6 +1446,9 @@ 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);
|
||||
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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1438,6 +1438,9 @@ 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);
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
79
gcc/cp/pt.c
79
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,8 +10353,32 @@ tsubst_exception_specification (tree fntype,
|
|||
if (specs && TREE_PURPOSE (specs))
|
||||
{
|
||||
/* A noexcept-specifier. */
|
||||
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
|
||||
(TREE_PURPOSE (specs), args, complain, in_decl, /*function_p=*/false,
|
||||
(expr, args, complain, in_decl, /*function_p=*/false,
|
||||
/*integral_constant_expression_p=*/true);
|
||||
new_specs = build_noexcept_spec (new_specs, complain);
|
||||
}
|
||||
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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> ();
|
||||
}
|
|
@ -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 { }
|
|
@ -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" }
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue