Allow --specs options.
authorChristian Bruel <christian.bruel@st.com>
Fri, 1 Jun 2012 07:55:39 +0000 (09:55 +0200)
committerChristian Bruel <chrbr@gcc.gnu.org>
Fri, 1 Jun 2012 07:55:39 +0000 (09:55 +0200)
2012-05-30  Christian Bruel  <christian.bruel@st.com>

* gcc.c (save_switch): Add user_p parameter.
(read_specs): Likewise.
(set_specs): Likewise.
(validate_switches): Likewise.
(validate_switches_from_spec): Likewise.
(validate_all_switches): Pass on user_p parameter.
(struct spec_list): Add user_p field.
(struct switchstr): Add known field.
(save_switch): Add known parameter.
(INIT_STATIC_SPEC): Initialize user_p;
(driver_unknown_option_callbac): call save_switch if
OPT_SPECIAL_unknown.
(driver_handle_option): Propagate OPT_specs.
(do_spec_1): Set validated only if known.
(check_live_switch): Likewise.
(validate_switches): Set validated if known or user_spec.

From-SVN: r188102

gcc/ChangeLog
gcc/gcc.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/foo.specs [new file with mode: 0644]
gcc/testsuite/gcc.dg/spec-options.c [new file with mode: 0644]

index 6f3460290589d32907f8d95abaade5e4cef18b96..25bf994c2c9ab22d0c3009169109f5dfc3a60af9 100644 (file)
@@ -1,3 +1,22 @@
+2012-06-01  Christian Bruel  <christian.bruel@st.com>
+
+       * gcc.c (save_switch): Add user_p parameter.
+       (read_specs): Likewise.
+       (set_specs): Likewise.
+       (validate_switches): Likewise.
+       (validate_switches_from_spec): Likewise.
+       (validate_all_switches): Pass on user_p parameter.
+       (struct spec_list): Add user_p field.
+       (struct switchstr): Add known field.
+       (save_switch): Add known parameter.
+       (INIT_STATIC_SPEC): Initialize user_p;
+       (driver_unknown_option_callbac): call save_switch if
+       OPT_SPECIAL_unknown.
+       (driver_handle_option): Propagate OPT_specs.
+       (do_spec_1): Set validated only if known.
+       (check_live_switch): Likewise.
+       (validate_switches): Set validated if known or user_spec.
+
 2012-06-01  Hans-Peter Nilsson  <hp@axis.com>
 
        Add CRIS atomic patterns for 1, 2, and 4 bytes.
index eb3b220d10af032f60a1c7033ad9f3f3ec75c1b7..116cf5d49b4a0e53405d5fe86fbf5eb398e075cc 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -190,8 +190,8 @@ static void init_spec (void);
 static void store_arg (const char *, int, int);
 static void insert_wrapper (const char *);
 static char *load_specs (const char *);
-static void read_specs (const char *, int);
-static void set_spec (const char *, const char *);
+static void read_specs (const char *, bool, bool);
+static void set_spec (const char *, const char *, bool);
 static struct compiler *lookup_compiler (const char *, size_t, const char *);
 static char *build_search_list (const struct path_prefix *, const char *,
                                bool, bool);
@@ -227,9 +227,9 @@ static void do_option_spec (const char *, const char *);
 static void do_self_spec (const char *);
 static const char *find_file (const char *);
 static int is_directory (const char *, bool);
-static const char *validate_switches (const char *);
+static const char *validate_switches (const char *, bool);
 static void validate_all_switches (void);
-static inline void validate_switches_from_spec (const char *);
+static inline void validate_switches_from_spec (const char *, bool);
 static void give_switch (int, int);
 static int used_arg (const char *, int);
 static int default_arg (const char *, int);
@@ -1171,11 +1171,12 @@ struct spec_list
   const char **ptr_spec;       /* pointer to the spec itself.  */
   struct spec_list *next;      /* Next spec in linked list.  */
   int name_len;                        /* length of the name */
-  int alloc_p;                 /* whether string was allocated */
+  bool user_p;                 /* whether string come from file spec.  */
+  bool alloc_p;                        /* whether string was allocated */
 };
 
 #define INIT_STATIC_SPEC(NAME,PTR) \
