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>
|
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
|
* semantics.c (potential_constant_expression_1): Handle destructor
|
||||||
call.
|
call.
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,7 @@ cp_tree_size (enum tree_code code)
|
||||||
case BASELINK: return sizeof (struct tree_baselink);
|
case BASELINK: return sizeof (struct tree_baselink);
|
||||||
case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index);
|
case TEMPLATE_PARM_INDEX: return sizeof (template_parm_index);
|
||||||
case DEFAULT_ARG: return sizeof (struct tree_default_arg);
|
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 OVERLOAD: return sizeof (struct tree_overload);
|
||||||
case STATIC_ASSERT: return sizeof (struct tree_static_assert);
|
case STATIC_ASSERT: return sizeof (struct tree_static_assert);
|
||||||
case TYPE_ARGUMENT_PACK:
|
case TYPE_ARGUMENT_PACK:
|
||||||
|
|
|
@ -214,6 +214,11 @@ DEFTREECODE (USING_STMT, "using_directive", tcc_statement, 1)
|
||||||
parsing had occurred. */
|
parsing had occurred. */
|
||||||
DEFTREECODE (DEFAULT_ARG, "default_arg", tcc_exceptional, 0)
|
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.
|
/* A template-id, like foo<int>. The first operand is the template.
|
||||||
The second is NULL if there are no explicit arguments, or a
|
The second is NULL if there are no explicit arguments, or a
|
||||||
TREE_VEC of arguments. The template will be a FUNCTION_DECL,
|
TREE_VEC of arguments. The template will be a FUNCTION_DECL,
|
||||||
|
|
|
@ -507,6 +507,22 @@ struct GTY (()) tree_default_arg {
|
||||||
VEC(tree,gc) *instantiations;
|
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
|
/* The condition associated with the static assertion. This must be
|
||||||
an integral constant expression. */
|
an integral constant expression. */
|
||||||
#define STATIC_ASSERT_CONDITION(NODE) \
|
#define STATIC_ASSERT_CONDITION(NODE) \
|
||||||
|
@ -693,6 +709,7 @@ enum cp_tree_node_structure_enum {
|
||||||
TS_CP_BASELINK,
|
TS_CP_BASELINK,
|
||||||
TS_CP_WRAPPER,
|
TS_CP_WRAPPER,
|
||||||
TS_CP_DEFAULT_ARG,
|
TS_CP_DEFAULT_ARG,
|
||||||
|
TS_CP_DEFERRED_NOEXCEPT,
|
||||||
TS_CP_STATIC_ASSERT,
|
TS_CP_STATIC_ASSERT,
|
||||||
TS_CP_ARGUMENT_PACK_SELECT,
|
TS_CP_ARGUMENT_PACK_SELECT,
|
||||||
TS_CP_TRAIT_EXPR,
|
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_overload GTY ((tag ("TS_CP_OVERLOAD"))) overload;
|
||||||
struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink;
|
struct tree_baselink GTY ((tag ("TS_CP_BASELINK"))) baselink;
|
||||||
struct tree_default_arg GTY ((tag ("TS_CP_DEFAULT_ARG"))) default_arg;
|
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 lang_identifier GTY ((tag ("TS_CP_IDENTIFIER"))) identifier;
|
||||||
struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT")))
|
struct tree_static_assert GTY ((tag ("TS_CP_STATIC_ASSERT")))
|
||||||
static_assertion;
|
static_assertion;
|
||||||
|
@ -5130,6 +5148,7 @@ extern int more_specialized_fn (tree, tree, int);
|
||||||
extern void do_decl_instantiation (tree, tree);
|
extern void do_decl_instantiation (tree, tree);
|
||||||
extern void do_type_instantiation (tree, tree, tsubst_flags_t);
|
extern void do_type_instantiation (tree, tree, tsubst_flags_t);
|
||||||
extern bool always_instantiate_p (tree);
|
extern bool always_instantiate_p (tree);
|
||||||
|
extern void maybe_instantiate_noexcept (tree);
|
||||||
extern tree instantiate_decl (tree, int, bool);
|
extern tree instantiate_decl (tree, int, bool);
|
||||||
extern int comp_template_parms (const_tree, const_tree);
|
extern int comp_template_parms (const_tree, const_tree);
|
||||||
extern bool uses_parameter_packs (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_ws_string (pp, "noexcept");
|
||||||
pp_cxx_whitespace (pp);
|
pp_cxx_whitespace (pp);
|
||||||
pp_cxx_left_paren (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_expression (pp, TREE_PURPOSE (ex_spec));
|
||||||
pp_cxx_right_paren (pp);
|
pp_cxx_right_paren (pp);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1784,6 +1784,9 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
|
||||||
tree oldtype = TREE_TYPE (olddecl);
|
tree oldtype = TREE_TYPE (olddecl);
|
||||||
tree newtype;
|
tree newtype;
|
||||||
|
|
||||||
|
if (TREE_CODE (newdecl) == FUNCTION_DECL)
|
||||||
|
maybe_instantiate_noexcept (olddecl);
|
||||||
|
|
||||||
/* Merge the data types specified in the two decls. */
|
/* Merge the data types specified in the two decls. */
|
||||||
newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
|
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))
|
switch (TREE_CODE (&t->generic))
|
||||||
{
|
{
|
||||||
case DEFAULT_ARG: return TS_CP_DEFAULT_ARG;
|
case DEFAULT_ARG: return TS_CP_DEFAULT_ARG;
|
||||||
|
case DEFERRED_NOEXCEPT: return TS_CP_DEFERRED_NOEXCEPT;
|
||||||
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
|
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
|
||||||
case OVERLOAD: return TS_CP_OVERLOAD;
|
case OVERLOAD: return TS_CP_OVERLOAD;
|
||||||
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
|
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
|
||||||
|
|
|
@ -4228,6 +4228,9 @@ mark_used (tree decl)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TREE_CODE (decl) == FUNCTION_DECL)
|
||||||
|
maybe_instantiate_noexcept (decl);
|
||||||
|
|
||||||
/* Normally, we can wait until instantiation-time to synthesize DECL.
|
/* Normally, we can wait until instantiation-time to synthesize DECL.
|
||||||
However, if DECL is a static data member initialized with a constant
|
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
|
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_ws_string (cxx_pp, "noexcept");
|
||||||
pp_cxx_whitespace (cxx_pp);
|
pp_cxx_whitespace (cxx_pp);
|
||||||
pp_cxx_left_paren (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);
|
dump_expr (TREE_PURPOSE (t), flags);
|
||||||
pp_cxx_right_paren (cxx_pp);
|
pp_cxx_right_paren (cxx_pp);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1160,6 +1160,7 @@ finish_noexcept_expr (tree expr, tsubst_flags_t complain)
|
||||||
bool
|
bool
|
||||||
nothrow_spec_p (const_tree spec)
|
nothrow_spec_p (const_tree spec)
|
||||||
{
|
{
|
||||||
|
gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
|
||||||
if (spec == NULL_TREE
|
if (spec == NULL_TREE
|
||||||
|| TREE_VALUE (spec) != NULL_TREE
|
|| TREE_VALUE (spec) != NULL_TREE
|
||||||
|| spec == noexcept_false_spec)
|
|| spec == noexcept_false_spec)
|
||||||
|
@ -1180,6 +1181,7 @@ bool
|
||||||
type_noexcept_p (const_tree type)
|
type_noexcept_p (const_tree type)
|
||||||
{
|
{
|
||||||
tree spec = TYPE_RAISES_EXCEPTIONS (type);
|
tree spec = TYPE_RAISES_EXCEPTIONS (type);
|
||||||
|
gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
|
||||||
if (flag_nothrow_opt)
|
if (flag_nothrow_opt)
|
||||||
return nothrow_spec_p (spec);
|
return nothrow_spec_p (spec);
|
||||||
else
|
else
|
||||||
|
@ -1193,6 +1195,7 @@ bool
|
||||||
type_throw_all_p (const_tree type)
|
type_throw_all_p (const_tree type)
|
||||||
{
|
{
|
||||||
tree spec = TYPE_RAISES_EXCEPTIONS (type);
|
tree spec = TYPE_RAISES_EXCEPTIONS (type);
|
||||||
|
gcc_assert (!DEFERRED_NOEXCEPT_SPEC_P (spec));
|
||||||
return spec == NULL_TREE || spec == noexcept_false_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
|
/* This isn't part of the signature, so don't bother trying to evaluate
|
||||||
it until instantiation. */
|
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,
|
expr = perform_implicit_conversion_flags (boolean_type_node, expr,
|
||||||
complain,
|
complain,
|
||||||
|
@ -1219,7 +1222,8 @@ build_noexcept_spec (tree expr, int complain)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
else
|
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);
|
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)
|
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);
|
*spec_p = merge_exception_specifiers (*spec_p, raises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1558,7 +1560,9 @@ defaulted_late_check (tree fn)
|
||||||
it had been implicitly declared. */
|
it had been implicitly declared. */
|
||||||
if (DECL_DEFAULTED_IN_CLASS_P (fn))
|
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))
|
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn))
|
||||||
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)),
|
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)),
|
||||||
eh_spec, ce_normal))
|
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,
|
tsubst_exception_specification (tree fntype,
|
||||||
tree args,
|
tree args,
|
||||||
tsubst_flags_t complain,
|
tsubst_flags_t complain,
|
||||||
tree in_decl)
|
tree in_decl,
|
||||||
|
bool defer_ok)
|
||||||
{
|
{
|
||||||
tree specs;
|
tree specs;
|
||||||
tree new_specs;
|
tree new_specs;
|
||||||
|
@ -10352,8 +10353,32 @@ tsubst_exception_specification (tree fntype,
|
||||||
if (specs && TREE_PURPOSE (specs))
|
if (specs && TREE_PURPOSE (specs))
|
||||||
{
|
{
|
||||||
/* A noexcept-specifier. */
|
/* 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
|
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);
|
/*integral_constant_expression_p=*/true);
|
||||||
new_specs = build_noexcept_spec (new_specs, complain);
|
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. */
|
/* Substitute the exception specification. */
|
||||||
specs = tsubst_exception_specification (t, args, complain,
|
specs = tsubst_exception_specification (t, args, complain,
|
||||||
in_decl);
|
in_decl, /*defer_ok*/true);
|
||||||
if (specs == error_mark_node)
|
if (specs == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
if (specs)
|
if (specs)
|
||||||
|
@ -17159,7 +17184,8 @@ regenerate_decl_from_template (tree decl, tree tmpl)
|
||||||
args = get_innermost_template_args (args, parms_depth);
|
args = get_innermost_template_args (args, parms_depth);
|
||||||
|
|
||||||
specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
|
specs = tsubst_exception_specification (TREE_TYPE (code_pattern),
|
||||||
args, tf_error, NULL_TREE);
|
args, tf_error, NULL_TREE,
|
||||||
|
/*defer_ok*/false);
|
||||||
if (specs)
|
if (specs)
|
||||||
TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
|
TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl),
|
||||||
specs);
|
specs);
|
||||||
|
@ -17324,6 +17350,46 @@ always_instantiate_p (tree decl)
|
||||||
&& decl_maybe_constant_var_p (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
|
/* 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
|
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
|
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);
|
SET_DECL_IMPLICIT_INSTANTIATION (d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (TREE_CODE (d) == FUNCTION_DECL)
|
||||||
|
maybe_instantiate_noexcept (d);
|
||||||
|
|
||||||
/* Recheck the substitutions to obtain any warning messages
|
/* Recheck the substitutions to obtain any warning messages
|
||||||
about ignoring cv qualifiers. Don't do this for artificial decls,
|
about ignoring cv qualifiers. Don't do this for artificial decls,
|
||||||
as it breaks the context-sensitive substitution for lambda op(). */
|
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 (DECL_ARGUMENTS (gen), gen_args, tf_warning_or_error, d);
|
||||||
tsubst_exception_specification (type, gen_args, tf_warning_or_error,
|
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
|
/* Don't simply tsubst the function type, as that will give
|
||||||
duplicate warnings about poor parameter qualifications.
|
duplicate warnings about poor parameter qualifications.
|
||||||
The function arguments are the same as the decl_arguments
|
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);
|
indent_to (file, indent + 3);
|
||||||
fprintf (file, "index %d", ARGUMENT_PACK_SELECT_INDEX (node));
|
fprintf (file, "index %d", ARGUMENT_PACK_SELECT_INDEX (node));
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1803,8 +1803,8 @@ check_final_overrider (tree overrider, tree basefn)
|
||||||
tree base_type = TREE_TYPE (basefn);
|
tree base_type = TREE_TYPE (basefn);
|
||||||
tree over_return = TREE_TYPE (over_type);
|
tree over_return = TREE_TYPE (over_type);
|
||||||
tree base_return = TREE_TYPE (base_type);
|
tree base_return = TREE_TYPE (base_type);
|
||||||
tree over_throw = TYPE_RAISES_EXCEPTIONS (over_type);
|
tree over_throw, base_throw;
|
||||||
tree base_throw = TYPE_RAISES_EXCEPTIONS (base_type);
|
|
||||||
int fail = 0;
|
int fail = 0;
|
||||||
|
|
||||||
if (DECL_INVALID_OVERRIDER_P (overrider))
|
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. */
|
/* 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))
|
if (!comp_except_specs (base_throw, over_throw, ce_derived))
|
||||||
{
|
{
|
||||||
error ("looser throw specifier for %q+#F", overrider);
|
error ("looser throw specifier for %q+#F", overrider);
|
||||||
|
|
|
@ -2340,6 +2340,13 @@ cp_tree_equal (tree t1, tree t2)
|
||||||
/* Now compare operands as usual. */
|
/* Now compare operands as usual. */
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1769,10 +1769,15 @@ merge_exception_specifiers (tree list, tree add)
|
||||||
return list;
|
return list;
|
||||||
else if (!add || add == noexcept_false_spec)
|
else if (!add || add == noexcept_false_spec)
|
||||||
return add;
|
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).
|
/* For merging noexcept(true) and throw(), take the more recent one (LIST).
|
||||||
Any other noexcept-spec should only be merged with an equivalent one.
|
Any other noexcept-spec should only be merged with an equivalent one.
|
||||||
So the !TREE_VALUE code below is correct for all cases. */
|
So the !TREE_VALUE code below is correct for all cases. */
|
||||||
else if (!TREE_VALUE (add))
|
if (!TREE_VALUE (add))
|
||||||
return list;
|
return list;
|
||||||
else if (!TREE_VALUE (list))
|
else if (!TREE_VALUE (list))
|
||||||
return add;
|
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>
|
2011-06-08 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
PR testsuite/49323
|
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;
|
T&& declval() noexcept;
|
||||||
|
|
||||||
template< class T >
|
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();
|
x.foo();
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@ inline void f2( T& x ) noexcept( Noexcept )
|
||||||
|
|
||||||
// a common and trivial mistake
|
// a common and trivial mistake
|
||||||
template< class T >
|
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();
|
x.foo();
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ int main()
|
||||||
static_assert( noexcept( f2(y) ), "OK." );
|
static_assert( noexcept( f2(y) ), "OK." );
|
||||||
// static_assert( noexcept( f3(y) ), "shall be ill-formed(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( 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