From d168aaeed942c2193519d7b732443972a32c04fa Mon Sep 17 00:00:00 2001 From: Christian Bruel Date: Fri, 1 Jun 2012 09:55:39 +0200 Subject: [PATCH] Allow --specs options. 2012-05-30 Christian Bruel * 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 | 19 +++++ gcc/gcc.c | 122 ++++++++++++++++------------ gcc/testsuite/ChangeLog | 5 ++ gcc/testsuite/gcc.dg/foo.specs | 2 + gcc/testsuite/gcc.dg/spec-options.c | 17 ++++ 5 files changed, 115 insertions(+), 50 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/foo.specs create mode 100644 gcc/testsuite/gcc.dg/spec-options.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6f3460290589..25bf994c2c9a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,22 @@ +2012-06-01 Christian Bruel + + * 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 Add CRIS atomic patterns for 1, 2, and 4 bytes. diff --git a/gcc/gcc.c b/gcc/gcc.c index eb3b220d10af..116cf5d49b4a 100644 --- 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; } /* 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; } /* 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) } 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; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f9707d21b760..56bc07071cad 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2012-06-01 Christian Bruel + + * gcc.dg/spec-options.c: New test. + * gcc.dg/foo.specs: New file. + 2012-06-01 Eric Botcazou PR ada/53517 diff --git a/gcc/testsuite/gcc.dg/foo.specs b/gcc/testsuite/gcc.dg/foo.specs new file mode 100644 index 000000000000..8819249fa340 --- /dev/null +++ b/gcc/testsuite/gcc.dg/foo.specs @@ -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 index 000000000000..1f9d8c1fd84a --- /dev/null +++ b/gcc/testsuite/gcc.dg/spec-options.c @@ -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 +}