-{ NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, 0 }
+  { NAME, NULL, PTR, (struct spec_list *) 0, sizeof (NAME) - 1, false, false }
 
 /* List of statically defined specs.  */
 static struct spec_list static_specs[] =
@@ -1479,7 +1480,7 @@ init_spec (void)
    current spec.  */
 
 static void
-set_spec (const char *name, const char *spec)
+set_spec (const char *name, const char *spec, bool user_p)
 {
   struct spec_list *sl;
   const char *old_spec;
@@ -1531,7 +1532,8 @@ set_spec (const char *name, const char *spec)
   if (old_spec && sl->alloc_p)
     free (CONST_CAST(char *, old_spec));
 
-  sl->alloc_p = 1;
+  sl->user_p = user_p;
+  sl->alloc_p = true;
 }
 \f
 /* Accumulate a command (program name and args), and run it.  */
@@ -1687,7 +1689,7 @@ load_specs (const char *filename)
    Anything invalid in the file is a fatal error.  */
 
 static void
-read_specs (const char *filename, int main_p)
+read_specs (const char *filename, bool main_p, bool user_p)
 {
   char *buffer;
   char *p;
@@ -1736,7 +1738,7 @@ read_specs (const char *filename, int main_p)
 
              p[-2] = '\0';
              new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
-             read_specs (new_filename ? new_filename : p1, FALSE);
+             read_specs (new_filename ? new_filename : p1, false, user_p);
              continue;
            }
          else if (!strncmp (p1, "%include_noerr", sizeof "%include_noerr" - 1)
@@ -1757,7 +1759,7 @@ read_specs (const char *filename, int main_p)
              p[-2] = '\0';
              new_filename = find_a_file (&startfile_prefixes, p1, R_OK, true);
              if (new_filename)
-               read_specs (new_filename, FALSE);
+               read_specs (new_filename, false, user_p);
              else if (verbose_flag)
                fnotice (stderr, "could not find specs file %s\n", p1);
              continue;
@@ -1834,7 +1836,7 @@ read_specs (const char *filename, int main_p)
 #endif
                }
 
-             set_spec (p2, *(sl->ptr_spec));
+             set_spec (p2, *(sl->ptr_spec), user_p);
              if (sl->alloc_p)
                free (CONST_CAST (char *, *(sl->ptr_spec)));
 
@@ -1900,7 +1902,7 @@ read_specs (const char *filename, int main_p)
          if (! strcmp (suffix, "*link_command"))
            link_command_spec = spec;
          else
-           set_spec (suffix + 1, spec);
+           set_spec (suffix + 1, spec, user_p);
        }
       else
        {
@@ -2820,8 +2822,9 @@ struct switchstr
   const char *part1;
   const char **args;
   unsigned int live_cond;
-  unsigned char validated;
-  unsigned char ordering;
+  bool known;
+  bool validated;
+  bool ordering;
 };
 
 static struct switchstr *switches;
@@ -3087,11 +3090,11 @@ alloc_switch (void)
 }
 
 /* Save an option OPT with N_ARGS arguments in array ARGS, marking it
-   as validated if VALIDATED.  */
+   as validated if VALIDATED and KNOWN if it is an internal switch.  */
 
 static void
 save_switch (const char *opt, size_t n_args, const char *const *args,
-            bool validated)
+            bool validated, bool known)
 {
   alloc_switch ();
   switches[n_switches].part1 = opt + 1;
@@ -3106,6 +3109,7 @@ save_switch (const char *opt, size_t n_args, const char *const *args,
 
   switches[n_switches].live_cond = 0;
   switches[n_switches].validated = validated;
+  switches[n_switches].known = known;
   switches[n_switches].ordering = 0;
   n_switches++;
 }
@@ -3124,7 +3128,15 @@ driver_unknown_option_callback (const struct cl_decoded_option *decoded)
         diagnosed only if there are warnings.  */
       save_switch (decoded->canonical_option[0],
                   decoded->canonical_option_num_elements - 1,
-                  &decoded->canonical_option[1], false);
+                  &decoded->canonical_option[1], false, true);
+      return false;
+    }
+  if (decoded->opt_index == OPT_SPECIAL_unknown)
+    {
+      /* Give it a chance to define it a a spec file.  */
+      save_switch (decoded->canonical_option[0],
+                  decoded->canonical_option_num_elements - 1,
+                  &decoded->canonical_option[1], false, false);
       return false;
     }
   else
