/* C/ObjC/C++ command line option handling.
- Copyright (C) 2002 Free Software Foundation, Inc.
+ Copyright (C) 2002, 2003 Free Software Foundation, Inc.
Contributed by Neil Booth.
This file is part of GCC.
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "c-common.h"
#include "c-pragma.h"
#include "tree-inline.h"
#include "diagnostic.h"
#include "intl.h"
+#include "cppdefault.h"
+#include "c-incpath.h"
+
+#ifndef TARGET_SYSTEM_ROOT
+# define TARGET_SYSTEM_ROOT NULL
+#endif
/* CPP's options. */
static cpp_options *cpp_opts;
/* If dependency switches (-MF etc.) have been given. */
static bool deps_seen;
+/* If -v seen. */
+static bool verbose;
+
/* Dependency output file. */
static const char *deps_file;
+/* The prefix given by -iprefix, if any. */
+static const char *iprefix;
+
+/* The system root, if any. Overridden by -isysroot. */
+static const char *sysroot = TARGET_SYSTEM_ROOT;
+
+/* Zero disables all standard directories for headers. */
+static bool std_inc = true;
+
+/* Zero disables the C++-specific standard directories for headers. */
+static bool std_cxx_inc = true;
+
+/* If the quote chain has been split by -I-. */
+static bool quote_chain_split;
+
/* Number of deferred options, deferred options array size. */
static size_t deferred_count, deferred_size;
static void preprocess_file PARAMS ((void));
static void handle_deferred_opts PARAMS ((void));
static void sanitize_cpp_opts PARAMS ((void));
+static void add_prefixed_path PARAMS ((const char *, size_t));
#ifndef STDC_0_IN_SYSTEM_HEADERS
#define STDC_0_IN_SYSTEM_HEADERS 0
#define COMMAND_LINE_OPTIONS \
OPT("-help", CL_ALL, OPT__help) \
+ OPT("-output-pch=", CL_ALL | CL_ARG, OPT__output_pch) \
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("I", CL_ALL | CL_ARG, OPT_I) \
OPT("M", CL_ALL, OPT_M) \
OPT("MD", CL_ALL | CL_SEPARATE, OPT_MD) \
OPT("MF", CL_ALL | CL_ARG, OPT_MF) \
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("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_CXX, OPT_Wimplicit) \
+ 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("Winvalid-pch", CL_ALL, OPT_Winvalid_pch) \
OPT("Wlong-long", CL_ALL, OPT_Wlong_long) \
OPT("Wmain", CL_C, OPT_Wmain) \
OPT("Wmissing-braces", CL_ALL, OPT_Wmissing_braces) \
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("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("fnonnull-objects", CL_CXX, OPT_fnonnull_objects) \
OPT("foperator-names", CL_CXX, OPT_foperator_names) \
OPT("foptional-diags", CL_CXX, OPT_foptional_diags) \
+ OPT("fpch-deps", CL_ALL, OPT_fpch_deps) \
OPT("fpermissive", CL_CXX, OPT_fpermissive) \
OPT("fpreprocessed", CL_ALL, OPT_fpreprocessed) \
OPT("frepo", CL_CXX, OPT_frepo) \
OPT("fweak", CL_CXX, OPT_fweak) \
OPT("fxref", CL_CXX, OPT_fxref) \
OPT("gen-decls", CL_OBJC, OPT_gen_decls) \
+ OPT("idirafter", CL_ALL | CL_ARG, OPT_idirafter) \
+ OPT("iprefix", CL_ALL | CL_ARG, OPT_iprefix) \
+ OPT("isysroot", CL_ALL | CL_ARG, OPT_isysroot) \
+ OPT("isystem", CL_ALL | CL_ARG, OPT_isystem) \
+ OPT("iwithprefix", CL_ALL | CL_ARG, OPT_iwithprefix) \
+ OPT("iwithprefixbefore", CL_ALL | CL_ARG, OPT_iwithprefixbefore) \
OPT("lang-asm", CL_C_ONLY, OPT_lang_asm) \
OPT("lang-objc", CL_ALL, OPT_lang_objc) \
OPT("nostdinc", CL_ALL, OPT_nostdinc) \
#undef COMMAND_LINE_OPTIONS
/* Holds switches parsed by c_common_decode_option (), but whose
- handling is deffered to c_common_post_options (). */
+ handling is deferred to c_common_post_options (). */
static void defer_opt PARAMS ((enum opt_code, const char *));
static struct deferred_opt
{
{
const char *opt_text = cl_options[opt_index].opt_text;
- switch (opt_index)
+ switch (cl_options[opt_index].opt_code)
{
+ case OPT__output_pch:
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:
+ case OPT_iprefix:
+ case OPT_iwithprefix:
+ case OPT_iwithprefixbefore:
default:
error ("missing argument to \"-%s\"", opt_text);
break;
error ("no class name specified with \"-%s\"", opt_text);
break;
+ case OPT_I:
+ case OPT_idirafter:
+ case OPT_isysroot:
+ case OPT_isystem:
+ error ("missing path after \"-%s\"", opt_text);
+ break;
+
case OPT_MF:
case OPT_MD:
case OPT_MMD:
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. */
+ 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;
{
size_t md, mn, mx;
size_t opt_len;
- size_t wrong_lang = N_OPTS;
+ size_t result = N_OPTS;
int comp;
mn = 0;
md = (mn + mx) / 2;
opt_len = cl_options[md].opt_len;
- comp = memcmp (input, cl_options[md].opt_text, opt_len);
+ comp = strncmp (input, cl_options[md].opt_text, opt_len);
if (comp < 0)
mx = md;
{
/* The switch matches. It it an exact match? */
if (input[opt_len] == '\0')
- {
- exact_match:
- if (cl_options[md].flags & lang_flag)
- return md;
- wrong_lang = md;
- break;
- }
+ return md;
else
{
mn = md + 1;
/* Is this switch valid for this front end? */
if (!(cl_options[md].flags & lang_flag))
{
- /* If subsequently we don't find a good match,
- report this as a bad match. */
- wrong_lang = md;
+ /* If subsequently we don't find a better match,
+ return this and let the caller report it as a bad
+ match. */
+ result = md;
continue;
}
for (md = md + 1; md < (size_t) N_OPTS; md++)
{
opt_len = cl_options[md].opt_len;
- if (memcmp (input, cl_options[md].opt_text, opt_len))
+ if (strncmp (input, cl_options[md].opt_text, opt_len))
break;
if (input[opt_len] == '\0')
- goto exact_match;
+ return md;
if (cl_options[md].flags & lang_flag
&& cl_options[md].flags & CL_JOINED)
mx = md;
}
}
- if (wrong_lang != N_OPTS)
- complain_wrong_lang (wrong_lang);
-
- return N_OPTS;
+ return result;
}
/* Defer option CODE with argument ARG. */
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);
warn_pointer_arith = (lang == clk_cplusplus);
if (lang == clk_c)
warn_sign_compare = -1;
-
- /* Mark as "unspecified" (see c_common_post_options). */
- flag_bounds_check = -1;
}
/* Handle one command-line option in (argc, argv).
int argc;
char **argv;
{
- static int lang_flags[] = {CL_C_ONLY, CL_C, CL_CXX_ONLY, CL_CXX};
+ 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;
+ int result, lang_flag;
const struct cl_option *option;
enum opt_code code;
result = cpp_handle_option (parse_in, argc, argv);
/* Skip over '-'. */
- opt_index = find_opt (opt + 1, lang_flags[(c_language << 1) + flag_objc]);
+ lang_flag = lang_flags[(c_language << 1) + flag_objc];
+ opt_index = find_opt (opt + 1, lang_flag);
if (opt_index == N_OPTS)
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);
+ goto done;
+ }
+
switch (code = option->opt_code)
{
case N_OPTS: /* Shut GCC up. */
print_help ();
break;
+ case OPT__output_pch:
+ pch_file = arg;
+ break;
+
case OPT_C:
cpp_opts->discard_comments = 0;
break;
cpp_opts->print_include_names = 1;
break;
+ case OPT_I:
+ if (strcmp (arg, "-"))
+ add_path (xstrdup (arg), BRACKET, 0);
+ else
+ {
+ if (quote_chain_split)
+ error ("-I- specified twice");
+ quote_chain_split = true;
+ split_quote_chain ();
+ }
+ break;
+
case OPT_M:
case OPT_MM:
/* When doing dependencies with -M or -MM, suppress normal
cpp_opts->no_line_commands = 1;
break;
+ case OPT_Wabi:
+ warn_abi = on;
+ break;
+
case OPT_Wall:
set_Wunused (on);
set_Wformat (on);
warn_sequence_point = on; /* Was C only. */
warn_sign_compare = on; /* Was C++ only. */
warn_switch = on;
-
+ warn_strict_aliasing = on;
+
/* Only warn about unknown pragmas that are not in system
headers. */
warn_unknown_pragmas = on;
case OPT_Wdeprecated:
warn_deprecated = on;
+ cpp_opts->warn_deprecated = on;
break;
case OPT_Wdiv_by_zero:
cpp_opts->warn_import = on;
break;
+ case OPT_Winvalid_pch:
+ cpp_opts->warn_invalid_pch = on;
+ break;
+
case OPT_Wlong_long:
warn_long_long = on;
break;
cpp_opts->warn_trigraphs = on;
break;
+ case OPT_Wundeclared_selector:
+ warn_undeclared_selector = on;
+ break;
+
case OPT_Wundef:
cpp_opts->warn_undef = on;
break;
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;
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;
flag_optional_diags = on;
break;
+ case OPT_fpch_deps:
+ cpp_opts->restore_pch_deps = on;
+ break;
+
case OPT_fpermissive:
flag_permissive = on;
break;
break;
case OPT_ftabstop:
- /* Don't recognise -fno-tabstop=. */
+ /* Don't recognize -fno-tabstop=. */
if (!on)
return 0;
flag_gen_declaration = 1;
break;
+ case OPT_idirafter:
+ add_path (xstrdup (arg), AFTER, 0);
+ break;
+
+ case OPT_iprefix:
+ iprefix = arg;
+ break;
+
+ case OPT_isysroot:
+ sysroot = arg;
+ break;
+
+ case OPT_isystem:
+ add_path (xstrdup (arg), SYSTEM, 0);
+ break;
+
+ case OPT_iwithprefix:
+ add_prefixed_path (arg, SYSTEM);
+ break;
+
+ case OPT_iwithprefixbefore:
+ add_prefixed_path (arg, BRACKET);
+ break;
+
case OPT_lang_asm:
cpp_set_lang (parse_in, CLK_ASM);
break;
break;
case OPT_nostdinc:
- /* No default include directories. You must specify all
- include-file directories with -I. */
- cpp_opts->no_standard_includes = 1;
+ std_inc = false;
break;
case OPT_nostdincplusplus:
- /* No default C++-specific include directories. */
- cpp_opts->no_standard_cplusplus_includes = 1;
+ std_cxx_inc = false;
break;
case OPT_o:
break;
case OPT_v:
- cpp_opts->verbose = 1;
+ verbose = true;
break;
}
if (out_fname == NULL || !strcmp (out_fname, "-"))
out_fname = "";
- if (cpp_opts->deps.style != DEPS_NONE)
+ if (cpp_opts->deps.style == DEPS_NONE)
check_deps_environment_vars ();
handle_deferred_opts ();
sanitize_cpp_opts ();
+ register_include_chains (parse_in, sysroot, iprefix,
+ std_inc, std_cxx_inc && c_language == clk_cplusplus,
+ verbose);
+
flag_inline_trees = 1;
/* Use tree inlining if possible. Function instrumentation is only
}
}
- /* If still "unspecified", make it match -fbounded-pointers. */
- if (flag_bounds_check == -1)
- flag_bounds_check = flag_bounded_pointers;
-
/* Special format checking options don't work without -Wformat; warn if
they are used. */
if (warn_format_y2k && !warn_format)
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. */
+ rather than overwriting it, and like Sun's compiler
+ SUNPRO_DEPENDENCIES suppresses the dependency on the main file. */
static void
check_deps_environment_vars ()
{
{
GET_ENVIRONMENT (spec, "SUNPRO_DEPENDENCIES");
if (spec)
- cpp_opts->deps.style = DEPS_SYSTEM;
+ {
+ cpp_opts->deps.style = DEPS_SYSTEM;
+ cpp_opts->deps.ignore_main_file = true;
+ }
}
if (spec)
= warn_long_long && ((!flag_isoc99 && pedantic) || warn_traditional);
}
+/* Add include path with a prefix at the front of its name. */
+static void
+add_prefixed_path (suffix, chain)
+ const char *suffix;
+ size_t chain;
+{
+ const char *prefix;
+
+ prefix = iprefix ? iprefix: cpp_GCC_INCLUDE_DIR;
+ add_path (concat (prefix, suffix), chain, 0);
+}
+
/* Set the C 89 standard (with 1994 amendments if C94, without GNU
extensions if ISO). There is no concept of gnu94. */
static void
}
/* Args to -d specify what to dump. Silently ignore
- unrecognised options; they may be aimed at toplev.c. */
+ unrecognized options; they may be aimed at toplev.c. */
static void
handle_OPT_d (arg)
const char *arg;
fputs (_("\
-f[no-]preprocessed Treat the input file as already preprocessed\n\
-ftabstop=<number> Distance between tab stops for column reporting\n\
+ -isysroot <dir> Set <dir> to be the system root directory\n\
-P Do not generate #line directives\n\
-remap Remap file names when including files\n\
--help Display this information\n\