cpplib: Fix PR 1011. Tighten up #line flags.

Neil Booth neil@daikokuya.demon.co.uk
Sat Dec 9 03:53:00 GMT 2000


Fixed PR 1011, and only restricts the flags on #NUMBER lines to the
valid possibilities.  Test cases for both.

Neil.

	* cppfiles.c (NEVER_REREAD, DO_NOT_REREAD): Move from cpphash.h.
	* cpphash.h (NEVER_REREAD, DO_NOT_REREAD, ABSOLUTE_PATH): Delete.
	* cpplex.c (parse_identifier): Improve diagnostic.
	(_cpp_lex_token): Return unconditionally at the end of a directive.
	* cpplib.c (read_flag): Verify legality of each flag.
	(end_directive): Resotre pfile->skipping before skip_rest_of_line.
	(do_line): Use the new read_flag.
	* cppmacro.c (struct cpp_macro, parse_arg, replace_args,
	check_macro_redefinition, parse_params): Rename var_args to
	variadic.

	* gcc.dg/cpp/lineflags.c: New tests.
	* gcc.dg/cpp/poison.c: Update.
	* gcc.dg/cpp/redef2.c: Update.
	* gcc.dg/cpp/skipping.c: New test.

Index: cppfiles.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppfiles.c,v
retrieving revision 1.90
diff -u -p -r1.90 cppfiles.c
--- cppfiles.c	2000/12/07 23:17:56	1.90
+++ cppfiles.c	2000/12/09 11:34:54
@@ -80,6 +80,16 @@ struct include_file
   unsigned char defined;	/* cmacro prevents inclusion in this state */
 };
 
+/* The cmacro works like this: If it's NULL, the file is to be
+   included again.  If it's NEVER_REREAD, the file is never to be
+   included again.  Otherwise it is a macro hashnode, and the file is
+   to be included again if the macro is defined or not as specified by
+   DEFINED.  */
+#define NEVER_REREAD ((const cpp_hashnode *)-1)
+#define DO_NOT_REREAD(inc) \
+((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
+		   || ((inc)->cmacro->type == NT_MACRO) == (inc)->defined))
+
 static struct file_name_map *read_name_map
 				PARAMS ((cpp_reader *, const char *));
 static char *read_filename_string PARAMS ((int, FILE *));
Index: cpphash.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpphash.h,v
retrieving revision 1.86
diff -u -p -r1.86 cpphash.h
--- cpphash.h	2000/12/08 03:00:23	1.86
+++ cpphash.h	2000/12/09 11:35:00
@@ -68,18 +68,7 @@ struct file_name_list
      Only used on MS-DOS and related platforms. */
   struct file_name_map *name_map;
 };
-#define ABSOLUTE_PATH ((struct file_name_list *)-1)
 
