Fix PR c++/18969 (invalid return statement diagnosed too late)
authorPatrick Palka <ppalka@gcc.gnu.org>
Sun, 26 Jul 2015 17:04:31 +0000 (17:04 +0000)
committerPatrick Palka <ppalka@gcc.gnu.org>
Sun, 26 Jul 2015 17:04:31 +0000 (17:04 +0000)
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
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/pr18969-2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/pr18969.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.jason/overload.C

index 94955195c4ac1263477b07034efba3b69d9f6cce..a9fa4457c6823050b03dafe020c08bbfc73eceb9 100644 (file)
@@ -1,3 +1,10 @@
+2015-07-26  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       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  <paolo.carlini@oracle.com>
 
        * decl.c (poplevel): Use Use DECL_SOURCE_LOCATION and "%qD"
index 86cf0866ce138a5df1fe84b41081c8de8ee25af6..2ed43beeb0d1edc1a5885559838f545d2218779a 100644 (file)
@@ -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__, "%<operator=%> 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
index 3ccbf5c0c7773142afc08989a250199883371f8f..c711f8362d5c9d4c7f2b7d1a11a4c82a17d49ace 100644 (file)
@@ -1,3 +1,11 @@
+2015-07-26  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       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  <ubizjak@gmail.com>
 
        * 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 (file)
index 0000000..e0b0c1b
--- /dev/null
@@ -0,0 +1,11 @@
+// PR c++/18969
+// { dg-do compile { target c++14 } }
+
+template <typename T>
+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 (file)
index 0000000..dba5eb9
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/18969
+
+template <typename T>
+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" }
+};
index 6a747ff96631c3d9dfa01e2bed7a1474b3c3a979..28b029f48be87f42afb3dbc048a3770e69f54757 100644 (file)
@@ -5,7 +5,7 @@ enum bar {};
 void operator+ (int, int);// { dg-error "" } .*
 void operator+ (bar&, int);
 
-template <class T> void operator+ (int b, T& t) { return b; }
+template <class T> void operator+ (int b, T& t) { return; }
 void operator+ (int, bar&);
 
 template <class T> class foo