[Ada] Consistently use explicit Entity_Id type instead of alias
[gcc.git] / libcpp / expr.c
index 61bc1b21af1837e0e1e98b0b9b3a079887f4dd0a..2ba7726d61c4679edca4270eb5d1d4e02cf566be 100644 (file)
@@ -1,5 +1,5 @@
 /* Parse C expressions for cpplib.
-   Copyright (C) 1987-2016 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
    Contributed by Per Bothner, 1994.
 
 This program is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@ 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.         */
+  location_t loc;          /* The location of this value.         */
   enum cpp_ttype op;
 };
 
@@ -52,20 +52,18 @@ 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);
+                          location_t);
 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 cpp_num eval_token (cpp_reader *, const cpp_token *, location_t);
 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);
-
 /* 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))
@@ -90,14 +88,16 @@ static cpp_num parse_has_include (cpp_reader *, enum include_type);
 static unsigned int
 interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 {
+  size_t orig_len = len;
+  const uchar *orig_s = s;
   size_t flags;
   size_t f, d, l, w, q, i, fn, fnx, fn_bits;
 
   flags = 0;
   f = d = l = w = q = i = fn = fnx = fn_bits = 0;
 
-  /* The following decimal float suffixes, from TR 24732:2009 and TS
-     18661-2:2015, are supported:
+  /* The following decimal float suffixes, from TR 24732:2009, TS
+     18661-2:2015 and C2X, are supported:
 
      df, DF - _Decimal32.
      dd, DD - _Decimal64.
@@ -269,8 +269,21 @@ interpret_float_suffix (cpp_reader *pfile, const uchar *s, size_t len)
   if (fn && fn_bits == 96)
     return 0;
 
-  if (i && !CPP_OPTION (pfile, ext_numeric_literals))
-    return 0;
+  if (i)
+    {
+      if (!CPP_OPTION (pfile, ext_numeric_literals))
+       return 0;
+
+      /* In C++14 and up these suffixes are in the standard library, so treat
+        them as user-defined literals.  */
+      if (CPP_OPTION (pfile, cplusplus)
+         && CPP_OPTION (pfile, lang) > CLK_CXX11
+         && orig_s[0] == 'i'
+         && (orig_len == 1
+             || (orig_len == 2
+                 && (orig_s[1] == 'f' || orig_s[1] == 'l'))))
+       return 0;
+    }
 
   if ((w || q) && !CPP_OPTION (pfile, ext_numeric_literals))
     return 0;
@@ -299,6 +312,7 @@ cpp_interpret_float_suffix (cpp_reader *pfile, const char *s, size_t len)
 static unsigned int
 interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
 {
+  size_t orig_len = len;
   size_t u, l, i;
 
   u = l = i = 0;
@@ -321,8 +335,19 @@ interpret_int_suffix (cpp_reader *pfile, const uchar *s, size_t len)
   if (l > 2 || u > 1 || i > 1)
     return 0;
 
-  if (i && !CPP_OPTION (pfile, ext_numeric_literals))
-    return 0;
+  if (i)
+    {
+      if (!CPP_OPTION (pfile, ext_numeric_literals))
+       return 0;
+
+      /* In C++14 and up these suffixes are in the standard library, so treat
+        them as user-defined literals.  */
+      if (CPP_OPTION (pfile, cplusplus)
+         && CPP_OPTION (pfile, lang) > CLK_CXX11
+         && s[0] == 'i'
+         && (orig_len == 1 || (orig_len == 2 && s[1] == 'l')))
+       return 0;
+    }
 
   return ((i ? CPP_N_IMAGINARY : 0)
          | (u ? CPP_N_UNSIGNED : 0)
@@ -478,7 +503,7 @@ cpp_get_userdef_suffix (const cpp_token *tok)
    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 char **ud_suffix, location_t virtual_location)
 {
   const uchar *str = token->val.str.text;
   const uchar *limit;
@@ -636,7 +661,7 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
        {
          if (CPP_OPTION (pfile, cplusplus))
            cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
-                                "use of C++1z hexadecimal floating constant");
+                                "use of C++17 hexadecimal floating constant");
          else
            cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
                                 "use of C99 hexadecimal floating constant");
