-/* Copyright (C) 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
This file is part of GCC.
#include "../../libcpp/internal.h"
#include "cpp.h"
#include "incpath.h"
+#include "cppbuiltin.h"
+#include "mkdeps.h"
+
+#ifndef TARGET_CPU_CPP_BUILTINS
+# define TARGET_CPU_CPP_BUILTINS()
+#endif
#ifndef TARGET_OS_CPP_BUILTINS
# define TARGET_OS_CPP_BUILTINS()
} gfc_cpp_macro_queue;
static gfc_cpp_macro_queue *cpp_define_queue, *cpp_undefine_queue;
-struct
+struct gfc_cpp_option_data
{
/* Argument of -cpp, implied by SPEC;
if NULL, preprocessing disabled. */
int no_predefined; /* -undef */
int standard_include_paths; /* -nostdinc */
int verbose; /* -v */
+ int deps; /* -M */
+ int deps_skip_system; /* -MM */
+ const char *deps_filename; /* -M[M]D */
+ const char *deps_filename_user; /* -MF <arg> */
+ int deps_missing_are_generated; /* -MG */
+ int deps_phony; /* -MP */
const char *multilib; /* -imultilib <dir> */
const char *prefix; /* -iprefix <dir> */
static cpp_options *cpp_option = NULL;
static cpp_reader *cpp_in = NULL;
-/* Defined in toplev.c. */
-extern const char *asm_file_name;
-
-
-
-
/* Encapsulates state used to convert a stream of cpp-tokens into
a text file. */
static struct
static void cb_ident (cpp_reader *, source_location, const cpp_string *);
static void cb_used_define (cpp_reader *, source_location, cpp_hashnode *);
static void cb_used_undef (cpp_reader *, source_location, cpp_hashnode *);
+static bool cb_cpp_error (cpp_reader *, int, int, location_t, unsigned int,
+ const char *, va_list *)
+ ATTRIBUTE_GCC_DIAG(6,0);
void pp_dir_change (cpp_reader *, const char *);
static int dump_macro (cpp_reader *, cpp_hashnode *, void *);
static void
cpp_define_builtins (cpp_reader *pfile)
{
- int major, minor, patchlevel;
-
/* Initialize CPP built-ins; '1' corresponds to 'flag_hosted'
in C, defines __STDC_HOSTED__?! */
cpp_init_builtins (pfile, 0);
/* Initialize GFORTRAN specific builtins.
These are documented. */
- if (sscanf (BASEVER, "%d.%d.%d", &major, &minor, &patchlevel) != 3)
- {
- sscanf (BASEVER, "%d.%d", &major, &minor);
- patchlevel = 0;
- }
- cpp_define_formatted (pfile, "__GNUC__=%d", major);
- cpp_define_formatted (pfile, "__GNUC_MINOR__=%d", minor);
- cpp_define_formatted (pfile, "__GNUC_PATCHLEVEL__=%d", patchlevel);
-
+ define_language_independent_builtin_macros (pfile);
cpp_define (pfile, "__GFORTRAN__=1");
cpp_define (pfile, "_LANGUAGE_FORTRAN=1");
- if (gfc_option.flag_openmp)
- cpp_define (pfile, "_OPENMP=200505");
-
-
- /* More builtins that might be useful, but are not documented
- (in no particular order). */
- cpp_define_formatted (pfile, "__VERSION__=\"%s\"", version_string);
-
- if (flag_pic)
- {
- cpp_define_formatted (pfile, "__pic__=%d", flag_pic);
- cpp_define_formatted (pfile, "__PIC__=%d", flag_pic);
- }
- if (flag_pie)
- {
- cpp_define_formatted (pfile, "__pie__=%d", flag_pie);
- cpp_define_formatted (pfile, "__PIE__=%d", flag_pie);
- }
-
- if (optimize_size)
- cpp_define (pfile, "__OPTIMIZE_SIZE__");
- if (optimize)
- cpp_define (pfile, "__OPTIMIZE__");
-
- if (fast_math_flags_set_p ())
- cpp_define (pfile, "__FAST_MATH__");
- if (flag_signaling_nans)
- cpp_define (pfile, "__SUPPORT_SNAN__");
-
- cpp_define_formatted (pfile, "__FINITE_MATH_ONLY__=%d", flag_finite_math_only);
-
- /* Definitions for LP64 model. */
- if (TYPE_PRECISION (long_integer_type_node) == 64
- && POINTER_SIZE == 64
- && TYPE_PRECISION (integer_type_node) == 32)
- {
- cpp_define (pfile, "_LP64");
- cpp_define (pfile, "__LP64__");
- }
-
- /* Define NAME with value TYPE size_unit.
- The C-side also defines __SIZEOF_WCHAR_T__, __SIZEOF_WINT_T__
- __SIZEOF_PTRDIFF_T__, however, fortran seems to lack the
- appropriate type nodes. */
-
-#define define_type_sizeof(NAME, TYPE) \
- cpp_define_formatted (pfile, NAME"="HOST_WIDE_INT_PRINT_DEC, \
- tree_low_cst (TYPE_SIZE_UNIT (TYPE), 1))
-
- define_type_sizeof ("__SIZEOF_INT__", integer_type_node);
- define_type_sizeof ("__SIZEOF_LONG__", long_integer_type_node);
- define_type_sizeof ("__SIZEOF_LONG_LONG__", long_long_integer_type_node);
- define_type_sizeof ("__SIZEOF_SHORT__", short_integer_type_node);
- define_type_sizeof ("__SIZEOF_FLOAT__", float_type_node);
- define_type_sizeof ("__SIZEOF_DOUBLE__", double_type_node);
- define_type_sizeof ("__SIZEOF_LONG_DOUBLE__", long_double_type_node);
- define_type_sizeof ("__SIZEOF_SIZE_T__", size_type_node);
-
-#undef define_type_sizeof
+ if (gfc_option.gfc_flag_openmp)
+ cpp_define (pfile, "_OPENMP=201107");
/* The defines below are necessary for the TARGET_* macros.
return gfc_cpp_option.preprocess_only;
}
+bool
+gfc_cpp_makedep (void)
+{
+ return gfc_cpp_option.deps;
+}
+
+void
+gfc_cpp_add_dep (const char *name, bool system)
+{
+ if (!gfc_cpp_option.deps_skip_system || !system)
+ deps_add_dep (cpp_get_deps (cpp_in), name);
+}
+
+void
+gfc_cpp_add_target (const char *name)
+{
+ deps_add_target (cpp_get_deps (cpp_in), name, 0);
+}
+
+
const char *
gfc_cpp_temporary_file (void)
{
}
void
-gfc_cpp_init_options (unsigned int argc,
- const char **argv ATTRIBUTE_UNUSED)
+gfc_cpp_init_options (unsigned int decoded_options_count,
+ struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED)
{
/* Do not create any objects from libcpp here. If no
preprocessing is requested, this would be wasted
gfc_cpp_option.no_predefined = 0;
gfc_cpp_option.standard_include_paths = 1;
gfc_cpp_option.verbose = 0;
+ gfc_cpp_option.deps = 0;
+ gfc_cpp_option.deps_skip_system = 0;
+ gfc_cpp_option.deps_phony = 0;
+ gfc_cpp_option.deps_missing_are_generated = 0;
+ gfc_cpp_option.deps_filename = NULL;
+ gfc_cpp_option.deps_filename_user = NULL;
gfc_cpp_option.multilib = NULL;
gfc_cpp_option.prefix = NULL;
gfc_cpp_option.sysroot = NULL;
- gfc_cpp_option.deferred_opt = XNEWVEC (gfc_cpp_deferred_opt_t, argc);
+ gfc_cpp_option.deferred_opt = XNEWVEC (gfc_cpp_deferred_opt_t,
+ decoded_options_count);
gfc_cpp_option.deferred_opt_count = 0;
}
result = 0;
break;
- case OPT_cpp:
+ case OPT_cpp_:
gfc_cpp_option.temporary_filename = arg;
break;
gfc_cpp_option.working_directory = value;
break;
+ case OPT_idirafter:
+ gfc_cpp_add_include_path_after (xstrdup(arg), true);
+ break;
+
case OPT_imultilib:
gfc_cpp_option.multilib = arg;
break;
gfc_cpp_option.print_include_names = 1;
break;
+ case OPT_MM:
+ gfc_cpp_option.deps_skip_system = 1;
+ /* fall through */
+
+ case OPT_M:
+ gfc_cpp_option.deps = 1;
+ break;
+
+ case OPT_MMD:
+ gfc_cpp_option.deps_skip_system = 1;
+ /* fall through */
+
+ case OPT_MD:
+ gfc_cpp_option.deps = 1;
+ gfc_cpp_option.deps_filename = arg;
+ break;
+
+ case OPT_MF:
+ /* If specified multiple times, last one wins. */
+ gfc_cpp_option.deps_filename_user = arg;
+ break;
+
+ case OPT_MG:
+ gfc_cpp_option.deps_missing_are_generated = 1;
+ break;
+
+ case OPT_MP:
+ gfc_cpp_option.deps_phony = 1;
+ break;
+
+ case OPT_MQ:
+ case OPT_MT:
+ gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].code = code;
+ gfc_cpp_option.deferred_opt[gfc_cpp_option.deferred_opt_count].arg = arg;
+ gfc_cpp_option.deferred_opt_count++;
+ break;
+
case OPT_P:
gfc_cpp_option.no_line_commands = 1;
break;
an error. */
if (!gfc_cpp_enabled ()
&& (gfc_cpp_preprocess_only ()
- || !gfc_cpp_option.discard_comments
- || !gfc_cpp_option.discard_comments_in_macro_exp
- || gfc_cpp_option.print_include_names
- || gfc_cpp_option.no_line_commands
- || gfc_cpp_option.dump_macros
- || gfc_cpp_option.dump_includes))
+ || gfc_cpp_makedep ()
+ || !gfc_cpp_option.discard_comments
+ || !gfc_cpp_option.discard_comments_in_macro_exp
+ || gfc_cpp_option.print_include_names
+ || gfc_cpp_option.no_line_commands
+ || gfc_cpp_option.dump_macros
+ || gfc_cpp_option.dump_includes))
gfc_fatal_error("To enable preprocessing, use -cpp");
- cpp_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
- if (!gfc_cpp_enabled())
+ if (!gfc_cpp_enabled ())
return;
+ cpp_in = cpp_create_reader (CLK_GNUC89, NULL, line_table);
gcc_assert (cpp_in);
/* The cpp_options-structure defines far more flags than those set here.
cpp_option->traditional = 1;
cpp_option->cplusplus_comments = 0;
- cpp_option->pedantic = pedantic;
- cpp_option->inhibit_warnings = inhibit_warnings;
+ cpp_option->cpp_pedantic = pedantic;
cpp_option->dollars_in_ident = gfc_option.flag_dollar_ok;
cpp_option->discard_comments = gfc_cpp_option.discard_comments;
cpp_option->print_include_names = gfc_cpp_option.print_include_names;
cpp_option->preprocessed = gfc_option.flag_preprocessed;
+ if (gfc_cpp_makedep ())
+ {
+ cpp_option->deps.style = DEPS_USER;
+ cpp_option->deps.phony_targets = gfc_cpp_option.deps_phony;
+ cpp_option->deps.missing_files = gfc_cpp_option.deps_missing_are_generated;
+
+ /* -MF <arg> overrides -M[M]D. */
+ if (gfc_cpp_option.deps_filename_user)
+ gfc_cpp_option.deps_filename = gfc_cpp_option.deps_filename_user;
+ }
+
if (gfc_cpp_option.working_directory == -1)
gfc_cpp_option.working_directory = (debug_info_level != DINFO_LEVEL_NONE);
cpp_post_options (cpp_in);
- /* If an error has occurred in cpplib, note it so we fail immediately. */
- errorcount += cpp_errors (cpp_in);
-
gfc_cpp_register_include_paths ();
}
cb->line_change = cb_line_change;
cb->ident = cb_ident;
cb->def_pragma = cb_def_pragma;
+ cb->error = cb_cpp_error;
if (gfc_cpp_option.dump_includes)
cb->include = cb_include;
print.outf = fopen (gfc_cpp_option.output_filename, "w");
if (print.outf == NULL)
gfc_fatal_error ("opening output file %s: %s",
- gfc_cpp_option.output_filename, strerror(errno));
+ gfc_cpp_option.output_filename,
+ xstrerror (errno));
}
else
print.outf = stdout;
print.outf = fopen (gfc_cpp_option.temporary_filename, "w");
if (print.outf == NULL)
gfc_fatal_error ("opening output file %s: %s",
- gfc_cpp_option.temporary_filename, strerror(errno));
+ gfc_cpp_option.temporary_filename, xstrerror (errno));
}
gcc_assert(cpp_in);
if (gfc_option.flag_preprocessed)
return;
- cpp_change_file (cpp_in, LC_RENAME, _("<built-in>"));
if (!gfc_cpp_option.no_predefined)
- cpp_define_builtins (cpp_in);
+ {
+ /* Make sure all of the builtins about to be declared have
+ BUILTINS_LOCATION has their source_location. */
+ source_location builtins_loc = BUILTINS_LOCATION;
+ cpp_force_token_locations (cpp_in, &builtins_loc);
+
+ cpp_define_builtins (cpp_in);
+
+ cpp_stop_forcing_token_locations (cpp_in);
+ }
/* Handle deferred options from command-line. */
cpp_change_file (cpp_in, LC_RENAME, _("<command-line>"));
else
cpp_assert (cpp_in, opt->arg);
}
+ else if (opt->code == OPT_MT || opt->code == OPT_MQ)
+ deps_add_target (cpp_get_deps (cpp_in),
+ opt->arg, opt->code == OPT_MQ);
}
if (gfc_cpp_option.working_directory
pp_dir_change (cpp_in, get_src_pwd ());
}
-try
+gfc_try
gfc_cpp_preprocess (const char *source_file)
{
if (!gfc_cpp_enabled ())
if (!gfc_cpp_enabled ())
return;
- /* TODO: if dependency tracking was enabled, call
- cpp_finish() here to write dependencies.
+ gcc_assert (cpp_in);
- Use cpp_get_deps() to access the current source's
- dependencies during parsing. Add dependencies using
- the mkdeps-interface (defined in libcpp). */
+ if (gfc_cpp_makedep ())
+ {
+ if (gfc_cpp_option.deps_filename)
+ {
+ FILE *f = fopen (gfc_cpp_option.deps_filename, "w");
+ if (f)
+ {
+ cpp_finish (cpp_in, f);
+ fclose (f);
+ }
+ else
+ gfc_fatal_error ("opening output file %s: %s",
+ gfc_cpp_option.deps_filename,
+ xstrerror (errno));
+ }
+ else
+ cpp_finish (cpp_in, stdout);
+ }
- gcc_assert (cpp_in);
cpp_undef_all (cpp_in);
cpp_clear_file_cache (cpp_in);
}
{
/* CHAIN sets cpp_dir->sysp which differs from 0 if PATH is a system
include path. Fortran does not define any system include paths. */
- int chain = 0;
int cxx_aware = 0;
- add_path (path, chain, cxx_aware, user_supplied);
+ add_path (path, BRACKET, cxx_aware, user_supplied);
+}
+
+void
+gfc_cpp_add_include_path_after (char *path, bool user_supplied)
+{
+ int cxx_aware = 0;
+ add_path (path, AFTER, cxx_aware, user_supplied);
}
void
if (!gfc_cpp_option.no_line_commands)
{
- const struct line_map *map = linemap_lookup (line_table, src_loc);
-
- size_t to_file_len = strlen (map->to_file);
- unsigned char *to_file_quoted =
- (unsigned char *) alloca (to_file_len * 4 + 1);
+ expanded_location loc;
+ size_t to_file_len;
+ unsigned char *to_file_quoted;
unsigned char *p;
- print.src_line = SOURCE_LINE (map, src_loc);
+ loc = expand_location (src_loc);
+ to_file_len = strlen (loc.file);
+ to_file_quoted = (unsigned char *) alloca (to_file_len * 4 + 1);
+
+ print.src_line = loc.line;
/* cpp_quote_string does not nul-terminate, so we have to do it
ourselves. */
p = cpp_quote_string (to_file_quoted,
- (const unsigned char *) map->to_file, to_file_len);
+ (const unsigned char *) loc.file, to_file_len);
*p = '\0';
fprintf (print.outf, "# %u \"%s\"%s",
print.src_line == 0 ? 1 : print.src_line,
to_file_quoted, special_flags);
- if (map->sysp == 2)
+ if (loc.sysp == 2)
fputs (" 3 4", print.outf);
- else if (map->sysp == 1)
+ else if (loc.sysp == 1)
fputs (" 3", print.outf);
putc ('\n', print.outf);
fputs ((const char *) NODE_NAME (node), print.outf);
putc ('\n', print.outf);
- if (linemap_lookup (line_table, line)->to_line != 0)
+ if (LOCATION_LINE (line) != 0)
print.src_line++;
}
cpp_define_queue = q;
}
+/* Callback from cpp_error for PFILE to print diagnostics from the
+ preprocessor. The diagnostic is of type LEVEL, with REASON set
+ to the reason code if LEVEL is represents a warning, at location
+ LOCATION, with column number possibly overridden by COLUMN_OVERRIDE
+ if not zero; MSG is the translated message and AP the arguments.
+ Returns true if a diagnostic was emitted, false otherwise. */
+
+static bool
+cb_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
+ location_t location, unsigned int column_override,
+ const char *msg, va_list *ap)
+{
+ diagnostic_info diagnostic;
+ diagnostic_t dlevel;
+ bool save_warn_system_headers = global_dc->dc_warn_system_headers;
+ bool ret;
+
+ switch (level)
+ {
+ case CPP_DL_WARNING_SYSHDR:
+ global_dc->dc_warn_system_headers = 1;
+ /* Fall through. */
+ case CPP_DL_WARNING:
+ dlevel = DK_WARNING;
+ break;
+ case CPP_DL_PEDWARN:
+ dlevel = DK_PEDWARN;
+ break;
+ case CPP_DL_ERROR:
+ dlevel = DK_ERROR;
+ break;
+ case CPP_DL_ICE:
+ dlevel = DK_ICE;
+ break;
+ case CPP_DL_NOTE:
+ dlevel = DK_NOTE;
+ break;
+ case CPP_DL_FATAL:
+ dlevel = DK_FATAL;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ diagnostic_set_info_translated (&diagnostic, msg, ap,
+ location, dlevel);
+ if (column_override)
+ diagnostic_override_column (&diagnostic, column_override);
+ if (reason == CPP_W_WARNING_DIRECTIVE)
+ diagnostic_override_option_index (&diagnostic, OPT_Wcpp);
+ ret = report_diagnostic (&diagnostic);
+ if (level == CPP_DL_WARNING_SYSHDR)
+ global_dc->dc_warn_system_headers = save_warn_system_headers;
+ return ret;
+}
/* Callback called when -fworking-director and -E to emit working
directory in cpp output file. */
print.src_line++;
oq = q;
q = q->next;
- gfc_free (oq->macro);
- gfc_free (oq);
+ free (oq->macro);
+ free (oq);
}
cpp_define_queue = NULL;
for (q = cpp_undefine_queue; q;)
print.src_line++;
oq = q;
q = q->next;
- gfc_free (oq->macro);
- gfc_free (oq);
+ free (oq->macro);
+ free (oq);
}
cpp_undefine_queue = NULL;
}
-
-