This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

cpplib: accept C++ comments and #endif labels in system headers


This patch causes cpplib to accept C++ comments and #endif labels in
system headers even in -pedantic mode.  It also corrects -std=gnu89 mode
such that C++ comments are treated as comments, but get pedantic
warnings (only one per file).  In -std=c89 and -traditional modes they
are not recognized at all, and in C++ and -std=c9x modes they are not
extensions.

Also added are a trio of test cases, which will fail with cccp.  It is
practical to make cccp do the same for #endif labels, but not C++
comments, and given the (so far) consensus that cccp can be retired,
I'm not inclined to bother patching it at all.

The complementary patch for fixincludes will wait till after cpplib is
on by default.

zw

	* cppinit.c (cpp_handle_option): Recognize C++ comments under
	-std=gnu89.
	* cpplib.c (skip_block_comment, skip_line_comment): Split code
	out of...
	(skip_comment) ... here.  Permit C++ comments in system
	headers always.  Warn about C++ comments in user code under
	-std=gnu89 -pedantic.
	(copy_comment): Use skip_comment.
	(cpp_skip_hspace, cpp_get_token): skip_comment can no longer
	return EOF.
	(consider_directive_while_skipping, do_else, do_endif): Call
	validate_else unconditionally.
	(validate_else): Check CPP_PEDANTIC here.  Accept non-comment
	text after the conditional in a system header.
	* cpplib.h (struct cpp_buffer): Add flag
	warned_cplusplus_comments.

===================================================================
Index: cppinit.c
--- cppinit.c	2000/01/27 18:37:50	1.31
+++ cppinit.c	2000/01/27 22:20:34
@@ -1345,7 +1345,7 @@ cpp_handle_option (pfile, argc, argv)
       case 's':
 	if (!strcmp (argv[i], "-std=gnu89"))
 	  {
-	    opts->cplusplus = 0, opts->cplusplus_comments = 0;
+	    opts->cplusplus = 0, opts->cplusplus_comments = 1;
 	    opts->c89 = 1, opts->c9x = 0, opts->objc = 0;
 	  }
 	else if (!strcmp (argv[i], "-std=gnu9x"))
===================================================================
Index: cpplib.c
--- cpplib.c	2000/01/19 23:47:13	1.99
+++ cpplib.c	2000/01/27 22:20:35
@@ -255,11 +255,70 @@ null_cleanup (pbuf, pfile)
   return 0;
 }
 
+/* Skip a C-style block comment.  We know it's a comment, and point is
+   at the second character of the starter.  */
+static void
+skip_block_comment (pfile)
+     cpp_reader *pfile;
+{
+  int c, prev_c = -1;
+  long line, col;
+
+  FORWARD(1);
+  cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
+  for (;;)
+    {
+      c = GETC ();
+      if (c == EOF)
+	{
+	  cpp_error_with_line (pfile, line, col, "unterminated comment");
+	  return;
+	}
+      else if (c == '\n' || c == '\r')
+	/* \r cannot be a macro escape marker here. */
+	CPP_BUMP_LINE (pfile);
+      else if (c == '/' && prev_c == '*')
+	return;
+      else if (c == '*' && prev_c == '/'
+	       && CPP_OPTIONS (pfile)->warn_comments)
+	cpp_warning (pfile, "`/*' within comment");
+
+      prev_c = c;
+    }
+}
+
+/* Skip a C++/Chill line comment.  We know it's a comment, and point
+   is at the second character of the initiator.  */
+static void
+skip_line_comment (pfile)
+     cpp_reader *pfile;
+{
+  FORWARD(1);
+  for (;;)
+    {
+      int c = GETC ();
+
+      /* We don't have to worry about EOF in here.  */
+      if (c == '\n')
+	{
+	  /* Don't consider final '\n' to be part of comment.  */
+	  FORWARD(-1);
+	  return;
+	}
+      else if (c == '\r')
+	{
+	  /* \r cannot be a macro escape marker here. */
+	  CPP_BUMP_LINE (pfile);
+	  if (CPP_OPTIONS (pfile)->warn_comments)
+	    cpp_warning (pfile, "backslash-newline within line comment");
+	}
+    }
+}
+
 /* Skip a comment - C, C++, or Chill style.  M is the first character
    of the comment marker.  If this really is a comment, skip to its
-   end and return ' '.  If we hit end-of-file before end-of-comment,
-   return EOF.  If this is not a comment, return M (which will be
-   '/' or '-').  */
+   end and return ' '.  If this is not a comment, return M (which will
+   be '/' or '-').  */
 
 static int
 skip_comment (pfile, m)
