| Index: gcc/libcpp/lex.c | 
| diff --git a/gcc/libcpp/lex.c b/gcc/libcpp/lex.c | 
| index e08c5bd81436c5fd5e6fd04d57de308b243c9842..f29998225340954e0affb7f59da3c1d66ea51bd9 100644 | 
| --- a/gcc/libcpp/lex.c | 
| +++ b/gcc/libcpp/lex.c | 
| @@ -76,7 +76,7 @@ cpp_ideq (const cpp_token *token, const char *string) | 
| if (token->type != CPP_NAME) | 
| return 0; | 
|  | 
| -  return !ustrcmp (NODE_NAME (token->val.node), (const uchar *) string); | 
| +  return !ustrcmp (NODE_NAME (token->val.node.node), (const uchar *) string); | 
| } | 
|  | 
| /* Record a note TYPE at byte POS into the current cleaned logical | 
| @@ -314,6 +314,8 @@ _cpp_process_line_notes (cpp_reader *pfile, int in_comment) | 
| } | 
| } | 
| } | 
| +      else if (note->type == 0) | 
| +	/* Already processed in lex_raw_string.  */; | 
| else | 
| abort (); | 
| } | 
| @@ -540,6 +542,12 @@ lex_identifier_intern (cpp_reader *pfile, const uchar *base) | 
| cpp_error (pfile, CPP_DL_PEDWARN, | 
| "__VA_ARGS__ can only appear in the expansion" | 
| " of a C99 variadic macro"); | 
| + | 
| +      /* For -Wc++-compat, warn about use of C++ named operators.  */ | 
| +      if (result->flags & NODE_WARN_OPERATOR) | 
| +	cpp_error (pfile, CPP_DL_WARNING, | 
| +		   "identifier \"%s\" is a special operator name in C++", | 
| +		   NODE_NAME (result)); | 
| } | 
|  | 
| return result; | 
| @@ -611,6 +619,12 @@ lex_identifier (cpp_reader *pfile, const uchar *base, bool starts_ucn, | 
| cpp_error (pfile, CPP_DL_PEDWARN, | 
| "__VA_ARGS__ can only appear in the expansion" | 
| " of a C99 variadic macro"); | 
| + | 
| +      /* For -Wc++-compat, warn about use of C++ named operators.  */ | 
| +      if (result->flags & NODE_WARN_OPERATOR) | 
| +	cpp_error (pfile, CPP_DL_WARNING, | 
| +		   "identifier \"%s\" is a special operator name in C++", | 
| +		   NODE_NAME (result)); | 
| } | 
|  | 
| return result; | 
| @@ -662,12 +676,291 @@ create_literal (cpp_reader *pfile, cpp_token *token, const uchar *base, | 
| token->val.str.text = dest; | 
| } | 
|  | 
| +/* Subroutine of lex_raw_string: Append LEN chars from BASE to the buffer | 
| +   sequence from *FIRST_BUFF_P to LAST_BUFF_P.  */ | 
| + | 
| +static void | 
| +bufring_append (cpp_reader *pfile, const uchar *base, size_t len, | 
| +		_cpp_buff **first_buff_p, _cpp_buff **last_buff_p) | 
| +{ | 
| +  _cpp_buff *first_buff = *first_buff_p; | 
| +  _cpp_buff *last_buff = *last_buff_p; | 
| + | 
| +  if (first_buff == NULL) | 
| +    first_buff = last_buff = _cpp_get_buff (pfile, len); | 
| +  else if (len > BUFF_ROOM (last_buff)) | 
| +    { | 
| +      size_t room = BUFF_ROOM (last_buff); | 
| +      memcpy (BUFF_FRONT (last_buff), base, room); | 
| +      BUFF_FRONT (last_buff) += room; | 
| +      base += room; | 
| +      len -= room; | 
| +      last_buff = _cpp_append_extend_buff (pfile, last_buff, len); | 
| +    } | 
| + | 
| +  memcpy (BUFF_FRONT (last_buff), base, len); | 
| +  BUFF_FRONT (last_buff) += len; | 
| + | 
| +  *first_buff_p = first_buff; | 
| +  *last_buff_p = last_buff; | 
| +} | 
| + | 
| +/* Lexes a raw string.  The stored string contains the spelling, including | 
| +   double quotes, delimiter string, '(' and ')', any leading | 
| +   'L', 'u', 'U' or 'u8' and 'R' modifier.  It returns the type of the | 
| +   literal, or CPP_OTHER if it was not properly terminated. | 
| + | 
| +   The spelling is NUL-terminated, but it is not guaranteed that this | 
| +   is the first NUL since embedded NULs are preserved.  */ | 
| + | 
| +static void | 
| +lex_raw_string (cpp_reader *pfile, cpp_token *token, const uchar *base, | 
| +		const uchar *cur) | 
| +{ | 
| +  source_location saw_NUL = 0; | 
| +  const uchar *raw_prefix; | 
| +  unsigned int raw_prefix_len = 0; | 
| +  enum cpp_ttype type; | 
| +  size_t total_len = 0; | 
| +  _cpp_buff *first_buff = NULL, *last_buff = NULL; | 
| +  _cpp_line_note *note = &pfile->buffer->notes[pfile->buffer->cur_note]; | 
| + | 
| +  type = (*base == 'L' ? CPP_WSTRING : | 
| +	  *base == 'U' ? CPP_STRING32 : | 
| +	  *base == 'u' ? (base[1] == '8' ? CPP_UTF8STRING : CPP_STRING16) | 
| +	  : CPP_STRING); | 
| + | 
| +  raw_prefix = cur + 1; | 
| +  while (raw_prefix_len < 16) | 
| +    { | 
| +      switch (raw_prefix[raw_prefix_len]) | 
| +	{ | 
| +	case ' ': case '(': case ')': case '\\': case '\t': | 
| +	case '\v': case '\f': case '\n': default: | 
| +	  break; | 
| +	/* Basic source charset except the above chars.  */ | 
| +	case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': | 
| +	case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': | 
| +	case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': | 
| +	case 's': case 't': case 'u': case 'v': case 'w': case 'x': | 
| +	case 'y': case 'z': | 
| +	case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': | 
| +	case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': | 
| +	case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': | 
| +	case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': | 
| +	case 'Y': case 'Z': | 
| +	case '0': case '1': case '2': case '3': case '4': case '5': | 
| +	case '6': case '7': case '8': case '9': | 
| +	case '_': case '{': case '}': case '#': case '[': case ']': | 
| +	case '<': case '>': case '%': case ':': case ';': case '.': | 
| +	case '?': case '*': case '+': case '-': case '/': case '^': | 
| +	case '&': case '|': case '~': case '!': case '=': case ',': | 
| +	case '"': case '\'': | 
| +	  raw_prefix_len++; | 
| +	  continue; | 
| +	} | 
| +      break; | 
| +    } | 
| + | 
| +  if (raw_prefix[raw_prefix_len] != '(') | 
| +    { | 
| +      int col = CPP_BUF_COLUMN (pfile->buffer, raw_prefix + raw_prefix_len) | 
| +		+ 1; | 
| +      if (raw_prefix_len == 16) | 
| +	cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, col, | 
| +			     "raw string delimiter longer than 16 characters"); | 
| +      else | 
| +	cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, col, | 
| +			     "invalid character '%c' in raw string delimiter", | 
| +			     (int) raw_prefix[raw_prefix_len]); | 
| +      pfile->buffer->cur = raw_prefix - 1; | 
| +      create_literal (pfile, token, base, raw_prefix - 1 - base, CPP_OTHER); | 
| +      return; | 
| +    } | 
| + | 
| +  cur = raw_prefix + raw_prefix_len + 1; | 
| +  for (;;) | 
| +    { | 
| +#define BUF_APPEND(STR,LEN)					\ | 
| +      do {							\ | 
| +	bufring_append (pfile, (const uchar *)(STR), (LEN),	\ | 
| +			&first_buff, &last_buff);		\ | 
| +	total_len += (LEN);					\ | 
| +      } while (0); | 
| + | 
| +      cppchar_t c; | 
| + | 
| +      /* If we previously performed any trigraph or line splicing | 
| +	 transformations, undo them within the body of the raw string.  */ | 
| +      while (note->pos < cur) | 
| +	++note; | 
| +      for (; note->pos == cur; ++note) | 
| +	{ | 
| +	  switch (note->type) | 
| +	    { | 
| +	    case '\\': | 
| +	    case ' ': | 
| +	      /* Restore backslash followed by newline.  */ | 
| +	      BUF_APPEND (base, cur - base); | 
| +	      base = cur; | 
| +	      BUF_APPEND ("\\", 1); | 
| +	    after_backslash: | 
| +	      if (note->type == ' ') | 
| +		{ | 
| +		  /* GNU backslash whitespace newline extension.  FIXME | 
| +		     could be any sequence of non-vertical space.  When we | 
| +		     can properly restore any such sequence, we should mark | 
| +		     this note as handled so _cpp_process_line_notes | 
| +		     doesn't warn.  */ | 
| +		  BUF_APPEND (" ", 1); | 
| +		} | 
| + | 
| +	      BUF_APPEND ("\n", 1); | 
| +	      break; | 
| + | 
| +	    case 0: | 
| +	      /* Already handled.  */ | 
| +	      break; | 
| + | 
| +	    default: | 
| +	      if (_cpp_trigraph_map[note->type]) | 
| +		{ | 
| +		  /* Don't warn about this trigraph in | 
| +		     _cpp_process_line_notes, since trigraphs show up as | 
| +		     trigraphs in raw strings.  */ | 
| +		  uchar type = note->type; | 
| +		  note->type = 0; | 
| + | 
| +		  if (!CPP_OPTION (pfile, trigraphs)) | 
| +		    /* If we didn't convert the trigraph in the first | 
| +		       place, don't do anything now either.  */ | 
| +		    break; | 
| + | 
| +		  BUF_APPEND (base, cur - base); | 
| +		  base = cur; | 
| +		  BUF_APPEND ("??", 2); | 
| + | 
| +		  /* ??/ followed by newline gets two line notes, one for | 
| +		     the trigraph and one for the backslash/newline.  */ | 
| +		  if (type == '/' && note[1].pos == cur) | 
| +		    { | 
| +		      if (note[1].type != '\\' | 
| +			  && note[1].type != ' ') | 
| +			abort (); | 
| +		      BUF_APPEND ("/", 1); | 
| +		      ++note; | 
| +		      goto after_backslash; | 
| +		    } | 
| +		  /* The ) from ??) could be part of the suffix.  */ | 
| +		  else if (type == ')' | 
| +			   && strncmp ((const char *) cur+1, | 
| +				       (const char *) raw_prefix, | 
| +				       raw_prefix_len) == 0 | 
| +			   && cur[raw_prefix_len+1] == '"') | 
| +		    { | 
| +		      cur += raw_prefix_len+2; | 
| +		      goto break_outer_loop; | 
| +		    } | 
| +		  else | 
| +		    { | 
| +		      /* Skip the replacement character.  */ | 
| +		      base = ++cur; | 
| +		      BUF_APPEND (&type, 1); | 
| +		    } | 
| +		} | 
| +	      else | 
| +		abort (); | 
| +	      break; | 
| +	    } | 
| +	} | 
| +      c = *cur++; | 
| + | 
| +      if (c == ')' | 
| +	  && strncmp ((const char *) cur, (const char *) raw_prefix, | 
| +		      raw_prefix_len) == 0 | 
| +	  && cur[raw_prefix_len] == '"') | 
| +	{ | 
| +	  cur += raw_prefix_len + 1; | 
| +	  break; | 
| +	} | 
| +      else if (c == '\n') | 
| +	{ | 
| +	  if (pfile->state.in_directive | 
| +	      || pfile->state.parsing_args | 
| +	      || pfile->state.in_deferred_pragma) | 
| +	    { | 
| +	      cur--; | 
| +	      type = CPP_OTHER; | 
| +	      cpp_error_with_line (pfile, CPP_DL_ERROR, token->src_loc, 0, | 
| +				   "unterminated raw string"); | 
| +	      break; | 
| +	    } | 
| + | 
| +	  BUF_APPEND (base, cur - base); | 
| + | 
| +	  if (pfile->buffer->cur < pfile->buffer->rlimit) | 
| +	    CPP_INCREMENT_LINE (pfile, 0); | 
| +	  pfile->buffer->need_line = true; | 
| + | 
| +	  pfile->buffer->cur = cur-1; | 
| +	  _cpp_process_line_notes (pfile, false); | 
| +	  if (!_cpp_get_fresh_line (pfile)) | 
| +	    { | 
| +	      source_location src_loc = token->src_loc; | 
| +	      token->type = CPP_EOF; | 
| +	      /* Tell the compiler the line number of the EOF token.  */ | 
| +	      token->src_loc = pfile->line_table->highest_line; | 
| +	      token->flags = BOL; | 
| +	      if (first_buff != NULL) | 
| +		_cpp_release_buff (pfile, first_buff); | 
| +	      cpp_error_with_line (pfile, CPP_DL_ERROR, src_loc, 0, | 
| +				   "unterminated raw string"); | 
| +	      return; | 
| +	    } | 
| + | 
| +	  cur = base = pfile->buffer->cur; | 
| +	  note = &pfile->buffer->notes[pfile->buffer->cur_note]; | 
| +	} | 
| +      else if (c == '\0' && !saw_NUL) | 
| +	LINEMAP_POSITION_FOR_COLUMN (saw_NUL, pfile->line_table, | 
| +				     CPP_BUF_COLUMN (pfile->buffer, cur)); | 
| +    } | 
| + break_outer_loop: | 
| + | 
| +  if (saw_NUL && !pfile->state.skipping) | 
| +    cpp_error_with_line (pfile, CPP_DL_WARNING, saw_NUL, 0, | 
| +	       "null character(s) preserved in literal"); | 
| + | 
| +  pfile->buffer->cur = cur; | 
| +  if (first_buff == NULL) | 
| +    create_literal (pfile, token, base, cur - base, type); | 
| +  else | 
| +    { | 
| +      uchar *dest = _cpp_unaligned_alloc (pfile, total_len + (cur - base) + 1); | 
| + | 
| +      token->type = type; | 
| +      token->val.str.len = total_len + (cur - base); | 
| +      token->val.str.text = dest; | 
| +      last_buff = first_buff; | 
| +      while (last_buff != NULL) | 
| +	{ | 
| +	  memcpy (dest, last_buff->base, | 
| +		  BUFF_FRONT (last_buff) - last_buff->base); | 
| +	  dest += BUFF_FRONT (last_buff) - last_buff->base; | 
| +	  last_buff = last_buff->next; | 
| +	} | 
| +      _cpp_release_buff (pfile, first_buff); | 
| +      memcpy (dest, base, cur - base); | 
| +      dest[cur - base] = '\0'; | 
| +    } | 
| +} | 
| + | 
| /* Lexes a string, character constant, or angle-bracketed header file | 
| name.  The stored string contains the spelling, including opening | 
| -   quote and leading any leading 'L', 'u' or 'U'.  It returns the type | 
| -   of the literal, or CPP_OTHER if it was not properly terminated, or | 
| -   CPP_LESS for an unterminated header name which must be relexed as | 
| -   normal tokens. | 
| +   quote and any leading 'L', 'u', 'U' or 'u8' and optional | 
| +   'R' modifier.  It returns the type of the literal, or CPP_OTHER | 
| +   if it was not properly terminated, or CPP_LESS for an unterminated | 
| +   header name which must be relexed as normal tokens. | 
|  | 
| The spelling is NUL-terminated, but it is not guaranteed that this | 
| is the first NUL since embedded NULs are preserved.  */ | 
| @@ -681,12 +974,24 @@ lex_string (cpp_reader *pfile, cpp_token *token, const uchar *base) | 
|  | 
| cur = base; | 
| terminator = *cur++; | 
| -  if (terminator == 'L' || terminator == 'u' || terminator == 'U') | 
| +  if (terminator == 'L' || terminator == 'U') | 
| terminator = *cur++; | 
| -  if (terminator == '\"') | 
| +  else if (terminator == 'u') | 
| +    { | 
| +      terminator = *cur++; | 
| +      if (terminator == '8') | 
| +	terminator = *cur++; | 
| +    } | 
| +  if (terminator == 'R') | 
| +    { | 
| +      lex_raw_string (pfile, token, base, cur); | 
| +      return; | 
| +    } | 
| +  if (terminator == '"') | 
| type = (*base == 'L' ? CPP_WSTRING : | 
| *base == 'U' ? CPP_STRING32 : | 
| -	    *base == 'u' ? CPP_STRING16 : CPP_STRING); | 
| +	    *base == 'u' ? (base[1] == '8' ? CPP_UTF8STRING : CPP_STRING16) | 
| +			 : CPP_STRING); | 
| else if (terminator == '\'') | 
| type = (*base == 'L' ? CPP_WCHAR : | 
| *base == 'U' ? CPP_CHAR32 : | 
| @@ -1146,10 +1451,21 @@ _cpp_lex_direct (cpp_reader *pfile) | 
| case 'L': | 
| case 'u': | 
| case 'U': | 
| -      /* 'L', 'u' or 'U' may introduce wide characters or strings.  */ | 
| +    case 'R': | 
| +      /* 'L', 'u', 'U', 'u8' or 'R' may introduce wide characters, | 
| +	 wide strings or raw strings.  */ | 
| if (c == 'L' || CPP_OPTION (pfile, uliterals)) | 
| { | 
| -	  if (*buffer->cur == '\'' || *buffer->cur == '"') | 
| +	  if ((*buffer->cur == '\'' && c != 'R') | 
| +	      || *buffer->cur == '"' | 
| +	      || (*buffer->cur == 'R' | 
| +		  && c != 'R' | 
| +		  && buffer->cur[1] == '"' | 
| +		  && CPP_OPTION (pfile, uliterals)) | 
| +	      || (*buffer->cur == '8' | 
| +		  && c == 'u' | 
| +		  && (buffer->cur[1] == '"' | 
| +		      || (buffer->cur[1] == 'R' && buffer->cur[2] == '"')))) | 
| { | 
| lex_string (pfile, result, buffer->cur - 1); | 
| break; | 
| @@ -1165,22 +1481,22 @@ _cpp_lex_direct (cpp_reader *pfile) | 
| case 'y': case 'z': | 
| case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': | 
| case 'G': case 'H': case 'I': case 'J': case 'K': | 
| -    case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': | 
| +    case 'M': case 'N': case 'O': case 'P': case 'Q': | 
| case 'S': case 'T':           case 'V': case 'W': case 'X': | 
| case 'Y': case 'Z': | 
| result->type = CPP_NAME; | 
| { | 
| struct normalize_state nst = INITIAL_NORMALIZE_STATE; | 
| -	result->val.node = lex_identifier (pfile, buffer->cur - 1, false, | 
| -					   &nst); | 
| +	result->val.node.node = lex_identifier (pfile, buffer->cur - 1, false, | 
| +						&nst); | 
| warn_about_normalization (pfile, result, &nst); | 
| } | 
|  | 
| /* Convert named operators to their proper types.  */ | 
| -      if (result->val.node->flags & NODE_OPERATOR) | 
| +      if (result->val.node.node->flags & NODE_OPERATOR) | 
| { | 
| result->flags |= NAMED_OP; | 
| -	  result->type = (enum cpp_ttype) result->val.node->directive_index; | 
| +	  result->type = (enum cpp_ttype) result->val.node.node->directive_index; | 
| } | 
| break; | 
|  | 
| @@ -1295,7 +1611,7 @@ _cpp_lex_direct (cpp_reader *pfile) | 
| result->flags |= DIGRAPH; | 
| result->type = CPP_HASH; | 
| if (*buffer->cur == '%' && buffer->cur[1] == ':') | 
| -		buffer->cur += 2, result->type = CPP_PASTE; | 
| +		buffer->cur += 2, result->type = CPP_PASTE, result->val.token_no = 0; | 
| } | 
| else if (*buffer->cur == '>') | 
| { | 
| @@ -1376,7 +1692,7 @@ _cpp_lex_direct (cpp_reader *pfile) | 
| case '=': IF_NEXT_IS ('=', CPP_EQ_EQ, CPP_EQ); break; | 
| case '!': IF_NEXT_IS ('=', CPP_NOT_EQ, CPP_NOT); break; | 
| case '^': IF_NEXT_IS ('=', CPP_XOR_EQ, CPP_XOR); break; | 
| -    case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); break; | 
| +    case '#': IF_NEXT_IS ('#', CPP_PASTE, CPP_HASH); result->val.token_no = 0; break; | 
|  | 
| case '?': result->type = CPP_QUERY; break; | 
| case '~': result->type = CPP_COMPL; break; | 
| @@ -1401,7 +1717,7 @@ _cpp_lex_direct (cpp_reader *pfile) | 
| if (forms_identifier_p (pfile, true, &nst)) | 
| { | 
| result->type = CPP_NAME; | 
| -	    result->val.node = lex_identifier (pfile, base, true, &nst); | 
| +	    result->val.node.node = lex_identifier (pfile, base, true, &nst); | 
| warn_about_normalization (pfile, result, &nst); | 
| break; | 
| } | 
| @@ -1427,7 +1743,7 @@ cpp_token_len (const cpp_token *token) | 
| { | 
| default:		len = 6;				break; | 
| case SPELL_LITERAL:	len = token->val.str.len;		break; | 
| -    case SPELL_IDENT:	len = NODE_LEN (token->val.node) * 10;	break; | 
| +    case SPELL_IDENT:	len = NODE_LEN (token->val.node.node) * 10;	break; | 
| } | 
|  | 
| return len; | 
| @@ -1467,6 +1783,13 @@ utf8_to_ucn (unsigned char *buffer, const unsigned char *name) | 
| 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. | 
| @@ -1486,8 +1809,7 @@ cpp_spell_token (cpp_reader *pfile, const cpp_token *token, | 
| 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 | 
| @@ -1502,23 +1824,23 @@ cpp_spell_token (cpp_reader *pfile, const cpp_token *token, | 
| case SPELL_IDENT: | 
| if (forstring) | 
| { | 
| -	  memcpy (buffer, NODE_NAME (token->val.node), | 
| -		  NODE_LEN (token->val.node)); | 
| -	  buffer += NODE_LEN (token->val.node); | 
| +	  memcpy (buffer, NODE_NAME (token->val.node.node), | 
| +		  NODE_LEN (token->val.node.node)); | 
| +	  buffer += NODE_LEN (token->val.node.node); | 
| } | 
| else | 
| { | 
| size_t i; | 
| -	  const unsigned char * name = NODE_NAME (token->val.node); | 
| +	  const unsigned char * name = NODE_NAME (token->val.node.node); | 
|  | 
| -	  for (i = 0; i < NODE_LEN (token->val.node); i++) | 
| +	  for (i = 0; i < NODE_LEN (token->val.node.node); i++) | 
| if (name[i] & ~0x7F) | 
| { | 
| i += utf8_to_ucn (buffer, name + i) - 1; | 
| buffer += 10; | 
| } | 
| else | 
| -	      *buffer++ = NODE_NAME (token->val.node)[i]; | 
| +	      *buffer++ = NODE_NAME (token->val.node.node)[i]; | 
| } | 
| break; | 
|  | 
| @@ -1550,11 +1872,17 @@ cpp_token_as_text (cpp_reader *pfile, const cpp_token *token) | 
| 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; | 
| } | 
|  | 
| @@ -1572,8 +1900,7 @@ cpp_output_token (const cpp_token *token, FILE *fp) | 
| 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 | 
| @@ -1590,9 +1917,9 @@ cpp_output_token (const cpp_token *token, FILE *fp) | 
| case SPELL_IDENT: | 
| { | 
| size_t i; | 
| -	const unsigned char * name = NODE_NAME (token->val.node); | 
| +	const unsigned char * name = NODE_NAME (token->val.node.node); | 
|  | 
| -	for (i = 0; i < NODE_LEN (token->val.node); i++) | 
| +	for (i = 0; i < NODE_LEN (token->val.node.node); i++) | 
| if (name[i] & ~0x7F) | 
| { | 
| unsigned char buffer[10]; | 
| @@ -1600,7 +1927,7 @@ cpp_output_token (const cpp_token *token, FILE *fp) | 
| fwrite (buffer, 1, 10, fp); | 
| } | 
| else | 
| -	    fputc (NODE_NAME (token->val.node)[i], fp); | 
| +	    fputc (NODE_NAME (token->val.node.node)[i], fp); | 
| } | 
| break; | 
|  | 
| @@ -1623,11 +1950,14 @@ _cpp_equiv_tokens (const cpp_token *a, const cpp_token *b) | 
| { | 
| default:			/* Keep compiler happy.  */ | 
| case SPELL_OPERATOR: | 
| -	return 1; | 
| +	/* token_no is used to track where multiple consecutive ## | 
| +	   tokens were originally located.  */ | 
| +	return (a->type != CPP_PASTE || a->val.token_no == b->val.token_no); | 
| case SPELL_NONE: | 
| -	return (a->type != CPP_MACRO_ARG || a->val.arg_no == b->val.arg_no); | 
| +	return (a->type != CPP_MACRO_ARG | 
| +		|| a->val.macro_arg.arg_no == b->val.macro_arg.arg_no); | 
| case SPELL_IDENT: | 
| -	return a->val.node == b->val.node; | 
| +	return a->val.node.node == b->val.node.node; | 
| case SPELL_LITERAL: | 
| return (a->val.str.len == b->val.str.len | 
| && !memcmp (a->val.str.text, b->val.str.text, | 
| @@ -1937,6 +2267,11 @@ cpp_token_val_index (cpp_token *tok) | 
| return CPP_TOKEN_FLD_NODE; | 
| case SPELL_LITERAL: | 
| return CPP_TOKEN_FLD_STR; | 
| +    case SPELL_OPERATOR: | 
| +      if (tok->type == CPP_PASTE) | 
| +	return CPP_TOKEN_FLD_TOKEN_NO; | 
| +      else | 
| +	return CPP_TOKEN_FLD_NONE; | 
| case SPELL_NONE: | 
| if (tok->type == CPP_MACRO_ARG) | 
| return CPP_TOKEN_FLD_ARG_NO; | 
|  |