Index: test/Parser/statements.c
===================================================================
--- test/Parser/statements.c	(revision 163060)
+++ test/Parser/statements.c	(working copy)
@@ -62,3 +62,7 @@
   // Should not skip '}' and produce a "expected '}'" error.
   undecl // expected-error {{use of undeclared identifier 'undecl'}}
 }
+
+int test9() {
+  return 4,   // expected-error {{xpected ';' at end of statement}}
+}
Index: include/clang/Basic/DiagnosticParseKinds.td
===================================================================
--- include/clang/Basic/DiagnosticParseKinds.td	(revision 163060)
+++ include/clang/Basic/DiagnosticParseKinds.td	(working copy)
@@ -151,6 +151,8 @@
 def err_expected_rbrace : Error<"expected '}'">;
 def err_expected_greater : Error<"expected '>'">;
 def err_expected_ggg : Error<"expected '>>>'">;
+def err_expected_semi_statement : Error<
+  "expected ';' at end of statement">;
 def err_expected_semi_declaration : Error<
   "expected ';' at end of declaration">;
 def err_expected_semi_decl_list : Error<
Index: include/clang/Parse/Parser.h
===================================================================
--- include/clang/Parse/Parser.h	(revision 163060)
+++ include/clang/Parse/Parser.h	(working copy)
@@ -1210,6 +1210,9 @@
                                  bool isAddressOfOperand = false,
                                  TypeCastState isTypeCast = NotTypeCast);
 
+  /// Returns true if the next token cannot start an expression.
+  bool isNotExpressionStart();
+
   /// Returns true if the next token would start a postfix-expression
   /// suffix.
   bool isPostfixExpressionSuffixStart() {
Index: lib/Parse/ParseExpr.cpp
===================================================================
--- lib/Parse/ParseExpr.cpp	(revision 163060)
+++ lib/Parse/ParseExpr.cpp	(working copy)
@@ -265,6 +265,14 @@
   return Actions.ActOnConstantExpression(Res);
 }
 
+bool Parser::isNotExpressionStart() {
+  tok::TokenKind K = Tok.getKind();
+  return (K == tok::l_brace || K == tok::r_brace  ||
+          K == tok::kw_for  || K == tok::kw_while ||
+          K == tok::kw_if   || K == tok::kw_else  ||
+          K == tok::kw_goto || K == tok::kw_try);
+}
+
 /// \brief Parse a binary expression that starts with \p LHS and has a
 /// precedence of at least \p MinPrec.
 ExprResult
@@ -349,6 +357,19 @@
       return ExprError();
     }
     
+    // Replace erroneous commas with semicolons when followed by a token
+    // indicating the start of a non-expression statement.
+    // e.g. f() { return 1, }
+    if (OpToken.is(tok::comma) && isNotExpressionStart()) {
+      Diag(OpToken.getLocation(), diag::err_expected_semi_statement)
+          << FixItHint::CreateReplacement(OpToken.getLocation(), ";");
+      PP.EnterToken(Tok);
+      Tok.setKind(tok::semi);
+      Tok.setLocation(OpToken.getLocation());
+      Tok.setLength(1);
+      return LHS;
+    }
+
     // Parse another leaf here for the RHS of the operator.
     // ParseCastExpression works here because all RHS expressions in C have it
     // as a prefix, at least. However, in C++, an assignment-expression could
