From 75a0d320063941e878f65177f59d2c0e5515472a Mon Sep 17 00:00:00 2001 From: Paolo Carlini Date: Tue, 30 Sep 2014 17:10:35 +0000 Subject: [PATCH] re PR c++/16564 (g++ seems to go into an infinite loop after errors) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit cp/ 2014-09-30 Manuel López-Ibáñez PR c++/16564 * error.c (print_instantiation_context): Delete. * typeck2.c (build_x_arrow): Record location when pushing template instantiation. * pt.c (push_tinst_level): Make it a wrapper around ... (push_tinst_level_loc): ... this. New function. Make excessive template instantiation depth a fatal error. Record location. Use bool as return type. (instantiate_pending_templates): Make excessive template instantiation depth a fatal error. (problematic_instantiation_changed): Use bool as return type. * cp-tree.h (print_instantiation_context): Delete. (push_tinst_level): Update declaration. (problematic_instantiation_changed): Likewise. (push_tinst_level_loc): New. testsuite/ 2014-09-30 Manuel López-Ibáñez PR c++/16564 * lib/gcc.exp: Accept "fatal error:" as error prefix. * lib/g++.exp: Likewise. * lib/obj-c++.exp: Likewise. * lib/objc.exp: Likewise. * g++.dg/template/pr16564.C: New test. 2014-09-30 Paolo Carlini PR c++/16564 * g++.dg/cpp0x/decltype26.C: Adjust. * g++.dg/cpp0x/decltype28.C: Likewise. * g++.dg/cpp0x/decltype29.C: Likewise. * g++.dg/cpp0x/decltype32.C: Likewise. * g++.dg/cpp0x/enum11.C: Likewise. * g++.dg/template/arrow1.C: Likewise. * g++.dg/template/pr23510.C: Likewise. * g++.dg/template/recurse.C: Likewise. * g++.dg/template/recurse2.C: Likewise. * g++.dg/template/vtable2.C: Likewise. * g++.old-deja/g++.pt/infinite1.C: Likewise. From-SVN: r215733 --- gcc/cp/ChangeLog | 18 ++++++++ gcc/cp/cp-tree.h | 6 +-- gcc/cp/error.c | 10 ----- gcc/cp/pt.c | 44 +++++++++---------- gcc/cp/typeck2.c | 7 ++- gcc/testsuite/ChangeLog | 26 ++++++++++- gcc/testsuite/g++.dg/cpp0x/decltype26.C | 4 +- gcc/testsuite/g++.dg/cpp0x/decltype28.C | 2 + gcc/testsuite/g++.dg/cpp0x/decltype29.C | 4 +- gcc/testsuite/g++.dg/cpp0x/decltype32.C | 4 +- gcc/testsuite/g++.dg/cpp0x/enum11.C | 10 ++--- gcc/testsuite/g++.dg/template/arrow1.C | 6 +-- gcc/testsuite/g++.dg/template/pr23510.C | 22 +++++----- gcc/testsuite/g++.dg/template/recurse.C | 11 ++--- gcc/testsuite/g++.dg/template/recurse2.C | 5 ++- gcc/testsuite/g++.dg/template/vtable2.C | 4 +- gcc/testsuite/g++.old-deja/g++.pt/infinite1.C | 2 +- gcc/testsuite/lib/g++.exp | 2 +- gcc/testsuite/lib/gcc.exp | 2 +- gcc/testsuite/lib/obj-c++.exp | 2 +- gcc/testsuite/lib/objc.exp | 2 +- 21 files changed, 115 insertions(+), 78 deletions(-) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 0beb9974521..3fe3f8d5775 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,21 @@ +2014-09-30 Manuel López-Ibáñez + + PR c++/16564 + * error.c (print_instantiation_context): Delete. + * typeck2.c (build_x_arrow): Record location when pushing + template instantiation. + * pt.c (push_tinst_level): Make it a wrapper around ... + (push_tinst_level_loc): ... this. New function. Make excessive + template instantiation depth a fatal error. Record location. Use + bool as return type. + (instantiate_pending_templates): Make excessive + template instantiation depth a fatal error. + (problematic_instantiation_changed): Use bool as return type. + * cp-tree.h (print_instantiation_context): Delete. + (push_tinst_level): Update declaration. + (problematic_instantiation_changed): Likewise. + (push_tinst_level_loc): New. + 2014-09-29 Richard Biener * typeck.c (enum_cast_to_int): Use CONVERT_EXPR_P to check diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 5d8badcfe75..f0783abff2d 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -5418,7 +5418,6 @@ extern const char *lang_decl_name (tree, int, bool); extern const char *lang_decl_dwarf_name (tree, int, bool); extern const char *language_to_string (enum languages); extern const char *class_key_or_enum_as_string (tree); -extern void print_instantiation_context (void); extern void maybe_warn_variadic_templates (void); extern void maybe_warn_cpp0x (cpp0x_warn_str str); extern bool pedwarn_cxx98 (location_t, int, const char *, ...) ATTRIBUTE_GCC_DIAG(3,4); @@ -5633,7 +5632,7 @@ extern tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree, bool, bool); extern tree most_general_template (tree); extern tree get_mostly_instantiated_function_type (tree); -extern int problematic_instantiation_changed (void); +extern bool problematic_instantiation_changed (void); extern void record_last_problematic_instantiation (void); extern struct tinst_level *current_instantiation(void); extern tree maybe_get_template_decl_from_type_decl (tree); @@ -5661,7 +5660,8 @@ extern tree fold_non_dependent_expr_sfinae (tree, tsubst_flags_t); extern bool alias_type_or_template_p (tree); extern bool alias_template_specialization_p (const_tree); extern bool explicit_class_specialization_p (tree); -extern int push_tinst_level (tree); +extern bool push_tinst_level (tree); +extern bool push_tinst_level_loc (tree, location_t); extern void pop_tinst_level (void); extern struct tinst_level *outermost_tinst_level(void); extern void init_template_processing (void); diff --git a/gcc/cp/error.c b/gcc/cp/error.c index a03bfe12c16..57f3c31972d 100644 --- a/gcc/cp/error.c +++ b/gcc/cp/error.c @@ -3360,16 +3360,6 @@ maybe_print_instantiation_context (diagnostic_context *context) record_last_problematic_instantiation (); print_instantiation_full_context (context); } - -/* Report the bare minimum context of a template instantiation. */ -void -print_instantiation_context (void) -{ - print_instantiation_partial_context - (global_dc, current_instantiation (), input_location); - pp_newline (global_dc->printer); - diagnostic_flush_buffer (global_dc); -} /* Report what constexpr call(s) we're trying to expand, if any. */ diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index da8bd8f30f6..9dd61f3608b 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8347,37 +8347,37 @@ static GTY(()) struct tinst_level *last_error_tinst_level; /* We're starting to instantiate D; record the template instantiation context for diagnostics and to restore it later. */ -int +bool push_tinst_level (tree d) +{ + return push_tinst_level_loc (d, input_location); +} + +/* We're starting to instantiate D; record the template instantiation context + at LOC for diagnostics and to restore it later. */ + +bool +push_tinst_level_loc (tree d, location_t loc) { struct tinst_level *new_level; if (tinst_depth >= max_tinst_depth) { - last_error_tinst_level = current_tinst_level; - if (TREE_CODE (d) == TREE_LIST) - error ("template instantiation depth exceeds maximum of %d (use " - "-ftemplate-depth= to increase the maximum) substituting %qS", - max_tinst_depth, d); - else - error ("template instantiation depth exceeds maximum of %d (use " - "-ftemplate-depth= to increase the maximum) instantiating %qD", - max_tinst_depth, d); - - print_instantiation_context (); - - return 0; + fatal_error ("template instantiation depth exceeds maximum of %d" + " (use -ftemplate-depth= to increase the maximum)", + max_tinst_depth); + return false; } /* If the current instantiation caused problems, don't let it instantiate anything else. Do allow deduction substitution and decls usable in constant expressions. */ if (limit_bad_template_recursion (d)) - return 0; + return false; new_level = ggc_alloc (); new_level->decl = d; - new_level->locus = input_location; + new_level->locus = loc; new_level->errors = errorcount+sorrycount; new_level->in_system_header_p = in_system_header_at (input_location); new_level->next = current_tinst_level; @@ -8387,7 +8387,7 @@ push_tinst_level (tree d) if (GATHER_STATISTICS && (tinst_depth > depth_reached)) depth_reached = tinst_depth; - return 1; + return true; } /* We're done instantiating this template; return to the instantiation @@ -20291,10 +20291,10 @@ instantiate_pending_templates (int retries) { tree decl = pending_templates->tinst->decl; - error ("template instantiation depth exceeds maximum of %d" - " instantiating %q+D, possibly from virtual table generation" - " (use -ftemplate-depth= to increase the maximum)", - max_tinst_depth, decl); + fatal_error ("template instantiation depth exceeds maximum of %d" + " instantiating %q+D, possibly from virtual table generation" + " (use -ftemplate-depth= to increase the maximum)", + max_tinst_depth, decl); if (TREE_CODE (decl) == FUNCTION_DECL) /* Pretend that we defined it. */ DECL_INITIAL (decl) = error_mark_node; @@ -20627,7 +20627,7 @@ get_mostly_instantiated_function_type (tree decl) /* Return truthvalue if we're processing a template different from the last one involved in diagnostics. */ -int +bool problematic_instantiation_changed (void) { return current_tinst_level != last_error_tinst_level; diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index c6306b519aa..0a851f11596 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1639,8 +1639,13 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain) if (expr == error_mark_node) return error_mark_node; + /* This provides a better instantiation backtrace in case of + error. */ if (fn && DECL_USE_TEMPLATE (fn)) - push_tinst_level (fn); + push_tinst_level_loc (fn, + (current_instantiation () != actual_inst) + ? DECL_SOURCE_LOCATION (fn) + : input_location); fn = NULL; if (vec_member (TREE_TYPE (expr), types_memoized)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6ffbbee2720..fae463c52d6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,27 @@ +2014-09-30 Manuel López-Ibáñez + + PR c++/16564 + * lib/gcc.exp: Accept "fatal error:" as error prefix. + * lib/g++.exp: Likewise. + * lib/obj-c++.exp: Likewise. + * lib/objc.exp: Likewise. + * g++.dg/template/pr16564.C: New test. + +2014-09-30 Paolo Carlini + + PR c++/16564 + * g++.dg/cpp0x/decltype26.C: Adjust. + * g++.dg/cpp0x/decltype28.C: Likewise. + * g++.dg/cpp0x/decltype29.C: Likewise. + * g++.dg/cpp0x/decltype32.C: Likewise. + * g++.dg/cpp0x/enum11.C: Likewise. + * g++.dg/template/arrow1.C: Likewise. + * g++.dg/template/pr23510.C: Likewise. + * g++.dg/template/recurse.C: Likewise. + * g++.dg/template/recurse2.C: Likewise. + * g++.dg/template/vtable2.C: Likewise. + * g++.old-deja/g++.pt/infinite1.C: Likewise. + 2014-09-30 Bernd Edlinger PR preprocessor/58893 @@ -9,7 +33,7 @@ PR middle-end/62120 * gcc.target/i386/avx512f-additional-reg-names.c: Use register valid in 32-bit mode. - * gcc.target/i386/pr62120.c: New. + * gcc.target/i386/pr62120.c: New. 2014-09-30 James Greenhalgh diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype26.C b/gcc/testsuite/g++.dg/cpp0x/decltype26.C index 0d320dadd20..58ba823aca0 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype26.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype26.C @@ -10,7 +10,7 @@ decltype(f(T())) f(T t) // { dg-error "depth" } int main() { - f(A()); // { dg-error "no match" } + f(A()); // { dg-message "from here" } } -// { dg-prune-output "note" } +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype28.C b/gcc/testsuite/g++.dg/cpp0x/decltype28.C index c1c5a1b305c..8c26fd7330d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype28.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype28.C @@ -14,3 +14,5 @@ ft (F f, typename enable_if::type) {} int main() { ft (0, 0); // { dg-message "from here" } } + +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype29.C b/gcc/testsuite/g++.dg/cpp0x/decltype29.C index d87299ccccb..51da8ddd0de 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype29.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype29.C @@ -13,7 +13,7 @@ decltype (ft (F())) // { dg-error "depth" } ft() {} int main() { - ft(); // { dg-error "no match|wrong number" } + ft(); // { dg-message "from here" } } -// { dg-prune-output "note" } +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype32.C b/gcc/testsuite/g++.dg/cpp0x/decltype32.C index 02c6316e16a..1deb964577d 100644 --- a/gcc/testsuite/g++.dg/cpp0x/decltype32.C +++ b/gcc/testsuite/g++.dg/cpp0x/decltype32.C @@ -4,10 +4,12 @@ template auto make_array(const T& il) -> -decltype(make_array(il)) // { dg-error "not declared|no matching|exceeds" } +decltype(make_array(il)) // { dg-error "not declared|no matching|depth" } { } int main() { int z = make_array(1); // { dg-error "no matching" } } + +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/cpp0x/enum11.C b/gcc/testsuite/g++.dg/cpp0x/enum11.C index a449f1c39a7..f15b6cda49b 100644 --- a/gcc/testsuite/g++.dg/cpp0x/enum11.C +++ b/gcc/testsuite/g++.dg/cpp0x/enum11.C @@ -4,12 +4,10 @@ template struct Pair { }; struct Foo { enum { Mask = 1 }; } foo; -template class Pair -operator|(const A &, const B &) // { dg-message "substitution" } +template class Pair // { dg-error "depth" } +operator|(const A &, const B &) { } -Pair f = foo|foo; // { dg-message "no match" } +Pair f = foo|foo; // { dg-message "from here" } -// { dg-prune-output "note" } -// { dg-prune-output "here" } -// { dg-prune-output "instantiation depth" } +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/template/arrow1.C b/gcc/testsuite/g++.dg/template/arrow1.C index c96141063a0..690df4c5fcc 100644 --- a/gcc/testsuite/g++.dg/template/arrow1.C +++ b/gcc/testsuite/g++.dg/template/arrow1.C @@ -9,9 +9,7 @@ struct a { }; int main() { - a<0>()->x; // { dg-error "instantiation depth exceeds maximum" } + a<0>()->x; // { dg-error "depth" } } -// { dg-prune-output "incomplete type" } -// { dg-prune-output "declaration of" } -// { dg-prune-output "used but never defined" } +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/template/pr23510.C b/gcc/testsuite/g++.dg/template/pr23510.C index 7163e30ba23..c1ffc176c5e 100644 --- a/gcc/testsuite/g++.dg/template/pr23510.C +++ b/gcc/testsuite/g++.dg/template/pr23510.C @@ -3,21 +3,21 @@ template struct Factorial { - enum { nValue = nFactor * Factorial::nValue }; // { dg-error "depth exceeds maximum" "exceeds" } - // { dg-message "recursively required" "recurse" { target *-*-* } 6 } - // { dg-error "incomplete type" "incomplete" { target *-*-* } 6 } -} // { dg-error "expected ';' after" } + enum { nValue = nFactor * Factorial::nValue }; // { dg-error "depth" } +}; - template<> - struct Factorial<0> - { - enum { nValue = 1 }; - }; +template<> +struct Factorial<0> +{ + enum { nValue = 1 }; +}; - static const unsigned int FACTOR = 20; +static const unsigned int FACTOR = 20; int main() { - Factorial::nValue; + Factorial::nValue; // { dg-message "from here" } return 0; } + +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/template/recurse.C b/gcc/testsuite/g++.dg/template/recurse.C index 94b56f67e99..fbd7def061c 100644 --- a/gcc/testsuite/g++.dg/template/recurse.C +++ b/gcc/testsuite/g++.dg/template/recurse.C @@ -5,10 +5,8 @@ template struct F { int operator()() { - F f; // { dg-error "incomplete type" "incomplete" } - // { dg-bogus "exceeds maximum.*exceeds maximum" "exceeds" { xfail *-*-* } 8 } - // { dg-error "exceeds maximum" "exceeds" { xfail *-*-* } 8 } - return f()*I; // { dg-message "recursively" "recurse" } + F f; // { dg-error "depth" } + return f()*I; } }; @@ -20,8 +18,7 @@ template <> struct F<52> int main () { F<1> f; - return f(); // { dg-message "from here" "excessive recursion" } + return f(); // { dg-message "from here" } } -// Ignore excess messages from recursion. -// { dg-prune-output "from 'int" } +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/template/recurse2.C b/gcc/testsuite/g++.dg/template/recurse2.C index eae411b5ead..0df8e5244fd 100644 --- a/gcc/testsuite/g++.dg/template/recurse2.C +++ b/gcc/testsuite/g++.dg/template/recurse2.C @@ -2,7 +2,8 @@ // We should not see an error about non-constant initialization. template struct X { - static const int value = X::value; // { dg-error "instantiation|incomplete" } - // { dg-message "recursively required" "" { target *-*-* } 5 } + static const int value = X::value; // { dg-error "depth" } }; template struct X<1000>; + +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.dg/template/vtable2.C b/gcc/testsuite/g++.dg/template/vtable2.C index 3bcc1ac3f8a..53b72f6f4e0 100644 --- a/gcc/testsuite/g++.dg/template/vtable2.C +++ b/gcc/testsuite/g++.dg/template/vtable2.C @@ -11,8 +11,10 @@ template struct inner {}; template struct parent { - virtual void f() // { dg-error "instantiation depth" } + virtual void f() // { dg-error "depth" } { parent > p; }; }; template struct parent; + +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C b/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C index 1e2a9f0fbdd..a5873b09ef5 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/infinite1.C @@ -20,4 +20,4 @@ int main() f<0>(); } -// { dg-prune-output "note" } +// { dg-prune-output "compilation terminated" } diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp index 6658c58cc2c..bad36c4222b 100644 --- a/gcc/testsuite/lib/g++.exp +++ b/gcc/testsuite/lib/g++.exp @@ -267,7 +267,7 @@ proc g++_init { args } { lappend ALWAYS_CXXFLAGS "additional_flags=-fmessage-length=0" set gcc_warning_prefix "warning:" - set gcc_error_prefix "error:" + set gcc_error_prefix "(fatal )?error:" if { [istarget *-*-darwin*] } { lappend ALWAYS_CXXFLAGS "ldflags=-multiply_defined suppress" diff --git a/gcc/testsuite/lib/gcc.exp b/gcc/testsuite/lib/gcc.exp index f9370646ca4..3507c8a18f3 100644 --- a/gcc/testsuite/lib/gcc.exp +++ b/gcc/testsuite/lib/gcc.exp @@ -111,7 +111,7 @@ proc gcc_init { args } { } set gcc_warning_prefix "warning:" - set gcc_error_prefix "error:" + set gcc_error_prefix "(fatal )?error:" gcc_maybe_build_wrapper "${tmpdir}/gcc-testglue.o" } diff --git a/gcc/testsuite/lib/obj-c++.exp b/gcc/testsuite/lib/obj-c++.exp index 93c7ff6b198..92a09feeb8b 100644 --- a/gcc/testsuite/lib/obj-c++.exp +++ b/gcc/testsuite/lib/obj-c++.exp @@ -275,7 +275,7 @@ proc obj-c++_init { args } { lappend ALWAYS_OBJCXXFLAGS "additional_flags=-fmessage-length=0" set gcc_warning_prefix "warning:" - set gcc_error_prefix "error:" + set gcc_error_prefix "(fatal )?error:" if { [istarget *-*-darwin*] } { lappend ALWAYS_OBJCXXFLAGS "ldflags=-multiply_defined suppress" diff --git a/gcc/testsuite/lib/objc.exp b/gcc/testsuite/lib/objc.exp index e19b2643863..c0b4da7360c 100644 --- a/gcc/testsuite/lib/objc.exp +++ b/gcc/testsuite/lib/objc.exp @@ -124,7 +124,7 @@ proc objc_init { args } { } set gcc_warning_prefix "warning:" - set gcc_error_prefix "error:" + set gcc_error_prefix "(fatal )?error:" objc_maybe_build_wrapper "${tmpdir}/objc-testglue.o"