mirror of git://gcc.gnu.org/git/gcc.git
				
				
				
			
		
			
				
	
	
		
			2171 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			2171 lines
		
	
	
		
			59 KiB
		
	
	
	
		
			C
		
	
	
	
/* Parse C expressions for cpplib.
 | 
						||
   Copyright (C) 1987-2014 Free Software Foundation, Inc.
 | 
						||
   Contributed by Per Bothner, 1994.
 | 
						||
 | 
						||
This program is free software; you can redistribute it and/or modify it
 | 
						||
under the terms of the GNU General Public License as published by the
 | 
						||
Free Software Foundation; either version 3, or (at your option) any
 | 
						||
later version.
 | 
						||
 | 
						||
This program is distributed in the hope that it will be useful,
 | 
						||
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						||
GNU General Public License for more details.
 | 
						||
 | 
						||
You should have received a copy of the GNU General Public License
 | 
						||
along with this program; see the file COPYING3.  If not see
 | 
						||
<http://www.gnu.org/licenses/>.  */
 | 
						||
 | 
						||
#include "config.h"
 | 
						||
#include "system.h"
 | 
						||
#include "cpplib.h"
 | 
						||
#include "internal.h"
 | 
						||
 | 
						||
#define PART_PRECISION (sizeof (cpp_num_part) * CHAR_BIT)
 | 
						||
#define HALF_MASK (~(cpp_num_part) 0 >> (PART_PRECISION / 2))
 | 
						||
#define LOW_PART(num_part) (num_part & HALF_MASK)
 | 
						||
#define HIGH_PART(num_part) (num_part >> (PART_PRECISION / 2))
 | 
						||
 | 
						||
struct op
 | 
						||
{
 | 
						||
  const cpp_token *token;	/* The token forming op (for diagnostics).  */
 | 
						||
  cpp_num value;		/* The value logically "right" of op.  */
 | 
						||
  source_location loc;          /* The location of this value.         */
 | 
						||
  enum cpp_ttype op;
 | 
						||
};
 | 
						||
 | 
						||
/* Some simple utility routines on double integers.  */
 | 
						||
#define num_zerop(num) ((num.low | num.high) == 0)
 | 
						||
#define num_eq(num1, num2) (num1.low == num2.low && num1.high == num2.high)
 | 
						||
static bool num_positive (cpp_num, size_t);
 | 
						||
static bool num_greater_eq (cpp_num, cpp_num, size_t);
 | 
						||
static cpp_num num_trim (cpp_num, size_t);
 | 
						||
static cpp_num num_part_mul (cpp_num_part, cpp_num_part);
 | 
						||
 | 
						||
static cpp_num num_unary_op (cpp_reader *, cpp_num, enum cpp_ttype);
 | 
						||
static cpp_num num_binary_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
 | 
						||
static cpp_num num_negate (cpp_num, size_t);
 | 
						||
static cpp_num num_bitwise_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype);
 | 
						||
static cpp_num num_inequality_op (cpp_reader *, cpp_num, cpp_num,
 | 
						||
				  enum cpp_ttype);
 | 
						||
static cpp_num num_equality_op (cpp_reader *, cpp_num, cpp_num,
 | 
						||
				enum cpp_ttype);
 | 
						||
static cpp_num num_mul (cpp_reader *, cpp_num, cpp_num);
 | 
						||
static cpp_num num_div_op (cpp_reader *, cpp_num, cpp_num, enum cpp_ttype,
 | 
						||
			   source_location);
 | 
						||
static cpp_num num_lshift (cpp_num, size_t, size_t);
 | 
						||
static cpp_num num_rshift (cpp_num, size_t, size_t);
 | 
						||
 | 
						||
static cpp_num append_digit (cpp_num, int, int, size_t);
 | 
						||
static cpp_num parse_defined (cpp_reader *);
 | 
						||
static cpp_num eval_token (cpp_reader *, const cpp_token *, source_location);
 | 
						||
static struct op *reduce (cpp_reader *, struct op *, enum cpp_ttype);
 | 
						||
static unsigned int interpret_float_suffix (cpp_reader *, const uchar *, size_t);
 | 
						||
static unsigned int interpret_int_suffix (cpp_reader *, const uchar *, size_t);
 | 
						||
static void check_promotion (cpp_reader *, const struct op *);
 | 
						||
 | 
						||
static cpp_num parse_has_include (cpp_reader *, enum include_type);
 | 
						||
static cpp_num parse_has_attribute (cpp_reader *);
 | 
						||
 | 
						||
/* Token type abuse to create unary plus and minus operators.  */
 | 
						||
#define CPP_UPLUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 1))
 | 
						||
#define CPP_UMINUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 2))
 | 
						||
 | 
						||
/* With -O2, gcc appears to produce nice code, moving the error
 | 
						||
   message load and subsequent jump completely out of the main path.  */
 | 
						||
#define SYNTAX_ERROR(msgid) \
 | 
						||
  do { cpp_error (pfile, CPP_DL_ERROR, msgid); goto syntax_error; } while(0)
 | 
						||
#define SYNTAX_ERROR2(msgid, arg) \
 | 
						||
  do { cpp_error (pfile, CPP_DL_ERROR, msgid, arg); goto syntax_error; } \
 | 
						||
  while(0)
 | 
						||
#define SYNTAX_ERROR_AT(loc, msgid) \
 | 
						||
  do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid); goto syntax_error; } \
 | 
						||
  while(0)
 | 
						||
#define SYNTAX_ERROR2_AT(loc, msgid, arg)					\
 | 
						||
  do { cpp_error_with_line (pfile, CPP_DL_ERROR, (loc), 0, msgid, arg); goto syntax_error; } \
 | 
						||
  while(0)
 | 
						||
 | 
						||
/* Subroutine of cpp_classify_number.  S points to a float suffix of
 | 
						||
   length LEN, possibly zero.  Returns 0 for an invalid suffix, or a
 | 
						||
   flag vector describing the suffix.  */
 | 
						||
static unsigned int
 | 
						||
interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 | 
						||
{
 | 
						||
  size_t flags;
 | 
						||
  size_t f, d, l, w, q, i;
 | 
						||
 | 
						||
  flags = 0;
 | 
						||
  f = d = l = w = q = i = 0;
 | 
						||
 | 
						||
  /* Process decimal float suffixes, which are two letters starting
 | 
						||
     with d or D.  Order and case are significant.  */
 | 
						||
  if (len == 2 && (*s == 'd' || *s == 'D'))
 | 
						||
    {
 | 
						||
      bool uppercase = (*s == 'D');
 | 
						||
      switch (s[1])
 | 
						||
      {
 | 
						||
      case 'f': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_SMALL): 0); break;
 | 
						||
      case 'F': return (uppercase ? (CPP_N_DFLOAT | CPP_N_SMALL) : 0); break;
 | 
						||
      case 'd': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_MEDIUM): 0); break;
 | 
						||
      case 'D': return (uppercase ? (CPP_N_DFLOAT | CPP_N_MEDIUM) : 0); break;
 | 
						||
      case 'l': return (!uppercase ? (CPP_N_DFLOAT | CPP_N_LARGE) : 0); break;
 | 
						||
      case 'L': return (uppercase ? (CPP_N_DFLOAT | CPP_N_LARGE) : 0); break;
 | 
						||
      default:
 | 
						||
	/* Additional two-character suffixes beginning with D are not
 | 
						||
	   for decimal float constants.  */
 | 
						||
	break;
 | 
						||
      }
 | 
						||
    }
 | 
						||
 | 
						||
  if (CPP_OPTION (pfile, ext_numeric_literals))
 | 
						||
    {
 | 
						||
      /* Recognize a fixed-point suffix.  */
 | 
						||
      if (len != 0)
 | 
						||
	switch (s[len-1])
 | 
						||
	  {
 | 
						||
	  case 'k': case 'K': flags = CPP_N_ACCUM; break;
 | 
						||
	  case 'r': case 'R': flags = CPP_N_FRACT; break;
 | 
						||
	  default: break;
 | 
						||
	  }
 | 
						||
 | 
						||
      /* Continue processing a fixed-point suffix.  The suffix is case
 | 
						||
	 insensitive except for ll or LL.  Order is significant.  */
 | 
						||
      if (flags)
 | 
						||
	{
 | 
						||
	  if (len == 1)
 | 
						||
	    return flags;
 | 
						||
	  len--;
 | 
						||
 | 
						||
	  if (*s == 'u' || *s == 'U')
 | 
						||
	    {
 | 
						||
	      flags |= CPP_N_UNSIGNED;
 | 
						||
	      if (len == 1)
 | 
						||
		return flags;
 | 
						||
	      len--;
 | 
						||
	      s++;
 | 
						||
            }
 | 
						||
 | 
						||
	  switch (*s)
 | 
						||
	  {
 | 
						||
	  case 'h': case 'H':
 | 
						||
	    if (len == 1)
 | 
						||
	      return flags |= CPP_N_SMALL;
 | 
						||
	    break;
 | 
						||
	  case 'l':
 | 
						||
	    if (len == 1)
 | 
						||
	      return flags |= CPP_N_MEDIUM;
 | 
						||
	    if (len == 2 && s[1] == 'l')
 | 
						||
	      return flags |= CPP_N_LARGE;
 | 
						||
	    break;
 | 
						||
	  case 'L':
 | 
						||
	    if (len == 1)
 | 
						||
	      return flags |= CPP_N_MEDIUM;
 | 
						||
	    if (len == 2 && s[1] == 'L')
 | 
						||
	      return flags |= CPP_N_LARGE;
 | 
						||
	    break;
 | 
						||
	  default:
 | 
						||
	    break;
 | 
						||
	  }
 | 
						||
	  /* Anything left at this point is invalid.  */
 | 
						||
	  return 0;
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  /* In any remaining valid suffix, the case and order don't matter.  */
 | 
						||
  while (len--)
 | 
						||
    switch (s[len])
 | 
						||
      {
 | 
						||
      case 'f': case 'F': f++; break;
 | 
						||
      case 'd': case 'D': d++; break;
 | 
						||
      case 'l': case 'L': l++; break;
 | 
						||
      case 'w': case 'W': w++; break;
 | 
						||
      case 'q': case 'Q': q++; break;
 | 
						||
      case 'i': case 'I':
 | 
						||
      case 'j': case 'J': i++; break;
 | 
						||
      default:
 | 
						||
	return 0;
 | 
						||
      }
 | 
						||
 | 
						||
  if (f + d + l + w + q > 1 || i > 1)
 | 
						||
    return 0;
 | 
						||
 | 
						||
  if (i && !CPP_OPTION (pfile, ext_numeric_literals))
 | 
						||
    return 0;
 | 
						||
 | 
						||
  if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals))
 | 
						||
    return 0;
 | 
						||
 | 
						||
  return ((i ? CPP_N_IMAGINARY : 0)
 | 
						||
	  | (f ? CPP_N_SMALL :
 | 
						||
	     d ? CPP_N_MEDIUM :
 | 
						||
	     l ? CPP_N_LARGE :
 | 
						||
	     w ? CPP_N_MD_W :
 | 
						||
	     q ? CPP_N_MD_Q : CPP_N_DEFAULT));
 | 
						||
}
 | 
						||
 | 
						||
/* Return the classification flags for a float suffix.  */
 | 
						||
unsigned int
 | 
						||
cpp_interpret_float_suffix (cpp_reader *pfile, const char *s, size_t len)
 | 
						||
{
 | 
						||
  return interpret_float_suffix (pfile, (const unsigned char *)s, len);
 | 
						||
}
 | 
						||
 | 
						||
/* Subroutine of cpp_classify_number.  S points to an integer suffix
 | 
						||
   of length LEN, possibly zero. Returns 0 for an invalid suffix, or a
 | 
						||
   flag vector describing the suffix.  */
 | 
						||
static unsigned int
 | 
						||
interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 | 
						||
{
 | 
						||
  size_t u, l, i;
 | 
						||
 | 
						||
  u = l = i = 0;
 | 
						||
 | 
						||
  while (len--)
 | 
						||
    switch (s[len])
 | 
						||
      {
 | 
						||
      case 'u': case 'U':	u++; break;
 | 
						||
      case 'i': case 'I':
 | 
						||
      case 'j': case 'J':	i++; break;
 | 
						||
      case 'l': case 'L':	l++;
 | 
						||
	/* If there are two Ls, they must be adjacent and the same case.  */
 | 
						||
	if (l == 2 && s[len] != s[len + 1])
 | 
						||
	  return 0;
 | 
						||
	break;
 | 
						||
      default:
 | 
						||
	return 0;
 | 
						||
      }
 | 
						||
 | 
						||
  if (l > 2 || u > 1 || i > 1)
 | 
						||
    return 0;
 | 
						||
 | 
						||
  if (i && !CPP_OPTION (pfile, ext_numeric_literals))
 | 
						||
    return 0;
 | 
						||
 | 
						||
  return ((i ? CPP_N_IMAGINARY : 0)
 | 
						||
	  | (u ? CPP_N_UNSIGNED : 0)
 | 
						||
	  | ((l == 0) ? CPP_N_SMALL
 | 
						||
	     : (l == 1) ? CPP_N_MEDIUM : CPP_N_LARGE));
 | 
						||
}
 | 
						||
 | 
						||
