aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-06-08 17:35:02 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-06-08 17:35:02 -0400
commit1026172832d7175b52ee0ddf5ef17d7f5b803e2e (patch)
treeee6f3f833ee964ac09575df2a56cdaf0ded1d159 /gcc/cp/pt.c
parent535fb6eb200870e582a7f4abf2ea929cfc7e24c6 (diff)
downloadgcc-1026172832d7175b52ee0ddf5ef17d7f5b803e2e.zip
gcc-1026172832d7175b52ee0ddf5ef17d7f5b803e2e.tar.gz
gcc-1026172832d7175b52ee0ddf5ef17d7f5b803e2e.tar.bz2
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
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c83
1 files changed, 76 insertions, 7 deletions
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