@@ -3151,7 +3163,7 @@ driver_wrong_lang_callback (const struct cl_decoded_option *decoded,
   else
     save_switch (decoded->canonical_option[0],
                 decoded->canonical_option_num_elements - 1,
-                &decoded->canonical_option[1], false);
+                &decoded->canonical_option[1], false, true);
 }
 
 static const char *spec_lang = 0;
@@ -3294,7 +3306,7 @@ driver_handle_option (struct gcc_options *opts,
        compare_debug_opt = NULL;
       else
        compare_debug_opt = arg;
-      save_switch (compare_debug_replacement_opt, 0, NULL, validated);
+      save_switch (compare_debug_replacement_opt, 0, NULL, validated, true);
       return true;
 
     case OPT_Wa_:
@@ -3379,12 +3391,12 @@ driver_handle_option (struct gcc_options *opts,
     case OPT_L:
       /* Similarly, canonicalize -L for linkers that may not accept
         separate arguments.  */
-      save_switch (concat ("-L", arg, NULL), 0, NULL, validated);
+      save_switch (concat ("-L", arg, NULL), 0, NULL, validated, true);
       return true;
 
     case OPT_F:
       /* Likewise -F.  */
-      save_switch (concat ("-F", arg, NULL), 0, NULL, validated);
+      save_switch (concat ("-F", arg, NULL), 0, NULL, validated, true);
       return true;
 
     case OPT_save_temps:
@@ -3427,7 +3439,7 @@ driver_handle_option (struct gcc_options *opts,
          user_specs_head = user;
        user_specs_tail = user;
       }
-      do_save = false;
+      validated = true;
       break;
 
     case OPT__sysroot_:
@@ -3506,7 +3518,7 @@ driver_handle_option (struct gcc_options *opts,
       save_temps_prefix = xstrdup (arg);
       /* On some systems, ld cannot handle "-o" without a space.  So
         split the option from its argument.  */
-      save_switch ("-o", 1, &arg, validated);
+      save_switch ("-o", 1, &arg, validated, true);
       return true;
 
     case OPT_static_libgcc:
@@ -3529,7 +3541,7 @@ driver_handle_option (struct gcc_options *opts,
   if (do_save)
     save_switch (decoded->canonical_option[0],
                 decoded->canonical_option_num_elements - 1,
-                &decoded->canonical_option[1], validated);
+                &decoded->canonical_option[1], validated, true);
   return true;
 }
 
@@ -3822,7 +3834,7 @@ process_command (unsigned int decoded_options_count,
            }
          else
            fname = xstrdup (arg);
+
           if (strcmp (fname, "-") != 0 && access (fname, F_OK) < 0)
            perror_with_name (fname);
           else
@@ -3956,7 +3968,8 @@ process_command (unsigned int decoded_options_count,
                                           NULL);
       switches[n_switches].args = 0;
       switches[n_switches].live_cond = 0;
-      switches[n_switches].validated = 0;
+      switches[n_switches].validated = false;
+      switches[n_switches].known = false;
       switches[n_switches].ordering = 0;
       n_switches++;
       compare_debug = 1;
@@ -4331,7 +4344,7 @@ do_self_spec (const char *spec)
              save_switch (decoded_options[j].canonical_option[0],
                           (decoded_options[j].canonical_option_num_elements
                            - 1),
-                          &decoded_options[j].canonical_option[1], false);
+                          &decoded_options[j].canonical_option[1], false, true);
              break;
 
            default:
@@ -5204,7 +5217,11 @@ do_spec_1 (const char *spec, int inswitch, const char *soft_matched_part)
                    && (have_wildcard || switches[i].part1[len] == '\0'))
                  {
                    switches[i].live_cond |= switch_option;
-                   switches[i].validated = 1;
+                   /* User switch be validated from validate_all_switches.
+                      when the definition is seen from the spec file.
+                      If not defined anywhere, will be rejected.  */
+                   if (switches[i].known)
+                     switches[i].validated = true;
                  }
 
              p += len;
