diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index afe489f1325c3542476bdf8fc6d0a811989adc91..5f635ca21b918c6d0d13dac5bb93c2bbba728cba 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2004-07-04  Neil Booth  <neil@duron.akihabara.co.uk>
+
+	* doc/cpp.texi: Don't document what we do for ill-formed expressions.
+	* doc/cppopts.texi: Clarify processing of command-line defines.
+
 2004-07-04  Gerald Pfeifer  <gerald@pfeifer.com>
 
 	* doc/contrib.texi (Contributors): Adjust link for GNU Classpath.
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 62151645c688879d88dd0ec9f422a5d0cc9a92f0..631992d517309e9fd80ff3578b4b2e090c44baaa 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -2965,9 +2965,6 @@ expression, and may give different results in some cases.  If the value
 comes out to be nonzero, the @samp{#if} succeeds and the @var{controlled
 text} is included; otherwise it is skipped.
 
-If @var{expression} is not correctly formed, GCC issues an error and
-treats the conditional as having failed.
-
 @node Defined
 @subsection Defined
 
diff --git a/gcc/doc/cppopts.texi b/gcc/doc/cppopts.texi
index 1b6307b2215d526db24390b60e3ab930f9ad2a04..a6b7eb44fbb4ac01ccad1a79dba1f1decb615219 100644
--- a/gcc/doc/cppopts.texi
+++ b/gcc/doc/cppopts.texi
@@ -16,11 +16,14 @@
 Predefine @var{name} as a macro, with definition @code{1}.
 
 @item -D @var{name}=@var{definition}
-Predefine @var{name} as a macro, with definition @var{definition}.
-There are no restrictions on the contents of @var{definition}, but if
-you are invoking the preprocessor from a shell or shell-like program you
-may need to use the shell's quoting syntax to protect characters such as
-spaces that have a meaning in the shell syntax.
+The contents of @var{definition} are tokenized and processed as if
+they appeared during translation phase three in a @samp{#define}
+directive.  In particular, the definition will be truncated by
+embedded newline characters.
+
+If you are invoking the preprocessor from a shell or shell-like
+program you may need to use the shell's quoting syntax to protect
+characters such as spaces that have a meaning in the shell syntax.
 
 If you wish to define a function-like macro on the command line, write
 its argument list with surrounding parentheses before the equals sign
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 1ca7e1a0a1f73d2d5de26efc757d497bd5a03f0e..9f03b45a6c16557318ca0b43f25cffd6eec9b574 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2004-07-04  Neil Booth  <neil@duron.akihabara.co.uk>
+
+	* gcc.dg/cpp/if-mop.c: Two new testcases.
+	* gcc.dg/cpp/trad/comment-3.c: New.
+
 2004-07-04  Paul Brook  <paul@codesourcery.com>
 
 	* gfortran.fortran-torture/compile/implicit_1.f90: New test.
diff --git a/gcc/testsuite/gcc.dg/cpp/if-mop.c b/gcc/testsuite/gcc.dg/cpp/if-mop.c
index 9202740e6b1246992ecbfa743bc8e5cdb2ca3c6a..119c7392e06caa5cf14e23442f259ec9ef405599 100644
--- a/gcc/testsuite/gcc.dg/cpp/if-mop.c
+++ b/gcc/testsuite/gcc.dg/cpp/if-mop.c
@@ -23,3 +23,9 @@
 
 #if (2) 4 * 2  /* { dg-error "missing bin" "close paren then immediate" } */
 #endif
+
+#if == 2  /* { dg-error "no left op" } */
+#endif
+
+#if (==2)  /* { dg-error "no left op" } */
+#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/trad/comment-3.c b/gcc/testsuite/gcc.dg/cpp/trad/comment-3.c
new file mode 100644
index 0000000000000000000000000000000000000000..e2710ad56297da70c3670d1cb24b2853b00eded7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cpp/trad/comment-3.c
@@ -0,0 +1,6 @@
+/* Test we don't accept C++ comments.  */
+
+/* { dg-do preprocess } */
+
+#if 0
+#endif //  /* { dg-warning "extra tokens" } */
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index 01cb5653f92b87226cdf1b11b19ba1ce64e22f85..2cdd78445b88340cf64ce9d3b4a1ac0644592932 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,12 @@
+2004-07-04  Neil Booth  <neil@duron.akihabara.co.uk>
+
+	PR preprocessor/16192
+	PR preprocessor/15913
+	PR preprocessor/15572
+	* expr.c (_cpp_parse_expr): Handle remaining cases where an
+	expression is missing.
+	* init.c (post_options): Traditional cpp doesn't do // comments.
+
 2004-06-30  Per Bothner  <per@bothner.com>
 
 	* include/line-map.h (fileline):  Remove old typedef.
diff --git a/libcpp/expr.c b/libcpp/expr.c
index f49bd082858edce6b8e3edc43c2fdc6737ec22a8..47689189b2b632379e24bf31c7aacb1a79f8b004 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -747,18 +747,22 @@ _cpp_parse_expr (cpp_reader *pfile)
 	}
       else if (want_value)
 	{
-	  /* Ordering here is subtle and intended to favor the
-	     missing parenthesis diagnostics over alternatives.  */
-	  if (op.op == CPP_CLOSE_PAREN)
-	    {
-	      if (top->op == CPP_OPEN_PAREN)
-		SYNTAX_ERROR ("void expression between '(' and ')'");
-	    }
-	  else if (top->op == CPP_EOF)
-	    SYNTAX_ERROR ("#if with no expression");
-	  if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
-	    SYNTAX_ERROR2 ("operator '%s' has no right operand",
-			   cpp_token_as_text (pfile, top->token));
+	  /* We want a number (or expression) and haven't got one.
+	     Try to emit a specific diagnostic.  */
+	  if (op.op == CPP_CLOSE_PAREN && top->op == CPP_OPEN_PAREN)
+	    SYNTAX_ERROR ("missing expression between '(' and ')'");
+
+	  if (op.op == CPP_EOF && top->op == CPP_EOF)
+ 	    SYNTAX_ERROR ("#if with no expression");
+
+ 	  if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
+ 	    SYNTAX_ERROR2 ("operator '%s' has no right operand",
+ 			   cpp_token_as_text (pfile, top->token));
+	  else if (op.op == CPP_CLOSE_PAREN || op.op == CPP_EOF)
+	    /* Complain about missing paren during reduction.  */;
+	  else
+	    SYNTAX_ERROR2 ("operator '%s' has no left operand",
+			   cpp_token_as_text (pfile, op.token));
 	}
 
       top = reduce (pfile, top, op.op);
diff --git a/libcpp/init.c b/libcpp/init.c
index 65cca9b2bab57d4a8987b107d4dc01e5c5d1b6ef..d1cc1e65d0fff2c100b57827767f7edaa9dbc0ea 100644
--- a/libcpp/init.c
+++ b/libcpp/init.c
@@ -611,6 +611,8 @@ post_options (cpp_reader *pfile)
 
   if (CPP_OPTION (pfile, traditional))
     {
+      CPP_OPTION (pfile, cplusplus_comments) = 0;
+
       /* Traditional CPP does not accurately track column information.  */
       CPP_OPTION (pfile, show_column) = 0;
       CPP_OPTION (pfile, trigraphs) = 0;