/* Return the classification flags for an int suffix.  */
 | 
						||
unsigned int
 | 
						||
cpp_interpret_int_suffix (cpp_reader *pfile, const char *s, size_t len)
 | 
						||
{
 | 
						||
  return interpret_int_suffix (pfile, (const unsigned char *)s, len);
 | 
						||
}
 | 
						||
 | 
						||
/* Return the string type corresponding to the the input user-defined string
 | 
						||
   literal type.  If the input type is not a user-defined string literal
 | 
						||
   type return the input type.  */
 | 
						||
enum cpp_ttype
 | 
						||
cpp_userdef_string_remove_type (enum cpp_ttype type)
 | 
						||
{
 | 
						||
  if (type == CPP_STRING_USERDEF)
 | 
						||
    return CPP_STRING;
 | 
						||
  else if (type == CPP_WSTRING_USERDEF)
 | 
						||
    return CPP_WSTRING;
 | 
						||
  else if (type == CPP_STRING16_USERDEF)
 | 
						||
    return CPP_STRING16;
 | 
						||
  else if (type == CPP_STRING32_USERDEF)
 | 
						||
    return CPP_STRING32;
 | 
						||
  else if (type == CPP_UTF8STRING_USERDEF)
 | 
						||
    return CPP_UTF8STRING;
 | 
						||
  else
 | 
						||
    return type;
 | 
						||
}
 | 
						||
 | 
						||
/* Return the user-defined string literal type corresponding to the input
 | 
						||
   string type.  If the input type is not a string type return the input
 | 
						||
   type.  */
 | 
						||
enum cpp_ttype
 | 
						||
cpp_userdef_string_add_type (enum cpp_ttype type)
 | 
						||
{
 | 
						||
  if (type == CPP_STRING)
 | 
						||
    return CPP_STRING_USERDEF;
 | 
						||
  else if (type == CPP_WSTRING)
 | 
						||
    return CPP_WSTRING_USERDEF;
 | 
						||
  else if (type == CPP_STRING16)
 | 
						||
    return CPP_STRING16_USERDEF;
 | 
						||
  else if (type == CPP_STRING32)
 | 
						||
    return CPP_STRING32_USERDEF;
 | 
						||
  else if (type == CPP_UTF8STRING)
 | 
						||
    return CPP_UTF8STRING_USERDEF;
 | 
						||
  else
 | 
						||
    return type;
 | 
						||
}
 | 
						||
 | 
						||
/* Return the char type corresponding to the the input user-defined char
 | 
						||
   literal type.  If the input type is not a user-defined char literal
 | 
						||
   type return the input type.  */
 | 
						||
enum cpp_ttype
 | 
						||
cpp_userdef_char_remove_type (enum cpp_ttype type)
 | 
						||
{
 | 
						||
  if (type == CPP_CHAR_USERDEF)
 | 
						||
    return CPP_CHAR;
 | 
						||
  else if (type == CPP_WCHAR_USERDEF)
 | 
						||
    return CPP_WCHAR;
 | 
						||
  else if (type == CPP_CHAR16_USERDEF)
 | 
						||
    return CPP_CHAR16;
 | 
						||
  else if (type == CPP_CHAR32_USERDEF)
 | 
						||
    return CPP_CHAR32;
 | 
						||
  else
 | 
						||
    return type;
 | 
						||
}
 | 
						||
 | 
						||
/* Return the user-defined char literal type corresponding to the input
 | 
						||
   char type.  If the input type is not a char type return the input
 | 
						||
   type.  */
 | 
						||
enum cpp_ttype
 | 
						||
cpp_userdef_char_add_type (enum cpp_ttype type)
 | 
						||
{
 | 
						||
  if (type == CPP_CHAR)
 | 
						||
    return CPP_CHAR_USERDEF;
 | 
						||
  else if (type == CPP_WCHAR)
 | 
						||
    return CPP_WCHAR_USERDEF;
 | 
						||
  else if (type == CPP_CHAR16)
 | 
						||
    return CPP_CHAR16_USERDEF;
 | 
						||
  else if (type == CPP_CHAR32)
 | 
						||
    return CPP_CHAR32_USERDEF;
 | 
						||
  else
 | 
						||
    return type;
 | 
						||
}
 | 
						||
 | 
						||
/* Return true if the token type is a user-defined string literal.  */
 | 
						||
bool
 | 
						||
cpp_userdef_string_p (enum cpp_ttype type)
 | 
						||
{
 | 
						||
  if (type == CPP_STRING_USERDEF
 | 
						||
   || type == CPP_WSTRING_USERDEF
 | 
						||
   || type == CPP_STRING16_USERDEF
 | 
						||
   || type == CPP_STRING32_USERDEF
 | 
						||
   || type == CPP_UTF8STRING_USERDEF)
 | 
						||
    return true;
 | 
						||
  else
 | 
						||
    return false;
 | 
						||
}
 | 
						||
 | 
						||
/* Return true if the token type is a user-defined char literal.  */
 | 
						||
bool
 | 
						||
cpp_userdef_char_p (enum cpp_ttype type)
 | 
						||
{
 | 
						||
  if (type == CPP_CHAR_USERDEF
 | 
						||
   || type == CPP_WCHAR_USERDEF
 | 
						||
   || type == CPP_CHAR16_USERDEF
 | 
						||
   || type == CPP_CHAR32_USERDEF)
 | 
						||
    return true;
 | 
						||
  else
 | 
						||
    return false;
 | 
						||
}
 | 
						||
 | 
						||
/* Extract the suffix from a user-defined literal string or char.  */
 | 
						||
const char *
 | 
						||
cpp_get_userdef_suffix (const cpp_token *tok)
 | 
						||
{
 | 
						||
  unsigned int len = tok->val.str.len;
 | 
						||
  const char *text = (const char *)tok->val.str.text;
 | 
						||
  char delim;
 | 
						||
  unsigned int i;
 | 
						||
  for (i = 0; i < len; ++i)
 | 
						||
    if (text[i] == '\'' || text[i] == '"')
 | 
						||
      break;
 | 
						||
  if (i == len)
 | 
						||
    return text + len;
 | 
						||
  delim = text[i];
 | 
						||
  for (i = len; i > 0; --i)
 | 
						||
    if (text[i - 1] == delim)
 | 
						||
      break;
 | 
						||
  return text + i;
 | 
						||
}
 | 
						||
 | 
						||
/* Categorize numeric constants according to their field (integer,
 | 
						||
   floating point, or invalid), radix (decimal, octal, hexadecimal),
 | 
						||
   and type suffixes.
 | 
						||
 | 
						||
   TOKEN is the token that represents the numeric constant to
 | 
						||
   classify.
 | 
						||
 | 
						||
   In C++0X if UD_SUFFIX is non null it will be assigned
 | 
						||
   any unrecognized suffix for a user-defined literal.
 | 
						||
 | 
						||
   VIRTUAL_LOCATION is the virtual location for TOKEN.  */
 | 
						||
unsigned int
 | 
						||
cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
 | 
						||
		     const char **ud_suffix, source_location virtual_location)
 | 
						||
{
 | 
						||
  const uchar *str = token->val.str.text;
 | 
						||
  const uchar *limit;
 | 
						||
  unsigned int max_digit, result, radix;
 | 
						||
  enum {NOT_FLOAT = 0, AFTER_POINT, AFTER_EXPON} float_flag;
 | 
						||
  bool seen_digit;
 | 
						||
  bool seen_digit_sep;
 | 
						||
 | 
						||
  if (ud_suffix)
 | 
						||
    *ud_suffix = NULL;
 | 
						||
 | 
						||
  /* If the lexer has done its job, length one can only be a single
 | 
						||
     digit.  Fast-path this very common case.  */
 | 
						||
  if (token->val.str.len == 1)
 | 
						||
    return CPP_N_INTEGER | CPP_N_SMALL | CPP_N_DECIMAL;
 | 
						||
 | 
						||
  limit = str + token->val.str.len;
 | 
						||
  float_flag = NOT_FLOAT;
 | 
						||
  max_digit = 0;
 | 
						||
  radix = 10;
 | 
						||
  seen_digit = false;
 | 
						||
  seen_digit_sep = false;
 | 
						||
 | 
						||
  /* First, interpret the radix.  */
 | 
						||
  if (*str == '0')
 | 
						||
    {
 | 
						||
      radix = 8;
 | 
						||
      str++;
 | 
						||
 | 
						||
      /* Require at least one hex digit to classify it as hex.  */
 | 
						||
      if (*str == 'x' || *str == 'X')
 | 
						||
	{
 | 
						||
	  if (str[1] == '.' || ISXDIGIT (str[1]))
 | 
						||
	    {
 | 
						||
	      radix = 16;
 | 
						||
	      str++;
 | 
						||
	    }
 | 
						||
	  else if (DIGIT_SEP (str[1]))
 | 
						||
	    SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			     "digit separator after base indicator");
 | 
						||
	}
 | 
						||
      else if (*str == 'b' || *str == 'B')
 | 
						||
	{
 | 
						||
	  if (str[1] == '0' || str[1] == '1')
 | 
						||
	    {
 | 
						||
	      radix = 2;
 | 
						||
	      str++;
 | 
						||
	    }
 | 
						||
	  else if (DIGIT_SEP (str[1]))
 | 
						||
	    SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			     "digit separator after base indicator");
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  /* Now scan for a well-formed integer or float.  */
 | 
						||
  for (;;)
 | 
						||
    {
 | 
						||
      unsigned int c = *str++;
 | 
						||
 | 
						||
      if (ISDIGIT (c) || (ISXDIGIT (c) && radix == 16))
 | 
						||
	{
 | 
						||
	  seen_digit_sep = false;
 | 
						||
	  seen_digit = true;
 | 
						||
	  c = hex_value (c);
 | 
						||
	  if (c > max_digit)
 | 
						||
	    max_digit = c;
 | 
						||
	}
 | 
						||
      else if (DIGIT_SEP (c))
 | 
						||
	{
 | 
						||
	  if (seen_digit_sep)
 | 
						||
	    SYNTAX_ERROR_AT (virtual_location, "adjacent digit separators");
 | 
						||
	  seen_digit_sep = true;
 | 
						||
	}
 | 
						||
      else if (c == '.')
 | 
						||
	{
 | 
						||
	  if (seen_digit_sep || DIGIT_SEP (*str))
 | 
						||
	    SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			     "digit separator adjacent to decimal point");
 | 
						||
	  seen_digit_sep = false;
 | 
						||
	  if (float_flag == NOT_FLOAT)
 | 
						||
	    float_flag = AFTER_POINT;
 | 
						||
	  else
 | 
						||
	    SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			     "too many decimal points in number");
 | 
						||
	}
 | 
						||
      else if ((radix <= 10 && (c == 'e' || c == 'E'))
 | 
						||
	       || (radix == 16 && (c == 'p' || c == 'P')))
 | 
						||
	{
 | 
						||
	  if (seen_digit_sep || DIGIT_SEP (*str))
 | 
						||
	    SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			     "digit separator adjacent to exponent");
 | 
						||
	  float_flag = AFTER_EXPON;
 | 
						||
	  break;
 | 
						||
	}
 | 
						||
      else
 | 
						||
	{
 | 
						||
	  /* Start of suffix.  */
 | 
						||
	  str--;
 | 
						||
	  break;
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  if (seen_digit_sep && float_flag != AFTER_EXPON)
 | 
						||
    SYNTAX_ERROR_AT (virtual_location,
 | 
						||
		     "digit separator outside digit sequence");
 | 
						||
 | 
						||
  /* The suffix may be for decimal fixed-point constants without exponent.  */
 | 
						||
  if (radix != 16 && float_flag == NOT_FLOAT)
 | 
						||
    {
 | 
						||
      result = interpret_float_suffix (pfile, str, limit - str);
 | 
						||
      if ((result & CPP_N_FRACT) || (result & CPP_N_ACCUM))
 | 
						||
	{
 | 
						||
	  result |= CPP_N_FLOATING;
 | 
						||
	  /* We need to restore the radix to 10, if the radix is 8.  */
 | 
						||
	  if (radix == 8)
 | 
						||
	    radix = 10;
 | 
						||
 | 
						||
	  if (CPP_PEDANTIC (pfile))
 | 
						||
	    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
				 "fixed-point constants are a GCC extension");
 | 
						||
	  goto syntax_ok;
 | 
						||
	}
 | 
						||
      else
 | 
						||
	result = 0;
 | 
						||
    }
 | 
						||
 | 
						||
  if (float_flag != NOT_FLOAT && radix == 8)
 | 
						||
    radix = 10;
 | 
						||
 | 
						||
  if (max_digit >= radix)
 | 
						||
    {
 | 
						||
      if (radix == 2)
 | 
						||
	SYNTAX_ERROR2_AT (virtual_location,
 | 
						||
			  "invalid digit \"%c\" in binary constant", '0' + max_digit);
 | 
						||
      else
 | 
						||
	SYNTAX_ERROR2_AT (virtual_location,
 | 
						||
			  "invalid digit \"%c\" in octal constant", '0' + max_digit);
 | 
						||
    }
 | 
						||
 | 
						||
  if (float_flag != NOT_FLOAT)
 | 
						||
    {
 | 
						||
      if (radix == 2)
 | 
						||
	{
 | 
						||
	  cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
 | 
						||
			       "invalid prefix \"0b\" for floating constant");
 | 
						||
	  return CPP_N_INVALID;
 | 
						||
	}
 | 
						||
 | 
						||
      if (radix == 16 && !seen_digit)
 | 
						||
	SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			 "no digits in hexadecimal floating constant");
 | 
						||
 | 
						||
      if (radix == 16 && CPP_PEDANTIC (pfile)
 | 
						||
	  && !CPP_OPTION (pfile, extended_numbers))
 | 
						||
	{
 | 
						||
	  if (CPP_OPTION (pfile, cplusplus))
 | 
						||
	    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
				 "use of C++11 hexadecimal floating constant");
 | 
						||
	  else
 | 
						||
	    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
				 "use of C99 hexadecimal floating constant");
 | 
						||
	}
 | 
						||
 | 
						||
      if (float_flag == AFTER_EXPON)
 | 
						||
	{
 | 
						||
	  if (*str == '+' || *str == '-')
 | 
						||
	    str++;
 | 
						||
 | 
						||
	  /* Exponent is decimal, even if string is a hex float.  */
 | 
						||
	  if (!ISDIGIT (*str))
 | 
						||
	    {
 | 
						||
	      if (DIGIT_SEP (*str))
 | 
						||
		SYNTAX_ERROR_AT (virtual_location,
 | 
						||
				 "digit separator adjacent to exponent");
 | 
						||
	      else
 | 
						||
		SYNTAX_ERROR_AT (virtual_location, "exponent has no digits");
 | 
						||
	    }
 | 
						||
	  do
 | 
						||
	    {
 | 
						||
	      seen_digit_sep = DIGIT_SEP (*str);
 | 
						||
	      str++;
 | 
						||
	    }
 | 
						||
	  while (ISDIGIT (*str) || DIGIT_SEP (*str));
 | 
						||
	}
 | 
						||
      else if (radix == 16)
 | 
						||
	SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			 "hexadecimal floating constants require an exponent");
 | 
						||
 | 
						||
      if (seen_digit_sep)
 | 
						||
	SYNTAX_ERROR_AT (virtual_location,
 | 
						||
			 "digit separator outside digit sequence");
 | 
						||
 | 
						||
      result = interpret_float_suffix (pfile, str, limit - str);
 | 
						||
      if (result == 0)
 | 
						||
	{
 | 
						||
	  if (CPP_OPTION (pfile, user_literals))
 | 
						||
	    {
 | 
						||
	      if (ud_suffix)
 | 
						||
		*ud_suffix = (const char *) str;
 | 
						||
	      result = CPP_N_LARGE | CPP_N_USERDEF;
 | 
						||
	    }
 | 
						||
	  else
 | 
						||
	    {
 | 
						||
	      cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
 | 
						||
				   "invalid suffix \"%.*s\" on floating constant",
 | 
						||
				   (int) (limit - str), str);
 | 
						||
	      return CPP_N_INVALID;
 | 
						||
	    }
 | 
						||
	}
 | 
						||
 | 
						||
      /* Traditional C didn't accept any floating suffixes.  */
 | 
						||
      if (limit != str
 | 
						||
	  && CPP_WTRADITIONAL (pfile)
 | 
						||
	  && ! cpp_sys_macro_p (pfile))
 | 
						||
	cpp_warning_with_line (pfile, CPP_W_TRADITIONAL, virtual_location, 0,
 | 
						||
			       "traditional C rejects the \"%.*s\" suffix",
 | 
						||
			       (int) (limit - str), str);
 | 
						||
 | 
						||
      /* A suffix for double is a GCC extension via decimal float support.
 | 
						||
	 If the suffix also specifies an imaginary value we'll catch that
 | 
						||
	 later.  */
 | 
						||
      if ((result == CPP_N_MEDIUM) && CPP_PEDANTIC (pfile))
 | 
						||
	cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
			     "suffix for double constant is a GCC extension");
 | 
						||
 | 
						||
      /* Radix must be 10 for decimal floats.  */
 | 
						||
      if ((result & CPP_N_DFLOAT) && radix != 10)
 | 
						||
        {
 | 
						||
          cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
 | 
						||
			       "invalid suffix \"%.*s\" with hexadecimal floating constant",
 | 
						||
			       (int) (limit - str), str);
 | 
						||
          return CPP_N_INVALID;
 | 
						||
        }
 | 
						||
 | 
						||
      if ((result & (CPP_N_FRACT | CPP_N_ACCUM)) && CPP_PEDANTIC (pfile))
 | 
						||
	cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
			     "fixed-point constants are a GCC extension");
 | 
						||
 | 
						||
      if ((result & CPP_N_DFLOAT) && CPP_PEDANTIC (pfile))
 | 
						||
	cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
			     "decimal float constants are a GCC extension");
 | 
						||
 | 
						||
      result |= CPP_N_FLOATING;
 | 
						||
    }
 | 
						||
  else
 | 
						||
    {
 | 
						||
      result = interpret_int_suffix (pfile, str, limit - str);
 | 
						||
      if (result == 0)
 | 
						||
	{
 | 
						||
	  if (CPP_OPTION (pfile, user_literals))
 | 
						||
	    {
 | 
						||
	      if (ud_suffix)
 | 
						||
		*ud_suffix = (const char *) str;
 | 
						||
	      result = CPP_N_UNSIGNED | CPP_N_LARGE | CPP_N_USERDEF;
 | 
						||
	    }
 | 
						||
	  else
 | 
						||
	    {
 | 
						||
	      cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
 | 
						||
				   "invalid suffix \"%.*s\" on integer constant",
 | 
						||
				   (int) (limit - str), str);
 | 
						||
	      return CPP_N_INVALID;
 | 
						||
	    }
 | 
						||
	}
 | 
						||
 | 
						||
      /* Traditional C only accepted the 'L' suffix.
 | 
						||
         Suppress warning about 'LL' with -Wno-long-long.  */
 | 
						||
      if (CPP_WTRADITIONAL (pfile) && ! cpp_sys_macro_p (pfile))
 | 
						||
	{
 | 
						||
	  int u_or_i = (result & (CPP_N_UNSIGNED|CPP_N_IMAGINARY));
 | 
						||
	  int large = (result & CPP_N_WIDTH) == CPP_N_LARGE
 | 
						||
		       && CPP_OPTION (pfile, cpp_warn_long_long);
 | 
						||
 | 
						||
	  if (u_or_i || large)
 | 
						||
	    cpp_warning_with_line (pfile, large ? CPP_W_LONG_LONG : CPP_W_TRADITIONAL,
 | 
						||
				   virtual_location, 0,
 | 
						||
				   "traditional C rejects the \"%.*s\" suffix",
 | 
						||
				   (int) (limit - str), str);
 | 
						||
	}
 | 
						||
 | 
						||
      if ((result & CPP_N_WIDTH) == CPP_N_LARGE
 | 
						||
	  && CPP_OPTION (pfile, cpp_warn_long_long))
 | 
						||
        {
 | 
						||
          const char *message = CPP_OPTION (pfile, cplusplus) 
 | 
						||
				? N_("use of C++11 long long integer constant")
 | 
						||
		                : N_("use of C99 long long integer constant");
 | 
						||
 | 
						||
	  if (CPP_OPTION (pfile, c99))
 | 
						||
            cpp_warning_with_line (pfile, CPP_W_LONG_LONG, virtual_location,
 | 
						||
				   0, message);
 | 
						||
          else
 | 
						||
            cpp_pedwarning_with_line (pfile, CPP_W_LONG_LONG,
 | 
						||
				      virtual_location, 0, message);
 | 
						||
        }
 | 
						||
 | 
						||
      result |= CPP_N_INTEGER;
 | 
						||
    }
 | 
						||
 | 
						||
 syntax_ok:
 | 
						||
  if ((result & CPP_N_IMAGINARY) && CPP_PEDANTIC (pfile))
 | 
						||
    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
			 "imaginary constants are a GCC extension");
 | 
						||
  if (radix == 2
 | 
						||
      && !CPP_OPTION (pfile, binary_constants)
 | 
						||
      && CPP_PEDANTIC (pfile))
 | 
						||
    cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
 | 
						||
			 CPP_OPTION (pfile, cplusplus)
 | 
						||
			 ? "binary constants are a C++14 feature "
 | 
						||
			   "or GCC extension"
 | 
						||
			 : "binary constants are a GCC extension");
 | 
						||
 | 
						||
  if (radix == 10)
 | 
						||
    result |= CPP_N_DECIMAL;
 | 
						||
  else if (radix == 16)
 | 
						||
    result |= CPP_N_HEX;
 | 
						||
  else if (radix == 2)
 | 
						||
    result |= CPP_N_BINARY;
 | 
						||
  else
 | 
						||
    result |= CPP_N_OCTAL;
 | 
						||
 | 
						||
  return result;
 | 
						||
 | 
						||
 syntax_error:
 | 
						||
  return CPP_N_INVALID;
 | 
						||
}
 | 
						||
 | 
						||
/* cpp_interpret_integer converts an integer constant into a cpp_num,
 | 
						||
   of precision options->precision.
 | 
						||
 | 
						||
   We do not provide any interface for decimal->float conversion,
 | 
						||
   because the preprocessor doesn't need it and we don't want to
 | 
						||
   drag in GCC's floating point emulator.  */
 | 
						||
cpp_num
 | 
						||