@@ -717,9 +742,16 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
        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");
+      if (result & CPP_N_DFLOAT)
+       {
+         if (CPP_PEDANTIC (pfile) && !CPP_OPTION (pfile, dfp_constants))
+           cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                                "decimal float constants are a C2X feature");
+         else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0)
+           cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT,
+                                  virtual_location, 0,
+                                  "decimal float constants are a C2X feature");
+       }
 
       result |= CPP_N_FLOATING;
     }
@@ -780,14 +812,21 @@ cpp_classify_number (cpp_reader *pfile, const cpp_token *token,
   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)
-                        ? N_("binary constants are a C++14 feature "
-                             "or GCC extension")
-                        : N_("binary constants are a GCC extension"));
+  if (radix == 2)
+    {
+      if (!CPP_OPTION (pfile, binary_constants)
+         && CPP_PEDANTIC (pfile))
+       cpp_error_with_line (pfile, CPP_DL_PEDWARN, virtual_location, 0,
+                            CPP_OPTION (pfile, cplusplus)
+                            ? N_("binary constants are a C++14 feature "
+                                 "or GCC extension")
+                            : N_("binary constants are a C2X feature "
+                                 "or GCC extension"));
+      else if (CPP_OPTION (pfile, cpp_warn_c11_c2x_compat) > 0)
+       cpp_warning_with_line (pfile, CPP_W_C11_C2X_COMPAT,
+                              virtual_location, 0,
+                              "binary constants are a C2X feature");
+    }
 
   if (radix == 10)
     result |= CPP_N_DECIMAL;
@@ -1029,30 +1068,19 @@ parse_defined (cpp_reader *pfile)
        }
     }
 
+  bool is_defined = false;
   if (node)
     {
-      if (pfile->context != initial_context && CPP_PEDANTIC (pfile))
-       cpp_error (pfile, CPP_DL_WARNING,
-                  "this use of \"defined\" may not be portable");
-
+      if ((pfile->context != initial_context
+          || initial_context != &pfile->base_context)
+         && CPP_OPTION (pfile, warn_expansion_to_defined))
+        cpp_pedwarning (pfile, CPP_W_EXPANSION_TO_DEFINED,
+                       "this use of \"defined\" may not be portable");
+      is_defined = _cpp_defined_macro_p (node);
+      if (!_cpp_maybe_notify_macro_use (pfile, node, token->src_loc))
+       /* It wasn't a macro after all.  */
+       is_defined = false;
       _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.  */
@@ -1062,14 +1090,13 @@ parse_defined (cpp_reader *pfile)
   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
+     powerpc port 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);
+  result.low = is_defined;
   return result;
 }
 
@@ -1078,7 +1105,7 @@ parse_defined (cpp_reader *pfile)
    operators).  */
 static cpp_num
 eval_token (cpp_reader *pfile, const cpp_token *token,
-           source_location virtual_location)
+           location_t virtual_location)
 {
   cpp_num result;
   unsigned int temp;
@@ -1140,10 +1167,6 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
     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 (CPP_OPTION (pfile, cplusplus)
               && (token->val.node.node == pfile->spec_nodes.n_true
                   || token->val.node.node == pfile->spec_nodes.n_false))
@@ -1275,7 +1298,7 @@ _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;
+  location_t virtual_location = 0;
 
   pfile->state.skip_eval = 0;
 
@@ -2073,7 +2096,7 @@ num_mul (cpp_reader *pfile, cpp_num lhs, cpp_num rhs)
 
 static cpp_num
 num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
-           source_location location)
+           location_t location)
 {
   cpp_num result, sub;
   cpp_num_part mask;
@@ -2170,71 +2193,3 @@ num_div_op (cpp_reader *pfile, cpp_num lhs, cpp_num rhs, enum cpp_ttype op,
   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;
-}