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]
Other format: [Raw text]

Re: PR c++/14875: When using 'or' keyword, the error message speaks of a '||' token


This is an updated patch addressing your comments.

Bootstrapped and regression tested on x86_64-unknown-linux-gnu with
--enable-languages=all,ada

OK for trunk?


2008-08-19  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

	PR c++/14875
	* c-common.c (c_parse_error): Take a token_flags parameter.
	Use token_type for the token type instead.
	Pass token_flags to cpp_type2name.
	* c-common.h (c_parse_error): Update declaration.
	* c-parser.c (c_parser_error): Pass 0 as token flags.
libcpp/
	* lex.c (cpp_type2name): Take a flags parameter. Call
	cpp_named_operator2name for named operators and cpp_digraph2name
	for digraphs.
	(cpp_digraph2name): New.
	(cpp_spell_token): Use it.
	(cpp_output_token): Likewise.
	* include/cpplib.h (cpp_type2name): Update declaration.
	* init.c (cpp_named_operator2name): New.
	* internal.h (cpp_named_operator2name): Declare.
cp/	
	* parser.c (cp_parser_error): Pass token->flags to c_parse_error.
testsuite/
	* g++.dg/parse/parser-pr14875.C: New.
	* g++.dg/parse/parser-pr14875-2.C: New.
	* g++.dg/parse/error6.C: Update match string.
Index: gcc/testsuite/g++.dg/parse/parser-pr14875-2.C
===================================================================
--- gcc/testsuite/g++.dg/parse/parser-pr14875-2.C	(revision 0)
+++ gcc/testsuite/g++.dg/parse/parser-pr14875-2.C	(revision 0)
@@ -0,0 +1,31 @@
+// PR 14875: When using 'or' keyword, the error message speaks of a '||' token
+// { dg-do compile }
+// { dg-options "" }
+#define CHECK(x)  void ::x
+  CHECK (and);      // { dg-error "error: expected \[^\n\]* before .and. token" }
+  CHECK (and_eq);   // { dg-error "error: expected \[^\n\]* before .and_eq. token" }
+  CHECK (bitand);   // { dg-error "error: expected \[^\n\]* before .bitand. token" }
+  CHECK (bitor);    // { dg-error "error: expected \[^\n\]* before .bitor. token" }
+  CHECK (compl);    // { dg-error "error: expected \[^\n\]* before .compl. token" }
+  CHECK (not);      // { dg-error "error: expected \[^\n\]* before .not. token" }
+  CHECK (not_eq);   // { dg-error "error: expected \[^\n\]* before .not_eq. token" }
+  CHECK (or);       // { dg-error "error: expected \[^\n\]* before .or. token" }
+  CHECK (or_eq);    // { dg-error "error: expected \[^\n\]* before .or_eq. token" }
+  CHECK (xor);      // { dg-error "error: expected \[^\n\]* before .xor. token" }
+  CHECK (xor_eq);   // { dg-error "error: expected \[^\n\]* before .xor_eq. token" }
+#undef CHECK
+#define CHECK(x)  int x
+  CHECK (<:);     // { dg-error "error: expected \[^\n\]* before .<:. token" }
+  CHECK (:>);     // { dg-error "error: expected \[^\n\]* before .:>. token" }
+#undef CHECK
+#define CHECK(x)  x
+  CHECK (<%);     // { dg-error "error: expected \[^\n\]* before .<%. token" }
+#undef CHECK
+#define CHECK(x)  x x
+  CHECK (%>);     // { dg-error "error: expected \[^\n\]* before .%>. token" }
+#undef CHECK
+#define CHECK(x)  x
+  CHECK (%:);     // { dg-error "error: stray .%:. " }
+  CHECK (%:%:);   // { dg-error "error: stray .%:%:. " }
+
+
Index: gcc/testsuite/g++.dg/parse/parser-pr14875.C
===================================================================
--- gcc/testsuite/g++.dg/parse/parser-pr14875.C	(revision 0)
+++ gcc/testsuite/g++.dg/parse/parser-pr14875.C	(revision 0)
@@ -0,0 +1,20 @@
+// PR 14875: When using 'or' keyword, the error message speaks of a '||' token
+// { dg-do compile }
+// { dg-options "" }
+using namespace std; 
+ 
+class Sample 
+{ 
+ 
+public: 
+  Sample(); 
+  void or(long Digital);  // { dg-error "error: expected \[^\n\]* before .or. token" }
+}; 
+ 
+Sample::Sample() 
+{ 
+} 
+ 
+void Sample::or(long Digital) // { dg-error "error: expected \[^\n\]* before .or. token" }
+{ 
+}
Index: gcc/testsuite/g++.dg/parse/error6.C
===================================================================
--- gcc/testsuite/g++.dg/parse/error6.C	(revision 139194)
+++ gcc/testsuite/g++.dg/parse/error6.C	(working copy)
@@ -3,9 +3,9 @@
 
 int f(int not) {
   return 1-not;
 } 
 