@@ -268,53 +327,43 @@ skip_comment (pfile, m)
 {
   if (m == '/' && PEEKC() == '*')
     {
-      int c, prev_c = -1;
-      long line, col;
-      
-      FORWARD(1);
-      cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
-      for (;;)
+      skip_block_comment (pfile);
+      return ' ';
+    }
+  else if (m == '/' && PEEKC() == '/')
+    {
+      if (CPP_BUFFER (pfile)->system_header_p)
 	{
-	  c = GETC ();
-	  if (c == EOF)
+	  /* We silently allow C++ comments in system headers, irrespective
+	     of conformance mode, because lots of busted systems do that
+	     and trying to clean it up in fixincludes is a nightmare.  */
+	  skip_line_comment (pfile);
+	  return ' ';
+	}
+      else if (CPP_OPTIONS (pfile)->cplusplus_comments)
+	{
+	  if (CPP_OPTIONS (pfile)->c89
+	      && CPP_PEDANTIC (pfile)
+	      && ! CPP_BUFFER (pfile)->warned_cplusplus_comments)
 	    {
-	      cpp_error_with_line (pfile, line, col, "unterminated comment");
-	      return EOF;
+	      cpp_pedwarn (pfile,
+			   "C++ style comments are not allowed in ISO C89");
+	      cpp_pedwarn (pfile,
+			   "(this will be reported only once per input file)");
+	      CPP_BUFFER (pfile)->warned_cplusplus_comments = 1;
 	    }
-	  else if (c == '\n' || c == '\r')
-	    /* \r cannot be a macro escape marker here. */
-	    CPP_BUMP_LINE (pfile);
-	  else if (c == '/' && prev_c == '*')
-	    return ' ';
-	  else if (c == '*' && prev_c == '/'
-		   && CPP_OPTIONS (pfile)->warn_comments)
-	    cpp_warning (pfile, "`/*' within comment");
-
-	  prev_c = c;
-	}
-    }
-  else if ((m == '/' && PEEKC() == '/'
-	    && CPP_OPTIONS (pfile)->cplusplus_comments)
-	   || (m == '-' && PEEKC() == '-'
-	       && CPP_OPTIONS (pfile)->chill))
-    {
-      FORWARD(1);
-      for (;;)
-	{
-	  int c = GETC ();
-	  if (c == EOF)
-	    return ' '; /* Allow // to be terminated by EOF.  */
-	      if (c == '\n')
-		{
-		  /* Don't consider final '\n' to be part of comment.  */
-		  FORWARD(-1);
-		  return ' ';
-		}
-	      else if (c == '\r')
-		/* \r cannot be a macro escape marker here. */
-		CPP_BUMP_LINE (pfile);
+	  skip_line_comment (pfile);
+	  return ' ';
 	}
+      else
+	return m;
     }
+  else if (m == '-' && PEEKC() == '-'
+	   && CPP_OPTIONS (pfile)->chill)
+    {
+      skip_line_comment (pfile);
+      return ' ';
+    }
   else
     return m;
 }
@@ -326,77 +375,18 @@ copy_comment (pfile, m)
      cpp_reader *pfile;
      int m;
 {
-  if (m == '/' && PEEKC() == '*')
-    {
-      int c, prev_c = -1;
-      long line, col;
+  U_CHAR *start = CPP_BUFFER (pfile)->cur;  /* XXX Layering violation */
+  U_CHAR *limit;
 
-      CPP_PUTC (pfile, '/');
-      CPP_PUTC (pfile, '*');
-      FORWARD(1);
-      cpp_buf_line_and_col (CPP_BUFFER (pfile), &line, &col);
-      for (;;)
-	{
-	  c = GETC ();
-	  if (c == EOF)
-	    {
-	      cpp_error_with_line (pfile, line, col, "unterminated comment");
-	      /* We must pretend this was a legitimate comment, so that the
-		 output in token_buffer is not passed back tagged CPP_POP. */
-	      return ' ';
-	    }
-	  else if (c == '\r')
-	    {
-	      /* \r cannot be a macro escape marker here. */
-	      CPP_BUMP_LINE (pfile);
-	      continue;
-	    }
-
-	  CPP_PUTC (pfile, c);
-	  if (c == '\n')
-	    {
-	      pfile->lineno++;
-	      CPP_BUMP_LINE (pfile);
-	    }
-	  else if (c == '/' && prev_c == '*')
-	    return ' ';
-	  else if (c == '*' && prev_c == '/'
-		   && CPP_OPTIONS (pfile)->warn_comments)
-	    cpp_warning (pfile, "`/*' within comment");
-
-	  prev_c = c;
-	}
-    }
-  else if ((m == '/' && PEEKC() == '/'
-	    && CPP_OPTIONS (pfile)->cplusplus_comments)
-	   || (m == '-' && PEEKC() == '-'
-	       && CPP_OPTIONS (pfile)->chill))
-    {
-      CPP_PUTC (pfile, m);
-      CPP_PUTC (pfile, m);
-      FORWARD(1);
-      for (;;)
-	{
-	  int c = GETC ();
-	  if (c == EOF)
-	    return ' '; /* Allow line comments to be terminated by EOF. */
-	  else if (c == '\n')
-	    {
-	      /* Don't consider final '\n' to be part of comment.  */
-	      FORWARD(-1);
-	      return ' ';
-	    }
-	  else if (c == '\r')
-	    /* \r cannot be a macro escape marker here. */
-	    CPP_BUMP_LINE (pfile);
-
-	  CPP_PUTC (pfile, c);
-	}
-    }
-  else
+  if (skip_comment (pfile, m) == m)
     return m;
-}
 