@@ -5817,7 +5834,7 @@ check_live_switch (int switchnum, int prefix_length)
       for (i = switchnum + 1; i < n_switches; i++)
        if (switches[i].part1[0] == 'O')
          {
-           switches[switchnum].validated = 1;
+           switches[switchnum].validated = true;
            switches[switchnum].live_cond = SWITCH_FALSE;
            return 0;
          }
@@ -5831,7 +5848,9 @@ check_live_switch (int switchnum, int prefix_length)
            if (switches[i].part1[0] == name[0]
                && ! strcmp (&switches[i].part1[1], &name[4]))
              {
-               switches[switchnum].validated = 1;
+               /* --specs are validated with the validate_switches mechanism.  */
+               if (switches[switchnum].known)
+                 switches[switchnum].validated = true;
                switches[switchnum].live_cond = SWITCH_FALSE;
                return 0;
              }
@@ -5846,7 +5865,9 @@ check_live_switch (int switchnum, int prefix_length)
                && switches[i].part1[3] == '-'
                && !strcmp (&switches[i].part1[4], &name[1]))
              {
-               switches[switchnum].validated = 1;
+               /* --specs are validated with the validate_switches mechanism.  */
+               if (switches[switchnum].known)
+                 switches[switchnum].validated = true;
                switches[switchnum].live_cond = SWITCH_FALSE;
                return 0;
              }
@@ -5910,7 +5931,7 @@ give_switch (int switchnum, int omit_first_word)
     }
 
   do_spec_1 (" ", 0, NULL);
-  switches[switchnum].validated = 1;
+  switches[switchnum].validated = true;
 }
 \f
 /* Search for a file named NAME trying various prefixes including the
@@ -6278,7 +6299,7 @@ main (int argc, char **argv)
   specs_file = find_a_file (&startfile_prefixes, "specs", R_OK, true);
   /* Read the specs file unless it is a default one.  */
   if (specs_file != 0 && strcmp (specs_file, "specs"))
-    read_specs (specs_file, TRUE);
+    read_specs (specs_file, true, false);
   else
     init_spec ();
 
@@ -6291,7 +6312,7 @@ main (int argc, char **argv)
   strcat (specs_file, just_machine_suffix);
   strcat (specs_file, "specs");
   if (access (specs_file, R_OK) == 0)
-    read_specs (specs_file, TRUE);
+    read_specs (specs_file, true, false);
 
   /* Process any configure-time defaults specified for the command line
      options, via OPTION_DEFAULT_SPECS.  */
@@ -6335,7 +6356,7 @@ main (int argc, char **argv)
     {
       obstack_grow (&obstack, "%(sysroot_spec) ", strlen ("%(sysroot_spec) "));
       obstack_grow0 (&obstack, link_spec, strlen (link_spec));
-      set_spec ("link", XOBFINISH (&obstack, const char *));
+      set_spec ("link", XOBFINISH (&obstack, const char *), false);
     }
 #endif
 
@@ -6411,7 +6432,7 @@ main (int argc, char **argv)
     {
       char *filename = find_a_file (&startfile_prefixes, uptr->filename,
                                    R_OK, true);
-      read_specs (filename ? filename : uptr->filename, FALSE);
+      read_specs (filename ? filename : uptr->filename, false, true);
     }
 
   /* Process any user self specs.  */
@@ -6506,11 +6527,11 @@ main (int argc, char **argv)
       xputenv (XOBFINISH (&collect_obstack, char *));
     }
 
-  /* Warn about any switches that no pass was interested in.  */
+  /* Reject switches that no pass was interested in.  */
 
   for (i = 0; (int) i < n_switches; i++)
     if (! switches[i].validated)
-      error ("unrecognized option %<-%s%>", switches[i].part1);
+      error ("unrecognized command line option %<-%s%>", switches[i].part1);
 
   /* Obey some of the options.  */
 
