diff gcc/opts-common.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents 04ced10e8804
children 1830386684a0
line wrap: on
line diff
--- a/gcc/opts-common.c	Fri Oct 27 22:46:09 2017 +0900
+++ b/gcc/opts-common.c	Thu Oct 25 07:37:49 2018 +0900
@@ -1,5 +1,5 @@
 /* Command line option handling.
-   Copyright (C) 2006-2017 Free Software Foundation, Inc.
+   Copyright (C) 2006-2018 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -169,32 +169,95 @@
   return match_wrong_lang;
 }
 
-/* If ARG is a non-negative decimal or hexadecimal integer, return its
-   value, otherwise return -1.  */
-
-int
-integral_argument (const char *arg)
-{
-  const char *p = arg;
-
-  while (*p && ISDIGIT (*p))
-    p++;
+/* If ARG is a non-negative decimal or hexadecimal integer representable
+   in HOST_WIDE_INT return its value, otherwise return -1.  If ERR is not
+   null set *ERR to zero on success or to EINVAL or to the value of errno
+   otherwise.  */
 
-  if (*p == '\0')
-    return atoi (arg);
+HOST_WIDE_INT
+integral_argument (const char *arg, int *err, bool byte_size_suffix)
+{
+  if (!err)
+    err = &errno;
 
-  /* It wasn't a decimal number - try hexadecimal.  */
-  if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X'))
+  if (!ISDIGIT (*arg))
     {
-      p = arg + 2;
-      while (*p && ISXDIGIT (*p))
-	p++;
-
-      if (p != arg + 2 && *p == '\0')
-	return strtol (arg, NULL, 16);
+      *err = EINVAL;
+      return -1;
     }
 
-  return -1;
+  *err = 0;
+  errno = 0;
+
+  char *end = NULL;
+  unsigned HOST_WIDE_INT unit = 1;
+  unsigned HOST_WIDE_INT value = strtoull (arg, &end, 10);
+
+  /* If the value is too large to be represented use the maximum
+     representable value that strtoull sets VALUE to (setting
+     errno to ERANGE).  */
+
+  if (end && *end)
+    {
+      if (!byte_size_suffix)
+	{
+	  errno = 0;
+	  value = strtoull (arg, &end, 0);
+	  if (*end)
+	    {
+	      /* errno is most likely EINVAL here.  */
+	      *err = errno;
+	      return -1;
+	    }
+
+	  return value;
+	}
+
+      /* Numeric option arguments are at most INT_MAX.  Make it
+	 possible to specify a larger value by accepting common
+	 suffixes.  */
+      if (!strcmp (end, "kB"))
+	unit = 1000;
+      else if (!strcasecmp (end, "KiB") || !strcmp (end, "KB"))
+	unit = 1024;
+      else if (!strcmp (end, "MB"))
+	unit = HOST_WIDE_INT_UC (1000) * 1000;
+      else if (!strcasecmp (end, "MiB"))
+	unit = HOST_WIDE_INT_UC (1024) * 1024;
+      else if (!strcasecmp (end, "GB"))
+	unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000;
+      else if (!strcasecmp (end, "GiB"))
+	unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024;
+      else if (!strcasecmp (end, "TB"))
+	unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000;
+      else if (!strcasecmp (end, "TiB"))
+	unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024;
+      else if (!strcasecmp (end, "PB"))
+	unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000;
+      else if (!strcasecmp (end, "PiB"))
+	unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024;
+      else if (!strcasecmp (end, "EB"))
+	unit = HOST_WIDE_INT_UC (1000) * 1000 * 1000 * 1000 * 1000
+	  * 1000;
+      else if (!strcasecmp (end, "EiB"))
+	unit = HOST_WIDE_INT_UC (1024) * 1024 * 1024 * 1024 * 1024
+	  * 1024;
+      else
+	{
+	  /* This could mean an unknown suffix or a bad prefix, like
+	     "+-1".  */
+	  *err = EINVAL;
+	  return -1;
+	}
+    }
+
+  if (unit)
+    {
+      unsigned HOST_WIDE_INT prod = value * unit;
+      value = prod < value ? HOST_WIDE_INT_M1U : prod;
+    }
+
+  return value;
 }
 
 /* Return whether OPTION is OK for the language given by
@@ -230,7 +293,8 @@
 
 static bool
 enum_arg_to_value (const struct cl_enum_arg *enum_args,
-		   const char *arg, int *value, unsigned int lang_mask)
+		   const char *arg, HOST_WIDE_INT *value,
+		   unsigned int lang_mask)
 {
   unsigned int i;
 
@@ -250,15 +314,22 @@
    and returning false without modifying *VALUE if not found.  */
 
 bool
-opt_enum_arg_to_value (size_t opt_index, const char *arg, int *value,
-		       unsigned int lang_mask)
+opt_enum_arg_to_value (size_t opt_index, const char *arg,
+		       int *value, unsigned int lang_mask)
 {
   const struct cl_option *option = &cl_options[opt_index];
 
   gcc_assert (option->var_type == CLVC_ENUM);
 
-  return enum_arg_to_value (cl_enums[option->var_enum].values, arg,
-			    value, lang_mask);
+  HOST_WIDE_INT wideval;
+  if (enum_arg_to_value (cl_enums[option->var_enum].values, arg,
+			 &wideval, lang_mask))
+    {
+      *value = wideval;
+      return true;
+    }
+
+  return false;
 }
 
 /* Look of VALUE in ENUM_ARGS for language LANG_MASK and store the
@@ -299,7 +370,8 @@
    described by OPT_INDEX, ARG and VALUE.  */
 
 static void
-generate_canonical_option (size_t opt_index, const char *arg, int value,
+generate_canonical_option (size_t opt_index, const char *arg,
+			   HOST_WIDE_INT value,
 			   struct cl_decoded_option *decoded)
 {
   const struct cl_option *option = &cl_options[opt_index];
@@ -449,7 +521,7 @@
 {
   size_t opt_index;
   const char *arg = 0;
-  int value = 1;
+  HOST_WIDE_INT value = 1;
   unsigned int result = 1, i, extra_args, separate_args = 0;
   int adjust_len = 0;
   size_t total_len;
@@ -520,6 +592,11 @@
       goto done;
     }
 
+  /* Clear the initial value for size options (it will be overwritten
+     later based on the Init(value) specification in the opt file.  */
+  if (option->var_type == CLVC_SIZE)
+    value = 0;
+
   result = extra_args + 1;
   warn_message = option->warn_message;
 
@@ -586,13 +663,13 @@
     {
       size_t new_opt_index = option->alias_target;
 
-      if (new_opt_index == OPT_SPECIAL_ignore)
+      if (new_opt_index == OPT_SPECIAL_ignore
+	  || new_opt_index == OPT_SPECIAL_deprecated)
 	{
 	  gcc_assert (option->alias_arg == NULL);
 	  gcc_assert (option->neg_alias_arg == NULL);
 	  opt_index = new_opt_index;
 	  arg = NULL;
-	  value = 1;
 	}
       else
 	{
@@ -680,11 +757,12 @@
       arg = arg_lower;
     }
 
-  /* If the switch takes an integer, convert it.  */
-  if (arg && option->cl_uinteger)
+  /* If the switch takes an integer argument, convert it.  */
+  if (arg && (option->cl_uinteger || option->cl_host_wide_int))
     {
-      value = integral_argument (arg);
-      if (value == -1)
+      int error = 0;
+      value = *arg ? integral_argument (arg, &error, option->cl_byte_size) : 0;
+      if (error)
 	errors |= CL_ERR_UINT_ARG;
 
       /* Reject value out of a range.  */
@@ -741,7 +819,8 @@
       else
 	decoded->canonical_option[i] = NULL;
     }
-  if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore)
+  if (opt_index != OPT_SPECIAL_unknown && opt_index != OPT_SPECIAL_ignore
+      && opt_index != OPT_SPECIAL_deprecated)
     {
       generate_canonical_option (opt_index, arg, value, decoded);
       if (separate_args > 1)
@@ -919,6 +998,7 @@
 	{
 	case OPT_SPECIAL_unknown:
 	case OPT_SPECIAL_ignore:
+	case OPT_SPECIAL_deprecated:
 	case OPT_SPECIAL_program_name:
 	case OPT_SPECIAL_input_file:
 	  goto keep;
@@ -1004,7 +1084,7 @@
 {
   size_t opt_index = decoded->opt_index;
   const char *arg = decoded->arg;
-  int value = decoded->value;
+  HOST_WIDE_INT value = decoded->value;
   const struct cl_option *option = &cl_options[opt_index];
   void *flag_var = option_flag_var (opt_index, opts);
   size_t i;
@@ -1034,7 +1114,7 @@
 bool
 handle_generated_option (struct gcc_options *opts,
 			 struct gcc_options *opts_set,
-			 size_t opt_index, const char *arg, int value,
+			 size_t opt_index, const char *arg, HOST_WIDE_INT value,
 			 unsigned int lang_mask, int kind, location_t loc,
 			 const struct cl_option_handlers *handlers,
 			 bool generated_p, diagnostic_context *dc)
@@ -1051,7 +1131,7 @@
    compiler generates options internally.  */
 
 void
-generate_option (size_t opt_index, const char *arg, int value,
+generate_option (size_t opt_index, const char *arg, HOST_WIDE_INT value,
 		 unsigned int lang_mask, struct cl_decoded_option *decoded)
 {
   const struct cl_option *option = &cl_options[opt_index];
@@ -1163,8 +1243,13 @@
 
   if (errors & CL_ERR_UINT_ARG)
     {
-      error_at (loc, "argument to %qs should be a non-negative integer",
-		option->opt_text);
+      if (option->cl_byte_size)
+	error_at (loc, "argument to %qs should be a non-negative integer "
+		  "optionally followed by a size unit",
+		  option->opt_text);
+      else
+	error_at (loc, "argument to %qs should be a non-negative integer",
+		  option->opt_text);
       return true;
     }
 
@@ -1181,6 +1266,7 @@
       unsigned int i;
       char *s;
 
+      auto_diagnostic_group d;
       if (e->unknown_error)
 	error_at (loc, e->unknown_error, arg);
       else
@@ -1237,6 +1323,14 @@
   if (decoded->opt_index == OPT_SPECIAL_ignore)
     return;
 
+  if (decoded->opt_index == OPT_SPECIAL_deprecated)
+    {
+      /* Warn only about positive ignored options.  */
+      if (decoded->value)
+	warning_at (loc, 0, "switch %qs is no longer supported", opt);
+      return;
+    }
+
   option = &cl_options[decoded->opt_index];
 
   if (decoded->errors
@@ -1264,7 +1358,7 @@
 
 void
 set_option (struct gcc_options *opts, struct gcc_options *opts_set,
-	    int opt_index, int value, const char *arg, int kind,
+	    int opt_index, HOST_WIDE_INT value, const char *arg, int kind,
 	    location_t loc, diagnostic_context *dc)
 {
   const struct cl_option *option = &cl_options[opt_index];
@@ -1283,22 +1377,54 @@
   switch (option->var_type)
     {
     case CLVC_BOOLEAN:
-	*(int *) flag_var = value;
-	if (set_flag_var)
-	  *(int *) set_flag_var = 1;
+	if (option->cl_host_wide_int)
+	  {
+	    *(HOST_WIDE_INT *) flag_var = value;
+	    if (set_flag_var)
+	      *(HOST_WIDE_INT *) set_flag_var = 1;
+	  }
+	else
+	  {
+	    *(int *) flag_var = value;
+	    if (set_flag_var)
+	      *(int *) set_flag_var = 1;
+	  }
+
+	break;
+
+    case CLVC_SIZE:
+	if (option->cl_host_wide_int)
+	  {
+	    *(HOST_WIDE_INT *) flag_var = value;
+	    if (set_flag_var)
+	      *(HOST_WIDE_INT *) set_flag_var = value;
+	  }
+	else
+	  {
+	    *(int *) flag_var = value;
+	    if (set_flag_var)
+	      *(int *) set_flag_var = value;
+	  }
+
 	break;
 
     case CLVC_EQUAL:
-	if (option->cl_host_wide_int) 
-	  *(HOST_WIDE_INT *) flag_var = (value
-					 ? option->var_value
-					 : !option->var_value);
+	if (option->cl_host_wide_int)
+	  {
+	    *(HOST_WIDE_INT *) flag_var = (value
+					   ? option->var_value
+					   : !option->var_value);
+	    if (set_flag_var)
+	      *(HOST_WIDE_INT *) set_flag_var = 1;
+	  }
 	else
-	  *(int *) flag_var = (value
-			       ? option->var_value
-			       : !option->var_value);
-	if (set_flag_var)
-	  *(int *) set_flag_var = 1;
+	  {
+	    *(int *) flag_var = (value
+				 ? option->var_value
+				 : !option->var_value);
+	    if (set_flag_var)
+	      *(int *) set_flag_var = 1;
+	  }
 	break;
 
     case CLVC_BIT_CLEAR:
@@ -1385,7 +1511,10 @@
     switch (option->var_type)
       {
       case CLVC_BOOLEAN:
-	return *(int *) flag_var != 0;
+	if (option->cl_host_wide_int)
+	  return *(HOST_WIDE_INT *) flag_var != 0;
+	else
+	  return *(int *) flag_var != 0;
 
       case CLVC_EQUAL:
 	if (option->cl_host_wide_int) 
@@ -1405,6 +1534,12 @@
 	else 
 	  return (*(int *) flag_var & option->var_value) != 0;
 
+      case CLVC_SIZE:
+	if (option->cl_host_wide_int)
+	  return *(HOST_WIDE_INT *) flag_var != -1;
+	else
+	  return *(int *) flag_var != -1;
+
       case CLVC_STRING:
       case CLVC_ENUM:
       case CLVC_DEFER:
@@ -1429,6 +1564,7 @@
     {
     case CLVC_BOOLEAN:
     case CLVC_EQUAL:
+    case CLVC_SIZE:
       state->data = flag_var;
       state->size = (cl_options[option].cl_host_wide_int
 		     ? sizeof (HOST_WIDE_INT)
@@ -1484,7 +1620,7 @@
 	arg = cl_options[opt_index].alias_arg;
       opt_index = cl_options[opt_index].alias_target;
     }
-  if (opt_index == OPT_SPECIAL_ignore)
+  if (opt_index == OPT_SPECIAL_ignore || opt_index == OPT_SPECIAL_deprecated)
     return;
   if (dc)
     diagnostic_classify_diagnostic (dc, opt_index, (diagnostic_t) kind, loc);
@@ -1493,9 +1629,11 @@
       const struct cl_option *option = &cl_options[opt_index];
 
       /* -Werror=foo implies -Wfoo.  */
-      if (option->var_type == CLVC_BOOLEAN || option->var_type == CLVC_ENUM)
+      if (option->var_type == CLVC_BOOLEAN
+	  || option->var_type == CLVC_ENUM
+	  || option->var_type == CLVC_SIZE)
 	{
-	  int value = 1;
+	  HOST_WIDE_INT value = 1;
 
 	  if (arg && *arg == '\0' && !option->cl_missing_ok)
 	    arg = NULL;
@@ -1507,11 +1645,13 @@
 	      return;
 	    }
 
-	  /* If the switch takes an integer, convert it.  */
-	  if (arg && option->cl_uinteger)
+	  /* If the switch takes an integer argument, convert it.  */
+	  if (arg && (option->cl_uinteger || option->cl_host_wide_int))
 	    {
-	      value = integral_argument (arg);
-	      if (value == -1)
+	      int error = 0;
+	      value = *arg ? integral_argument (arg, &error,
+						option->cl_byte_size) : 0;
+	      if (error)
 		{
 		  cmdline_handle_error (loc, option, option->opt_text, arg,
 					CL_ERR_UINT_ARG, lang_mask);