cpp_interpret_integer (cpp_reader *pfile, const cpp_token *token,
 | 
						||
		       unsigned int type)
 | 
						||
{
 | 
						||
  const uchar *p, *end;
 | 
						||
  cpp_num result;
 | 
						||
 | 
						||
  result.low = 0;
 | 
						||
  result.high = 0;
 | 
						||
  result.unsignedp = !!(type & CPP_N_UNSIGNED);
 | 
						||
  result.overflow = false;
 | 
						||
 | 
						||
  p = token->val.str.text;
 | 
						||
  end = p + token->val.str.len;
 | 
						||
 | 
						||
  /* Common case of a single digit.  */
 | 
						||
  if (token->val.str.len == 1)
 | 
						||
    result.low = p[0] - '0';
 | 
						||
  else
 | 
						||
    {
 | 
						||
      cpp_num_part max;
 | 
						||
      size_t precision = CPP_OPTION (pfile, precision);
 | 
						||
      unsigned int base = 10, c = 0;
 | 
						||
      bool overflow = false;
 | 
						||
 | 
						||
      if ((type & CPP_N_RADIX) == CPP_N_OCTAL)
 | 
						||
	{
 | 
						||
	  base = 8;
 | 
						||
	  p++;
 | 
						||
	}
 | 
						||
      else if ((type & CPP_N_RADIX) == CPP_N_HEX)
 | 
						||
	{
 | 
						||
	  base = 16;
 | 
						||
	  p += 2;
 | 
						||
	}
 | 
						||
      else if ((type & CPP_N_RADIX) == CPP_N_BINARY)
 | 
						||
	{
 | 
						||
	  base = 2;
 | 
						||
	  p += 2;
 | 
						||
	}
 | 
						||
 | 
						||
      /* We can add a digit to numbers strictly less than this without
 | 
						||
	 needing the precision and slowness of double integers.  */
 | 
						||
      max = ~(cpp_num_part) 0;
 | 
						||
      if (precision < PART_PRECISION)
 | 
						||
	max >>= PART_PRECISION - precision;
 | 
						||
      max = (max - base + 1) / base + 1;
 | 
						||
 | 
						||
      for (; p < end; p++)
 | 
						||
	{
 | 
						||
	  c = *p;
 | 
						||
 | 
						||
	  if (ISDIGIT (c) || (base == 16 && ISXDIGIT (c)))
 | 
						||
	    c = hex_value (c);
 | 
						||
	  else if (DIGIT_SEP (c))
 | 
						||
	    continue;
 | 
						||
	  else
 | 
						||
	    break;
 | 
						||
 | 
						||
	  /* Strict inequality for when max is set to zero.  */
 | 
						||
	  if (result.low < max)
 | 
						||
	    result.low = result.low * base + c;
 | 
						||
	  else
 | 
						||
	    {
 | 
						||
	      result = append_digit (result, c, base, precision);
 | 
						||
	      overflow |= result.overflow;
 | 
						||
	      max = 0;
 | 
						||
	    }
 | 
						||
	}
 | 
						||
 | 
						||
      if (overflow && !(type & CPP_N_USERDEF))
 | 
						||
	cpp_error (pfile, CPP_DL_PEDWARN,
 | 
						||
		   "integer constant is too large for its type");
 | 
						||
      /* If too big to be signed, consider it unsigned.  Only warn for
 | 
						||
	 decimal numbers.  Traditional numbers were always signed (but
 | 
						||
	 we still honor an explicit U suffix); but we only have
 | 
						||
	 traditional semantics in directives.  */
 | 
						||
      else if (!result.unsignedp
 | 
						||
	       && !(CPP_OPTION (pfile, traditional)
 | 
						||
		    && pfile->state.in_directive)
 | 
						||
	       && !num_positive (result, precision))
 | 
						||
	{
 | 
						||
	  /* This is for constants within the range of uintmax_t but
 | 
						||
	     not that of intmax_t.  For such decimal constants, a
 | 
						||
	     diagnostic is required for C99 as the selected type must
 | 
						||
	     be signed and not having a type is a constraint violation
 | 
						||
	     (DR#298, TC3), so this must be a pedwarn.  For C90,
 | 
						||
	     unsigned long is specified to be used for a constant that
 | 
						||
	     does not fit in signed long; if uintmax_t has the same
 | 
						||
	     range as unsigned long this means only a warning is
 | 
						||
	     appropriate here.  C90 permits the preprocessor to use a
 | 
						||
	     wider range than unsigned long in the compiler, so if
 | 
						||
	     uintmax_t is wider than unsigned long no diagnostic is
 | 
						||
	     required for such constants in preprocessor #if
 | 
						||
	     expressions and the compiler will pedwarn for such
 | 
						||
	     constants outside the range of unsigned long that reach
 | 
						||
	     the compiler so a diagnostic is not required there
 | 
						||
	     either; thus, pedwarn for C99 but use a plain warning for
 | 
						||
	     C90.  */
 | 
						||
	  if (base == 10)
 | 
						||
	    cpp_error (pfile, (CPP_OPTION (pfile, c99)
 | 
						||
			       ? CPP_DL_PEDWARN
 | 
						||
			       : CPP_DL_WARNING),
 | 
						||
		       "integer constant is so large that it is unsigned");
 | 
						||
	  result.unsignedp = true;
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  return result;
 | 
						||
}
 | 
						||
 | 
						||
/* Append DIGIT to NUM, a number of PRECISION bits being read in base BASE.  */
 | 
						||
static cpp_num
 | 
						||
append_digit (cpp_num num, int digit, int base, size_t precision)
 | 
						||
{
 | 
						||
  cpp_num result;
 | 
						||
  unsigned int shift;
 | 
						||
  bool overflow;
 | 
						||
  cpp_num_part add_high, add_low;
 | 
						||
 | 
						||
  /* Multiply by 2, 8 or 16.  Catching this overflow here means we don't
 | 
						||
     need to worry about add_high overflowing.  */
 | 
						||
  switch (base)
 | 
						||
    {
 | 
						||
    case 2:
 | 
						||
      shift = 1;
 | 
						||
      break;
 | 
						||
 | 
						||
    case 16:
 | 
						||
      shift = 4;
 | 
						||
      break;
 | 
						||
 | 
						||
    default:
 | 
						||
      shift = 3;
 | 
						||
    }
 | 
						||
  overflow = !!(num.high >> (PART_PRECISION - shift));
 | 
						||
  result.high = num.high << shift;
 | 
						||
  result.low = num.low << shift;
 | 
						||
  result.high |= num.low >> (PART_PRECISION - shift);
 | 
						||
  result.unsignedp = num.unsignedp;
 | 
						||
 | 
						||
  if (base == 10)
 | 
						||
    {
 | 
						||
      add_low = num.low << 1;
 | 
						||
      add_high = (num.high << 1) + (num.low >> (PART_PRECISION - 1));
 | 
						||
    }
 | 
						||
  else
 | 
						||
    add_high = add_low = 0;
 | 
						||
 | 
						||
  if (add_low + digit < add_low)
 | 
						||
    add_high++;
 | 
						||
  add_low += digit;
 | 
						||
 | 
						||
  if (result.low + add_low < result.low)
 | 
						||
    add_high++;
 | 
						||
  if (result.high + add_high < result.high)
 | 
						||
    overflow = true;
 | 
						||
 | 
						||
  result.low += add_low;
 | 
						||
  result.high += add_high;
 | 
						||
  result.overflow = overflow;
 | 
						||
 | 
						||
  /* The above code catches overflow of a cpp_num type.  This catches
 | 
						||
     overflow of the (possibly shorter) target precision.  */
 | 
						||
  num.low = result.low;
 | 
						||
  num.high = result.high;
 | 
						||
  result = num_trim (result, precision);
 | 
						||
  if (!num_eq (result, num))
 | 
						||
    result.overflow = true;
 | 
						||
 | 
						||
  return result;
 | 
						||
}
 | 
						||
 | 
						||
/* Handle meeting "defined" in a preprocessor expression.  */
 | 
						||
static cpp_num
 | 
						||
parse_defined (cpp_reader *pfile)
 | 
						||
{
 | 
						||
  cpp_num result;
 | 
						||
  int paren = 0;
 | 
						||
  cpp_hashnode *node = 0;
 | 
						||
  const cpp_token *token;
 | 
						||
  cpp_context *initial_context = pfile->context;
 | 
						||
 | 
						||
  /* Don't expand macros.  */
 | 
						||
  pfile->state.prevent_expansion++;
 | 
						||
 | 
						||
  token = cpp_get_token (pfile);
 | 
						||
  if (token->type == CPP_OPEN_PAREN)
 | 
						||
    {
 | 
						||
      paren = 1;
 | 
						||
      token = cpp_get_token (pfile);
 | 
						||
    }
 | 
						||
 | 
						||
  if (token->type == CPP_NAME)
 | 
						||
    {
 | 
						||
      node = token->val.node.node;
 | 
						||
      if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
 | 
						||
	{
 | 
						||
	  cpp_error (pfile, CPP_DL_ERROR, "missing ')' after \"defined\"");
 | 
						||
	  node = 0;
 | 
						||
	}
 | 
						||
    }
 | 
						||
  else
 | 
						||
    {
 | 
						||
      cpp_error (pfile, CPP_DL_ERROR,
 | 
						||
		 "operator \"defined\" requires an identifier");
 | 
						||
      if (token->flags & NAMED_OP)
 | 
						||
	{
 | 
						||
	  cpp_token op;
 | 
						||
 | 
						||
	  op.flags = 0;
 | 
						||
	  op.type = token->type;
 | 
						||
	  cpp_error (pfile, CPP_DL_ERROR,
 | 
						||
		     "(\"%s\" is an alternative token for \"%s\" in C++)",
 | 
						||
		     cpp_token_as_text (pfile, token),
 | 
						||
		     cpp_token_as_text (pfile, &op));
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  if (node)
 | 
						||
    {
 | 
						||
      if (pfile->context != initial_context && CPP_PEDANTIC (pfile))
 | 
						||
	cpp_error (pfile, CPP_DL_WARNING,
 | 
						||
		   "this use of \"defined\" may not be portable");
 | 
						||
 | 
						||
      _cpp_mark_macro_used (node);
 | 
						||
      if (!(node->flags & NODE_USED))
 | 
						||
	{
 | 
						||
	  node->flags |= NODE_USED;
 | 
						||
	  if (node->type == NT_MACRO)
 | 
						||
	    {
 | 
						||
	      if ((node->flags & NODE_BUILTIN)
 | 
						||
		  && pfile->cb.user_builtin_macro)
 | 
						||
		pfile->cb.user_builtin_macro (pfile, node);
 | 
						||
	      if (pfile->cb.used_define)
 | 
						||
		pfile->cb.used_define (pfile, pfile->directive_line, node);
 | 
						||
	    }
 | 
						||
	  else
 | 
						||
	    {
 | 
						||
	      if (pfile->cb.used_undef)
 | 
						||
		pfile->cb.used_undef (pfile, pfile->directive_line, node);
 | 
						||
	    }
 | 
						||
	}
 | 
						||
 | 
						||
      /* A possible controlling macro of the form #if !defined ().
 | 
						||
	 _cpp_parse_expr checks there was no other junk on the line.  */
 | 
						||
      pfile->mi_ind_cmacro = node;
 | 
						||
    }
 | 
						||
 | 
						||
  pfile->state.prevent_expansion--;
 | 
						||
 | 
						||
  /* Do not treat conditional macros as being defined.  This is due to the
 | 
						||
     powerpc and spu ports using conditional macros for 'vector', 'bool', and
 | 
						||
     'pixel' to act as conditional keywords.  This messes up tests like #ifndef
 | 
						||
     bool.  */
 | 
						||
  result.unsignedp = false;
 | 
						||
  result.high = 0;
 | 
						||
  result.overflow = false;
 | 
						||
  result.low = (node && node->type == NT_MACRO
 | 
						||
		&& (node->flags & NODE_CONDITIONAL) == 0);
 | 
						||
  return result;
 | 
						||
}
 | 
						||
 | 
						||
/* Convert a token into a CPP_NUMBER (an interpreted preprocessing
 | 
						||
   number or character constant, or the result of the "defined" or "#"
 | 
						||
   operators).  */
 | 
						||
static cpp_num
 | 
						||
eval_token (cpp_reader *pfile, const cpp_token *token,
 | 
						||
	    source_location virtual_location)
 | 
						||
{
 | 
						||
  cpp_num result;
 | 
						||
  unsigned int temp;
 | 
						||
  int unsignedp = 0;
 | 
						||
 | 
						||
  result.unsignedp = false;
 | 
						||
  result.overflow = false;
 | 
						||
 | 
						||
  switch (token->type)
 | 
						||
    {
 | 
						||
    case CPP_NUMBER:
 | 
						||
      temp = cpp_classify_number (pfile, token, NULL, virtual_location);
 | 
						||
      if (temp & CPP_N_USERDEF)
 | 
						||
	cpp_error (pfile, CPP_DL_ERROR,
 | 
						||
		   "user-defined literal in preprocessor expression");
 | 
						||
      switch (temp & CPP_N_CATEGORY)
 | 
						||
	{
 | 
						||
	case CPP_N_FLOATING:
 | 
						||
	  cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
 | 
						||
			       "floating constant in preprocessor expression");
 | 
						||
	  break;
 | 
						||
	case CPP_N_INTEGER:
 | 
						||
	  if (!(temp & CPP_N_IMAGINARY))
 | 
						||
	    return cpp_interpret_integer (pfile, token, temp);
 | 
						||
	  cpp_error_with_line (pfile, CPP_DL_ERROR, virtual_location, 0,
 | 
						||
			       "imaginary number in preprocessor expression");
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_N_INVALID:
 | 
						||
	  /* Error already issued.  */
 | 
						||
	  break;
 | 
						||
	}
 | 
						||
      result.high = result.low = 0;
 | 
						||
      break;
 | 
						||
 | 
						||
    case CPP_WCHAR:
 | 
						||
    case CPP_CHAR:
 | 
						||
    case CPP_CHAR16:
 | 
						||
    case CPP_CHAR32:
 | 
						||
      {
 | 
						||
	cppchar_t cc = cpp_interpret_charconst (pfile, token,
 | 
						||
						&temp, &unsignedp);
 | 
						||
 | 
						||
	result.high = 0;
 | 
						||
	result.low = cc;
 | 
						||
	/* Sign-extend the result if necessary.  */
 | 
						||
	if (!unsignedp && (cppchar_signed_t) cc < 0)
 | 
						||
	  {
 | 
						||
	    if (PART_PRECISION > BITS_PER_CPPCHAR_T)
 | 
						||
	      result.low |= ~(~(cpp_num_part) 0
 | 
						||
			      >> (PART_PRECISION - BITS_PER_CPPCHAR_T));
 | 
						||
	    result.high = ~(cpp_num_part) 0;
 | 
						||
	    result = num_trim (result, CPP_OPTION (pfile, precision));
 | 
						||
	  }
 | 
						||
      }
 | 
						||
      break;
 | 
						||
 | 
						||
    case CPP_NAME:
 | 
						||
      if (token->val.node.node == pfile->spec_nodes.n_defined)
 | 
						||
	return parse_defined (pfile);
 | 
						||
      else if (token->val.node.node == pfile->spec_nodes.n__has_include__)
 | 
						||
	return parse_has_include (pfile, IT_INCLUDE);
 | 
						||
      else if (token->val.node.node == pfile->spec_nodes.n__has_include_next__)
 | 
						||
	return parse_has_include (pfile, IT_INCLUDE_NEXT);
 | 
						||
      else if (token->val.node.node == pfile->spec_nodes.n__has_attribute__)
 | 
						||
	return parse_has_attribute (pfile);
 | 
						||
      else if (CPP_OPTION (pfile, cplusplus)
 | 
						||
	       && (token->val.node.node == pfile->spec_nodes.n_true
 | 
						||
		   || token->val.node.node == pfile->spec_nodes.n_false))
 | 
						||
	{
 | 
						||
	  result.high = 0;
 | 
						||
	  result.low = (token->val.node.node == pfile->spec_nodes.n_true);
 | 
						||
	}
 | 
						||
      else
 | 
						||
	{
 | 
						||
	  result.high = 0;
 | 
						||
	  result.low = 0;
 | 
						||
	  if (CPP_OPTION (pfile, warn_undef) && !pfile->state.skip_eval)
 | 
						||
	    cpp_warning_with_line (pfile, CPP_W_UNDEF, virtual_location, 0,
 | 
						||
				   "\"%s\" is not defined",
 | 
						||
				   NODE_NAME (token->val.node.node));
 | 
						||
	}
 | 
						||
      break;
 | 
						||
 | 
						||
    case CPP_HASH:
 | 
						||
      if (!pfile->state.skipping)
 | 
						||
	{
 | 
						||
	  /* A pedantic warning takes precedence over a deprecated
 | 
						||
	     warning here.  */
 | 
						||
	  if (CPP_PEDANTIC (pfile))
 | 
						||
	    cpp_error_with_line (pfile, CPP_DL_PEDWARN,
 | 
						||
				 virtual_location, 0,
 | 
						||
				 "assertions are a GCC extension");
 | 
						||
	  else if (CPP_OPTION (pfile, cpp_warn_deprecated))
 | 
						||
	    cpp_warning_with_line (pfile, CPP_W_DEPRECATED, virtual_location, 0,
 | 
						||
				   "assertions are a deprecated extension");
 | 
						||
	}
 | 
						||
      _cpp_test_assertion (pfile, &temp);
 | 
						||
      result.high = 0;
 | 
						||
      result.low = temp;
 | 
						||
      break;
 | 
						||
 | 
						||
    default:
 | 
						||
      abort ();
 | 
						||
    }
 | 
						||
 | 
						||
  result.unsignedp = !!unsignedp;
 | 
						||
  return result;
 | 
						||
}
 | 
						||
 | 
						||
/* Operator precedence and flags table.
 | 
						||
 | 
						||
After an operator is returned from the lexer, if it has priority less
 | 
						||
than the operator on the top of the stack, we reduce the stack by one
 | 
						||
operator and repeat the test.  Since equal priorities do not reduce,
 | 
						||
this is naturally right-associative.
 | 
						||
 | 
						||
We handle left-associative operators by decrementing the priority of
 | 
						||
just-lexed operators by one, but retaining the priority of operators
 | 
						||
already on the stack.
 | 
						||
 | 
						||
The remaining cases are '(' and ')'.  We handle '(' by skipping the
 | 
						||
reduction phase completely.  ')' is given lower priority than
 | 
						||
everything else, including '(', effectively forcing a reduction of the
 | 
						||
parenthesized expression.  If there is a matching '(', the routine
 | 
						||
reduce() exits immediately.  If the normal exit route sees a ')', then
 | 
						||
there cannot have been a matching '(' and an error message is output.
 | 
						||
 | 
						||
The parser assumes all shifted operators require a left operand unless
 | 
						||
the flag NO_L_OPERAND is set.  These semantics are automatic; any
 | 
						||
extra semantics need to be handled with operator-specific code.  */
 | 
						||
 | 
						||
/* Flags.  If CHECK_PROMOTION, we warn if the effective sign of an
 | 
						||
   operand changes because of integer promotions.  */
 | 
						||
#define NO_L_OPERAND	(1 << 0)
 | 
						||
#define LEFT_ASSOC	(1 << 1)
 | 
						||
#define CHECK_PROMOTION	(1 << 2)
 | 
						||
 | 
						||
/* Operator to priority map.  Must be in the same order as the first
 | 
						||
   N entries of enum cpp_ttype.  */
 | 
						||
static const struct cpp_operator
 | 
						||
{
 | 
						||
  uchar prio;
 | 
						||
  uchar flags;
 | 
						||
} optab[] =
 | 
						||
{
 | 
						||
  /* EQ */		{0, 0},	/* Shouldn't happen.  */
 | 
						||
  /* NOT */		{16, NO_L_OPERAND},
 | 
						||
  /* GREATER */		{12, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* LESS */		{12, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* PLUS */		{14, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* MINUS */		{14, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* MULT */		{15, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* DIV */		{15, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* MOD */		{15, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* AND */		{9, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* OR */		{7, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* XOR */		{8, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* RSHIFT */		{13, LEFT_ASSOC},
 | 
						||
  /* LSHIFT */		{13, LEFT_ASSOC},
 | 
						||
 | 
						||
  /* COMPL */		{16, NO_L_OPERAND},
 | 
						||
  /* AND_AND */		{6, LEFT_ASSOC},
 | 
						||
  /* OR_OR */		{5, LEFT_ASSOC},
 | 
						||
  /* Note that QUERY, COLON, and COMMA must have the same precedence.
 | 
						||
     However, there are some special cases for these in reduce().  */
 | 
						||
  /* QUERY */		{4, 0},
 | 
						||
  /* COLON */		{4, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* COMMA */		{4, LEFT_ASSOC},
 | 
						||
  /* OPEN_PAREN */	{1, NO_L_OPERAND},
 | 
						||
  /* CLOSE_PAREN */	{0, 0},
 | 
						||
  /* EOF */		{0, 0},
 | 
						||
  /* EQ_EQ */		{11, LEFT_ASSOC},
 | 
						||
  /* NOT_EQ */		{11, LEFT_ASSOC},
 | 
						||
  /* GREATER_EQ */	{12, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* LESS_EQ */		{12, LEFT_ASSOC | CHECK_PROMOTION},
 | 
						||
  /* UPLUS */		{16, NO_L_OPERAND},
 | 
						||
  /* UMINUS */		{16, NO_L_OPERAND}
 | 
						||
};
 | 
						||
 | 
						||
/* Parse and evaluate a C expression, reading from PFILE.
 | 
						||
   Returns the truth value of the expression.
 | 
						||
 | 
						||
   The implementation is an operator precedence parser, i.e. a
 | 
						||
   bottom-up parser, using a stack for not-yet-reduced tokens.
 | 
						||
 | 
						||
   The stack base is op_stack, and the current stack pointer is 'top'.
 | 
						||
   There is a stack element for each operator (only), and the most
 | 
						||
   recently pushed operator is 'top->op'.  An operand (value) is
 | 
						||
   stored in the 'value' field of the stack element of the operator
 | 
						||
   that precedes it.  */
 | 
						||
bool
 | 
						||
_cpp_parse_expr (cpp_reader *pfile, bool is_if)
 | 
						||
{
 | 
						||
  struct op *top = pfile->op_stack;
 | 
						||
  unsigned int lex_count;
 | 
						||
  bool saw_leading_not, want_value = true;
 | 
						||
  source_location virtual_location = 0;
 | 
						||
 | 
						||
  pfile->state.skip_eval = 0;
 | 
						||
 | 
						||
  /* Set up detection of #if ! defined().  */
 | 
						||
  pfile->mi_ind_cmacro = 0;
 | 
						||
  saw_leading_not = false;
 | 
						||
  lex_count = 0;
 | 
						||
 | 
						||
  /* Lowest priority operator prevents further reductions.  */
 | 
						||
  top->op = CPP_EOF;
 | 
						||
 | 
						||
  for (;;)
 | 
						||
    {
 | 
						||
      struct op op;
 | 
						||
 | 
						||
      lex_count++;
 | 
						||
      op.token = cpp_get_token_with_location (pfile, &virtual_location);
 | 
						||
      op.op = op.token->type;
 | 
						||
      op.loc = virtual_location;
 | 
						||
 | 
						||
      switch (op.op)
 | 
						||
	{
 | 
						||
	  /* These tokens convert into values.  */
 | 
						||
	case CPP_NUMBER:
 | 
						||
	case CPP_CHAR:
 | 
						||
	case CPP_WCHAR:
 | 
						||
	case CPP_CHAR16:
 | 
						||
	case CPP_CHAR32:
 | 
						||
	case CPP_NAME:
 | 
						||
	case CPP_HASH:
 | 
						||
	  if (!want_value)
 | 
						||
	    SYNTAX_ERROR2_AT (op.loc,
 | 
						||
			      "missing binary operator before token \"%s\"",
 | 
						||
			      cpp_token_as_text (pfile, op.token));
 | 
						||
	  want_value = false;
 | 
						||
	  top->value = eval_token (pfile, op.token, op.loc);
 | 
						||
	  continue;
 | 
						||
 | 
						||
	case CPP_NOT:
 | 
						||
	  saw_leading_not = lex_count == 1;
 | 
						||
	  break;
 | 
						||
	case CPP_PLUS:
 | 
						||
	  if (want_value)
 | 
						||
	    op.op = CPP_UPLUS;
 | 
						||
	  break;
 | 
						||
	case CPP_MINUS:
 | 
						||
	  if (want_value)
 | 
						||
	    op.op = CPP_UMINUS;
 | 
						||
	  break;
 | 
						||
 | 
						||
	default:
 | 
						||
	  if ((int) op.op <= (int) CPP_EQ || (int) op.op >= (int) CPP_PLUS_EQ)
 | 
						||
	    SYNTAX_ERROR2_AT (op.loc,
 | 
						||
			      "token \"%s\" is not valid in preprocessor expressions",
 | 
						||
			      cpp_token_as_text (pfile, op.token));
 | 
						||
	  break;
 | 
						||
	}
 | 
						||
 | 
						||
      /* Check we have a value or operator as appropriate.  */
 | 
						||
      if (optab[op.op].flags & NO_L_OPERAND)
 | 
						||
	{
 | 
						||
	  if (!want_value)
 | 
						||
	    SYNTAX_ERROR2_AT (op.loc,
 | 
						||
			      "missing binary operator before token \"%s\"",
 | 
						||
			      cpp_token_as_text (pfile, op.token));
 | 
						||
	}
 | 
						||
      else if (want_value)
 | 
						||
	{
 | 
						||
	  /* 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_AT (op.loc,
 | 
						||
			     "missing expression between '(' and ')'");
 | 
						||
 | 
						||
	  if (op.op == CPP_EOF && top->op == CPP_EOF)
 | 
						||
 	    SYNTAX_ERROR2_AT (op.loc,
 | 
						||
			      "%s with no expression", is_if ? "#if" : "#elif");
 | 
						||
 | 
						||
 	  if (top->op != CPP_EOF && top->op != CPP_OPEN_PAREN)
 | 
						||
 	    SYNTAX_ERROR2_AT (op.loc,
 | 
						||
			      "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_AT (op.loc,
 | 
						||
			      "operator '%s' has no left operand",
 | 
						||
			      cpp_token_as_text (pfile, op.token));
 | 
						||
	}
 | 
						||
 | 
						||
      top = reduce (pfile, top, op.op);
 | 
						||
      if (!top)
 | 
						||
	goto syntax_error;
 | 
						||
 | 
						||
      if (op.op == CPP_EOF)
 | 
						||
	break;
 | 
						||
 | 
						||
      switch (op.op)
 | 
						||
	{
 | 
						||
	case CPP_CLOSE_PAREN:
 | 
						||
	  continue;
 | 
						||
	case CPP_OR_OR:
 | 
						||
	  if (!num_zerop (top->value))
 | 
						||
	    pfile->state.skip_eval++;
 | 
						||
	  break;
 | 
						||
	case CPP_AND_AND:
 | 
						||
	case CPP_QUERY:
 | 
						||
	  if (num_zerop (top->value))
 | 
						||
	    pfile->state.skip_eval++;
 | 
						||
	  break;
 | 
						||
	case CPP_COLON:
 | 
						||
	  if (top->op != CPP_QUERY)
 | 
						||
	    SYNTAX_ERROR_AT (op.loc,
 | 
						||
			     " ':' without preceding '?'");
 | 
						||
	  if (!num_zerop (top[-1].value)) /* Was '?' condition true?  */
 | 
						||
	    pfile->state.skip_eval++;
 | 
						||
	  else
 | 
						||
	    pfile->state.skip_eval--;
 | 
						||
	default:
 | 
						||
	  break;
 | 
						||
	}
 | 
						||
 | 
						||
      want_value = true;
 | 
						||
 | 
						||
      /* Check for and handle stack overflow.  */
 | 
						||
      if (++top == pfile->op_limit)
 | 
						||
	top = _cpp_expand_op_stack (pfile);
 | 
						||
 | 
						||
      top->op = op.op;
 | 
						||
      top->token = op.token;
 | 
						||
      top->loc = op.loc;
 | 
						||
    }
 | 
						||
 | 
						||
  /* The controlling macro expression is only valid if we called lex 3
 | 
						||
     times: <!> <defined expression> and <EOF>.  push_conditional ()
 | 
						||
     checks that we are at top-of-file.  */
 | 
						||
  if (pfile->mi_ind_cmacro && !(saw_leading_not && lex_count == 3))
 | 
						||
    pfile->mi_ind_cmacro = 0;
 | 
						||
 | 
						||
  if (top != pfile->op_stack)
 | 
						||
    {
 | 
						||
      cpp_error_with_line (pfile, CPP_DL_ICE, top->loc, 0,
 | 
						||
			   "unbalanced stack in %s",
 | 
						||
			   is_if ? "#if" : "#elif");
 | 
						||
    syntax_error:
 | 
						||
      return false;  /* Return false on syntax error.  */
 | 
						||
    }
 | 
						||
 | 
						||
  return !num_zerop (top->value);
 | 
						||
}
 | 
						||
 | 
						||
/* Reduce the operator / value stack if possible, in preparation for
 | 
						||
   pushing operator OP.  Returns NULL on error, otherwise the top of
 | 
						||
   the stack.  */
 | 
						||
static struct op *
 | 
						||
reduce (cpp_reader *pfile, struct op *top, enum cpp_ttype op)
 | 
						||
{
 | 
						||
  unsigned int prio;
 | 
						||
 | 
						||
  if (top->op <= CPP_EQ || top->op > CPP_LAST_CPP_OP + 2)
 | 
						||
    {
 | 
						||
    bad_op:
 | 
						||
      cpp_error (pfile, CPP_DL_ICE, "impossible operator '%u'", top->op);
 | 
						||
      return 0;
 | 
						||
    }
 | 
						||
 | 
						||
  if (op == CPP_OPEN_PAREN)
 | 
						||
    return top;
 | 
						||
 | 
						||
  /* Decrement the priority of left-associative operators to force a
 | 
						||
     reduction with operators of otherwise equal priority.  */
 | 
						||
  prio = optab[op].prio - ((optab[op].flags & LEFT_ASSOC) != 0);
 | 
						||
  while (prio < optab[top->op].prio)
 | 
						||
    {
 | 
						||
      if (CPP_OPTION (pfile, warn_num_sign_change)
 | 
						||
	  && optab[top->op].flags & CHECK_PROMOTION)
 | 
						||
	check_promotion (pfile, top);
 | 
						||
 | 
						||
      switch (top->op)
 | 
						||
	{
 | 
						||
	case CPP_UPLUS:
 | 
						||
	case CPP_UMINUS:
 | 
						||
	case CPP_NOT:
 | 
						||
	case CPP_COMPL:
 | 
						||
	  top[-1].value = num_unary_op (pfile, top->value, top->op);
 | 
						||
	  top[-1].loc = top->loc;
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_PLUS:
 | 
						||
	case CPP_MINUS:
 | 
						||
	case CPP_RSHIFT:
 | 
						||
	case CPP_LSHIFT:
 | 
						||
	case CPP_COMMA:
 | 
						||
	  top[-1].value = num_binary_op (pfile, top[-1].value,
 | 
						||
					 top->value, top->op);
 | 
						||
	  top[-1].loc = top->loc;
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_GREATER:
 | 
						||
	case CPP_LESS:
 | 
						||
	case CPP_GREATER_EQ:
 | 
						||
	case CPP_LESS_EQ:
 | 
						||
	  top[-1].value
 | 
						||
	    = num_inequality_op (pfile, top[-1].value, top->value, top->op);
 | 
						||
	  top[-1].loc = top->loc;
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_EQ_EQ:
 | 
						||
	case CPP_NOT_EQ:
 | 
						||
	  top[-1].value
 | 
						||
	    = num_equality_op (pfile, top[-1].value, top->value, top->op);
 | 
						||
	  top[-1].loc = top->loc;
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_AND:
 | 
						||
	case CPP_OR:
 | 
						||
	case CPP_XOR:
 | 
						||
	  top[-1].value
 | 
						||
	    = num_bitwise_op (pfile, top[-1].value, top->value, top->op);
 | 
						||
	  top[-1].loc = top->loc;
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_MULT:
 | 
						||
	  top[-1].value = num_mul (pfile, top[-1].value, top->value);
 | 
						||
	  top[-1].loc = top->loc;
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_DIV:
 | 
						||
	case CPP_MOD:
 | 
						||
	  top[-1].value = num_div_op (pfile, top[-1].value,
 | 
						||
				      top->value, top->op, top->loc);
 | 
						||
	  top[-1].loc = top->loc;
 | 
						||
	  break;
 | 
						||
 | 
						||
	case CPP_OR_OR:
 | 
						||
	  top--;
 | 
						||
	  if (!num_zerop (top->value))
 | 
						||
	    pfile->state.skip_eval--;
 | 
						||
	  top->value.low = (!num_zerop (top->value)
 | 
						||
			    || !num_zerop (top[1].value));
 | 
						||
	  top->value.high = 0;
 | 
						||
	  top->value.unsignedp = false;
 | 
						||
	  top->value.overflow = false;
 | 
						||
	  top->loc = top[1].loc;
 | 
						||
	  continue;
 | 
						||
 | 
						||
	case CPP_AND_AND:
 | 
						||
	  top--;
 | 
						||
	  if (num_zerop (top->value))
 | 
						||
	    pfile->state.skip_eval--;
 | 
						||
	  top->value.low = (!num_zerop (top->value)
 | 
						||
			    && !num_zerop (top[1].value));
 | 
						||
	  top->value.high = 0;
 | 
						||
	  top->value.unsignedp = false;
 | 
						||
	  top->value.overflow = false;
 | 
						||
	  top->loc = top[1].loc;
 | 
						||
	  continue;
 | 
						||
 | 
						||
	case CPP_OPEN_PAREN:
 | 
						||
	  if (op != CPP_CLOSE_PAREN)
 | 
						||
	    {
 | 
						||
	      cpp_error_with_line (pfile, CPP_DL_ERROR, 
 | 
						||
				   top->token->src_loc,
 | 
						||
				   0, "missing ')' in expression");
 | 
						||
	      return 0;
 | 
						||
	    }
 | 
						||
	  top--;
 | 
						||
	  top->value = top[1].value;
 | 
						||
	  top->loc = top[1].loc;
 | 
						||
	  return top;
 | 
						||
 | 
						||
	case CPP_COLON:
 | 
						||
	  top -= 2;
 | 
						||
	  if (!num_zerop (top->value))
 | 
						||
	    {
 | 
						||
	      pfile->state.skip_eval--;
 | 
						||
	      top->value = top[1].value;
 | 
						||
	      top->loc = top[1].loc;
 | 
						||
	    }
 | 
						||
	  else
 | 
						||
	    {
 | 
						||
	      top->value = top[2].value;
 | 
						||
	      top->loc = top[2].loc;
 | 
						||
	    }
 | 
						||
	  top->value.unsignedp = (top[1].value.unsignedp
 | 
						||
				  || top[2].value.unsignedp);
 | 
						||
	  continue;
 | 
						||
 | 
						||
	case CPP_QUERY:
 | 
						||
	  /* COMMA and COLON should not reduce a QUERY operator.  */
 | 
						||
	  if (op == CPP_COMMA || op == CPP_COLON)
 | 
						||
	    return top;
 | 
						||
	  cpp_error (pfile, CPP_DL_ERROR, "'?' without following ':'");
 | 
						||
	  return 0;
 | 
						||
 | 
						||
	default:
 | 
						||
	  goto bad_op;
 | 
						||
	}
 | 
						||
 | 
						||
      top--;
 | 
						||
      if (top->value.overflow && !pfile->state.skip_eval)
 | 
						||
	cpp_error (pfile, CPP_DL_PEDWARN,
 | 
						||
		   "integer overflow in preprocessor expression");
 | 
						||
    }
 | 
						||
 | 
						||
  if (op == CPP_CLOSE_PAREN)
 | 
						||
    {
 | 
						||
      cpp_error (pfile, CPP_DL_ERROR, "missing '(' in expression");
 | 
						||
      return 0;
 | 
						||
    }
 | 
						||
 | 
						||
  return top;
 | 
						||
}
 | 
						||
 | 
						||
/* Returns the position of the old top of stack after expansion.  */
 | 
						||
struct op *
 | 
						||
_cpp_expand_op_stack (cpp_reader *pfile)
 | 
						||
{
 | 
						||
  size_t old_size = (size_t) (pfile->op_limit - pfile->op_stack);
 | 
						||
  size_t new_size = old_size * 2 + 20;
 | 
						||
 | 
						||
  pfile->op_stack = XRESIZEVEC (struct op, pfile->op_stack, new_size);
 | 
						||
  pfile->op_limit = pfile->op_stack + new_size;
 | 
						||
 | 
						||
  return pfile->op_stack + old_size;
 | 
						||
}
 | 
						||
 | 
						||
/* Emits a warning if the effective sign of either operand of OP
 | 
						||
   changes because of integer promotions.  */
 | 
						||
static void
 | 
						||
check_promotion (cpp_reader *pfile, const struct op *op)
 | 
						||
{
 | 
						||
  if (op->value.unsignedp == op[-1].value.unsignedp)
 | 
						||
    return;
 | 
						||
 | 
						||
  if (op->value.unsignedp)
 | 
						||
    {
 | 
						||
      if (!num_positive (op[-1].value, CPP_OPTION (pfile, precision)))
 | 
						||
	cpp_error_with_line (pfile, CPP_DL_WARNING, op[-1].loc, 0,
 | 
						||
			     "the left operand of \"%s\" changes sign when promoted",
 | 
						||
			     cpp_token_as_text (pfile, op->token));
 | 
						||
    }
 | 
						||
  else if (!num_positive (op->value, CPP_OPTION (pfile, precision)))
 | 
						||
    cpp_error_with_line (pfile, CPP_DL_WARNING, op->loc, 0,
 | 
						||
	       "the right operand of \"%s\" changes sign when promoted",
 | 
						||
	       cpp_token_as_text (pfile, op->token));
 | 
						||
}
 | 
						||
 | 
						||
/* Clears the unused high order bits of the number pointed to by PNUM.  */
 | 
						||
static cpp_num
 | 
						||
num_trim (cpp_num num, size_t precision)
 | 
						||
{
 | 
						||
  if (precision > PART_PRECISION)
 | 
						||
    {
 | 
						||
      precision -= PART_PRECISION;
 | 
						||
      if (precision < PART_PRECISION)
 | 
						||
	num.high &= ((cpp_num_part) 1 << precision) - 1;
 | 
						||
    }
 | 
						||
  else
 | 
						||
    {
 | 
						||
      if (precision < PART_PRECISION)
 | 
						||
	num.low &= ((cpp_num_part) 1 << precision) - 1;
 | 
						||
      num.high = 0;
 | 
						||
    }
 | 
						||
 | 
						||
  return num;
 | 
						||
}
 | 
						||
 | 
						||
/* True iff A (presumed signed) >= 0.  */
 | 
						||
static bool
 | 
						||
num_positive (cpp_num num, size_t precision)
 | 
						||
{
 | 
						||
  if (precision > PART_PRECISION)
 | 
						||
    {
 | 
						||
      precision -= PART_PRECISION;
 | 
						||
      return (num.high & (cpp_num_part) 1 << (precision - 1)) == 0;
 | 
						||
    }
 | 
						||
 | 
						||
  return (num.low & (cpp_num_part) 1 << (precision - 1)) == 0;
 | 
						||
}
 | 
						||
 | 
						||
/* Sign extend a number, with PRECISION significant bits and all
 | 
						||
   others assumed clear, to fill out a cpp_num structure.  */
 | 
						||
cpp_num
 | 
						||
cpp_num_sign_extend (cpp_num num, size_t precision)
 | 
						||
{
 | 
						||
  if (!num.unsignedp)
 | 
						||
    {
 | 
						||
      if (precision > PART_PRECISION)
 | 
						||
	{
 | 
						||
	  precision -= PART_PRECISION;
 | 
						||
	  if (precision < PART_PRECISION
 | 
						||
	      && (num.high & (cpp_num_part) 1 << (precision - 1)))
 | 
						||
	    num.high |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
 | 
						||
	}
 | 
						||
      else if (num.low & (cpp_num_part) 1 << (precision - 1))
 | 
						||
	{
 | 
						||
	  if (precision < PART_PRECISION)
 | 
						||
	    num.low |= ~(~(cpp_num_part) 0 >> (PART_PRECISION - precision));
 | 
						||
	  num.high = ~(cpp_num_part) 0;
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  return num;
 | 
						||
}
 | 
						||
 | 
						||
/* Returns the negative of NUM.  */
 | 
						||
static cpp_num
 | 
						||
num_negate (cpp_num num, size_t precision)
 | 
						||
{
 | 
						||
  cpp_num copy;
 | 
						||
 | 
						||
  copy = num;
 | 
						||
  num.high = ~num.high;
 | 
						||
  num.low = ~num.low;
 | 
						||
  if (++num.low == 0)
 | 
						||
    num.high++;
 | 
						||
  num = num_trim (num, precision);
 | 
						||
  num.overflow = (!num.unsignedp && num_eq (num, copy) && !num_zerop (num));
 | 
						||
 | 
						||
  return num;
 | 
						||
}
 | 
						||
 | 
						||
/* Returns true if A >= B.  */
 | 
						||
static bool
 | 
						||
num_greater_eq (cpp_num pa, cpp_num pb, size_t precision)
 | 
						||
{
 | 
						||
  bool unsignedp;
 | 
						||
 | 
						||
  unsignedp = pa.unsignedp || pb.unsignedp;
 | 
						||
 | 
						||
  if (!unsignedp)
 | 
						||
    {
 | 
						||
      /* Both numbers have signed type.  If they are of different
 | 
						||
       sign, the answer is the sign of A.  */
 | 
						||
      unsignedp = num_positive (pa, precision);
 | 
						||
 | 
						||
      if (unsignedp != num_positive (pb, precision))
 | 
						||
	return unsignedp;
 | 
						||
 | 
						||
      /* Otherwise we can do an unsigned comparison.  */
 | 
						||
    }
 | 
						||
 | 
						||
  return (pa.high > pb.high) || (pa.high == pb.high && pa.low >= pb.low);
 | 
						||
}
 | 
						||
 | 
						||
/* Returns LHS OP RHS, where OP is a bit-wise operation.  */
 | 
						||
static cpp_num
 | 
						||
num_bitwise_op (cpp_reader *pfile ATTRIBUTE_UNUSED,
 | 
						||
		cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
 | 
						||
{
 | 
						||
  lhs.overflow = false;
 | 
						||
  lhs.unsignedp = lhs.unsignedp || rhs.unsignedp;
 | 
						||
 | 
						||
  /* As excess precision is zeroed, there is no need to num_trim () as
 | 
						||
     these operations cannot introduce a set bit there.  */
 | 
						||
  if (op == CPP_AND)
 | 
						||
    {
 | 
						||
      lhs.low &= rhs.low;
 | 
						||
      lhs.high &= rhs.high;
 | 
						||
    }
 | 
						||
  else if (op == CPP_OR)
 | 
						||
    {
 | 
						||
      lhs.low |= rhs.low;
 | 
						||
      lhs.high |= rhs.high;
 | 
						||
    }
 | 
						||
  else
 | 
						||
    {
 | 
						||
      lhs.low ^= rhs.low;
 | 
						||
      lhs.high ^= rhs.high;
 | 
						||
    }
 | 
						||
 | 
						||
  return lhs;
 | 
						||
}
 | 
						||
 | 
						||
/* Returns LHS OP RHS, where OP is an inequality.  */
 | 
						||
static cpp_num
 | 
						||
num_inequality_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs,
 | 
						||
		   enum cpp_ttype op)
 | 
						||
{
 | 
						||
  bool gte = num_greater_eq (lhs, rhs, CPP_OPTION (pfile, precision));
 | 
						||
 | 
						||
  if (op == CPP_GREATER_EQ)
 | 
						||
    lhs.low = gte;
 | 
						||
  else if (op == CPP_LESS)
 | 
						||
    lhs.low = !gte;
 | 
						||
  else if (op == CPP_GREATER)
 | 
						||
    lhs.low = gte && !num_eq (lhs, rhs);
 | 
						||
  else /* CPP_LESS_EQ.  */
 | 
						||
    lhs.low = !gte || num_eq (lhs, rhs);
 | 
						||
 | 
						||
  lhs.high = 0;
 | 
						||
  lhs.overflow = false;
 | 
						||
  lhs.unsignedp = false;
 | 
						||
  return lhs;
 | 
						||
}
 | 
						||
 | 
						||
/* Returns LHS OP RHS, where OP is == or !=.  */
 | 
						||
static cpp_num
 | 
						||
num_equality_op (cpp_reader *pfile ATTRIBUTE_UNUSED,
 | 
						||
		 cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
 | 
						||
{
 | 
						||
  /* Work around a 3.0.4 bug; see PR 6950.  */
 | 
						||
  bool eq = num_eq (lhs, rhs);
 | 
						||
  if (op == CPP_NOT_EQ)
 | 
						||
    eq = !eq;
 | 
						||
  lhs.low = eq;
 | 
						||
  lhs.high = 0;
 | 
						||
  lhs.overflow = false;
 | 
						||
  lhs.unsignedp = false;
 | 
						||
  return lhs;
 | 
						||
}
 | 
						||
 | 
						||
/* Shift NUM, of width PRECISION, right by N bits.  */
 | 
						||
static cpp_num
 | 
						||
num_rshift (cpp_num num, size_t precision, size_t n)
 | 
						||
{
 | 
						||
  cpp_num_part sign_mask;
 | 
						||
  bool x = num_positive (num, precision);
 | 
						||
 | 
						||
  if (num.unsignedp || x)
 | 
						||
    sign_mask = 0;
 | 
						||
  else
 | 
						||
    sign_mask = ~(cpp_num_part) 0;
 | 
						||
 | 
						||
  if (n >= precision)
 | 
						||
    num.high = num.low = sign_mask;
 | 
						||
  else
 | 
						||
    {
 | 
						||
      /* Sign-extend.  */
 | 
						||
      if (precision < PART_PRECISION)
 | 
						||
	num.high = sign_mask, num.low |= sign_mask << precision;
 | 
						||
      else if (precision < 2 * PART_PRECISION)
 | 
						||
	num.high |= sign_mask << (precision - PART_PRECISION);
 | 
						||
 | 
						||
      if (n >= PART_PRECISION)
 | 
						||
	{
 | 
						||
	  n -= PART_PRECISION;
 | 
						||
	  num.low = num.high;
 | 
						||
	  num.high = sign_mask;
 | 
						||
	}
 | 
						||
 | 
						||
      if (n)
 | 
						||
	{
 | 
						||
	  num.low = (num.low >> n) | (num.high << (PART_PRECISION - n));
 | 
						||
	  num.high = (num.high >> n) | (sign_mask << (PART_PRECISION - n));
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  num = num_trim (num, precision);
 | 
						||
  num.overflow = false;
 | 
						||
  return num;
 | 
						||
}
 | 
						||
 | 
						||
/* Shift NUM, of width PRECISION, left by N bits.  */
 | 
						||
static cpp_num
 | 
						||
num_lshift (cpp_num num, size_t precision, size_t n)
 | 
						||
{
 | 
						||
  if (n >= precision)
 | 
						||
    {
 | 
						||
      num.overflow = !num.unsignedp && !num_zerop (num);
 | 
						||
      num.high = num.low = 0;
 | 
						||
    }
 | 
						||
  else
 | 
						||
    {
 | 
						||
      cpp_num orig, maybe_orig;
 | 
						||
      size_t m = n;
 | 
						||
 | 
						||
      orig = num;
 | 
						||
      if (m >= PART_PRECISION)
 | 
						||
	{
 | 
						||
	  m -= PART_PRECISION;
 | 
						||
	  num.high = num.low;
 | 
						||
	  num.low = 0;
 | 
						||
	}
 | 
						||
      if (m)
 | 
						||
	{
 | 
						||
	  num.high = (num.high << m) | (num.low >> (PART_PRECISION - m));
 | 
						||
	  num.low <<= m;
 | 
						||
	}
 | 
						||
      num = num_trim (num, precision);
 | 
						||
 | 
						||
      if (num.unsignedp)
 | 
						||
	num.overflow = false;
 | 
						||
      else
 | 
						||
	{
 | 
						||
	  maybe_orig = num_rshift (num, precision, n);
 | 
						||
	  num.overflow = !num_eq (orig, maybe_orig);
 | 
						||
	}
 | 
						||
    }
 | 
						||
 | 
						||
  return num;
 | 
						||
}
 | 
						||
 | 
						||
/* The four unary operators: +, -, ! and ~.  */
 | 
						||
static cpp_num
 | 
						||
num_unary_op (cpp_reader *pfile, cpp_num num, enum cpp_ttype op)
 | 
						||
{
 | 
						||
  switch (op)
 | 
						||
    {
 | 
						||
    case CPP_UPLUS:
 | 
						||
      if (CPP_WTRADITIONAL (pfile) && !pfile->state.skip_eval)
 | 
						||
	cpp_warning (pfile, CPP_W_TRADITIONAL,
 | 
						||
		     "traditional C rejects the unary plus operator");
 | 
						||
      num.overflow = false;
 | 
						||
      break;
 | 
						||
 | 
						||
    case CPP_UMINUS:
 | 
						||
      num = num_negate (num, CPP_OPTION (pfile, precision));
 | 
						||
      break;
 | 
						||
 | 
						||
    case CPP_COMPL:
 | 
						||
      num.high = ~num.high;
 | 
						||
      num.low = ~num.low;
 | 
						||
      num = num_trim (num, CPP_OPTION (pfile, precision));
 | 
						||
      num.overflow = false;
 | 
						||
      break;
 | 
						||
 | 
						||
    default: /* case CPP_NOT: */
 | 
						||
      num.low = num_zerop (num);
 | 
						||
      num.high = 0;
 | 
						||
      num.overflow = false;
 | 
						||
      num.unsignedp = false;
 | 
						||
      break;
 | 
						||
    }
 | 
						||
 | 
						||
  return num;
 | 
						||
}
 | 
						||
 | 
						||
/* The various binary operators.  */
 | 
						||
static cpp_num
 | 
						||
num_binary_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op)
 | 
						||
{
 | 
						||
  cpp_num result;
 | 
						||
  size_t precision = CPP_OPTION (pfile, precision);
 | 
						||
  size_t n;
 | 
						||
 | 
						||
  switch (op)
 | 
						||
    {
 | 
						||
      /* Shifts.  */
 | 
						||
    case CPP_LSHIFT:
 | 
						||
    case CPP_RSHIFT:
 | 
						||
      if (!rhs.unsignedp && !num_positive (rhs, precision))
 | 
						||
	{
 | 
						||
	  /* A negative shift is a positive shift the other way.  */
 | 
						||
	  if (op == CPP_LSHIFT)
 | 
						||
	    op = CPP_RSHIFT;
 | 
						||
	  else
 | 
						||
	    op = CPP_LSHIFT;
 | 
						||
	  rhs = num_negate (rhs, precision);
 | 
						||
	}
 | 
						||
      if (rhs.high)
 | 
						||
	n = ~0;			/* Maximal.  */
 | 
						||
      else
 | 
						||
	n = rhs.low;
 | 
						||
      if (op == CPP_LSHIFT)
 | 
						||
	lhs = num_lshift (lhs, precision, n);
 | 
						||
      else
 | 
						||
	lhs = num_rshift (lhs, precision, n);
 | 
						||
      break;
 | 
						||
 | 
						||
      /* Arithmetic.  */
 | 
						||
    case CPP_MINUS:
 | 
						||
      result.low = lhs.low - rhs.low;
 | 
						||
      result.high = lhs.high - rhs.high;
 | 
						||
      if (result.low > lhs.low)
 | 
						||
	result.high--;
 | 
						||
      result.unsignedp = lhs.unsignedp || rhs.unsignedp;
 | 
						||
      result.overflow = false;
 | 
						||
 | 
						||
      result = num_trim (result, precision);
 | 
						||
      if (!result.unsignedp)
 | 
						||
	{
 | 
						||
	  bool lhsp = num_positive (lhs, precision);
 | 
						||
	  result.overflow = (lhsp != num_positive (rhs, precision)
 | 
						||
			     && lhsp != num_positive (result, precision));
 | 
						||
	}
 | 
						||
      return result;
 | 
						||
 | 
						||
    case CPP_PLUS:
 | 
						||
      result.low = lhs.low + rhs.low;
 | 
						||
      result.high = lhs.high + rhs.high;
 | 
						||
      if (result.low < lhs.low)
 | 
						||
	result.high++;
 | 
						||
      result.unsignedp = lhs.unsignedp || rhs.unsignedp;
 | 
						||
      result.overflow = false;
 | 
						||
 | 
						||
      result = num_trim (result, precision);
 | 
						||
      if (!result.unsignedp)
 | 
						||
	{
 | 
						||
	  bool lhsp = num_positive (lhs, precision);
 | 
						||
	  result.overflow = (lhsp == num_positive (rhs, precision)
 | 
						||
			     && lhsp != num_positive (result, precision));
 | 
						||
	}
 | 
						||
      return result;
 | 
						||
 | 
						||
      /* Comma.  */
 | 
						||
    default: /* case CPP_COMMA: */
 | 
						||
      if (CPP_PEDANTIC (pfile) && (!CPP_OPTION (pfile, c99)
 | 
						||
				   || !pfile->state.skip_eval))
 | 
						||
	cpp_pedwarning (pfile, CPP_W_PEDANTIC,
 | 
						||
			"comma operator in operand of #if");
 | 
						||
      lhs = rhs;
 | 
						||
      break;
 | 
						||
    }
 | 
						||
 | 
						||
  return lhs;
 | 
						||
}
 | 
						||
 | 
						||
/* Multiplies two unsigned cpp_num_parts to give a cpp_num.  This
 | 
						||
   cannot overflow.  */
 | 
						||
static cpp_num
 | 
						||
num_part_mul (cpp_num_part lhs, cpp_num_part rhs)
 | 
						||
{
 | 
						||
  cpp_num result;
 | 
						||
  cpp_num_part middle[2], temp;
 | 
						||
 | 
						||
  result.low = LOW_PART (lhs) * LOW_PART (rhs);
 | 
						||
  result.high = HIGH_PART (lhs) * HIGH_PART (rhs);
 | 
						||
 | 
						||
  middle[0] = LOW_PART (lhs) * HIGH_PART (rhs);
 | 
						||
  middle[1] = HIGH_PART (lhs) * LOW_PART (rhs);
 | 
						||
 | 
						||
  temp = result.low;
 | 
						||
  result.low += LOW_PART (middle[0]) << (PART_PRECISION / 2);
 | 
						||
  if (result.low < temp)
 | 
						||
    result.high++;
 | 
						||
 | 
						||
  temp = result.low;
 | 
						||
  result.low += LOW_PART (middle[1]) << (PART_PRECISION / 2);
 | 
						||
  if (result.low < temp)
 | 
						||
    result.high++;
 | 
						||
 | 
						||
  result.high += HIGH_PART (middle[0]);
 | 
						||
  result.high += HIGH_PART (middle[1]);
 | 
						||
  result.unsignedp = true;
 | 
						||
  result.overflow = false;
 | 
						||
 | 
						||
  return result;
 | 
						||
}
 | 
						||
 | 
						||
/* Multiply two preprocessing numbers.  */
 | 
						||
static cpp_num
 | 
						||
num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
 | 
						||
{
 | 
						||
  cpp_num result, temp;
 | 
						||
  bool unsignedp = lhs.unsignedp || rhs.unsignedp;
 | 
						||
  bool overflow, negate = false;
 | 
						||
  size_t precision = CPP_OPTION (pfile, precision);
 | 
						||
 | 
						||
  /* Prepare for unsigned multiplication.  */
 | 
						||
  if (!unsignedp)
 | 
						||
    {
 | 
						||
      if (!num_positive (lhs, precision))
 | 
						||
	negate = !negate, lhs = num_negate (lhs, precision);
 | 
						||
      if (!num_positive (rhs, precision))
 | 
						||
	negate = !negate, rhs = num_negate (rhs, precision);
 | 
						||
    }
 | 
						||
 | 
						||
  overflow = lhs.high && rhs.high;
 | 
						||
  result = num_part_mul (lhs.low, rhs.low);
 | 
						||
 | 
						||
  temp = num_part_mul (lhs.high, rhs.low);
 | 
						||
  result.high += temp.low;
 | 
						||
  if (temp.high)
 | 
						||
    overflow = true;
 | 
						||
 | 
						||
  temp = num_part_mul (lhs.low, rhs.high);
 | 
						||
  result.high += temp.low;
 | 
						||
  if (temp.high)
 | 
						||
    overflow = true;
 | 
						||
 | 
						||
  temp.low = result.low, temp.high = result.high;
 | 
						||
  result = num_trim (result, precision);
 | 
						||
  if (!num_eq (result, temp))
 | 
						||
    overflow = true;
 | 
						||
 | 
						||
  if (negate)
 | 
						||
    result = num_negate (result, precision);
 | 
						||
 | 
						||
  if (unsignedp)
 | 
						||
    result.overflow = false;
 | 
						||
  else
 | 
						||
    result.overflow = overflow || (num_positive (result, precision) ^ !negate
 | 
						||
				   && !num_zerop (result));
 | 
						||
  result.unsignedp = unsignedp;
 | 
						||
 | 
						||
  return result;
 | 
						||
}
 | 
						||
 | 
						||
/* Divide two preprocessing numbers, LHS and RHS, returning the answer
 | 
						||
   or the remainder depending upon OP. LOCATION is the source location
 | 
						||
   of this operator (for diagnostics).  */
 | 
						||
 | 
						||
static cpp_num
 | 
						||
num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
 | 
						||
	    source_location location)
 | 
						||
{
 | 
						||
  cpp_num result, sub;
 | 
						||
  cpp_num_part mask;
 | 
						||
  bool unsignedp = lhs.unsignedp || rhs.unsignedp;
 | 
						||
  bool negate = false, lhs_neg = false;
 | 
						||
  size_t i, precision = CPP_OPTION (pfile, precision);
 | 
						||
 | 
						||
  /* Prepare for unsigned division.  */
 | 
						||
  if (!unsignedp)
 | 
						||
    {
 | 
						||
      if (!num_positive (lhs, precision))
 | 
						||
	negate = !negate, lhs_neg = true, lhs = num_negate (lhs, precision);
 | 
						||
      if (!num_positive (rhs, precision))
 | 
						||
	negate = !negate, rhs = num_negate (rhs, precision);
 | 
						||
    }
 | 
						||
 | 
						||
  /* Find the high bit.  */
 | 
						||
  if (rhs.high)
 | 
						||
    {
 | 
						||
      i = precision - 1;
 | 
						||
      mask = (cpp_num_part) 1 << (i - PART_PRECISION);
 | 
						||
      for (; ; i--, mask >>= 1)
 | 
						||
	if (rhs.high & mask)
 | 
						||
	  break;
 | 
						||
    }
 | 
						||
  else if (rhs.low)
 | 
						||
    {
 | 
						||
      if (precision > PART_PRECISION)
 | 
						||
	i = precision - PART_PRECISION - 1;
 | 
						||
      else
 | 
						||
	i = precision - 1;
 | 
						||
      mask = (cpp_num_part) 1 << i;
 | 
						||
      for (; ; i--, mask >>= 1)
 | 
						||
	if (rhs.low & mask)
 | 
						||
	  break;
 | 
						||
    }
 | 
						||
  else
 | 
						||
    {
 | 
						||
      if (!pfile->state.skip_eval)
 | 
						||
	cpp_error_with_line (pfile, CPP_DL_ERROR, location, 0,
 | 
						||
			     "division by zero in #if");
 | 
						||
      return lhs;
 | 
						||
    }
 | 
						||
 | 
						||
  /* First nonzero bit of RHS is bit I.  Do naive division by
 | 
						||
     shifting the RHS fully left, and subtracting from LHS if LHS is
 | 
						||
     at least as big, and then repeating but with one less shift.
 | 
						||
     This is not very efficient, but is easy to understand.  */
 | 
						||
 | 
						||
  rhs.unsignedp = true;
 | 
						||
  lhs.unsignedp = true;
 | 
						||
  i = precision - i - 1;
 | 
						||
  sub = num_lshift (rhs, precision, i);
 | 
						||
 | 
						||
  result.high = result.low = 0;
 | 
						||
  for (;;)
 | 
						||
    {
 | 
						||
      if (num_greater_eq (lhs, sub, precision))
 | 
						||
	{
 | 
						||
	  lhs = num_binary_op (pfile, lhs, sub, CPP_MINUS);
 | 
						||
	  if (i >= PART_PRECISION)
 | 
						||
	    result.high |= (cpp_num_part) 1 << (i - PART_PRECISION);
 | 
						||
	  else
 | 
						||
	    result.low |= (cpp_num_part) 1 << i;
 | 
						||
	}
 | 
						||
      if (i-- == 0)
 | 
						||
	break;
 | 
						||
      sub.low = (sub.low >> 1) | (sub.high << (PART_PRECISION - 1));
 | 
						||
      sub.high >>= 1;
 | 
						||
    }
 | 
						||
 | 
						||
  /* We divide so that the remainder has the sign of the LHS.  */
 | 
						||
  if (op == CPP_DIV)
 | 
						||
    {
 | 
						||
      result.unsignedp = unsignedp;
 | 
						||
      result.overflow = false;
 | 
						||
      if (!unsignedp)
 | 
						||
	{
 | 
						||
	  if (negate)
 | 
						||
	    result = num_negate (result, precision);
 | 
						||
	  result.overflow = (num_positive (result, precision) ^ !negate
 | 
						||
			     && !num_zerop (result));
 | 
						||
	}
 | 
						||
 | 
						||
      return result;
 | 
						||
    }
 | 
						||
 | 
						||
  /* CPP_MOD.  */
 | 
						||
  lhs.unsignedp = unsignedp;
 | 
						||
  lhs.overflow = false;
 | 
						||
  if (lhs_neg)
 | 
						||
    lhs = num_negate (lhs, precision);
 | 
						||
 | 
						||
  return lhs;
 | 
						||
}
 | 
						||
 | 
						||
/* Handle meeting "__has_include__" in a preprocessor expression.  */
 | 
						||
static cpp_num
 | 
						||
parse_has_include (cpp_reader *pfile, enum include_type type)
 | 
						||
{
 | 
						||
  cpp_num result;
 | 
						||
  bool paren = false;
 | 
						||
  cpp_hashnode *node = 0;
 | 
						||
  const cpp_token *token;
 | 
						||
  bool bracket = false;
 | 
						||
  char *fname = 0;
 | 
						||
 | 
						||
  result.unsignedp = false;
 | 
						||
  result.high = 0;
 | 
						||
  result.overflow = false;
 | 
						||
  result.low = 0;
 | 
						||
 | 
						||
  pfile->state.in__has_include__++;
 | 
						||
 | 
						||
  token = cpp_get_token (pfile);
 | 
						||
  if (token->type == CPP_OPEN_PAREN)
 | 
						||
    {
 | 
						||
      paren = true;
 | 
						||
      token = cpp_get_token (pfile);
 | 
						||
    }
 | 
						||
 | 
						||
  if (token->type == CPP_STRING || token->type == CPP_HEADER_NAME)
 | 
						||
    {
 | 
						||
      if (token->type == CPP_HEADER_NAME)
 | 
						||
	bracket = true;
 | 
						||
      fname = XNEWVEC (char, token->val.str.len - 1);
 | 
						||
      memcpy (fname, token->val.str.text + 1, token->val.str.len - 2);
 | 
						||
      fname[token->val.str.len - 2] = '\0';
 | 
						||
      node = token->val.node.node;
 | 
						||
    }
 | 
						||
  else if (token->type == CPP_LESS)
 | 
						||
    {
 | 
						||
      bracket = true;
 | 
						||
      fname = _cpp_bracket_include (pfile);
 | 
						||
    }
 | 
						||
  else
 | 
						||
    cpp_error (pfile, CPP_DL_ERROR,
 | 
						||
	       "operator \"__has_include__\" requires a header string");
 | 
						||
 | 
						||
  if (fname)
 | 
						||
    {
 | 
						||
      int angle_brackets = (bracket ? 1 : 0);
 | 
						||
 | 
						||
      if (_cpp_has_header (pfile, fname, angle_brackets, type))
 | 
						||
	result.low = 1;
 | 
						||
      else
 | 
						||
	result.low = 0;
 | 
						||
 | 
						||
      XDELETEVEC (fname);
 | 
						||
    }
 | 
						||
 | 
						||
  if (paren && cpp_get_token (pfile)->type != CPP_CLOSE_PAREN)
 | 
						||
    cpp_error (pfile, CPP_DL_ERROR,
 | 
						||
	       "missing ')' after \"__has_include__\"");
 | 
						||
 | 
						||
  /* A possible controlling macro of the form #if !__has_include__ ().
 | 
						||
     _cpp_parse_expr checks there was no other junk on the line.  */
 | 
						||
  if (node)
 | 
						||
    pfile->mi_ind_cmacro = node;
 | 
						||
 | 
						||
  pfile->state.in__has_include__--;
 | 
						||
 | 
						||
  return result;
 | 
						||
}
 | 
						||
 | 
						||
/* Handle meeting "__has_attribute__" in a preprocessor expression.  */
 | 
						||
static cpp_num
 | 
						||
parse_has_attribute (cpp_reader *pfile)
 | 
						||
{
 | 
						||
  pfile->state.in__has_attribute__++;
 | 
						||
 | 
						||
  cpp_num result;
 | 
						||
  result.unsignedp = false;
 | 
						||
  result.high = 0;
 | 
						||
  result.overflow = false;
 | 
						||
 | 
						||
  result.low = pfile->cb.has_attribute (pfile);
 | 
						||
 | 
						||
  pfile->state.in__has_attribute__--;
 | 
						||
 | 
						||
  return result;
 | 
						||
}
 |