| /* C/ObjC/C++ command line option handling. |
| Copyright (C) 2002 Free Software Foundation, Inc. |
| Contributed by Neil Booth. |
| |
| This file is part of GCC. |
| |
| GCC 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 2, or (at your option) any later |
| version. |
| |
| GCC 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 GCC; see the file COPYING. If not, write to the Free |
| Software Foundation, 59 Temple Place - Suite 330, Boston, MA |
| 02111-1307, USA. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "tree.h" |
| #include "c-common.h" |
| #include "c-pragma.h" |
| #include "flags.h" |
| #include "toplev.h" |
| #include "langhooks.h" |
| #include "tree-inline.h" |
| #include "diagnostic.h" |
| #include "intl.h" |
| |
| /* CPP's options. */ |
| static cpp_options *cpp_opts; |
| |
| /* Input filename. */ |
| static const char *in_fname; |
| |
| /* Filename and stream for preprocessed output. */ |
| static const char *out_fname; |
| static FILE *out_stream; |
| |
| /* Append dependencies to deps_file. */ |
| static bool deps_append; |
| |
| /* If dependency switches (-MF etc.) have been given. */ |
| static bool deps_seen; |
| |
| /* Dependency output file. */ |
| static const char *deps_file; |
| |
| /* Number of deferred options, deferred options array size. */ |
| static size_t deferred_count, deferred_size; |
| |
| static void missing_arg PARAMS ((size_t)); |
| static size_t find_opt PARAMS ((const char *, int)); |
| static void set_Wimplicit PARAMS ((int)); |
| static void complain_wrong_lang PARAMS ((size_t, int)); |
| static void write_langs PARAMS ((char *, int)); |
| static void print_help PARAMS ((void)); |
| static void handle_OPT_d PARAMS ((const char *)); |
| static void set_std_cxx98 PARAMS ((int)); |
| static void set_std_c89 PARAMS ((int, int)); |
| static void set_std_c99 PARAMS ((int)); |
| static void check_deps_environment_vars PARAMS ((void)); |
| static void preprocess_file PARAMS ((void)); |
| static void handle_deferred_opts PARAMS ((void)); |
| static void sanitize_cpp_opts PARAMS ((void)); |
| |
| #ifndef STDC_0_IN_SYSTEM_HEADERS |
| #define STDC_0_IN_SYSTEM_HEADERS 0 |
| #endif |
| |
| #define CL_C_ONLY (1 << 0) /* Only C. */ |
| #define CL_OBJC_ONLY (1 << 1) /* Only ObjC. */ |
| #define CL_CXX_ONLY (1 << 2) /* Only C++. */ |
| #define CL_OBJCXX_ONLY (1 << 3) /* Only ObjC++. */ |
| #define CL_JOINED (1 << 4) /* If takes joined argument. */ |
| #define CL_SEPARATE (1 << 5) /* If takes a separate argument. */ |
| |
| #define CL_ARG (CL_JOINED | CL_SEPARATE) |
| #define CL_C (CL_C_ONLY | CL_OBJC_ONLY) |
| #define CL_OBJC (CL_OBJC_ONLY | CL_OBJCXX_ONLY) |
| #define CL_CXX (CL_CXX_ONLY | CL_OBJCXX_ONLY) |
| #define CL_ALL (CL_C | CL_CXX) |
| |
| /* This is the list of all command line options, with the leading "-" |
| removed. It must be sorted in ASCII collating order. All options |
| beginning with "f" or "W" are implicitly assumed to take a "no-" |
| form; this form should not be listed. The variable "on" is true if |
| the positive form is given, otherwise it is false. If you don't |
| want to allow a "no-" form, your handler should reject "on" being |
| false by returning zero. See, for example, the handling of |
| -ftabstop=. |
| |
| If the user gives an option to a front end that doesn't support it, |
| an error is output, mentioning which front ends the option is valid |
| for. If you don't want this, you must accept it for all front |
| ends, and test for the front end in the option handler. See, for |
| example, the handling of -Wno-strict-prototypes for C++. |
| |
| If you request an argument with CL_JOINED, CL_SEPARATE or their |
| combination CL_ARG, it is stored in the variable "arg", which is |
| guaranteed to be non-NULL and to not be an empty string. It points |
| to the argument either within the argv[] vector or within one of |
| that vector's strings, and so the text is permanent and copies need |
| not be made. Be sure to add an error message in missing_arg() if |
| the default is not appropriate. */ |
| |
| #define COMMAND_LINE_OPTIONS \ |
| OPT("-help", CL_ALL, OPT__help) \ |
| OPT("C", CL_ALL, OPT_C) \ |
| OPT("CC", CL_ALL, OPT_CC) \ |
| OPT("E", CL_ALL, OPT_E) \ |
| OPT("H", CL_ALL, OPT_H) \ |
| OPT("M", CL_ALL, OPT_M) \ |
| OPT("MD", CL_ALL | CL_SEPARATE, OPT_MD) \ |
| OPT("MF", CL_ALL | CL_ARG, OPT_MF) \ |
| OPT("MG", CL_ALL, OPT_MG) \ |
| OPT("MM", CL_ALL, OPT_MM) \ |
| OPT("MMD", CL_ALL | CL_SEPARATE, OPT_MMD) \ |
| OPT("MP", CL_ALL, OPT_MP) \ |
| OPT("MQ", CL_ALL | CL_ARG, OPT_MQ) \ |
| OPT("MT", CL_ALL | CL_ARG, OPT_MT) \ |
| OPT("P", CL_ALL, OPT_P) \ |
| OPT("Wabi", CL_CXX, OPT_Wabi) \ |
| OPT("Wall", CL_ALL, OPT_Wall) \ |
| OPT("Wbad-function-cast", CL_C, OPT_Wbad_function_cast) \ |
| OPT("Wcast-qual", CL_ALL, OPT_Wcast_qual) \ |
| OPT("Wchar-subscripts", CL_ALL, OPT_Wchar_subscripts) \ |
| OPT("Wcomment", CL_ALL, OPT_Wcomment) \ |
| OPT("Wcomments", CL_ALL, OPT_Wcomments) \ |
| OPT("Wconversion", CL_ALL, OPT_Wconversion) \ |
| OPT("Wctor-dtor-privacy", CL_CXX, OPT_Wctor_dtor_privacy) \ |
| OPT("Wdeprecated", CL_CXX, OPT_Wdeprecated) \ |
| OPT("Wdiv-by-zero", CL_C, OPT_Wdiv_by_zero) \ |
| OPT("Weffc++", CL_CXX, OPT_Weffcxx) \ |
| OPT("Wendif-labels", CL_ALL, OPT_Wendif_labels) \ |
| OPT("Werror", CL_ALL, OPT_Werror) \ |
| OPT("Werror-implicit-function-declaration", \ |
| CL_C, OPT_Werror_implicit_function_decl) \ |
| OPT("Wfloat-equal", CL_ALL, OPT_Wfloat_equal) \ |
| OPT("Wformat", CL_ALL, OPT_Wformat) \ |
| OPT("Wformat-extra-args", CL_ALL, OPT_Wformat_extra_args) \ |
| OPT("Wformat-nonliteral", CL_ALL, OPT_Wformat_nonliteral) \ |
| OPT("Wformat-security", CL_ALL, OPT_Wformat_security) \ |
| OPT("Wformat-y2k", CL_ALL, OPT_Wformat_y2k) \ |
| OPT("Wformat-zero-length", CL_C, OPT_Wformat_zero_length) \ |
| OPT("Wformat=", CL_ALL | CL_JOINED, OPT_Wformat_eq) \ |
| OPT("Wimplicit", CL_ALL, OPT_Wimplicit) \ |
| OPT("Wimplicit-function-declaration", CL_C, OPT_Wimplicit_function_decl) \ |
| OPT("Wimplicit-int", CL_C, OPT_Wimplicit_int) \ |
| OPT("Wimport", CL_ALL, OPT_Wimport) \ |
| OPT("Wlong-long", CL_ALL, OPT_Wlong_long) \ |
| OPT("Wmain", CL_C, OPT_Wmain) \ |
| OPT("Wmissing-braces", CL_ALL, OPT_Wmissing_braces) \ |
| OPT("Wmissing-declarations", CL_C, OPT_Wmissing_declarations) \ |
| OPT("Wmissing-format-attribute",CL_ALL, OPT_Wmissing_format_attribute) \ |
| OPT("Wmissing-prototypes", CL_ALL, OPT_Wmissing_prototypes) \ |
| OPT("Wmultichar", CL_ALL, OPT_Wmultichar) \ |
| OPT("Wnested-externs", CL_C, OPT_Wnested_externs) \ |
| OPT("Wnon-template-friend", CL_CXX, OPT_Wnon_template_friend) \ |
| OPT("Wnon-virtual-dtor", CL_CXX, OPT_Wnon_virtual_dtor) \ |
| OPT("Wnonnull", CL_C, OPT_Wnonnull) \ |
| OPT("Wold-style-cast", CL_CXX, OPT_Wold_style_cast) \ |
| OPT("Woverloaded-virtual", CL_CXX, OPT_Woverloaded_virtual) \ |
| OPT("Wparentheses", CL_ALL, OPT_Wparentheses) \ |
| OPT("Wpmf-conversions", CL_CXX, OPT_Wpmf_conversions) \ |
| OPT("Wpointer-arith", CL_ALL, OPT_Wpointer_arith) \ |
| OPT("Wprotocol", CL_OBJC, OPT_Wprotocol) \ |
| OPT("Wredundant-decls", CL_ALL, OPT_Wredundant_decls) \ |
| OPT("Wreorder", CL_CXX, OPT_Wreorder) \ |
| OPT("Wreturn-type", CL_ALL, OPT_Wreturn_type) \ |
| OPT("Wselector", CL_OBJC, OPT_Wselector) \ |
| OPT("Wsequence-point", CL_C, OPT_Wsequence_point) \ |
| OPT("Wsign-compare", CL_ALL, OPT_Wsign_compare) \ |
| OPT("Wsign-promo", CL_CXX, OPT_Wsign_promo) \ |
| OPT("Wstrict-prototypes", CL_ALL, OPT_Wstrict_prototypes) \ |
| OPT("Wsynth", CL_CXX, OPT_Wsynth) \ |
| OPT("Wsystem-headers", CL_ALL, OPT_Wsystem_headers) \ |
| OPT("Wtraditional", CL_C, OPT_Wtraditional) \ |
| OPT("Wtrigraphs", CL_ALL, OPT_Wtrigraphs) \ |
| OPT("Wundeclared-selector", CL_OBJC, OPT_Wundeclared_selector) \ |
| OPT("Wundef", CL_ALL, OPT_Wundef) \ |
| OPT("Wunknown-pragmas", CL_ALL, OPT_Wunknown_pragmas) \ |
| OPT("Wunused-macros", CL_ALL, OPT_Wunused_macros) \ |
| OPT("Wwrite-strings", CL_ALL, OPT_Wwrite_strings) \ |
| OPT("ansi", CL_ALL, OPT_ansi) \ |
| OPT("d", CL_ALL | CL_JOINED, OPT_d) \ |
| OPT("fabi-version=", CL_CXX | CL_JOINED, OPT_fabi_version) \ |
| OPT("faccess-control", CL_CXX, OPT_faccess_control) \ |
| OPT("fall-virtual", CL_CXX, OPT_fall_virtual) \ |
| OPT("falt-external-templates",CL_CXX, OPT_falt_external_templates) \ |
| OPT("fasm", CL_ALL, OPT_fasm) \ |
| OPT("fbuiltin", CL_ALL, OPT_fbuiltin) \ |
| OPT("fbuiltin-", CL_ALL | CL_JOINED, OPT_fbuiltin_) \ |
| OPT("fcheck-new", CL_CXX, OPT_fcheck_new) \ |
| OPT("fcond-mismatch", CL_ALL, OPT_fcond_mismatch) \ |
| OPT("fconserve-space", CL_CXX, OPT_fconserve_space) \ |
| OPT("fconst-strings", CL_CXX, OPT_fconst_strings) \ |
| OPT("fconstant-string-class=", CL_OBJC | CL_JOINED, \ |
| OPT_fconstant_string_class) \ |
| OPT("fdefault-inline", CL_CXX, OPT_fdefault_inline) \ |
| OPT("fdollars-in-identifiers",CL_ALL, OPT_fdollars_in_identifiers) \ |
| OPT("fdump-", CL_ALL | CL_JOINED, OPT_fdump) \ |
| OPT("felide-constructors", CL_CXX, OPT_felide_constructors) \ |
| OPT("fenforce-eh-specs", CL_CXX, OPT_fenforce_eh_specs) \ |
| OPT("fenum-int-equiv", CL_CXX, OPT_fenum_int_equiv) \ |
| OPT("fexternal-templates", CL_CXX, OPT_fexternal_templates) \ |
| OPT("ffixed-form", CL_C, OPT_ffixed_form) \ |
| OPT("ffixed-line-length-", CL_C | CL_JOINED, OPT_ffixed_line_length) \ |
| OPT("ffor-scope", CL_CXX, OPT_ffor_scope) \ |
| OPT("ffreestanding", CL_C, OPT_ffreestanding) \ |
| OPT("fgnu-keywords", CL_CXX, OPT_fgnu_keywords) \ |
| OPT("fgnu-runtime", CL_OBJC, OPT_fgnu_runtime) \ |
| OPT("fguiding-decls", CL_CXX, OPT_fguiding_decls) \ |
| OPT("fhandle-exceptions", CL_CXX, OPT_fhandle_exceptions) \ |
| OPT("fhonor-std", CL_CXX, OPT_fhonor_std) \ |
| OPT("fhosted", CL_C, OPT_fhosted) \ |
| OPT("fhuge-objects", CL_CXX, OPT_fhuge_objects) \ |
| OPT("fimplement-inlines", CL_CXX, OPT_fimplement_inlines) \ |
| OPT("fimplicit-inline-templates", CL_CXX, OPT_fimplicit_inline_templates) \ |
| OPT("fimplicit-templates", CL_CXX, OPT_fimplicit_templates) \ |
| OPT("flabels-ok", CL_CXX, OPT_flabels_ok) \ |
| OPT("fms-extensions", CL_ALL, OPT_fms_extensions) \ |
| OPT("fname-mangling-version-",CL_CXX | CL_JOINED, OPT_fname_mangling) \ |
| OPT("fnew-abi", CL_CXX, OPT_fnew_abi) \ |
| OPT("fnext-runtime", CL_OBJC, OPT_fnext_runtime) \ |
| OPT("fnonansi-builtins", CL_CXX, OPT_fnonansi_builtins) \ |
| OPT("fnonnull-objects", CL_CXX, OPT_fnonnull_objects) \ |
| OPT("foperator-names", CL_CXX, OPT_foperator_names) \ |
| OPT("foptional-diags", CL_CXX, OPT_foptional_diags) \ |
| OPT("fpermissive", CL_CXX, OPT_fpermissive) \ |
| OPT("fpreprocessed", CL_ALL, OPT_fpreprocessed) \ |
| OPT("frepo", CL_CXX, OPT_frepo) \ |
| OPT("frtti", CL_CXX, OPT_frtti) \ |
| OPT("fshort-double", CL_ALL, OPT_fshort_double) \ |
| OPT("fshort-enums", CL_ALL, OPT_fshort_enums) \ |
| OPT("fshort-wchar", CL_ALL, OPT_fshort_wchar) \ |
| OPT("fshow-column", CL_ALL, OPT_fshow_column) \ |
| OPT("fsigned-bitfields", CL_ALL, OPT_fsigned_bitfields) \ |
| OPT("fsigned-char", CL_ALL, OPT_fsigned_char) \ |
| OPT("fsquangle", CL_CXX, OPT_fsquangle) \ |
| OPT("fstats", CL_CXX, OPT_fstats) \ |
| OPT("fstrict-prototype", CL_CXX, OPT_fstrict_prototype) \ |
| OPT("ftabstop=", CL_ALL | CL_JOINED, OPT_ftabstop) \ |
| OPT("ftemplate-depth-", CL_CXX | CL_JOINED, OPT_ftemplate_depth) \ |
| OPT("fthis-is-variable", CL_CXX, OPT_fthis_is_variable) \ |
| OPT("funsigned-bitfields", CL_ALL, OPT_funsigned_bitfields) \ |
| OPT("funsigned-char", CL_ALL, OPT_funsigned_char) \ |
| OPT("fuse-cxa-atexit", CL_CXX, OPT_fuse_cxa_atexit) \ |
| OPT("fvtable-gc", CL_CXX, OPT_fvtable_gc) \ |
| OPT("fvtable-thunks", CL_CXX, OPT_fvtable_thunks) \ |
| OPT("fweak", CL_CXX, OPT_fweak) \ |
| OPT("fxref", CL_CXX, OPT_fxref) \ |
| OPT("gen-decls", CL_OBJC, OPT_gen_decls) \ |
| OPT("lang-asm", CL_C_ONLY, OPT_lang_asm) \ |
| OPT("lang-objc", CL_ALL, OPT_lang_objc) \ |
| OPT("nostdinc", CL_ALL, OPT_nostdinc) \ |
| OPT("nostdinc++", CL_ALL, OPT_nostdincplusplus) \ |
| OPT("o", CL_ALL | CL_ARG, OPT_o) \ |
| OPT("pedantic", CL_ALL, OPT_pedantic) \ |
| OPT("pedantic-errors", CL_ALL, OPT_pedantic_errors) \ |
| OPT("print-objc-runtime-info", CL_OBJC, OPT_print_objc_runtime_info) \ |
| OPT("remap", CL_ALL, OPT_remap) \ |
| OPT("std=c++98", CL_CXX, OPT_std_cplusplus98) \ |
| OPT("std=c89", CL_C, OPT_std_c89) \ |
| OPT("std=c99", CL_C, OPT_std_c99) \ |
| OPT("std=c9x", CL_C, OPT_std_c9x) \ |
| OPT("std=gnu++98", CL_CXX, OPT_std_gnuplusplus98) \ |
| OPT("std=gnu89", CL_C, OPT_std_gnu89) \ |
| OPT("std=gnu99", CL_C, OPT_std_gnu99) \ |
| OPT("std=gnu9x", CL_C, OPT_std_gnu9x) \ |
| OPT("std=iso9899:1990", CL_C, OPT_std_iso9899_1990) \ |
| OPT("std=iso9899:199409", CL_C, OPT_std_iso9899_199409) \ |
| OPT("std=iso9899:1999", CL_C, OPT_std_iso9899_1999) \ |
| OPT("std=iso9899:199x", CL_C, OPT_std_iso9899_199x) \ |
| OPT("traditional-cpp", CL_ALL, OPT_traditional_cpp) \ |
| OPT("trigraphs", CL_ALL, OPT_trigraphs) \ |
| OPT("undef", CL_ALL, OPT_undef) \ |
| OPT("v", CL_ALL, OPT_v) \ |
| OPT("w", CL_ALL, OPT_w) |
| |
| #define OPT(text, flags, code) code, |
| enum opt_code |
| { |
| COMMAND_LINE_OPTIONS |
| N_OPTS |
| }; |
| #undef OPT |
| |
| struct cl_option |
| { |
| const char *opt_text; |
| unsigned char opt_len; |
| unsigned char flags; |
| ENUM_BITFIELD (opt_code) opt_code : 2 * CHAR_BIT; |
| }; |
| |
| #define OPT(text, flags, code) { text, sizeof(text) - 1, flags, code }, |
| #ifdef HOST_EBCDIC |
| static struct cl_option cl_options[] = |
| #else |
| static const struct cl_option cl_options[] = |
| #endif |
| { |
| COMMAND_LINE_OPTIONS |
| }; |
| #undef OPT |
| #undef COMMAND_LINE_OPTIONS |
| |
| /* Holds switches parsed by c_common_decode_option (), but whose |
| handling is deffered to c_common_post_options (). */ |
| static void defer_opt PARAMS ((enum opt_code, const char *)); |
| static struct deferred_opt |
| { |
| enum opt_code code; |
| const char *arg; |
| } *deferred_opts; |
| |
| |
| #ifdef HOST_EBCDIC |
| static int opt_comp PARAMS ((const void *, const void *)); |
| |
| /* Run-time sorting of options array. */ |
| static int |
| opt_comp (p1, p2) |
| const void *p1, *p2; |
| { |
| return strcmp (((struct cl_option *) p1)->opt_text, |
| ((struct cl_option *) p2)->opt_text); |
| } |
| #endif |
| |
| /* Complain that switch OPT_INDEX expects an argument but none was |
| provided. */ |
| static void |
| missing_arg (opt_index) |
| size_t opt_index; |
| { |
| const char *opt_text = cl_options[opt_index].opt_text; |
| |
| switch (cl_options[opt_index].opt_code) |
| { |
| case OPT_Wformat_eq: |
| case OPT_d: |
| case OPT_fabi_version: |
| case OPT_fbuiltin_: |
| case OPT_fdump: |
| case OPT_fname_mangling: |
| case OPT_ftabstop: |
| case OPT_ftemplate_depth: |
| default: |
| error ("missing argument to \"-%s\"", opt_text); |
| break; |
| |
| case OPT_fconstant_string_class: |
| error ("no class name specified with \"-%s\"", opt_text); |
| break; |
| |
| case OPT_MF: |
| case OPT_MD: |
| case OPT_MMD: |
| case OPT_o: |
| error ("missing filename after \"-%s\"", opt_text); |
| break; |
| |
| case OPT_MQ: |
| case OPT_MT: |
| error ("missing target after \"-%s\"", opt_text); |
| break; |
| } |
| } |
| |
| /* Perform a binary search to find which option the command-line INPUT |
| matches. Returns its index in the option array, and N_OPTS on |
| failure. |
| |
| Complications arise since some options can be suffixed with an |
| argument, and multiple complete matches can occur, e.g. -pedantic |
| and -pedantic-errors. Also, some options are only accepted by some |
| languages. If a switch matches for a different language and |
| doesn't match any alternatives for the true front end, the index of |
| the matched switch is returned anyway. The caller should check for |
| this case. */ |
| static size_t |
| find_opt (input, lang_flag) |
| const char *input; |
| int lang_flag; |
| { |
| size_t md, mn, mx; |
| size_t opt_len; |
| size_t result = N_OPTS; |
| int comp; |
| |
| mn = 0; |
| mx = N_OPTS; |
| |
| while (mx > mn) |
| { |
| md = (mn + mx) / 2; |
| |
| opt_len = cl_options[md].opt_len; |
| comp = strncmp (input, cl_options[md].opt_text, opt_len); |
| |
| if (comp < 0) |
| mx = md; |
| else if (comp > 0) |
| mn = md + 1; |
| else |
| { |
| /* The switch matches. It it an exact match? */ |
| if (input[opt_len] == '\0') |
| return md; |
| else |
| { |
| mn = md + 1; |
| |
| /* If the switch takes no arguments this is not a proper |
| match, so we continue the search (e.g. input="stdc++" |
| match was "stdc"). */ |
| if (!(cl_options[md].flags & CL_JOINED)) |
| continue; |
| |
| /* Is this switch valid for this front end? */ |
| if (!(cl_options[md].flags & lang_flag)) |
| { |
| /* If subsequently we don't find a better match, |
| return this and let the caller report it as a bad |
| match. */ |
| result = md; |
| continue; |
| } |
| |
| /* Two scenarios remain: we have the switch's argument, |
| or we match a longer option. This can happen with |
| -iwithprefix and -withprefixbefore. The longest |
| possible option match succeeds. |
| |
| Scan forwards, and return an exact match. Otherwise |
| return the longest valid option-accepting match (mx). |
| This loops at most twice with current options. */ |
| mx = md; |
| for (md = md + 1; md < (size_t) N_OPTS; md++) |
| { |
| opt_len = cl_options[md].opt_len; |
| if (strncmp (input, cl_options[md].opt_text, opt_len)) |
| break; |
| if (input[opt_len] == '\0') |
| return md; |
| if (cl_options[md].flags & lang_flag |
| && cl_options[md].flags & CL_JOINED) |
| mx = md; |
| } |
| |
| return mx; |
| } |
| } |
| } |
| |
| return result; |
| } |
| |
| /* Defer option CODE with argument ARG. */ |
| static void |
| defer_opt (code, arg) |
| enum opt_code code; |
| const char *arg; |
| { |
| /* FIXME: this should be in c_common_init_options, which should take |
| argc and argv. */ |
| if (!deferred_opts) |
| { |
| extern int save_argc; |
| deferred_size = save_argc; |
| deferred_opts = (struct deferred_opt *) |
| xmalloc (deferred_size * sizeof (struct deferred_opt)); |
| } |
| |
| if (deferred_count == deferred_size) |
| abort (); |
| |
| deferred_opts[deferred_count].code = code; |
| deferred_opts[deferred_count].arg = arg; |
| deferred_count++; |
| } |
| |
| /* Common initialization before parsing options. */ |
| void |
| c_common_init_options (lang) |
| enum c_language_kind lang; |
| { |
| #ifdef HOST_EBCDIC |
| /* For non-ASCII hosts, the cl_options array needs to be sorted at |
| runtime. */ |
| qsort (cl_options, N_OPTS, sizeof (struct cl_option), opt_comp); |
| #endif |
| #if ENABLE_CHECKING |
| { |
| size_t i; |
| |
| for (i = 1; i < N_OPTS; i++) |
| if (strcmp (cl_options[i - 1].opt_text, cl_options[i].opt_text) >= 0) |
| error ("options array incorrectly sorted: %s is before %s", |
| cl_options[i - 1].opt_text, cl_options[i].opt_text); |
| } |
| #endif |
| |
| c_language = lang; |
| parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89 : CLK_GNUCXX); |
| cpp_opts = cpp_get_options (parse_in); |
| if (flag_objc) |
| cpp_opts->objc = 1; |
| |
| flag_const_strings = (lang == clk_cplusplus); |
| warn_pointer_arith = (lang == clk_cplusplus); |
| if (lang == clk_c) |
| warn_sign_compare = -1; |
| } |
| |
| /* Handle one command-line option in (argc, argv). |
| Can be called multiple times, to handle multiple sets of options. |
| Returns number of strings consumed. */ |
| int |
| c_common_decode_option (argc, argv) |
| int argc; |
| char **argv; |
| { |
| static const int lang_flags[] = {CL_C_ONLY, CL_C, CL_CXX_ONLY, CL_CXX}; |
| size_t opt_index; |
| const char *opt, *arg = 0; |
| char *dup = 0; |
| bool on = true; |
| int result, lang_flag; |
| const struct cl_option *option; |
| enum opt_code code; |
| |
| opt = argv[0]; |
| |
| /* Interpret "-" or a non-switch as a file name. */ |
| if (opt[0] != '-' || opt[1] == '\0') |
| { |
| if (!in_fname) |
| in_fname = opt; |
| else if (!out_fname) |
| out_fname = opt; |
| else |
| { |
| error ("too many filenames given. Type %s --help for usage", |
| progname); |
| return argc; |
| } |
| |
| return 1; |
| } |
| |
| /* Drop the "no-" from negative switches. */ |
| if ((opt[1] == 'W' || opt[1] == 'f') |
| && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-') |
| { |
| size_t len = strlen (opt) - 3; |
| |
| dup = xmalloc (len + 1); |
| dup[0] = '-'; |
| dup[1] = opt[1]; |
| memcpy (dup + 2, opt + 5, len - 2 + 1); |
| opt = dup; |
| on = false; |
| } |
| |
| result = cpp_handle_option (parse_in, argc, argv); |
| |
| /* Skip over '-'. */ |
| lang_flag = lang_flags[(c_language << 1) + flag_objc]; |
| opt_index = find_opt (opt + 1, lang_flag); |
| if (opt_index == N_OPTS) |
| goto done; |
| |
| result = 1; |
| option = &cl_options[opt_index]; |
| |
| /* Sort out any argument the switch takes. */ |
| if (option->flags & CL_ARG) |
| { |
| if (option->flags & CL_JOINED) |
| { |
| /* Have arg point to the original switch. This is because |
| some code, such as disable_builtin_function, expects its |
| argument to be persistent until the program exits. */ |
| arg = argv[0] + cl_options[opt_index].opt_len + 1; |
| if (!on) |
| arg += strlen ("no-"); |
| } |
| |
| /* If we don't have an argument, and CL_SEPARATE, try the next |
| argument in the vector. */ |
| if (!arg || (*arg == '\0' && option->flags & CL_SEPARATE)) |
| { |
| arg = argv[1]; |
| result = 2; |
| } |
| |
| if (!arg || *arg == '\0') |
| { |
| missing_arg (opt_index); |
| result = argc; |
| goto done; |
| } |
| } |
| |
| /* Complain about the wrong language after we've swallowed any |
| necessary extra argument. Eventually make this a hard error |
| after the call to find_opt, and return argc. */ |
| if (!(cl_options[opt_index].flags & lang_flag)) |
| { |
| complain_wrong_lang (opt_index, on); |
| goto done; |
| } |
| |
| switch (code = option->opt_code) |
| { |
| case N_OPTS: /* Shut GCC up. */ |
| break; |
| |
| case OPT__help: |
| print_help (); |
| break; |
| |
| case OPT_C: |
| cpp_opts->discard_comments = 0; |
| break; |
| |
| case OPT_CC: |
| cpp_opts->discard_comments = 0; |
| cpp_opts->discard_comments_in_macro_exp = 0; |
| break; |
| |
| case OPT_E: |
| flag_preprocess_only = 1; |
| break; |
| |
| case OPT_H: |
| cpp_opts->print_include_names = 1; |
| break; |
| |
| case OPT_M: |
| case OPT_MM: |
| /* When doing dependencies with -M or -MM, suppress normal |
| preprocessed output, but still do -dM etc. as software |
| depends on this. Preprocessed output does occur if -MD, -MMD |
| or environment var dependency generation is used. */ |
| cpp_opts->deps.style = (code == OPT_M ? DEPS_SYSTEM: DEPS_USER); |
| cpp_opts->no_output = 1; |
| cpp_opts->inhibit_warnings = 1; |
| break; |
| |
| case OPT_MD: |
| case OPT_MMD: |
| cpp_opts->deps.style = (code == OPT_MD ? DEPS_SYSTEM: DEPS_USER); |
| deps_file = arg; |
| break; |
| |
| case OPT_MF: |
| deps_seen = true; |
| deps_file = arg; |
| break; |
| |
| case OPT_MG: |
| deps_seen = true; |
| cpp_opts->deps.missing_files = true; |
| break; |
| |
| case OPT_MP: |
| deps_seen = true; |
| cpp_opts->deps.phony_targets = true; |
| break; |
| |
| case OPT_MQ: |
| case OPT_MT: |
| deps_seen = true; |
| defer_opt (code, arg); |
| break; |
| |
| case OPT_P: |
| cpp_opts->no_line_commands = 1; |
| break; |
| |
| case OPT_Wabi: |
| warn_abi = on; |
| break; |
| |
| case OPT_Wall: |
| set_Wunused (on); |
| set_Wformat (on); |
| set_Wimplicit (on); |
| warn_char_subscripts = on; |
| warn_missing_braces = on; |
| warn_parentheses = on; |
| warn_return_type = on; |
| warn_sequence_point = on; /* Was C only. */ |
| if (c_language == clk_cplusplus) |
| warn_sign_compare = on; |
| warn_switch = on; |
| warn_strict_aliasing = on; |
| |
| /* Only warn about unknown pragmas that are not in system |
| headers. */ |
| warn_unknown_pragmas = on; |
| |
| /* We save the value of warn_uninitialized, since if they put |
| -Wuninitialized on the command line, we need to generate a |
| warning about not using it without also specifying -O. */ |
| if (warn_uninitialized != 1) |
| warn_uninitialized = (on ? 2 : 0); |
| |
| if (c_language == clk_c) |
| /* We set this to 2 here, but 1 in -Wmain, so -ffreestanding |
| can turn it off only if it's not explicit. */ |
| warn_main = on * 2; |
| else |
| { |
| /* C++-specific warnings. */ |
| warn_ctor_dtor_privacy = on; |
| warn_nonvdtor = on; |
| warn_reorder = on; |
| warn_nontemplate_friend = on; |
| } |
| |
| cpp_opts->warn_trigraphs = on; |
| cpp_opts->warn_comments = on; |
| cpp_opts->warn_num_sign_change = on; |
| cpp_opts->warn_multichar = on; /* Was C++ only. */ |
| break; |
| |
| case OPT_Wbad_function_cast: |
| warn_bad_function_cast = on; |
| break; |
| |
| case OPT_Wcast_qual: |
| warn_cast_qual = on; |
| break; |
| |
| case OPT_Wchar_subscripts: |
| warn_char_subscripts = on; |
| break; |
| |
| case OPT_Wcomment: |
| case OPT_Wcomments: |
| cpp_opts->warn_comments = on; |
| break; |
| |
| case OPT_Wconversion: |
| warn_conversion = on; |
| break; |
| |
| case OPT_Wctor_dtor_privacy: |
| warn_ctor_dtor_privacy = on; |
| break; |
| |
| case OPT_Wdeprecated: |
| warn_deprecated = on; |
| break; |
| |
| case OPT_Wdiv_by_zero: |
| warn_div_by_zero = on; |
| break; |
| |
| case OPT_Weffcxx: |
| warn_ecpp = on; |
| break; |
| |
| case OPT_Wendif_labels: |
| cpp_opts->warn_endif_labels = on; |
| break; |
| |
| case OPT_Werror: |
| cpp_opts->warnings_are_errors = on; |
| break; |
| |
| case OPT_Werror_implicit_function_decl: |
| if (!on) |
| result = 0; |
| else |
| mesg_implicit_function_declaration = 2; |
| break; |
| |
| case OPT_Wfloat_equal: |
| warn_float_equal = on; |
| break; |
| |
| case OPT_Wformat: |
| set_Wformat (on); |
| break; |
| |
| case OPT_Wformat_eq: |
| set_Wformat (atoi (arg)); |
| break; |
| |
| case OPT_Wformat_extra_args: |
| warn_format_extra_args = on; |
| break; |
| |
| case OPT_Wformat_nonliteral: |
| warn_format_nonliteral = on; |
| break; |
| |
| case OPT_Wformat_security: |
| warn_format_security = on; |
| break; |
| |
| case OPT_Wformat_y2k: |
| warn_format_y2k = on; |
| break; |
| |
| case OPT_Wformat_zero_length: |
| warn_format_zero_length = on; |
| break; |
| |
| case OPT_Wimplicit: |
| set_Wimplicit (on); |
| break; |
| |
| case OPT_Wimplicit_function_decl: |
| mesg_implicit_function_declaration = on; |
| break; |
| |
| case OPT_Wimplicit_int: |
| warn_implicit_int = on; |
| break; |
| |
| case OPT_Wimport: |
| cpp_opts->warn_import = on; |
| break; |
| |
| case OPT_Wlong_long: |
| warn_long_long = on; |
| break; |
| |
| case OPT_Wmain: |
| if (on) |
| warn_main = 1; |
| else |
| warn_main = -1; |
| break; |
| |
| case OPT_Wmissing_braces: |
| warn_missing_braces = on; |
| break; |
| |
| case OPT_Wmissing_declarations: |
| warn_missing_declarations = on; |
| break; |
| |
| case OPT_Wmissing_format_attribute: |
| warn_missing_format_attribute = on; |
| break; |
| |
| case OPT_Wmissing_prototypes: |
| warn_missing_prototypes = on; |
| break; |
| |
| case OPT_Wmultichar: |
| cpp_opts->warn_multichar = on; |
| break; |
| |
| case OPT_Wnested_externs: |
| warn_nested_externs = on; |
| break; |
| |
| case OPT_Wnon_template_friend: |
| warn_nontemplate_friend = on; |
| break; |
| |
| case OPT_Wnon_virtual_dtor: |
| warn_nonvdtor = on; |
| break; |
| |
| case OPT_Wnonnull: |
| warn_nonnull = on; |
| break; |
| |
| case OPT_Wold_style_cast: |
| warn_old_style_cast = on; |
| break; |
| |
| case OPT_Woverloaded_virtual: |
| warn_overloaded_virtual = on; |
| break; |
| |
| case OPT_Wparentheses: |
| warn_parentheses = on; |
| break; |
| |
| case OPT_Wpmf_conversions: |
| warn_pmf2ptr = on; |
| break; |
| |
| case OPT_Wpointer_arith: |
| warn_pointer_arith = on; |
| break; |
| |
| case OPT_Wprotocol: |
| warn_protocol = on; |
| break; |
| |
| case OPT_Wselector: |
| warn_selector = on; |
| break; |
| |
| case OPT_Wredundant_decls: |
| warn_redundant_decls = on; |
| break; |
| |
| case OPT_Wreorder: |
| warn_reorder = on; |
| break; |
| |
| case OPT_Wreturn_type: |
| warn_return_type = on; |
| break; |
| |
| case OPT_Wsequence_point: |
| warn_sequence_point = on; |
| break; |
| |
| case OPT_Wsign_compare: |
| warn_sign_compare = on; |
| break; |
| |
| case OPT_Wsign_promo: |
| warn_sign_promo = on; |
| break; |
| |
| case OPT_Wstrict_prototypes: |
| if (!on && c_language == clk_cplusplus) |
| warning ("-Wno-strict-prototypes is not supported in C++"); |
| else |
| warn_strict_prototypes = on; |
| break; |
| |
| case OPT_Wsynth: |
| warn_synth = on; |
| break; |
| |
| case OPT_Wsystem_headers: |
| cpp_opts->warn_system_headers = on; |
| break; |
| |
| case OPT_Wtraditional: |
| warn_traditional = on; |
| cpp_opts->warn_traditional = on; |
| break; |
| |
| case OPT_Wtrigraphs: |
| cpp_opts->warn_trigraphs = on; |
| break; |
| |
| case OPT_Wundeclared_selector: |
| warn_undeclared_selector = on; |
| break; |
| |
| case OPT_Wundef: |
| cpp_opts->warn_undef = on; |
| break; |
| |
| case OPT_Wunknown_pragmas: |
| /* Set to greater than 1, so that even unknown pragmas in |
| system headers will be warned about. */ |
| warn_unknown_pragmas = on * 2; |
| break; |
| |
| case OPT_Wunused_macros: |
| cpp_opts->warn_unused_macros = on; |
| break; |
| |
| case OPT_Wwrite_strings: |
| if (c_language == clk_c) |
| flag_const_strings = on; |
| else |
| warn_write_strings = on; |
| break; |
| |
| case OPT_ansi: |
| if (c_language == clk_c) |
| set_std_c89 (false, true); |
| else |
| set_std_cxx98 (true); |
| break; |
| |
| case OPT_d: |
| handle_OPT_d (arg); |
| break; |
| |
| case OPT_fcond_mismatch: |
| if (c_language == clk_c) |
| { |
| flag_cond_mismatch = on; |
| break; |
| } |
| /* Fall through. */ |
| |
| case OPT_fall_virtual: |
| case OPT_fenum_int_equiv: |
| case OPT_fguiding_decls: |
| case OPT_fhonor_std: |
| case OPT_fhuge_objects: |
| case OPT_flabels_ok: |
| case OPT_fname_mangling: |
| case OPT_fnew_abi: |
| case OPT_fnonnull_objects: |
| case OPT_fsquangle: |
| case OPT_fstrict_prototype: |
| case OPT_fthis_is_variable: |
| case OPT_fvtable_thunks: |
| case OPT_fxref: |
| warning ("switch \"%s\" is no longer supported", argv[0]); |
| break; |
| |
| case OPT_fabi_version: |
| flag_abi_version = read_integral_parameter (arg, argv[0], 1); |
| break; |
| |
| case OPT_faccess_control: |
| flag_access_control = on; |
| break; |
| |
| case OPT_falt_external_templates: |
| flag_alt_external_templates = on; |
| if (on) |
| flag_external_templates = true; |
| cp_deprecated: |
| warning ("switch \"%s\" is deprecated, please see documentation for details", argv[0]); |
| break; |
| |
| case OPT_fasm: |
| flag_no_asm = !on; |
| break; |
| |
| case OPT_fbuiltin: |
| flag_no_builtin = !on; |
| break; |
| |
| case OPT_fbuiltin_: |
| if (on) |
| result = 0; |
| else |
| disable_builtin_function (arg); |
| break; |
| |
| case OPT_fdollars_in_identifiers: |
| dollars_in_ident = on; |
| break; |
| |
| case OPT_fdump: |
| if (!on || !dump_switch_p (argv[0] + strlen ("-f"))) |
| result = 0; |
| break; |
| |
| case OPT_ffreestanding: |
| on = !on; |
| /* Fall through... */ |
| case OPT_fhosted: |
| flag_hosted = on; |
| flag_no_builtin = !on; |
| /* warn_main will be 2 if set by -Wall, 1 if set by -Wmain */ |
| if (!on && warn_main == 2) |
| warn_main = 0; |
| break; |
| |
| case OPT_fshort_double: |
| flag_short_double = on; |
| break; |
| |
| case OPT_fshort_enums: |
| flag_short_enums = on; |
| break; |
| |
| case OPT_fshort_wchar: |
| flag_short_wchar = on; |
| break; |
| |
| case OPT_fsigned_bitfields: |
| flag_signed_bitfields = on; |
| explicit_flag_signed_bitfields = 1; |
| break; |
| |
| case OPT_fsigned_char: |
| flag_signed_char = on; |
| break; |
| |
| case OPT_funsigned_bitfields: |
| flag_signed_bitfields = !on; |
| explicit_flag_signed_bitfields = 1; |
| break; |
| |
| case OPT_funsigned_char: |
| flag_signed_char = !on; |
| break; |
| |
| case OPT_fcheck_new: |
| flag_check_new = on; |
| break; |
| |
| case OPT_fconserve_space: |
| flag_conserve_space = on; |
| break; |
| |
| case OPT_fconst_strings: |
| flag_const_strings = on; |
| break; |
| |
| case OPT_fconstant_string_class: |
| constant_string_class_name = arg; |
| break; |
| |
| case OPT_fdefault_inline: |
| flag_default_inline = on; |
| break; |
| |
| case OPT_felide_constructors: |
| flag_elide_constructors = on; |
| break; |
| |
| case OPT_fenforce_eh_specs: |
| flag_enforce_eh_specs = on; |
| break; |
| |
| case OPT_fexternal_templates: |
| flag_external_templates = on; |
| goto cp_deprecated; |
| |
| case OPT_ffixed_form: |
| case OPT_ffixed_line_length: |
| /* Fortran front end options ignored when preprocessing only. */ |
| if (flag_preprocess_only) |
| result = -1; |
| break; |
| |
| case OPT_ffor_scope: |
| flag_new_for_scope = on; |
| break; |
| |
| case OPT_fgnu_keywords: |
| flag_no_gnu_keywords = !on; |
| break; |
| |
| case OPT_fgnu_runtime: |
| flag_next_runtime = !on; |
| break; |
| |
| case OPT_fhandle_exceptions: |
| warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)"); |
| flag_exceptions = on; |
| break; |
| |
| case OPT_fimplement_inlines: |
| flag_implement_inlines = on; |
| break; |
| |
| case OPT_fimplicit_inline_templates: |
| flag_implicit_inline_templates = on; |
| break; |
| |
| case OPT_fimplicit_templates: |
| flag_implicit_templates = on; |
| break; |
| |
| case OPT_fms_extensions: |
| flag_ms_extensions = on; |
| break; |
| |
| case OPT_fnext_runtime: |
| flag_next_runtime = on; |
| break; |
| |
| case OPT_fnonansi_builtins: |
| flag_no_nonansi_builtin = !on; |
| break; |
| |
| case OPT_foperator_names: |
| cpp_opts->operator_names = on; |
| break; |
| |
| case OPT_foptional_diags: |
| flag_optional_diags = on; |
| break; |
| |
| case OPT_fpermissive: |
| flag_permissive = on; |
| break; |
| |
| case OPT_fpreprocessed: |
| cpp_opts->preprocessed = on; |
| break; |
| |
| case OPT_frepo: |
| flag_use_repository = on; |
| if (on) |
| flag_implicit_templates = 0; |
| break; |
| |
| case OPT_frtti: |
| flag_rtti = on; |
| break; |
| |
| case OPT_fshow_column: |
| cpp_opts->show_column = on; |
| break; |
| |
| case OPT_fstats: |
| flag_detailed_statistics = on; |
| break; |
| |
| case OPT_ftabstop: |
| /* Don't recognize -fno-tabstop=. */ |
| if (!on) |
| return 0; |
| |
| /* It is documented that we silently ignore silly values. */ |
| { |
| char *endptr; |
| long tabstop = strtol (arg, &endptr, 10); |
| if (*endptr == '\0' && tabstop >= 1 && tabstop <= 100) |
| cpp_opts->tabstop = tabstop; |
| } |
| break; |
| |
| case OPT_ftemplate_depth: |
| max_tinst_depth = read_integral_parameter (arg, argv[0], 0); |
| break; |
| |
| case OPT_fvtable_gc: |
| flag_vtable_gc = on; |
| break; |
| |
| case OPT_fuse_cxa_atexit: |
| flag_use_cxa_atexit = on; |
| break; |
| |
| case OPT_fweak: |
| flag_weak = on; |
| break; |
| |
| case OPT_gen_decls: |
| flag_gen_declaration = 1; |
| break; |
| |
| case OPT_lang_asm: |
| cpp_set_lang (parse_in, CLK_ASM); |
| break; |
| |
| case OPT_lang_objc: |
| cpp_opts->objc = 1; |
| break; |
| |
| case OPT_nostdinc: |
| /* No default include directories. You must specify all |
| include-file directories with -I. */ |
| cpp_opts->no_standard_includes = 1; |
| break; |
| |
| case OPT_nostdincplusplus: |
| /* No default C++-specific include directories. */ |
| cpp_opts->no_standard_cplusplus_includes = 1; |
| break; |
| |
| case OPT_o: |
| if (!out_fname) |
| out_fname = arg; |
| else |
| { |
| error ("output filename specified twice"); |
| result = argc; |
| } |
| break; |
| |
| /* We need to handle the -pedantic switches here, rather than in |
| c_common_post_options, so that a subsequent -Wno-endif-labels |
| is not overridden. */ |
| case OPT_pedantic_errors: |
| cpp_opts->pedantic_errors = 1; |
| /* fall through */ |
| case OPT_pedantic: |
| cpp_opts->pedantic = 1; |
| cpp_opts->warn_endif_labels = 1; |
| break; |
| |
| case OPT_print_objc_runtime_info: |
| print_struct_values = 1; |
| break; |
| |
| case OPT_remap: |
| cpp_opts->remap = 1; |
| break; |
| |
| case OPT_std_cplusplus98: |
| case OPT_std_gnuplusplus98: |
| set_std_cxx98 (code == OPT_std_cplusplus98 /* ISO */); |
| break; |
| |
| case OPT_std_c89: |
| case OPT_std_iso9899_1990: |
| case OPT_std_iso9899_199409: |
| set_std_c89 (code == OPT_std_iso9899_199409 /* c94 */, true /* ISO */); |
| break; |
| |
| case OPT_std_gnu89: |
| set_std_c89 (false /* c94 */, false /* ISO */); |
| break; |
| |
| case OPT_std_c99: |
| case OPT_std_c9x: |
| case OPT_std_iso9899_1999: |
| case OPT_std_iso9899_199x: |
| set_std_c99 (true /* ISO */); |
| break; |
| |
| case OPT_std_gnu99: |
| case OPT_std_gnu9x: |
| set_std_c99 (false /* ISO */); |
| break; |
| |
| case OPT_trigraphs: |
| cpp_opts->trigraphs = 1; |
| break; |
| |
| case OPT_traditional_cpp: |
| cpp_opts->traditional = 1; |
| break; |
| |
| case OPT_undef: |
| flag_undef = 1; |
| break; |
| |
| case OPT_w: |
| cpp_opts->inhibit_warnings = 1; |
| break; |
| |
| case OPT_v: |
| cpp_opts->verbose = 1; |
| break; |
| } |
| |
| done: |
| if (dup) |
| free (dup); |
| return result; |
| } |
| |
| /* Post-switch processing. */ |
| bool |
| c_common_post_options () |
| { |
| /* Canonicalize the input and output filenames. */ |
| if (in_fname == NULL || !strcmp (in_fname, "-")) |
| in_fname = ""; |
| |
| if (out_fname == NULL || !strcmp (out_fname, "-")) |
| out_fname = ""; |
| |
| if (cpp_opts->deps.style == DEPS_NONE) |
| check_deps_environment_vars (); |
| |
| handle_deferred_opts (); |
| |
| sanitize_cpp_opts (); |
| |
| flag_inline_trees = 1; |
| |
| /* Use tree inlining if possible. Function instrumentation is only |
| done in the RTL level, so we disable tree inlining. */ |
| if (! flag_instrument_function_entry_exit) |
| { |
| if (!flag_no_inline) |
| flag_no_inline = 1; |
| if (flag_inline_functions) |
| { |
| flag_inline_trees = 2; |
| flag_inline_functions = 0; |
| } |
| } |
| |
| /* Special format checking options don't work without -Wformat; warn if |
| they are used. */ |
| if (warn_format_y2k && !warn_format) |
| warning ("-Wformat-y2k ignored without -Wformat"); |
| if (warn_format_extra_args && !warn_format) |
| warning ("-Wformat-extra-args ignored without -Wformat"); |
| if (warn_format_zero_length && !warn_format) |
| warning ("-Wformat-zero-length ignored without -Wformat"); |
| if (warn_format_nonliteral && !warn_format) |
| warning ("-Wformat-nonliteral ignored without -Wformat"); |
| if (warn_format_security && !warn_format) |
| warning ("-Wformat-security ignored without -Wformat"); |
| if (warn_missing_format_attribute && !warn_format) |
| warning ("-Wmissing-format-attribute ignored without -Wformat"); |
| |
| /* If an error has occurred in cpplib, note it so we fail |
| immediately. */ |
| errorcount += cpp_errors (parse_in); |
| |
| return flag_preprocess_only; |
| } |
| |
| /* Preprocess the input file to out_stream. */ |
| static void |
| preprocess_file () |
| { |
| /* Open the output now. We must do so even if no_output is on, |
| because there may be other output than from the actual |
| preprocessing (e.g. from -dM). */ |
| if (out_fname[0] == '\0') |
| out_stream = stdout; |
| else |
| out_stream = fopen (out_fname, "w"); |
| |
| if (out_stream == NULL) |
| fatal_io_error ("opening output file %s", out_fname); |
| else |
| cpp_preprocess_file (parse_in, in_fname, out_stream); |
| } |
| |
| /* Front end initialization common to C, ObjC and C++. */ |
| const char * |
| c_common_init (filename) |
| const char *filename; |
| { |
| /* Set up preprocessor arithmetic. Must be done after call to |
| c_common_nodes_and_builtins for type nodes to be good. */ |
| cpp_opts->precision = TYPE_PRECISION (intmax_type_node); |
| cpp_opts->char_precision = TYPE_PRECISION (char_type_node); |
| cpp_opts->int_precision = TYPE_PRECISION (integer_type_node); |
| cpp_opts->wchar_precision = TYPE_PRECISION (wchar_type_node); |
| cpp_opts->unsigned_wchar = TREE_UNSIGNED (wchar_type_node); |
| |
| /* Register preprocessor built-ins before calls to |
| cpp_main_file. */ |
| cpp_get_callbacks (parse_in)->register_builtins = cb_register_builtins; |
| |
| /* NULL is passed up to toplev.c and we exit quickly. */ |
| if (flag_preprocess_only) |
| { |
| preprocess_file (); |
| return NULL; |
| } |
| |
| /* Do this before initializing pragmas, as then cpplib's hash table |
| has been set up. NOTE: we are using our own file name here, not |
| the one supplied. */ |
| filename = init_c_lex (in_fname); |
| |
| init_pragma (); |
| |
| return filename; |
| } |
| |
| /* Common finish hook for the C, ObjC and C++ front ends. */ |
| void |
| c_common_finish () |
| { |
| FILE *deps_stream = NULL; |
| |
| if (cpp_opts->deps.style != DEPS_NONE) |
| { |
| /* If -M or -MM was seen without -MF, default output to the |
| output stream. */ |
| if (!deps_file) |
| deps_stream = out_stream; |
| else |
| { |
| deps_stream = fopen (deps_file, deps_append ? "a": "w"); |
| if (!deps_stream) |
| fatal_io_error ("opening dependency file %s", deps_file); |
| } |
| } |
| |
| /* For performance, avoid tearing down cpplib's internal structures |
| with cpp_destroy (). */ |
| errorcount += cpp_finish (parse_in, deps_stream); |
| |
| if (deps_stream && deps_stream != out_stream |
| && (ferror (deps_stream) || fclose (deps_stream))) |
| fatal_io_error ("closing dependency file %s", deps_file); |
| |
| if (out_stream && (ferror (out_stream) || fclose (out_stream))) |
| fatal_io_error ("when writing output to %s", out_fname); |
| } |
| |
| /* Either of two environment variables can specify output of |
| dependencies. Their value is either "OUTPUT_FILE" or "OUTPUT_FILE |
| DEPS_TARGET", where OUTPUT_FILE is the file to write deps info to |
| and DEPS_TARGET is the target to mention in the deps. They also |
| result in dependency information being appended to the output file |
| rather than overwriting it, and like Sun's compiler |
| SUNPRO_DEPENDENCIES suppresses the dependency on the main file. */ |
| static void |
| check_deps_environment_vars () |
| { |
| char *spec; |
| |
| GET_ENVIRONMENT (spec, "DEPENDENCIES_OUTPUT"); |
| if (spec) |
| cpp_opts->deps.style = DEPS_USER; |
| else |
| { |
| GET_ENVIRONMENT (spec, "SUNPRO_DEPENDENCIES"); |
| if (spec) |
| { |
| cpp_opts->deps.style = DEPS_SYSTEM; |
| cpp_opts->deps.ignore_main_file = true; |
| } |
| } |
| |
| if (spec) |
| { |
| /* Find the space before the DEPS_TARGET, if there is one. */ |
| char *s = strchr (spec, ' '); |
| if (s) |
| { |
| /* Let the caller perform MAKE quoting. */ |
| defer_opt (OPT_MT, s + 1); |
| *s = '\0'; |
| } |
| |
| /* Command line -MF overrides environment variables and default. */ |
| if (!deps_file) |
| deps_file = spec; |
| |
| deps_append = 1; |
| } |
| } |
| |
| /* Handle deferred command line switches. */ |
| static void |
| handle_deferred_opts () |
| { |
| size_t i; |
| |
| for (i = 0; i < deferred_count; i++) |
| { |
| struct deferred_opt *opt = &deferred_opts[i]; |
| |
| switch (opt->code) |
| { |
| case OPT_MT: |
| case OPT_MQ: |
| cpp_add_dependency_target (parse_in, opt->arg, opt->code == OPT_MQ); |
| break; |
| |
| default: |
| abort (); |
| } |
| } |
| |
| free (deferred_opts); |
| } |
| |
| /* These settings are appropriate for GCC, but not necessarily so for |
| cpplib as a library. */ |
| static void |
| sanitize_cpp_opts () |
| { |
| /* If we don't know what style of dependencies to output, complain |
| if any other dependency switches have been given. */ |
| if (deps_seen && cpp_opts->deps.style == DEPS_NONE) |
| error ("to generate dependencies you must specify either -M or -MM"); |
| |
| /* -dM and dependencies suppress normal output; do it here so that |
| the last -d[MDN] switch overrides earlier ones. */ |
| if (cpp_opts->dump_macros == dump_only) |
| cpp_opts->no_output = 1; |
| |
| /* Disable -dD, -dN and -dI if normal output is suppressed. Allow |
| -dM since at least glibc relies on -M -dM to work. */ |
| if (cpp_opts->no_output) |
| { |
| if (cpp_opts->dump_macros != dump_only) |
| cpp_opts->dump_macros = dump_none; |
| cpp_opts->dump_includes = 0; |
| } |
| |
| cpp_opts->unsigned_char = !flag_signed_char; |
| cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS; |
| |
| /* We want -Wno-long-long to override -pedantic -std=non-c99 |
| and/or -Wtraditional, whatever the ordering. */ |
| cpp_opts->warn_long_long |
| = warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional); |
| } |
| |
| /* Set the C 89 standard (with 1994 amendments if C94, without GNU |
| extensions if ISO). There is no concept of gnu94. */ |
| static void |
| set_std_c89 (c94, iso) |
| int c94, iso; |
| { |
| cpp_set_lang (parse_in, c94 ? CLK_STDC94: iso ? CLK_STDC89: CLK_GNUC89); |
| flag_iso = iso; |
| flag_no_asm = iso; |
| flag_no_gnu_keywords = iso; |
| flag_no_nonansi_builtin = iso; |
| flag_noniso_default_format_attributes = !iso; |
| flag_isoc94 = c94; |
| flag_isoc99 = 0; |
| flag_writable_strings = 0; |
| } |
| |
| /* Set the C 99 standard (without GNU extensions if ISO). */ |
| static void |
| set_std_c99 (iso) |
| int iso; |
| { |
| cpp_set_lang (parse_in, iso ? CLK_STDC99: CLK_GNUC99); |
| flag_no_asm = iso; |
| flag_no_nonansi_builtin = iso; |
| flag_noniso_default_format_attributes = !iso; |
| flag_iso = iso; |
| flag_isoc99 = 1; |
| flag_isoc94 = 1; |
| flag_writable_strings = 0; |
| } |
| |
| /* Set the C++ 98 standard (without GNU extensions if ISO). */ |
| static void |
| set_std_cxx98 (iso) |
| int iso; |
| { |
| cpp_set_lang (parse_in, iso ? CLK_CXX98: CLK_GNUCXX); |
| flag_no_gnu_keywords = iso; |
| flag_no_nonansi_builtin = iso; |
| flag_noniso_default_format_attributes = !iso; |
| flag_iso = iso; |
| } |
| |
| /* Handle setting implicit to ON. */ |
| static void |
| set_Wimplicit (on) |
| int on; |
| { |
| warn_implicit = on; |
| warn_implicit_int = on; |
| if (on) |
| { |
| if (mesg_implicit_function_declaration != 2) |
| mesg_implicit_function_declaration = 1; |
| } |
| else |
| mesg_implicit_function_declaration = 0; |
| } |
| |
| /* Args to -d specify what to dump. Silently ignore |
| unrecognized options; they may be aimed at toplev.c. */ |
| static void |
| handle_OPT_d (arg) |
| const char *arg; |
| { |
| char c; |
| |
| while ((c = *arg++) != '\0') |
| switch (c) |
| { |
| case 'M': |
| cpp_opts->dump_macros = dump_only; |
| break; |
| |
| case 'N': |
| cpp_opts->dump_macros = dump_names; |
| break; |
| |
| case 'D': |
| cpp_opts->dump_macros = dump_definitions; |
| break; |
| |
| case 'I': |
| cpp_opts->dump_includes = 1; |
| break; |
| } |
| } |
| |
| /* Write a slash-separated list of languages in FLAGS to BUF. */ |
| static void |
| write_langs (buf, flags) |
| char *buf; |
| int flags; |
| { |
| *buf = '\0'; |
| if (flags & CL_C_ONLY) |
| strcat (buf, "C"); |
| if (flags & CL_OBJC_ONLY) |
| { |
| if (*buf) |
| strcat (buf, "/"); |
| strcat (buf, "ObjC"); |
| } |
| if (flags & CL_CXX_ONLY) |
| { |
| if (*buf) |
| strcat (buf, "/"); |
| strcat (buf, "C++"); |
| } |
| } |
| |
| /* Complain that switch OPT_INDEX does not apply to this front end. */ |
| static void |
| complain_wrong_lang (opt_index, on) |
| size_t opt_index; |
| int on; |
| { |
| char ok_langs[60], bad_langs[60]; |
| int ok_flags = cl_options[opt_index].flags; |
| |
| write_langs (ok_langs, ok_flags); |
| write_langs (bad_langs, ~ok_flags); |
| warning ("\"-%c%s%s\" is valid for %s but not for %s", |
| cl_options[opt_index].opt_text[0], on ? "" : "no-", |
| cl_options[opt_index].opt_text + 1, ok_langs, bad_langs); |
| } |
| |
| /* Handle --help output. */ |
| static void |
| print_help () |
| { |
| /* To keep the lines from getting too long for some compilers, limit |
| to about 500 characters (6 lines) per chunk. */ |
| fputs (_("\ |
| Switches:\n\ |
| -include <file> Include the contents of <file> before other files\n\ |
| -imacros <file> Accept definition of macros in <file>\n\ |
| -iprefix <path> Specify <path> as a prefix for next two options\n\ |
| -iwithprefix <dir> Add <dir> to the end of the system include path\n\ |
| -iwithprefixbefore <dir> Add <dir> to the end of the main include path\n\ |
| -isystem <dir> Add <dir> to the start of the system include path\n\ |
| "), stdout); |
| fputs (_("\ |
| -idirafter <dir> Add <dir> to the end of the system include path\n\ |
| -I <dir> Add <dir> to the end of the main include path\n\ |
| -I- Fine-grained include path control; see info docs\n\ |
| -nostdinc Do not search system include directories\n\ |
| (dirs specified with -isystem will still be used)\n\ |
| -nostdinc++ Do not search system include directories for C++\n\ |
| -o <file> Put output into <file>\n\ |
| "), stdout); |
| fputs (_("\ |
| -trigraphs Support ISO C trigraphs\n\ |
| -std=<std name> Specify the conformance standard; one of:\n\ |
| gnu89, gnu99, c89, c99, iso9899:1990,\n\ |
| iso9899:199409, iso9899:1999, c++98\n\ |
| -w Inhibit warning messages\n\ |
| -W[no-]trigraphs Warn if trigraphs are encountered\n\ |
| -W[no-]comment{s} Warn if one comment starts inside another\n\ |
| "), stdout); |
| fputs (_("\ |
| -W[no-]traditional Warn about features not present in traditional C\n\ |
| -W[no-]undef Warn if an undefined macro is used by #if\n\ |
| -W[no-]import Warn about the use of the #import directive\n\ |
| "), stdout); |
| fputs (_("\ |
| -W[no-]error Treat all warnings as errors\n\ |
| -W[no-]system-headers Do not suppress warnings from system headers\n\ |
| -W[no-]all Enable most preprocessor warnings\n\ |
| "), stdout); |
| fputs (_("\ |
| -M Generate make dependencies\n\ |
| -MM As -M, but ignore system header files\n\ |
| -MD Generate make dependencies and compile\n\ |
| -MMD As -MD, but ignore system header files\n\ |
| -MF <file> Write dependency output to the given file\n\ |
| -MG Treat missing header file as generated files\n\ |
| "), stdout); |
| fputs (_("\ |
| -MP Generate phony targets for all headers\n\ |
| -MQ <target> Add a MAKE-quoted target\n\ |
| -MT <target> Add an unquoted target\n\ |
| "), stdout); |
| fputs (_("\ |
| -D<macro> Define a <macro> with string '1' as its value\n\ |
| -D<macro>=<val> Define a <macro> with <val> as its value\n\ |
| -A<question>=<answer> Assert the <answer> to <question>\n\ |
| -A-<question>=<answer> Disable the <answer> to <question>\n\ |
| -U<macro> Undefine <macro> \n\ |
| -v Display the version number\n\ |
| "), stdout); |
| fputs (_("\ |
| -H Print the name of header files as they are used\n\ |
| -C Do not discard comments\n\ |
| -dM Display a list of macro definitions active at end\n\ |
| -dD Preserve macro definitions in output\n\ |
| -dN As -dD except that only the names are preserved\n\ |
| -dI Include #include directives in the output\n\ |
| "), stdout); |
| fputs (_("\ |
| -f[no-]preprocessed Treat the input file as already preprocessed\n\ |
| -ftabstop=<number> Distance between tab stops for column reporting\n\ |
| -P Do not generate #line directives\n\ |
| -remap Remap file names when including files\n\ |
| --help Display this information\n\ |
| "), stdout); |
| } |