@@ -7050,14 +7071,14 @@ perror_with_name (const char *name)
 }
 \f
 static inline void
-validate_switches_from_spec (const char *spec)
+validate_switches_from_spec (const char *spec, bool user)
 {
   const char *p = spec;
   char c;
   while ((c = *p++))
     if (c == '%' && (*p == '{' || *p == '<' || (*p == 'W' && *++p == '{')))
       /* We have a switch spec.  */
-      p = validate_switches (p + 1);
+      p = validate_switches (p + 1, user);
 }
 
 static void
@@ -7067,20 +7088,20 @@ validate_all_switches (void)
   struct spec_list *spec;
 
   for (comp = compilers; comp->spec; comp++)
-    validate_switches_from_spec (comp->spec);
+    validate_switches_from_spec (comp->spec, false);
 
   /* Look through the linked list of specs read from the specs file.  */
   for (spec = specs; spec; spec = spec->next)
-    validate_switches_from_spec (*spec->ptr_spec);
+    validate_switches_from_spec (*spec->ptr_spec, spec->user_p);
 
-  validate_switches_from_spec (link_command_spec);
+  validate_switches_from_spec (link_command_spec, false);
 }
 
 /* Look at the switch-name that comes after START
    and mark as valid all supplied switches that match it.  */
 
 static const char *
-validate_switches (const char *start)
+validate_switches (const char *start, bool user_spec)
 {
   const char *p = start;
   const char *atom;
@@ -7117,8 +7138,9 @@ next_member:
       /* Mark all matching switches as valid.  */
       for (i = 0; i < n_switches; i++)
        if (!strncmp (switches[i].part1, atom, len)
-           && (starred || switches[i].part1[len] == 0))
-         switches[i].validated = 1;
+           && (starred || switches[i].part1[len] == '\0')
+           && (switches[i].known || user_spec))
+             switches[i].validated = true;
     }
 
   if (*p) p++;
@@ -7133,9 +7155,9 @@ next_member:
            {
              p++;
              if (*p == '{' || *p == '<')
-               p = validate_switches (p+1);
+               p = validate_switches (p+1, user_spec);
              else if (p[0] == 'W' && p[1] == '{')
-               p = validate_switches (p+2);
+               p = validate_switches (p+2, user_spec);
            }
          else
            p++;
@@ -8065,7 +8087,7 @@ include_spec_function (int argc, const char **argv)
     abort ();
 
   file = find_a_file (&startfile_prefixes, argv[0], R_OK, true);
-  read_specs (file ? file : argv[0], FALSE);
+  read_specs (file ? file : argv[0], false, false);
 
   return NULL;
 }
index f9707d21b7605957e7fdf352eec448e4d05657d2..56bc07071cade390c39f064eb95b60c0449bdca6 100644 (file)
@@ -1,3 +1,8 @@
+2012-06-01  Christian Bruel  <christian.bruel@st.com>
+
+       * gcc.dg/spec-options.c: New test.
+       * gcc.dg/foo.specs: New file.
+
 2012-06-01  Eric Botcazou  <ebotcazou@adacore.com>
 
        PR ada/53517
diff --git a/gcc/testsuite/gcc.dg/foo.specs b/gcc/testsuite/gcc.dg/foo.specs
new file mode 100644 (file)
index 0000000..8819249
--- /dev/null
@@ -0,0 +1,2 @@
+*cppruntime:
++ %{tfoo: -DFOO}
diff --git a/gcc/testsuite/gcc.dg/spec-options.c b/gcc/testsuite/gcc.dg/spec-options.c
new file mode 100644 (file)
index 0000000..1f9d8c1
--- /dev/null
@@ -0,0 +1,17 @@
+/* Check that -mfoo is accepted if defined in a user spec
+   and that it is not passed on the command line.  */
+/* Must be processed in EXTRA_SPECS to run.  */
+/* { dg-do run { target sh*-*-* } } */
+/* { dg-do compile } */
+/* { dg-options "-B${srcdir}/gcc.dg --specs=foo.specs -tfoo" } */
+
+extern void abort(void);
+
+int main(void)
+{
+#ifdef FOO
+  return 0;
+#else
+  abort();
+#endif
+}