+  CPP_PUTC (pfile, m);
+  for (limit = CPP_BUFFER (pfile)->cur; start <= limit; start++)
+    if (*start != '\r')
+      CPP_PUTC (pfile, *start);
+  return ' ';
+}
 
 /* Skip whitespace \-newline and comments.  Does not macro-expand.  */
 
@@ -433,9 +423,7 @@ cpp_skip_hspace (pfile)
       else if (c == '/' || c == '-')
 	{
 	  c = skip_comment (pfile, c);
-	  if (c == EOF)
-	    return;
-	  else if (c != ' ')
+	  if (c  != ' ')
 	    break;
 	}
       else
@@ -2008,7 +1996,7 @@ consider_directive_while_skipping (pfile
 	    return 0;
 
 	case T_ELSE:
-	    if (CPP_PEDANTIC (pfile) && pfile->if_stack != stack)
+	    if (pfile->if_stack != stack)
 	      validate_else (pfile, "#else");
 	    /* fall through */
 	case T_ELIF:
@@ -2024,7 +2012,7 @@ consider_directive_while_skipping (pfile
 	      }
 
 	    case T_ENDIF:
-		if (CPP_PEDANTIC (pfile) && pfile->if_stack != stack)
+		if (pfile->if_stack != stack)
 		  validate_else (pfile, "#endif");
 
 		if (pfile->if_stack == stack)
@@ -2140,8 +2128,7 @@ do_else (pfile, keyword)
 {
   cpp_buffer *ip = CPP_BUFFER (pfile);
 
-  if (CPP_PEDANTIC (pfile))
-    validate_else (pfile, "#else");
+  validate_else (pfile, "#else");
   skip_rest_of_line (pfile);
 
   if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack) {
@@ -2180,8 +2167,7 @@ do_endif (pfile, keyword)
      cpp_reader *pfile;
      const struct directive *keyword ATTRIBUTE_UNUSED;
 {
-  if (CPP_PEDANTIC (pfile))
-    validate_else (pfile, "#endif");
+  validate_else (pfile, "#endif");
   skip_rest_of_line (pfile);
 
   if (pfile->if_stack == CPP_BUFFER (pfile)->if_stack)
@@ -2226,19 +2212,20 @@ do_endif (pfile, keyword)
   return 0;
 }
 
-/* When an #else or #endif is found while skipping failed conditional,
-   if -pedantic was specified, this is called to warn about text after
-   the command name.  P points to the first char after the command name.  */
+/* Issue -pedantic warning for text which is not a comment following
+   an #else or #endif.  Do not warn in system headers, as this is harmless
+   and very common on old systems.  */
 
 static void
 validate_else (pfile, directive)
      cpp_reader *pfile;
      const char *directive;
 {
-  int c;
+  if (! CPP_PEDANTIC (pfile) || CPP_BUFFER (pfile)->system_header_p)
+    return;
+
   cpp_skip_hspace (pfile);
-  c = PEEKC ();
-  if (c != EOF && c != '\n')
+  if (PEEKC () != '\n')
     cpp_pedwarn (pfile,
 		 "text following `%s' violates ANSI standard", directive);
 }
@@ -2277,7 +2264,6 @@ cpp_get_token (pfile)
   c = GETC();
   if (c == EOF)
     {
-    handle_eof:
       if (CPP_BUFFER (pfile)->manual_pop)
 	/* If we've been reading from redirected input, the
 	   frontend will pop the buffer.  */
@@ -2339,9 +2325,7 @@ cpp_get_token (pfile)
 	    c = copy_comment (pfile, c);
 	  else
 	    c = skip_comment (pfile, c);
-	  if (c == EOF)
-	    goto handle_eof;
-	  else if (c != ' ')
+	  if (c != ' ')
 	    goto randomchar;
 	  
 	  /* Comments are equivalent to spaces.
===================================================================
Index: cpplib.h
--- cpplib.h	2000/01/19 23:47:13	1.47
+++ cpplib.h	2000/01/27 22:20:36
@@ -140,6 +140,11 @@ struct cpp_buffer
   /* Used by the C++ frontend to implement redirected input (such as for
      default argument and/or template parsing).  */
   char manual_pop;
+
+  /* True if we have already warned about C++ comments in this file.
+     The warning happens only for C89 extended mode with -pedantic on,
+     and only once per file (otherwise it would be far too noisy).  */
+  char warned_cplusplus_comments;
 };
 
 struct file_name_map_list;
===================================================================
Index: testsuite/gcc.dg/cxx-comments-1.c
--- testsuite/gcc.dg/cxx-comments-1.c	Tue May  5 13:32:27 1998
+++ testsuite/gcc.dg/cxx-comments-1.c	Thu Jan 27 14:20:37 2000
@@ -0,0 +1,20 @@
+/* { dg-do preprocess } */
+/* { dg-options "-pedantic -std=gnu89" } */
+
+/* You can't do this in your own code... */
+// C++ comment is not in C89  { dg-warning "style comment|reported only once" "good warning" }
+
+/* ...but we don't bitch about it more than once.  */
+// C++ comment is not in C89  { dg-bogus "style comment" "bad warning" }
+
+/*
+   { dg-final { if ![file exists cxx-comments-1.i] { return }		} }
+   { dg-final { set tmp [grep cxx-comments-1.i "is not in C89" line]	} }
+   { dg-final { # send_user "$tmp\n"					} }
+   { dg-final { if [regexp "is not in C89" $tmp] \{			} }
+   { dg-final {     fail "cxx-comments-1: comment strip check"		} }
+   { dg-final { \} else \{						} }
+   { dg-final {     pass "cxx-comments-1: comment strip check"		} }
+   { dg-final { \}							} }
+*/
+
===================================================================
Index: testsuite/gcc.dg/cxx-comments-2.c
--- testsuite/gcc.dg/cxx-comments-2.c	Tue May  5 13:32:27 1998
+++ testsuite/gcc.dg/cxx-comments-2.c	Thu Jan 27 14:20:37 2000
@@ -0,0 +1,20 @@
+/* { dg-do preprocess } */
+/* { dg-options "-pedantic -std=c89" } */
+
+/* This is an extension and therefore gets a warning.  */
+#line 5 "cxx-comments-2.c" 3  /* { dg-warning "garbage at end" "#line extension" } */
+
+/* A system header may contain C++ comments irrespective of mode.  */
+// C++ comment is not in C89  { dg-bogus "style comment" "bad warning" }
+
+/*
+   { dg-final { if ![file exists cxx-comments-2.i] { return }		} }
+   { dg-final { set tmp [grep cxx-comments-2.i "is not in C89" line]	} }
+   { dg-final { # send_user "$tmp\n"					} }
+   { dg-final { if [regexp "is not in C89" $tmp] \{			} }
+   { dg-final {     fail "cxx-comments-2: comment strip check"		} }
+   { dg-final { \} else \{						} }
+   { dg-final {     pass "cxx-comments-2: comment strip check"		} }
+   { dg-final { \}							} }
+*/
+
===================================================================
Index: testsuite/gcc.dg/endif-label.c
--- testsuite/gcc.dg/endif-label.c	Tue May  5 13:32:27 1998
+++ testsuite/gcc.dg/endif-label.c	Thu Jan 27 14:20:37 2000
@@ -0,0 +1,15 @@
+/* { dg-do preprocess } */
+/* { dg-options "-pedantic -Wall" } */
+
+/* You can't get away with this in your own code... */
+#ifdef KERNEL
+#define foo
+#endif KERNEL  /* { dg-warning "text following" "good warning" } */
+
+/* This will provoke a warning because the '3' is an extension.  */
+#line 10 "endif-label.c" 3 /* { dg-warning "garbage at end" "#line extension" } */
+
+/* ... but in a system header, it's acceptable.  */
+#ifdef KERNEL
+#define foo
+#endif KERNEL  /* { dg-bogus "text following" "bad warning" } */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]