-// { dg-error "11: error: expected ',' or '...' before '!' token" "" { target *-*-* } { 4 } }
+// { dg-error "11: error: expected ',' or '...' before 'not' token" "" { target *-*-* } { 4 } }
 
 // { dg-error "15: error: expected primary\\-expression before ';' token" "" { target *-*-* }  { 5 } }
 
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c	(revision 139194)
+++ gcc/cp/parser.c	(working copy)
@@ -2082,11 +2082,11 @@ cp_parser_error (cp_parser* parser, cons
       c_parse_error (message,
 		     /* Because c_parser_error does not understand
 			CPP_KEYWORD, keywords are treated like
 			identifiers.  */
 		     (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-		     token->u.value);
+		     token->u.value, token->flags);
     }
 }
 
 /* Issue an error about name-lookup failing.  NAME is the
    IDENTIFIER_NODE DECL is the result of
Index: gcc/c-common.c
===================================================================
--- gcc/c-common.c	(revision 139194)
+++ gcc/c-common.c	(working copy)
@@ -7478,25 +7478,28 @@ catenate_strings (const char *lhs, const
 
 /* Issue the error given by GMSGID, indicating that it occurred before
    TOKEN, which had the associated VALUE.  */
 
 void
-c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
+c_parse_error (const char *gmsgid, enum cpp_ttype token_type, 
+	       tree value, unsigned char token_flags)
 {
 #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
 
   char *message = NULL;
 
-  if (token == CPP_EOF)
+  if (token_type == CPP_EOF)
     message = catenate_messages (gmsgid, " at end of input");
-  else if (token == CPP_CHAR || token == CPP_WCHAR || token == CPP_CHAR16
-	   || token == CPP_CHAR32)
+  else if (token_type == CPP_CHAR 
+	   || token_type == CPP_WCHAR 
+	   || token_type == CPP_CHAR16
+	   || token_type == CPP_CHAR32)
     {
       unsigned int val = TREE_INT_CST_LOW (value);
       const char *prefix;
 
-      switch (token)
+      switch (token_type)
 	{
 	default:
 	  prefix = "";
 	  break;
 	case CPP_WCHAR:
@@ -7517,30 +7520,32 @@ c_parse_error (const char *gmsgid, enum 
 
       error (message, prefix, val);
       free (message);
       message = NULL;
     }
-  else if (token == CPP_STRING || token == CPP_WSTRING || token == CPP_STRING16
-	   || token == CPP_STRING32)
+  else if (token_type == CPP_STRING 
+	   || token_type == CPP_WSTRING 
+	   || token_type == CPP_STRING16
+	   || token_type == CPP_STRING32)
     message = catenate_messages (gmsgid, " before string constant");
-  else if (token == CPP_NUMBER)
+  else if (token_type == CPP_NUMBER)
     message = catenate_messages (gmsgid, " before numeric constant");
-  else if (token == CPP_NAME)
+  else if (token_type == CPP_NAME)
     {
       message = catenate_messages (gmsgid, " before %qE");
       error (message, value);
       free (message);
       message = NULL;
     }
-  else if (token == CPP_PRAGMA)
+  else if (token_type == CPP_PRAGMA)
     message = catenate_messages (gmsgid, " before %<#pragma%>");
-  else if (token == CPP_PRAGMA_EOL)
+  else if (token_type == CPP_PRAGMA_EOL)
     message = catenate_messages (gmsgid, " before end of line");
-  else if (token < N_TTYPES)
+  else if (token_type < N_TTYPES)
     {
       message = catenate_messages (gmsgid, " before %qs token");
-      error (message, cpp_type2name (token));
+      error (message, cpp_type2name (token_type, token_flags));
       free (message);
       message = NULL;
     }
   else
     error (gmsgid);
Index: gcc/c-common.h
===================================================================
--- gcc/c-common.h	(revision 139194)
+++ gcc/c-common.h	(working copy)
@@ -949,11 +949,11 @@ extern const unsigned char executable_ch
 /* In c-cppbuiltin.c  */
 extern void builtin_define_std (const char *macro);
 extern void builtin_define_with_value (const char *, const char *, int);
 extern void c_stddef_cpp_builtins (void);
 extern void fe_file_change (const struct line_map *);
-extern void c_parse_error (const char *, enum cpp_ttype, tree);
+extern void c_parse_error (const char *, enum cpp_ttype, tree, unsigned char);
 
 /* Objective-C / Objective-C++ entry points.  */
 
 /* The following ObjC/ObjC++ functions are called by the C and/or C++
    front-ends; they all must have corresponding stubs in stub-objc.c.  */
Index: gcc/c-parser.c
===================================================================
--- gcc/c-parser.c	(revision 139194)
+++ gcc/c-parser.c	(working copy)
@@ -570,11 +570,15 @@ c_parser_error (c_parser *parser, const 
   c_parse_error (gmsgid,
 		 /* Because c_parse_error does not understand
 		    CPP_KEYWORD, keywords are treated like
 		    identifiers.  */
 		 (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-		 token->value);
+		 /* ??? The C parser does not save the cpp flags of a
+		    token, we need to pass 0 here and we will not get
+		    the source spelling of some tokens but rather the
+		    canonical spelling.  */
+		 token->value, /*flags=*/0);
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
    issue the error MSGID.  If MSGID is NULL then a message has already
    been produced and no message will be produced this time.  Returns
Index: libcpp/include/cpplib.h
===================================================================
--- libcpp/include/cpplib.h	(revision 139194)
+++ libcpp/include/cpplib.h	(working copy)
@@ -855,11 +855,11 @@ extern void cpp_error_with_line (cpp_rea
 extern int cpp_ideq (const cpp_token *, const char *);
 extern void cpp_output_line (cpp_reader *, FILE *);
 extern unsigned char *cpp_output_line_to_string (cpp_reader *,
 						 const unsigned char *);
 extern void cpp_output_token (const cpp_token *, FILE *);
-extern const char *cpp_type2name (enum cpp_ttype);
+extern const char *cpp_type2name (enum cpp_ttype, unsigned char flags);
 /* Returns the value of an escape sequence, truncated to the correct
    target precision.  PSTR points to the input pointer, which is just
    after the backslash.  LIMIT is how much text we have.  WIDE is true
    if the escape sequence is part of a wide character constant or
    string literal.  Handles all relevant diagnostics.  */
Index: libcpp/init.c
===================================================================
--- libcpp/init.c	(revision 139194)
+++ libcpp/init.c	(working copy)
@@ -358,10 +358,28 @@ mark_named_operators (cpp_reader *pfile)
       hp->is_directive = 0;
       hp->directive_index = b->value;
     }
 }
 
+/* Helper function of cpp_type2name. Return the string associated with
+   named operator TYPE.  */
+const char *
+cpp_named_operator2name (enum cpp_ttype type)
+{
+  const struct builtin *b;
+
+  for (b = operator_array;
+       b < (operator_array + ARRAY_SIZE (operator_array));
+       b++)
+    {
+      if (type == b->value)
+	return (const char *) b->name;
+    }
+
+  return NULL;
+}
+
 void
 cpp_init_special_builtins (cpp_reader *pfile)
 {
   const struct builtin *b;
   size_t n = ARRAY_SIZE (builtin_array);
Index: libcpp/internal.h
===================================================================
--- libcpp/internal.h	(revision 139194)
+++ libcpp/internal.h	(working copy)
@@ -572,10 +572,11 @@ extern cpp_token *_cpp_lex_direct (cpp_r
 extern int _cpp_equiv_tokens (const cpp_token *, const cpp_token *);
 extern void _cpp_init_tokenrun (tokenrun *, unsigned int);
 
 /* In init.c.  */
 extern void _cpp_maybe_push_include_file (cpp_reader *);
+extern const char *cpp_named_operator2name (enum cpp_ttype type);
 
 /* In directives.c */
 extern int _cpp_test_assertion (cpp_reader *, unsigned int *);
 extern int _cpp_handle_directive (cpp_reader *, int);
 extern void _cpp_define_builtin (cpp_reader *, const char *);
Index: libcpp/lex.c
===================================================================
--- libcpp/lex.c	(revision 139194)
+++ libcpp/lex.c	(working copy)
@@ -1353,10 +1353,17 @@ utf8_to_ucn (unsigned char *buffer, cons
   for (j = 7; j >= 0; j--)
     *buffer++ = "0123456789abcdef"[(utf32 >> (4 * j)) & 0xF];
   return ucn_len;
 }
 
+/* Given a token TYPE corresponding to a digraph, return a pointer to
+   the spelling of the digraph.  */
+static const unsigned char *
+cpp_digraph2name (enum cpp_ttype type)
+{
+  return digraph_spellings[(int) type - (int) CPP_FIRST_DIGRAPH];
+}
 
 /* Write the spelling of a token TOKEN to BUFFER.  The buffer must
    already contain the enough space to hold the token's spelling.
    Returns a pointer to the character after the last character written.
    FORSTRING is true if this is to be the spelling after translation
@@ -1372,12 +1379,11 @@ cpp_spell_token (cpp_reader *pfile, cons
       {
 	const unsigned char *spelling;
 	unsigned char c;
 
 	if (token->flags & DIGRAPH)
-	  spelling
-	    = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH];
+	  spelling = cpp_digraph2name (token->type);
 	else if (token->flags & NAMED_OP)
 	  goto spell_ident;
 	else
 	  spelling = TOKEN_NAME (token);
 
@@ -1436,15 +1442,21 @@ cpp_token_as_text (cpp_reader *pfile, co
   end[0] = '\0';
 
   return start;
 }
 
-/* Used by C front ends, which really should move to using
-   cpp_token_as_text.  */
+/* Returns a pointer to a string which spells the token defined by
+   TYPE and FLAGS.  Used by C front ends, which really should move to
+   using cpp_token_as_text.  */
 const char *
-cpp_type2name (enum cpp_ttype type)
+cpp_type2name (enum cpp_ttype type, unsigned char flags)
 {
+  if (flags & DIGRAPH)
+    return (const char *) cpp_digraph2name (type);
+  else if (flags & NAMED_OP)
+    return cpp_named_operator2name (type);
+
   return (const char *) token_spellings[type].name;
 }
 
 /* Writes the spelling of token to FP, without any preceding space.
    Separated from cpp_spell_token for efficiency - to avoid stdio
@@ -1458,12 +1470,11 @@ cpp_output_token (const cpp_token *token
       {
 	const unsigned char *spelling;
 	int c;
 
 	if (token->flags & DIGRAPH)
-	  spelling
-	    = digraph_spellings[(int) token->type - (int) CPP_FIRST_DIGRAPH];
+	  spelling = cpp_digraph2name (token->type);
 	else if (token->flags & NAMED_OP)
 	  goto spell_ident;
 	else
 	  spelling = TOKEN_NAME (token);
 

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