OSDN Git Service

* trans-array.c (set_vector_loop_bounds): Loop over the parents.
[pf3gnuchains/gcc-fork.git] / gcc / fortran / cpp.c
index 76ab9a3..2f18893 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2008 Free Software Foundation, Inc.
+/* Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -35,6 +35,12 @@ along with GCC; see the file COPYING3.  If not see
 #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()
@@ -66,7 +72,7 @@ typedef struct gfc_cpp_macro_queue
 } 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.  */
@@ -84,6 +90,12 @@ struct
   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>  */
@@ -103,12 +115,6 @@ gfc_cpp_option;
 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
@@ -137,6 +143,9 @@ static void cb_include (cpp_reader *, source_location, const unsigned char *,
 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 *);
@@ -146,85 +155,18 @@ static void dump_queued_macros (cpp_reader *);
 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.
 
@@ -267,6 +209,26 @@ gfc_cpp_preprocess_only (void)
   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)
 {
@@ -274,8 +236,8 @@ 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
@@ -296,12 +258,19 @@ gfc_cpp_init_options (unsigned int argc,
   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;
 }
 
@@ -317,7 +286,7 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED
       result = 0;
       break;
 
-    case OPT_cpp:
+    case OPT_cpp_:
       gfc_cpp_option.temporary_filename = arg;
       break;
 
@@ -346,6 +315,10 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED
       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;
@@ -407,6 +380,43 @@ gfc_cpp_handle_option (size_t scode, const char *arg, int value ATTRIBUTE_UNUSED
       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;
@@ -423,18 +433,19 @@ gfc_cpp_post_options (void)
      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.
@@ -447,8 +458,7 @@ gfc_cpp_post_options (void)
   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;
@@ -456,14 +466,22 @@ gfc_cpp_post_options (void)
   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 ();
 }
 
@@ -478,6 +496,7 @@ gfc_cpp_init_0 (void)
   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;
@@ -519,7 +538,8 @@ gfc_cpp_init_0 (void)
          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;
@@ -529,7 +549,7 @@ gfc_cpp_init_0 (void)
       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);
@@ -545,9 +565,17 @@ gfc_cpp_init (void)
   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>"));
@@ -567,6 +595,9 @@ gfc_cpp_init (void)
          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
@@ -574,7 +605,7 @@ gfc_cpp_init (void)
     pp_dir_change (cpp_in, get_src_pwd ());
 }
 
-try
+gfc_try
 gfc_cpp_preprocess (const char *source_file)
 {
   if (!gfc_cpp_enabled ())
@@ -610,14 +641,27 @@ gfc_cpp_done (void)
   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);
 }
@@ -628,10 +672,16 @@ gfc_cpp_add_include_path (char *path, bool user_supplied)
 {
   /* 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
@@ -768,27 +818,29 @@ print_line (source_location src_loc, const char *special_flags)
 
   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);
@@ -885,7 +937,7 @@ cb_define (cpp_reader *pfile ATTRIBUTE_UNUSED, source_location line,
     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++;
 }
 
@@ -951,6 +1003,60 @@ cb_used_define (cpp_reader *pfile, source_location line ATTRIBUTE_UNUSED,
   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.  */
@@ -1013,8 +1119,8 @@ dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
       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;)
@@ -1024,10 +1130,8 @@ dump_queued_macros (cpp_reader *pfile ATTRIBUTE_UNUSED)
       print.src_line++;
       oq = q;
       q = q->next;
-      gfc_free (oq->macro);
-      gfc_free (oq);
+      free (oq->macro);
+      free (oq);
     }
   cpp_undefine_queue = NULL;
 }
-
-