From 11f2c78ae877382e2c25313b520aaf9b4e111be6 Mon Sep 17 00:00:00 2001 From: Patrick Palka Date: Sun, 26 Jul 2015 17:04:31 +0000 Subject: [PATCH] Fix PR c++/18969 (invalid return statement diagnosed too late) gcc/cp/ChangeLog: PR c++/18969 * typeck.c (check_return_expr): Also do the basic return-value validity checking if processing_template_decl and yet types are not dependent. Remove obsolete code. gcc/testsuite/ChangeLog: PR c++/18969 * g++.dg/template/pr18969.C: New test. * g++.dg/template/pr18969-2.C: New test. * g++.old-deja/g++.jason/overload.C: Remove return value in template function returning void. From-SVN: r226236 --- gcc/cp/ChangeLog | 7 ++++++ gcc/cp/typeck.c | 22 ++++++++++++++----- gcc/testsuite/ChangeLog | 8 +++++++ gcc/testsuite/g++.dg/template/pr18969-2.C | 11 ++++++++++ gcc/testsuite/g++.dg/template/pr18969.C | 14 ++++++++++++ .../g++.old-deja/g++.jason/overload.C | 2 +- 6 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/pr18969-2.C create mode 100644 gcc/testsuite/g++.dg/template/pr18969.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 94955195c4a..a9fa4457c68 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2015-07-26 Patrick Palka + + PR c++/18969 + * typeck.c (check_return_expr): Also do the basic return-value + validity checking if processing_template_decl and yet types are + not dependent. Remove obsolete code. + 2015-07-26 Paolo Carlini * decl.c (poplevel): Use Use DECL_SOURCE_LOCATION and "%qD" diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 86cf0866ce1..2ed43beeb0d 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -8519,12 +8519,19 @@ check_return_expr (tree retval, bool *no_warning) return NULL_TREE; } + const tree saved_retval = retval; + if (processing_template_decl) { current_function_returns_value = 1; + if (check_for_bare_parameter_packs (retval)) - retval = error_mark_node; - return retval; + return error_mark_node; + + if (WILDCARD_TYPE_P (TREE_TYPE (DECL_RESULT (current_function_decl))) + || (retval != NULL_TREE + && type_dependent_expression_p (retval))) + return retval; } functype = TREE_TYPE (TREE_TYPE (current_function_decl)); @@ -8568,14 +8575,10 @@ check_return_expr (tree retval, bool *no_warning) functype = type; } - /* When no explicit return-value is given in a function with a named - return value, the named return value is used. */ result = DECL_RESULT (current_function_decl); valtype = TREE_TYPE (result); gcc_assert (valtype != NULL_TREE); fn_returns_value_p = !VOID_TYPE_P (valtype); - if (!retval && DECL_NAME (result) && fn_returns_value_p) - retval = result; /* Check for a return statement with no return value in a function that's supposed to return a value. */ @@ -8660,6 +8663,13 @@ check_return_expr (tree retval, bool *no_warning) warning (OPT_Weffc__, "% should return a reference to %<*this%>"); } + if (processing_template_decl) + { + /* We should not have changed the return value. */ + gcc_assert (retval == saved_retval); + return retval; + } + /* The fabled Named Return Value optimization, as per [class.copy]/15: [...] For a function with a class return type, if the expression diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 3ccbf5c0c77..c711f8362d5 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2015-07-26 Patrick Palka + + PR c++/18969 + * g++.dg/template/pr18969.C: New test. + * g++.dg/template/pr18969-2.C: New test. + * g++.old-deja/g++.jason/overload.C: Remove return value in + template function returning void. + 2015-07-26 Uros Bizjak * gcc.target/alpha/pr66140.c (lpfc_bg_setup_bpl): Use unsigned diff --git a/gcc/testsuite/g++.dg/template/pr18969-2.C b/gcc/testsuite/g++.dg/template/pr18969-2.C new file mode 100644 index 00000000000..e0b0c1bf9d4 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr18969-2.C @@ -0,0 +1,11 @@ +// PR c++/18969 +// { dg-do compile { target c++14 } } + +template +struct A +{ + auto *f1 () { return; } // { dg-error "return-statement" } + auto &f2 () { return; } // { dg-error "return-statement" } + + auto f3 () { return; } // { dg-bogus "return-statement" } +}; diff --git a/gcc/testsuite/g++.dg/template/pr18969.C b/gcc/testsuite/g++.dg/template/pr18969.C new file mode 100644 index 00000000000..dba5eb92eb9 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/pr18969.C @@ -0,0 +1,14 @@ +// PR c++/18969 + +template +struct A +{ + int f1 () { return; } // { dg-error "return-statement" } + void f2 () { return 5; } // { dg-error "return-statement" } + T *f3 () { return; } // { dg-error "return-statement" } + typename T::f &f4 () { return; } // { dg-error "return-statement" } + + T f5 () { return; } // { dg-bogus "return-statement" } + void f6 () { return (T)true; } // { dg-bogus "return-statement" } + typename T::f f7 () { return; } // { dg-bogus "return-statement" } +}; diff --git a/gcc/testsuite/g++.old-deja/g++.jason/overload.C b/gcc/testsuite/g++.old-deja/g++.jason/overload.C index 6a747ff9663..28b029f48be 100644 --- a/gcc/testsuite/g++.old-deja/g++.jason/overload.C +++ b/gcc/testsuite/g++.old-deja/g++.jason/overload.C @@ -5,7 +5,7 @@ enum bar {}; void operator+ (int, int);// { dg-error "" } .* void operator+ (bar&, int); -template void operator+ (int b, T& t) { return b; } +template void operator+ (int b, T& t) { return; } void operator+ (int, bar&); template class foo -- 2.30.2