-/* The cmacro works like this: If it's NULL, the file is to be
-   included again.  If it's NEVER_REREAD, the file is never to be
-   included again.  Otherwise it is a macro hashnode, and the file is
-   to be included again if the macro is defined or not as specified by
-   DEFINED.  */
-#define NEVER_REREAD ((const cpp_hashnode *)-1)
-#define DO_NOT_REREAD(inc) \
-((inc)->cmacro && ((inc)->cmacro == NEVER_REREAD \
-		   || ((inc)->cmacro->type == NT_MACRO) == (inc)->defined))
-
 struct cpp_buffer
 {
   const unsigned char *cur;	 /* current position */
@@ -168,10 +157,8 @@ extern unsigned char _cpp_trigraph_map[U
 #define CPP_PRINT_DEPS(PFILE) CPP_OPTION (PFILE, print_deps)
 #define CPP_IN_SYSTEM_HEADER(PFILE) \
   (CPP_BUFFER (PFILE) && CPP_BUFFER (PFILE)->sysp)
-#define CPP_PEDANTIC(PF) \
-  CPP_OPTION (PF, pedantic)
-#define CPP_WTRADITIONAL(PF) \
-  CPP_OPTION (PF, warn_traditional)
+#define CPP_PEDANTIC(PF) CPP_OPTION (PF, pedantic)
+#define CPP_WTRADITIONAL(PF) CPP_OPTION (PF, warn_traditional)
 
 /* Hash step.  The hash calculation is duplicated in cpp_lookup and
    parse_name.  */
Index: cpplex.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplex.c,v
retrieving revision 1.123
diff -u -p -r1.123 cpplex.c
--- cpplex.c	2000/12/06 20:12:59	1.123
+++ cpplex.c	2000/12/09 11:35:07
@@ -521,10 +521,10 @@ parse_identifier (pfile, c)
 	cpp_error (pfile, "attempt to use poisoned \"%s\"", result->name);
 
       /* Constraint 6.10.3.5: __VA_ARGS__ should only appear in the
-	 replacement list of a variable-arguments macro.  */
+	 replacement list of a variadic macro.  */
       if (result == pfile->spec_nodes.n__VA_ARGS__
 	  && !pfile->state.va_args_ok)
-	cpp_pedwarn (pfile, "__VA_ARGS__ can only appear in the expansion of a C99 variable-argument macro");
+	cpp_pedwarn (pfile, "__VA_ARGS__ can only appear in the expansion of a C99 variadic macro");
     }
 
   return result;
@@ -907,7 +907,8 @@ _cpp_lex_token (pfile, result)
       buffer->read_ahead = c;
       pfile->state.next_bol = 1;
       result->type = CPP_EOF;
-      break;
+      /* Don't break; pfile->skipping might be true.  */
+      return;
 
     case '?':
     case '\\':
Index: cpplib.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cpplib.c,v
retrieving revision 1.229
diff -u -p -r1.229 cpplib.c
--- cpplib.c	2000/12/07 23:17:55	1.229
+++ cpplib.c	2000/12/09 11:35:07
@@ -90,7 +90,7 @@ static int glue_header_name	PARAMS ((cpp
 static int  parse_include	PARAMS ((cpp_reader *, cpp_token *));
 static void push_conditional	PARAMS ((cpp_reader *, int, int,
 					 const cpp_hashnode *));
-static unsigned int read_flag	PARAMS ((cpp_reader *));
+static unsigned int read_flag	PARAMS ((cpp_reader *, unsigned int));
 static int  strtoul_for_line	PARAMS ((const U_CHAR *, unsigned int,
 					 unsigned long *));
 static void do_diagnostic	PARAMS ((cpp_reader *, enum error_type, int));
@@ -247,14 +247,14 @@ end_directive (pfile, skip_line)
 {
   cpp_buffer *buffer = pfile->buffer;
 
+  /* Restore pfile->skipping before skip_rest_of_line, so that e.g.
+     __VA_ARGS__ in the rest of the directive doesn't warn.  */
+  pfile->skipping = buffer->was_skipping;
+
   /* We don't skip for an assembler #.  */
   if (skip_line)
     skip_rest_of_line (pfile);
 
-  /* Restore pfile->skipping after skip_rest_of_line.  Otherwise the
-     lexer might not return!  */
-  pfile->skipping = buffer->was_skipping;
-
   /* Restore state.  */
   pfile->la_write = pfile->la_saved;
   pfile->state.save_comments = ! CPP_OPTION (pfile, discard_comments);
@@ -639,22 +639,26 @@ do_include_next (pfile)
     _cpp_execute_include (pfile, &header, 0, 1);
 }
 
-/* Subroutine of do_line.  Read possible flags after file name.  If it
-   is a number between 1 and 4, return it, otherwise return 0.  If
-   it's not the end of the directive complain.  */
+/* Subroutine of do_line.  Read possible flags after file name.  LAST
+   is the last flag seen; 0 if this is the first flag. Return the flag
+   if it is valid, 0 at the end of the directive. Otherwise complain.  */
 
 static unsigned int
-read_flag (pfile)
+read_flag (pfile, last)
      cpp_reader *pfile;
+     unsigned int last;
 {
   cpp_token token;
 
   _cpp_lex_token (pfile, &token);
   if (token.type == CPP_NUMBER && token.val.str.len == 1)
     {
-      unsigned int flag = token.val.str.text[0] - '1';
-      if (flag <= 3)
-	return flag + 1;
+      unsigned int flag = token.val.str.text[0] - '0';
+
+      if (flag > last && flag <= 4
+	  && (flag != 4 || last == 3)
+	  && (flag != 2 || last == 0))
+	return flag;
     }
 
   if (token.type != CPP_EOF)
@@ -733,31 +737,33 @@ do_line (pfile)
       _cpp_simplify_pathname (fname);
       buffer->nominal_fname = fname;
 
-      if (pfile->state.line_extension)
+      if (! pfile->state.line_extension)
+	check_eol (pfile);
+      else
 	{
-	  int flag, sysp = 0;
+	  int flag = 0, sysp = 0;
 
-	  flag = read_flag (pfile);
+	  flag = read_flag (pfile, flag);
 	  if (flag == 1)
 	    {
 	      reason = FC_ENTER;
-	      flag = read_flag (pfile);
+	      flag = read_flag (pfile, flag);
 	    }
 	  else if (flag == 2)
 	    {
 	      reason = FC_LEAVE;
-	      flag = read_flag (pfile);
+	      flag = read_flag (pfile, flag);
 	    }
 	  if (flag == 3)
 	    {
-	      flag = read_flag (pfile);
 	      sysp = 1;
+	      flag = read_flag (pfile, flag);
+	      if (flag == 4)
+		sysp = 2, read_flag (pfile, flag);
 	    }
 
-	  cpp_make_system_header (pfile, sysp, flag == 4);
+	  cpp_make_system_header (pfile, sysp, sysp == 2);
 	}
-
-      check_eol (pfile);
     }
   else if (token.type != CPP_EOF)
     {
Index: cppmacro.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cppmacro.c,v
retrieving revision 1.34
diff -u -p -r1.34 cppmacro.c
--- cppmacro.c	2000/12/03 12:06:23	1.34
+++ cppmacro.c	2000/12/09 11:35:11
@@ -42,7 +42,7 @@ struct cpp_macro
   unsigned int count;		/* Number of tokens in expansion.  */
   unsigned short paramc;	/* Number of parameters.  */
   unsigned int fun_like : 1;	/* If a function-like macro.  */
-  unsigned int var_args : 1;	/* If a variable-args macro.  */
+  unsigned int variadic : 1;	/* If a variadic macro.  */
   unsigned int disabled : 1;	/* If macro is disabled.  */
 };
 
@@ -475,13 +475,13 @@ paste_all_tokens (pfile, lhs)
 }
 
 /* Reads the unexpanded tokens of a macro argument into ARG.  VAR_ARGS
-   is non-zero if this is a variable argument.  Returns the type of
-   the token that caused reading to finish.  */
+   is non-zero if this is a variadic macro.  Returns the type of the
+   token that caused reading to finish.  */
 static enum cpp_ttype
-parse_arg (pfile, arg, var_args)
+parse_arg (pfile, arg, variadic)
      cpp_reader *pfile;
      struct macro_arg *arg;
-     int var_args;
+     int variadic;
 {
   enum cpp_ttype result;
   unsigned int paren = 0;
@@ -509,8 +509,8 @@ parse_arg (pfile, arg, var_args)
 	paren++;
       else if (result == CPP_CLOSE_PAREN && paren-- == 0)
 	break;
-      /* Commas are not terminators within parantheses or var_args.  */
-      else if (result == CPP_COMMA && paren == 0 && !var_args)
+      /* Commas are not terminators within parantheses or variadic.  */
+      else if (result == CPP_COMMA && paren == 0 && !variadic)
 	break;
       else if (result == CPP_EOF)
 	break;		/* Error reported by caller.  */
@@ -541,7 +541,7 @@ parse_args (pfile, node)
     {
       argc++;
 
-      type = parse_arg (pfile, cur, argc == macro->paramc && macro->var_args);
+      type = parse_arg (pfile, cur, argc == macro->paramc && macro->variadic);
       if (type == CPP_CLOSE_PAREN || type == CPP_EOF)
 	break;
 
@@ -566,7 +566,7 @@ parse_args (pfile, node)
 	 This is exactly the same as if there had been an empty rest
 	 argument - debug("string", ).  */
 
-      if (argc + 1 == macro->paramc && macro->var_args)
+      if (argc + 1 == macro->paramc && macro->variadic)
 	{
 	  if (CPP_PEDANTIC (pfile))
 	    cpp_pedwarn (pfile, "ISO C99 requires rest arguments to be used");
@@ -794,7 +794,7 @@ replace_args (pfile, macro, args, list)
 		   given no actual arguments (not merely if b is an
 		   empty argument); otherwise pasting is turned off.  */
 		if (dest[-1].type == CPP_COMMA
-		    && macro->var_args
+		    && macro->variadic
 		    && src->val.arg_no == macro->paramc)
 		  {
 		    if (count == 0)
@@ -1182,7 +1182,7 @@ check_macro_redefinition (pfile, node, m
   if (macro1->count != macro2->count
       || macro1->paramc != macro2->paramc
       || macro1->fun_like != macro2->fun_like
-      || macro1->var_args != macro2->var_args)
+      || macro1->variadic != macro2->variadic)
     return 0;
 
   /* Check each token.  */
@@ -1287,18 +1287,17 @@ parse_params (pfile, macro)
 	  continue;
 
 	case CPP_ELLIPSIS:
-	  macro->var_args = 1;
+	  macro->variadic = 1;
 	  if (!prev_ident)
 	    {
 	      save_parameter (pfile, macro, pfile->spec_nodes.n__VA_ARGS__);
 	      pfile->state.va_args_ok = 1;
 	      if (! CPP_OPTION (pfile, c99) && CPP_OPTION (pfile, pedantic))
 		cpp_pedwarn (pfile,
-		     "anonymous variable arguments were introduced in C99");
+		     "anonymous variadic macros were introduced in C99");
 	    }
 	  else if (CPP_OPTION (pfile, pedantic))
-	    cpp_pedwarn (pfile,
-			 "ISO C does not permit named variable arguments");
+	    cpp_pedwarn (pfile, "ISO C does not permit named variadic macros");
 
 	  /* We're at the end, and just expect a closing parenthesis.  */
 	  _cpp_lex_token (pfile, &token);
@@ -1368,7 +1367,7 @@ _cpp_create_definition (pfile, node)
   macro->params = 0;
   macro->paramc = 0;
   macro->fun_like = 0;
-  macro->var_args = 0;
+  macro->variadic = 0;
   macro->count = 0;
   macro->expansion = (cpp_token *) POOL_FRONT (&pfile->macro_pool);
 
@@ -1598,7 +1597,7 @@ cpp_macro_definition (pfile, node)
 
 	  if (i + 1 < macro->paramc)
 	    *buffer++ = ',', *buffer++ = ' ';
-	  else if (macro->var_args)
+	  else if (macro->variadic)
 	    *buffer++ = '.', *buffer++ = '.', *buffer++ = '.';
 	}
       *buffer++ = ')';
Index: testsuite/gcc.dg/cpp/lineflags.c
===================================================================
RCS file: lineflags.c
diff -N lineflags.c
--- /dev/null	Tue May  5 13:32:27 1998
+++ lineflags.c	Sat Dec  9 03:35:26 2000
@@ -0,0 +1,35 @@
+/* Copyright (C) 2000 Free Software Foundation, Inc.  */
+
+/* { dg-do preprocess } */
+/* { dg-options "-fno-show-column" } */
+
+/* This tests whether various combinations of flags are correctly
+   accepted after #line.
+
+   Neil Booth, 8 Dec 2000.  */
+
+#line 12 "file" 3		/* { dg-warning "extra tokens" } */
+
+# 14 "file" 1 1			/* { dg-error "invalid flag" } */
+# 15 "file" 1 2			/* { dg-error "invalid flag" } */
+# 16 "file" 1 3 3		/* { dg-error "invalid flag" } */
+# 17 "file" 1 4			/* { dg-error "invalid flag" } */
+# 18 "file" 2 3 4 4		/* { dg-error "invalid flag" } */
+# 19 "file" 2 4			/* { dg-error "invalid flag" } */
+# 20 "file" 2 2			/* { dg-error "invalid flag" } */
+# 21 "file" 2 1			/* { dg-error "invalid flag" } */
+# 22 "file" 4			/* { dg-error "invalid flag" } */
+# 23 "file" 4 5			/* { dg-error "invalid flag" } */
+# 24 "file" 0			/* { dg-error "invalid flag" } */
+# 25 "file" 5			/* { dg-error "invalid flag" } */
+# 26 "file" foo			/* { dg-error "invalid flag" } */
+
+
+# 29 "file" 1			/* { dg-bogus "invalid flag" } */
+# 30 "file" 2			/* { dg-bogus "invalid flag" } */
+# 31 "file" 1 3			/* { dg-bogus "invalid flag" } */
+# 32 "file" 2 3			/* { dg-bogus "invalid flag" } */
+# 33 "file" 1 3 4		/* { dg-bogus "invalid flag" } */
+# 34 "file" 2 3	4		/* { dg-bogus "invalid flag" } */
+# 35 "file" 3			/* { dg-bogus "invalid flag" } */
+# 36 "file" 3 4			/* { dg-bogus "invalid flag" } */
Index: testsuite/gcc.dg/cpp/poison.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/cpp/poison.c,v
retrieving revision 1.2
diff -u -p -r1.2 poison.c
--- poison.c	2000/12/01 22:03:57	1.2
+++ poison.c	2000/12/09 11:35:26
@@ -15,10 +15,10 @@ foo5			/* { dg-error "foo5" "use of foo5
 #define foo6 345	/* { dg-error "foo6" "def of foo6" } */
 #define foo6 456	/* { dg-error "foo6" "redef of foo6" } */
 #ifdef foo6		/* { dg-error "foo6" "#ifdef foo6" } */
-#error hey!  foo6 poisoned! /* { dg-error "foo6" "poisoned identifiers" } */
+#error hey! foo6 defined!
 #endif
 #if defined(foo6)	/* { dg-error "foo6" "#if defined foo6" } */
-#error foo6 still poisoned! /* { dg-error "foo6" "poisoned identifiers" } */
+#error foo6 still defined!
 #else
 foo6			/* { dg-error "foo6" "use of foo6" } */
 #endif
Index: testsuite/gcc.dg/cpp/redef2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/cpp/redef2.c,v
retrieving revision 1.2
diff -u -p -r1.2 redef2.c
--- redef2.c	2000/10/28 18:01:40	1.2
+++ redef2.c	2000/12/09 11:35:26
@@ -26,5 +26,5 @@
    { dg-warning "previous"  "prev def ro"   { target *-*-* } 11 }
    { dg-warning "previous"  "prev def va"   { target *-*-* } 14 }
 
-   { dg-warning "named variable"   "named"  { target *-*-* } 14 }
-   { dg-warning "anonymous variable" "anon" { target *-*-* } 15 } */ 
+   { dg-warning "named var" "named variadic"  { target *-*-* } 14 }
+   { dg-warning "anonymous var" "anon variadic" { target *-*-* } 15 } */ 
Index: testsuite/gcc.dg/cpp/skipping.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/cpp/skipping.c,v
retrieving revision 1.1
diff -u -p -r1.1 skipping.c
--- skipping.c	2000/10/29 17:43:57	1.1
+++ skipping.c	2000/12/09 11:35:26
@@ -18,3 +18,8 @@ F(			/* No diagnostic: don't even try to
 #else
 #error Macros not expanded in #elif
 #endif
+
+/* Check we don't warn about bad identifiers when skipping.  */
+#if 0
+#define foo __VA_ARGS__	/* { dg-bogus "warned about identifier" } */
+#endif



More information about the Gcc-patches mailing list