global trees
[gcc.git] / gcc / c-family / c-opts.c
index 9ae181f26ed6ce9bbca4b8137af9f3027fe15773..77844d7daf19eaecb3dc1d690dcd3be4fd806d99 100644 (file)
@@ -1,5 +1,5 @@
 /* C/ObjC/C++ command line option handling.
-   Copyright (C) 2002-2015 Free Software Foundation, Inc.
+   Copyright (C) 2002-2020 Free Software Foundation, Inc.
    Contributed by Neil Booth.
 
 This file is part of GCC.
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "c-target.h"
 #include "c-common.h"
+#include "memmodel.h"
 #include "tm_p.h"              /* For C_COMMON_OVERRIDE_OPTIONS.  */
 #include "diagnostic.h"
 #include "c-pragma.h"
@@ -39,6 +40,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "plugin.h"            /* For PLUGIN_INCLUDE_FILE event.  */
 #include "mkdeps.h"
 #include "dumpfile.h"
+#include "file-prefix-map.h"    /* add_*_prefix_map()  */
 
 #ifndef DOLLARS_IN_IDENTIFIERS
 # define DOLLARS_IN_IDENTIFIERS true
@@ -100,9 +102,7 @@ static size_t include_cursor;
 
 /* Dump files/flags to use during parsing.  */
 static FILE *original_dump_file = NULL;
-static int original_dump_flags;
-static FILE *class_dump_file = NULL;
-static int class_dump_flags;
+static dump_flags_t original_dump_flags;
 
 /* Whether any standard preincluded header has been preincluded.  */
 static bool done_preinclude;
@@ -111,14 +111,17 @@ static void handle_OPT_d (const char *);
 static void set_std_cxx98 (int);
 static void set_std_cxx11 (int);
 static void set_std_cxx14 (int);
-static void set_std_cxx1z (int);
+static void set_std_cxx17 (int);
+static void set_std_cxx20 (int);
 static void set_std_c89 (int, int);
 static void set_std_c99 (int);
 static void set_std_c11 (int);
+static void set_std_c17 (int);
+static void set_std_c2x (int);
 static void check_deps_environment_vars (void);
 static void handle_deferred_opts (void);
 static void sanitize_cpp_opts (void);
-static void add_prefixed_path (const char *, size_t);
+static void add_prefixed_path (const char *, incpath_kind);
 static void push_command_line_include (void);
 static void cb_file_change (cpp_reader *, const line_map_ordinary *);
 static void cb_dir_change (cpp_reader *, const char *);
@@ -162,14 +165,18 @@ c_common_option_lang_mask (void)
 /* Diagnostic finalizer for C/C++/Objective-C/Objective-C++.  */
 static void
 c_diagnostic_finalizer (diagnostic_context *context,
-                       diagnostic_info *diagnostic)
+                       diagnostic_info *diagnostic,
+                       diagnostic_t)
 {
-  diagnostic_show_locus (context, diagnostic);
+  char *saved_prefix = pp_take_prefix (context->printer);
+  pp_set_prefix (context->printer, NULL);
+  pp_newline (context->printer);
+  diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
   /* By default print macro expansion contexts in the diagnostic
      finalizer -- for tokens resulting from macro expansion.  */
   virt_loc_aware_diagnostic_finalizer (context, diagnostic);
-  pp_destroy_prefix (context->printer);
-  pp_newline_and_flush (context->printer);
+  pp_set_prefix (context->printer, saved_prefix);
+  pp_flush (context->printer);
 }
 
 /* Common default settings for diagnostics.  */
@@ -216,10 +223,13 @@ c_common_init_options (unsigned int decoded_options_count,
   unsigned int i;
   struct cpp_callbacks *cb;
 
+  g_string_concat_db
+    = new (ggc_alloc <string_concat_db> ()) string_concat_db ();
+
   parse_in = cpp_create_reader (c_dialect_cxx () ? CLK_GNUCXX: CLK_GNUC89,
                                ident_hash, line_table);
   cb = cpp_get_callbacks (parse_in);
-  cb->error = c_cpp_error;
+  cb->diagnostic = c_cpp_diagnostic;
 
   cpp_opts = cpp_get_options (parse_in);
   cpp_opts->dollars_in_ident = DOLLARS_IN_IDENTIFIERS;
@@ -233,8 +243,8 @@ c_common_init_options (unsigned int decoded_options_count,
 
   if (c_language == clk_c)
     {
-      /* The default for C is gnu11.  */
-      set_std_c11 (false /* ISO */);
+      /* The default for C is gnu17.  */
+      set_std_c17 (false /* ISO */);
 
       /* If preprocessing assembly language, accept any of the C-family
         front end options since the driver may pass them through.  */
@@ -246,6 +256,10 @@ c_common_init_options (unsigned int decoded_options_count,
          }
     }
 
+  /* Set C++ standard to C++17 if not specified on the command line.  */
+  if (c_dialect_cxx ())
+    set_std_cxx17 (/*ISO*/false);
+
   global_dc->colorize_source_p = true;
 }
 
@@ -253,7 +267,7 @@ c_common_init_options (unsigned int decoded_options_count,
    form of an -f or -W option was given.  Returns false if the switch was
    invalid, true if valid.  Use HANDLERS in recursive handle_option calls.  */
 bool
-c_common_handle_option (size_t scode, const char *arg, int value,
+c_common_handle_option (size_t scode, const char *arg, HOST_WIDE_INT value,
                        int kind, location_t loc,
                        const struct cl_option_handlers *handlers)
 {
@@ -309,14 +323,15 @@ c_common_handle_option (size_t scode, const char *arg, int value,
 
     case OPT_I:
       if (strcmp (arg, "-"))
-       add_path (xstrdup (arg), BRACKET, 0, true);
+       add_path (xstrdup (arg), INC_BRACKET, 0, true);
       else
        {
          if (quote_chain_split)
-           error ("-I- specified twice");
+           error ("%<-I-%> specified twice");
          quote_chain_split = true;
          split_quote_chain ();
-         inform (input_location, "obsolete option -I- used, please use -iquote instead");
+         inform (input_location, "obsolete option %<-I-%> used, "
+                 "please use %<-iquote%> instead");
        }
       break;
 
@@ -398,8 +413,6 @@ c_common_handle_option (size_t scode, const char *arg, int value,
          value = 2;
        }
       warn_abi_version = value;
-      if (flag_abi_compat_version == -1)
-       flag_abi_compat_version = value;
       break;
 
     case OPT_fcanonical_system_headers:
@@ -430,9 +443,13 @@ c_common_handle_option (size_t scode, const char *arg, int value,
       cpp_opts->dollars_in_ident = value;
       break;
 
+    case OPT_fmacro_prefix_map_:
+      add_macro_prefix_map (arg);
+      break;
+
     case OPT_ffreestanding:
       value = !value;
-      /* Fall through....  */
+      /* Fall through.  */
     case OPT_fhosted:
       flag_hosted = value;
       flag_no_builtin = !value;
@@ -446,6 +463,10 @@ c_common_handle_option (size_t scode, const char *arg, int value,
       cpp_opts->extended_identifiers = value;
       break;
 
+    case OPT_fmax_include_depth_:
+       cpp_opts->max_include_depth = value;
+      break;
+
     case OPT_foperator_names:
       cpp_opts->operator_names = value;
       break;
@@ -483,18 +504,6 @@ c_common_handle_option (size_t scode, const char *arg, int value,
        cpp_opts->track_macro_expansion = 2;
       break;
 
-    case OPT_frepo:
-      flag_use_repository = value;
-      if (value)
-       flag_implicit_templates = 0;
-      break;
-
-    case OPT_ftabstop_:
-      /* It is documented that we silently ignore silly values.  */
-      if (value >= 1 && value <= 100)
-       cpp_opts->tabstop = value;
-      break;
-
     case OPT_fexec_charset_:
       cpp_opts->narrow_charset = arg;
       break;
@@ -533,7 +542,7 @@ c_common_handle_option (size_t scode, const char *arg, int value,
       break;
 
     case OPT_idirafter:
-      add_path (xstrdup (arg), AFTER, 0, true);
+      add_path (xstrdup (arg), INC_AFTER, 0, true);
       break;
 
     case OPT_imacros:
@@ -550,7 +559,7 @@ c_common_handle_option (size_t scode, const char *arg, int value,
       break;
 
     case OPT_iquote:
-      add_path (xstrdup (arg), QUOTE, 0, true);
+      add_path (xstrdup (arg), INC_QUOTE, 0, true);
       break;
 
     case OPT_isysroot:
@@ -558,15 +567,15 @@ c_common_handle_option (size_t scode, const char *arg, int value,
       break;
 
     case OPT_isystem:
-      add_path (xstrdup (arg), SYSTEM, 0, true);
+      add_path (xstrdup (arg), INC_SYSTEM, 0, true);
       break;
 
     case OPT_iwithprefix:
-      add_prefixed_path (arg, SYSTEM);
+      add_prefixed_path (arg, INC_SYSTEM);
       break;
 
     case OPT_iwithprefixbefore:
-      add_prefixed_path (arg, BRACKET);
+      add_prefixed_path (arg, INC_BRACKET);
       break;
 
     case OPT_lang_asm:
@@ -606,31 +615,25 @@ c_common_handle_option (size_t scode, const char *arg, int value,
     case OPT_std_c__11:
     case OPT_std_gnu__11:
       if (!preprocessing_asm_p)
-       {
-         set_std_cxx11 (code == OPT_std_c__11 /* ISO */);
-         if (code == OPT_std_c__11)
-           cpp_opts->ext_numeric_literals = 0;
-       }
+       set_std_cxx11 (code == OPT_std_c__11 /* ISO */);
       break;
 
     case OPT_std_c__14:
     case OPT_std_gnu__14:
       if (!preprocessing_asm_p)
-       {
-         set_std_cxx14 (code == OPT_std_c__14 /* ISO */);
-         if (code == OPT_std_c__14)
-           cpp_opts->ext_numeric_literals = 0;
-       }
+       set_std_cxx14 (code == OPT_std_c__14 /* ISO */);
       break;
 
-    case OPT_std_c__1z:
-    case OPT_std_gnu__1z:
+    case OPT_std_c__17:
+    case OPT_std_gnu__17:
       if (!preprocessing_asm_p)
-       {
-         set_std_cxx1z (code == OPT_std_c__1z /* ISO */);
-         if (code == OPT_std_c__1z)
-           cpp_opts->ext_numeric_literals = 0;
-       }
+       set_std_cxx17 (code == OPT_std_c__17 /* ISO */);
+      break;
+
+    case OPT_std_c__20:
+    case OPT_std_gnu__20:
+      if (!preprocessing_asm_p)
+       set_std_cxx20 (code == OPT_std_c__20 /* ISO */);
       break;
 
     case OPT_std_c90:
@@ -664,6 +667,26 @@ c_common_handle_option (size_t scode, const char *arg, int value,
        set_std_c11 (false /* ISO */);
       break;
 
+    case OPT_std_c17:
+      if (!preprocessing_asm_p)
+       set_std_c17 (true /* ISO */);
+      break;
+
+    case OPT_std_gnu17:
+      if (!preprocessing_asm_p)
+       set_std_c17 (false /* ISO */);
+      break;
+
+    case OPT_std_c2x:
+      if (!preprocessing_asm_p)
+       set_std_c2x (true /* ISO */);
+      break;
+
+    case OPT_std_gnu2x:
+      if (!preprocessing_asm_p)
+       set_std_c2x (false /* ISO */);
+      break;
+
     case OPT_trigraphs:
       cpp_opts->trigraphs = 1;
       break;
@@ -729,8 +752,6 @@ default_handle_c_option (size_t code ATTRIBUTE_UNUSED,
 bool
 c_common_post_options (const char **pfilename)
 {
-  struct cpp_callbacks *cb;
-
   /* Canonicalize the input and output filenames.  */
   if (in_fnames == NULL)
     {
@@ -738,7 +759,12 @@ c_common_post_options (const char **pfilename)
       in_fnames[0] = "";
     }
   else if (strcmp (in_fnames[0], "-") == 0)
-    in_fnames[0] = "";
+    {
+      if (pch_file)
+       error ("cannot use %<-%> as input filename for a precompiled header");
+
+      in_fnames[0] = "";
+    }
 
   if (out_fname == NULL || !strcmp (out_fname, "-"))
     out_fname = "";
@@ -763,15 +789,13 @@ c_common_post_options (const char **pfilename)
      support.  */
   if (c_dialect_cxx ())
     {
-      if (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD
-         && TARGET_FLT_EVAL_METHOD_NON_DEFAULT)
-       sorry ("-fexcess-precision=standard for C++");
-      flag_excess_precision_cmdline = EXCESS_PRECISION_FAST;
+      if (flag_excess_precision == EXCESS_PRECISION_STANDARD)
+       sorry ("%<-fexcess-precision=standard%> for C++");
+      flag_excess_precision = EXCESS_PRECISION_FAST;
     }
-  else if (flag_excess_precision_cmdline == EXCESS_PRECISION_DEFAULT)
-    flag_excess_precision_cmdline = (flag_iso
-                                    ? EXCESS_PRECISION_STANDARD
-                                    : EXCESS_PRECISION_FAST);
+  else if (flag_excess_precision == EXCESS_PRECISION_DEFAULT)
+    flag_excess_precision = (flag_iso ? EXCESS_PRECISION_STANDARD
+                                     : EXCESS_PRECISION_FAST);
 
   /* ISO C restricts floating-point expression contraction to within
      source-language expressions (-ffp-contract=on, currently an alias
@@ -783,12 +807,30 @@ c_common_post_options (const char **pfilename)
       && flag_unsafe_math_optimizations == 0)
     flag_fp_contract_mode = FP_CONTRACT_OFF;
 
+  /* If we are compiling C, and we are outside of a standards mode,
+     we can permit the new values from ISO/IEC TS 18661-3 for
+     FLT_EVAL_METHOD.  Otherwise, we must restrict the possible values to
+     the set specified in ISO C99/C11.  */
+  if (!flag_iso
+      && !c_dialect_cxx ()
+      && (global_options_set.x_flag_permitted_flt_eval_methods
+         == PERMITTED_FLT_EVAL_METHODS_DEFAULT))
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_TS_18661;
+  else
+    flag_permitted_flt_eval_methods = PERMITTED_FLT_EVAL_METHODS_C11;
+
+  /* C2X Annex F does not permit certain built-in functions to raise
+     "inexact".  */
+  if (flag_isoc2x)
+    SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                        flag_fp_int_builtin_inexact, 0);
+
   /* By default we use C99 inline semantics in GNU99 or C99 mode.  C99
      inline semantics are not supported in GNU89 or C89 mode.  */
   if (flag_gnu89_inline == -1)
     flag_gnu89_inline = !flag_isoc99;
   else if (!flag_gnu89_inline && !flag_isoc99)
-    error ("-fno-gnu89-inline is only supported in GNU99 or C99 mode");
+    error ("%<-fno-gnu89-inline%> is only supported in GNU99 or C99 mode");
 
   /* Default to ObjC sjlj exception handling if NeXT runtime.  */
   if (flag_objc_sjlj_exceptions < 0)
@@ -798,13 +840,9 @@ c_common_post_options (const char **pfilename)
 
   /* If -ffreestanding, -fno-hosted or -fno-builtin then disable
      pattern recognition.  */
-  if (!global_options_set.x_flag_tree_loop_distribute_patterns
-      && flag_no_builtin)
-    flag_tree_loop_distribute_patterns = 0;
-
-  /* Set C++ standard to C++14 if not specified on the command line.  */
-  if (c_dialect_cxx () && cxx_dialect == cxx_unset)
-    set_std_cxx14 (/*ISO*/false);
+  if (flag_no_builtin)
+    SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                        flag_tree_loop_distribute_patterns, 0);
 
   /* -Woverlength-strings is off by default, but is enabled by -Wpedantic.
      It is never enabled in C++, as the minimum limit is not normative
@@ -838,17 +876,17 @@ c_common_post_options (const char **pfilename)
   if (!warn_format)
     {
       warning (OPT_Wformat_y2k,
-              "-Wformat-y2k ignored without -Wformat");
+              "%<-Wformat-y2k%> ignored without %<-Wformat%>");
       warning (OPT_Wformat_extra_args,
-              "-Wformat-extra-args ignored without -Wformat");
+              "%<-Wformat-extra-args%> ignored without %<-Wformat%>");
       warning (OPT_Wformat_zero_length,
-              "-Wformat-zero-length ignored without -Wformat");
+              "%<-Wformat-zero-length%> ignored without %<-Wformat%>");
       warning (OPT_Wformat_nonliteral,
-              "-Wformat-nonliteral ignored without -Wformat");
+              "%<-Wformat-nonliteral%> ignored without %<-Wformat%>");
       warning (OPT_Wformat_contains_nul,
-              "-Wformat-contains-nul ignored without -Wformat");
+              "%<-Wformat-contains-nul%> ignored without %<-Wformat%>");
       warning (OPT_Wformat_security,
-              "-Wformat-security ignored without -Wformat");
+              "%<-Wformat-security%> ignored without %<-Wformat%>");
     }
 
   /* -Wimplicit-function-declaration is enabled by default for C99.  */
@@ -859,6 +897,10 @@ c_common_post_options (const char **pfilename)
   if (warn_implicit_int == -1)
     warn_implicit_int = flag_isoc99;
 
+  /* -Wold-style-definition is enabled by default for C2X.  */
+  if (warn_old_style_definition == -1)
+    warn_old_style_definition = flag_isoc2x;
+
   /* -Wshift-overflow is enabled by default in C99 and C++11 modes.  */
   if (warn_shift_overflow == -1)
     warn_shift_overflow = cxx_dialect >= cxx11 || flag_isoc99;
@@ -868,34 +910,90 @@ c_common_post_options (const char **pfilename)
     warn_shift_negative_value = (extra_warnings
                                 && (cxx_dialect >= cxx11 || flag_isoc99));
 
+  /* -Wregister is enabled by default in C++17.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_register,
+                      cxx_dialect >= cxx17);
+
+  /* -Wcomma-subscript is enabled by default in C++20.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                      warn_comma_subscript,
+                      cxx_dialect >= cxx20 && warn_deprecated);
+
+  /* -Wvolatile is enabled by default in C++20.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set, warn_volatile,
+                      cxx_dialect >= cxx20 && warn_deprecated);
+
+  /* -Wdeprecated-enum-enum-conversion is enabled by default in C++20.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                      warn_deprecated_enum_enum_conv,
+                      cxx_dialect >= cxx20 && warn_deprecated);
+
+  /* -Wdeprecated-enum-float-conversion is enabled by default in C++20.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                      warn_deprecated_enum_float_conv,
+                      cxx_dialect >= cxx20 && warn_deprecated);
+
   /* Declone C++ 'structors if -Os.  */
   if (flag_declone_ctor_dtor == -1)
     flag_declone_ctor_dtor = optimize_size;
 
-  if (warn_abi_version == -1)
-    {
-      if (flag_abi_compat_version != -1)
-       warn_abi_version = flag_abi_compat_version;
-      else
-       warn_abi_version = 0;
-    }
-
   if (flag_abi_compat_version == 1)
     {
       warning (0, "%<-fabi-compat-version=1%> is not supported, using =2");
       flag_abi_compat_version = 2;
     }
-  else if (flag_abi_compat_version == -1)
+
+  /* Change flag_abi_version to be the actual current ABI level, for the
+     benefit of c_cpp_builtins, and to make comparison simpler.  */
+  const int latest_abi_version = 15;
+  /* Generate compatibility aliases for ABI v11 (7.1) by default.  */
+  const int abi_compat_default = 11;
+
+#define clamp(X) if (X == 0 || X > latest_abi_version) X = latest_abi_version
+  clamp (flag_abi_version);
+  clamp (warn_abi_version);
+  clamp (flag_abi_compat_version);
+#undef clamp
+
+  /* Default -Wabi= or -fabi-compat-version= from each other.  */
+  if (warn_abi_version == -1 && flag_abi_compat_version != -1)
+    warn_abi_version = flag_abi_compat_version;
+  else if (flag_abi_compat_version == -1 && warn_abi_version != -1)
+    flag_abi_compat_version = warn_abi_version;
+  else if (warn_abi_version == -1 && flag_abi_compat_version == -1)
     {
-      /* Generate compatibility aliases for ABI v8 (5.1) by default. */
-      flag_abi_compat_version
-       = (flag_abi_version == 0 ? 8 : 0);
+      warn_abi_version = latest_abi_version;
+      if (flag_abi_version == latest_abi_version)
+       {
+         auto_diagnostic_group d;
+         if (warning (OPT_Wabi, "%<-Wabi%> won%'t warn about anything"))
+           {
+             inform (input_location, "%<-Wabi%> warns about differences "
+                     "from the most up-to-date ABI, which is also used "
+                     "by default");
+             inform (input_location, "use e.g. %<-Wabi=11%> to warn about "
+                     "changes from GCC 7");
+           }
+         flag_abi_compat_version = abi_compat_default;
+       }
+      else
+       flag_abi_compat_version = latest_abi_version;
     }
 
-  /* Change flag_abi_version to be the actual current ABI level for the
-     benefit of c_cpp_builtins.  */
-  if (flag_abi_version == 0)
-    flag_abi_version = 10;
+  /* By default, enable the new inheriting constructor semantics along with ABI
+     11.  New and old should coexist fine, but it is a change in what
+     artificial symbols are generated.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set,
+                      flag_new_inheriting_ctors,
+                      abi_version_at_least (11));
+
+  /* For GCC 7, only enable DR150 resolution by default if -std=c++17.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_new_ttp,
+                      cxx_dialect >= cxx17);
+
+  /* C++11 guarantees forward progress.  */
+  SET_OPTION_IF_UNSET (&global_options, &global_options_set, flag_finite_loops,
+                      optimize >= 2 && cxx_dialect >= cxx11);
 
   if (cxx_dialect >= cxx11)
     {
@@ -906,28 +1004,63 @@ c_common_post_options (const char **pfilename)
 
       if (warn_narrowing == -1)
        warn_narrowing = 1;
+
+      /* Unless -f{,no-}ext-numeric-literals has been used explicitly,
+        for -std=c++{11,14,17,2a} default to -fno-ext-numeric-literals.  */
+      if (flag_iso && !global_options_set.x_flag_ext_numeric_literals)
+       cpp_opts->ext_numeric_literals = 0;
     }
   else if (warn_narrowing == -1)
     warn_narrowing = 0;
 
+  /* C++17 has stricter evaluation order requirements; let's use some of them
+     for earlier C++ as well, so chaining works as expected.  */
+  if (c_dialect_cxx ()
+      && flag_strong_eval_order == -1)
+    flag_strong_eval_order = (cxx_dialect >= cxx17 ? 2 : 1);
+
   /* Global sized deallocation is new in C++14.  */
   if (flag_sized_deallocation == -1)
     flag_sized_deallocation = (cxx_dialect >= cxx14);
 
+  /* char8_t support is new in C++20.  */
+  if (flag_char8_t == -1)
+    flag_char8_t = (cxx_dialect >= cxx20);
+
   if (flag_extern_tls_init)
     {
-#if !defined (ASM_OUTPUT_DEF) || !SUPPORTS_WEAK
-      /* Lazy TLS initialization for a variable in another TU requires
-        alias and weak reference support. */
-      if (flag_extern_tls_init > 0)
-       sorry ("external TLS initialization functions not supported "
-              "on this target");
-      flag_extern_tls_init = 0;
-#else
-      flag_extern_tls_init = 1;
-#endif
+      if (!TARGET_SUPPORTS_ALIASES || !SUPPORTS_WEAK)
+       {
+         /* Lazy TLS initialization for a variable in another TU requires
+            alias and weak reference support.  */
+         if (flag_extern_tls_init > 0)
+           sorry ("external TLS initialization functions not supported "
+                  "on this target");
+
+         flag_extern_tls_init = 0;
+       }
+      else
+       flag_extern_tls_init = 1;
     }
 
+  /* Enable by default only for C++ and C++ with ObjC extensions.  */
+  if (warn_return_type == -1 && c_dialect_cxx ())
+    warn_return_type = 1;
+
+  /* C++20 is the final version of concepts. We still use -fconcepts
+     to know when concepts are enabled. Note that -fconcepts-ts can
+     be used to include additional features, although modified to
+     work with the standard.  */
+  if (cxx_dialect >= cxx20 || flag_concepts_ts)
+    flag_concepts = 1;
+  else if (flag_concepts)
+    /* For -std=c++17 -fconcepts, imply -fconcepts-ts.  */
+    flag_concepts_ts = 1;
+
+  if (num_in_fnames > 1)
+    error ("too many filenames given; type %<%s %s%> for usage",
+          progname, "--help");
+
   if (flag_preprocess_only)
     {
       /* Open the output now.  We must do so even if flag_no_output is
@@ -944,10 +1077,6 @@ c_common_post_options (const char **pfilename)
          return false;
        }
 
-      if (num_in_fnames > 1)
-       error ("too many filenames given.  Type %s --help for usage",
-              progname);
-
       init_pp_output (out_stream);
     }
   else
@@ -964,7 +1093,7 @@ c_common_post_options (const char **pfilename)
             debug formats we warn here and refuse to load any PCH files.  */
          if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
            warning (OPT_Wdeprecated,
-                    "the \"%s\" debug format cannot be used with "
+                    "the %qs debug format cannot be used with "
                     "pre-compiled headers", debug_type_names[write_symbols]);
        }
       else if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
@@ -974,16 +1103,22 @@ c_common_post_options (const char **pfilename)
       input_location = UNKNOWN_LOCATION;
     }
 
-  cb = cpp_get_callbacks (parse_in);
+  struct cpp_callbacks *cb = cpp_get_callbacks (parse_in);
   cb->file_change = cb_file_change;
   cb->dir_change = cb_dir_change;
+  if (lang_hooks.preprocess_options)
+    lang_hooks.preprocess_options (parse_in);
   cpp_post_options (parse_in);
   init_global_opts_from_cpp (&global_options, cpp_get_options (parse_in));
 
   input_location = UNKNOWN_LOCATION;
 
   *pfilename = this_input_filename
-    = cpp_read_main_file (parse_in, in_fnames[0]);
+    = cpp_read_main_file (parse_in, in_fnames[0],
+                         /* We'll inject preamble pieces if this is
+                            not preprocessed.  */
+                         !cpp_opts->preprocessed);
+
   /* Don't do any compilation or preprocessing if there is no input file.  */
   if (this_input_filename == NULL)
     {
@@ -1055,10 +1190,9 @@ c_common_parse_file (void)
   for (;;)
     {
       c_finish_options ();
-      /* Open the dump files to use for the original and class dump output
+      /* Open the dump file to use for the original dump output
          here, to be used during parsing for the current file.  */
       original_dump_file = dump_begin (TDI_original, &original_dump_flags);
-      class_dump_file = dump_begin (TDI_class, &class_dump_flags);
       pch_init ();
       push_file_scope ();
       c_parse_file ();
@@ -1077,11 +1211,6 @@ c_common_parse_file (void)
           dump_end (TDI_original, original_dump_file);
           original_dump_file = NULL;
         }
-      if (class_dump_file)
-        {
-          dump_end (TDI_class, class_dump_file);
-          class_dump_file = NULL;
-        }
       /* If an input file is missing, abandon further compilation.
         cpplib has issued a diagnostic.  */
       if (!this_input_filename)
@@ -1092,20 +1221,14 @@ c_common_parse_file (void)
 }
 
 /* Returns the appropriate dump file for PHASE to dump with FLAGS.  */
+
 FILE *
-get_dump_info (int phase, int *flags)
+get_dump_info (int phase, dump_flags_t *flags)
 {
-  gcc_assert (phase == TDI_original || phase == TDI_class);
-  if (phase == TDI_original)
-    {
-      *flags = original_dump_flags;
-      return original_dump_file;
-    }
-  else
-    {
-      *flags = class_dump_flags;
-      return class_dump_file;
-    }
+  gcc_assert (phase == TDI_original);
+
+  *flags = original_dump_flags;
+  return original_dump_file;
 }
 
 /* Common finish hook for the C, ObjC and C++ front ends.  */
@@ -1114,13 +1237,18 @@ c_common_finish (void)
 {
   FILE *deps_stream = NULL;
 
-  /* Don't write the deps file if there are errors.  */
-  if (cpp_opts->deps.style != DEPS_NONE && !seen_error ())
+  /* Note that we write the dependencies even if there are errors. This is
+     useful for handling outdated generated headers that now trigger errors
+     (for example, with #error) which would be resolved by re-generating
+     them. In a sense, this complements -MG.  */
+  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 if (deps_file[0] == '-' && deps_file[1] == '\0')
+       deps_stream = stdout;
       else
        {
          deps_stream = fopen (deps_file, deps_append ? "a": "w");
@@ -1134,7 +1262,7 @@ c_common_finish (void)
      with cpp_destroy ().  */
   cpp_finish (parse_in, deps_stream);
 
-  if (deps_stream && deps_stream != out_stream
+  if (deps_stream && deps_stream != out_stream && deps_stream != stdout
       && (ferror (deps_stream) || fclose (deps_stream)))
     fatal_error (input_location, "closing dependency file %s: %m", deps_file);
 
@@ -1191,24 +1319,20 @@ check_deps_environment_vars (void)
 static void
 handle_deferred_opts (void)
 {
-  size_t i;
-  struct deps *deps;
-
   /* Avoid allocating the deps buffer if we don't need it.
      (This flag may be true without there having been -MT or -MQ
      options, but we'll still need the deps buffer.)  */
   if (!deps_seen)
     return;
 
-  deps = cpp_get_deps (parse_in);
-
-  for (i = 0; i < deferred_count; i++)
-    {
-      struct deferred_opt *opt = &deferred_opts[i];
+  if (mkdeps *deps = cpp_get_deps (parse_in))
+    for (unsigned i = 0; i < deferred_count; i++)
+      {
+       struct deferred_opt *opt = &deferred_opts[i];
 
-      if (opt->code == OPT_MT || opt->code == OPT_MQ)
-       deps_add_target (deps, opt->arg, opt->code == OPT_MQ);
-    }
+       if (opt->code == OPT_MT || opt->code == OPT_MQ)
+         deps_add_target (deps, opt->arg, opt->code == OPT_MQ);
+      }
 }
 
 /* These settings are appropriate for GCC, but not necessarily so for
@@ -1219,7 +1343,8 @@ sanitize_cpp_opts (void)
   /* 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");
+    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.  */
@@ -1242,7 +1367,7 @@ sanitize_cpp_opts (void)
       flag_no_line_commands = 1;
     }
   else if (cpp_opts->deps.missing_files)
-    error ("-MG may only be used with -M or -MM");
+    error ("%<-MG%> may only be used with %<-M%> or %<-MM%>");
 
   cpp_opts->unsigned_char = !flag_signed_char;
   cpp_opts->stdc_0_in_system_headers = STDC_0_IN_SYSTEM_HEADERS;
@@ -1267,18 +1392,24 @@ sanitize_cpp_opts (void)
   if (flag_working_directory == -1)
     flag_working_directory = (debug_info_level != DINFO_LEVEL_NONE);
 
+  if (warn_implicit_fallthrough < 5)
+    cpp_opts->cpp_warn_implicit_fallthrough = warn_implicit_fallthrough;
+  else
+    cpp_opts->cpp_warn_implicit_fallthrough = 0;
+
   if (cpp_opts->directives_only)
     {
       if (cpp_warn_unused_macros)
-       error ("-fdirectives-only is incompatible with -Wunused_macros");
+       error ("%<-fdirectives-only%> is incompatible "
+              "with %<-Wunused-macros%>");
       if (cpp_opts->traditional)
-       error ("-fdirectives-only is incompatible with -traditional");
+       error ("%<-fdirectives-only%> is incompatible with %<-traditional%>");
     }
 }
 
 /* Add include path with a prefix at the front of its name.  */
 static void
-add_prefixed_path (const char *suffix, size_t chain)
+add_prefixed_path (const char *suffix, incpath_kind chain)
 {
   char *path;
   const char *prefix;
@@ -1302,23 +1433,19 @@ c_finish_options (void)
 {
   if (!cpp_opts->preprocessed)
     {
-      size_t i;
+      const line_map_ordinary *bltin_map
+       = linemap_check_ordinary (linemap_add (line_table, LC_RENAME, 0,
+                                              _("<built-in>"), 0));
+      cb_file_change (parse_in, bltin_map);
+      linemap_line_start (line_table, 0, 1);
 
-      cb_file_change (parse_in,
-                     linemap_check_ordinary (linemap_add (line_table,
-                                                          LC_RENAME, 0,
-                                                          _("<built-in>"),
-                                                          0)));
       /* 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 (parse_in, &builtins_loc);
+        BUILTINS_LOCATION has their location_t.  */
+      cpp_force_token_locations (parse_in, BUILTINS_LOCATION);
 
       cpp_init_builtins (parse_in, flag_hosted);
       c_cpp_builtins (parse_in);
 
-      cpp_stop_forcing_token_locations (parse_in);
-
       /* We're about to send user input to cpplib, so make it warn for
         things that we previously (when we sent it internal definitions)
         told it to not warn.
@@ -1330,11 +1457,15 @@ c_finish_options (void)
         their acceptance on the -std= setting.  */
       cpp_opts->warn_dollars = (cpp_opts->cpp_pedantic && !cpp_opts->c99);
 
-      cb_file_change (parse_in,
-                     linemap_check_ordinary (linemap_add (line_table, LC_RENAME, 0,
-                                                          _("<command-line>"), 0)));
+      const line_map_ordinary *cmd_map
+       = linemap_check_ordinary (linemap_add (line_table, LC_RENAME, 0,
+                                              _("<command-line>"), 0));
+      cb_file_change (parse_in, cmd_map);
+      linemap_line_start (line_table, 0, 1);
 
-      for (i = 0; i < deferred_count; i++)
+      /* All command line defines must have the same location.  */
+      cpp_force_token_locations (parse_in, line_table->highest_line);
+      for (size_t i = 0; i < deferred_count; i++)
        {
          struct deferred_opt *opt = &deferred_opts[i];
 
@@ -1351,35 +1482,30 @@ c_finish_options (void)
            }
        }
 
-      /* Start the main input file, if the debug writer wants it. */
-      if (debug_hooks->start_end_main_source_file
-         && !flag_preprocess_only)
-       (*debug_hooks->start_source_file) (0, this_input_filename);
+      cpp_stop_forcing_token_locations (parse_in);
+    }
+  else if (cpp_opts->directives_only)
+    cpp_init_special_builtins (parse_in);
 
-      /* Handle -imacros after -D and -U.  */
-      for (i = 0; i < deferred_count; i++)
-       {
-         struct deferred_opt *opt = &deferred_opts[i];
+  /* Start the main input file, if the debug writer wants it. */
+  if (debug_hooks->start_end_main_source_file
+      && !flag_preprocess_only)
+    (*debug_hooks->start_source_file) (0, this_input_filename);
 
-         if (opt->code == OPT_imacros
-             && cpp_push_include (parse_in, opt->arg))
-           {
-             /* Disable push_command_line_include callback for now.  */
-             include_cursor = deferred_count + 1;
-             cpp_scan_nooutput (parse_in);
-           }
-       }
-    }
-  else
-    {
-      if (cpp_opts->directives_only)
-       cpp_init_special_builtins (parse_in);
+  if (!cpp_opts->preprocessed)
+    /* Handle -imacros after -D and -U.  */
+    for (size_t i = 0; i < deferred_count; i++)
+      {
+       struct deferred_opt *opt = &deferred_opts[i];
 
-      /* Start the main input file, if the debug writer wants it. */
-      if (debug_hooks->start_end_main_source_file
-         && !flag_preprocess_only)
-       (*debug_hooks->start_source_file) (0, this_input_filename);
-    }
+       if (opt->code == OPT_imacros
+           && cpp_push_include (parse_in, opt->arg))
+         {
+           /* Disable push_command_line_include callback for now.  */
+           include_cursor = deferred_count + 1;
+           cpp_scan_nooutput (parse_in);
+         }
+      }
 
   include_cursor = 0;
   push_command_line_include ();
@@ -1422,9 +1548,15 @@ push_command_line_include (void)
       include_cursor++;
       /* -Wunused-macros should only warn about macros defined hereafter.  */
       cpp_opts->warn_unused_macros = cpp_warn_unused_macros;
-      /* Restore the line map from <command line>.  */
+      /* Restore the line map back to the main file.  */
       if (!cpp_opts->preprocessed)
-       cpp_change_file (parse_in, LC_RENAME, this_input_filename);
+       {
+         cpp_change_file (parse_in, LC_RENAME, this_input_filename);
+         if (lang_hooks.preprocess_main_file)
+           /* We're starting the main file.  Inform the FE of that.  */
+           lang_hooks.preprocess_main_file
+             (parse_in, line_table, LINEMAPS_LAST_ORDINARY_MAP (line_table));
+       }
 
       /* Set this here so the client can change the option if it wishes,
         and after stacking the main file so we don't trace the main file.  */
@@ -1434,14 +1566,19 @@ push_command_line_include (void)
 
 /* File change callback.  Has to handle -include files.  */
 static void
-cb_file_change (cpp_reader * ARG_UNUSED (pfile),
-               const line_map_ordinary *new_map)
+cb_file_change (cpp_reader *reader, const line_map_ordinary *new_map)
 {
   if (flag_preprocess_only)
     pp_file_change (new_map);
   else
     fe_file_change (new_map);
 
+  if (new_map && cpp_opts->preprocessed
+      && lang_hooks.preprocess_main_file && MAIN_FILE_P (new_map)
+      && ORDINARY_MAP_STARTING_LINE_NUMBER (new_map))
+    /* We're starting the main file.  Inform the FE of that.  */
+    lang_hooks.preprocess_main_file (reader, line_table, new_map);
+
   if (new_map 
       && (new_map->reason == LC_ENTER || new_map->reason == LC_RENAME))
     {
@@ -1480,6 +1617,7 @@ set_std_c89 (int c94, int iso)
   flag_isoc94 = c94;
   flag_isoc99 = 0;
   flag_isoc11 = 0;
+  flag_isoc2x = 0;
   lang_hooks.name = "GNU C89";
 }
 
@@ -1491,6 +1629,7 @@ set_std_c99 (int iso)
   flag_no_asm = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
+  flag_isoc2x = 0;
   flag_isoc11 = 0;
   flag_isoc99 = 1;
   flag_isoc94 = 1;
@@ -1505,12 +1644,44 @@ set_std_c11 (int iso)
   flag_no_asm = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
+  flag_isoc2x = 0;
   flag_isoc11 = 1;
   flag_isoc99 = 1;
   flag_isoc94 = 1;
   lang_hooks.name = "GNU C11";
 }
 
+/* Set the C 17 standard (without GNU extensions if ISO).  */
+static void
+set_std_c17 (int iso)
+{
+  cpp_set_lang (parse_in, iso ? CLK_STDC17: CLK_GNUC17);
+  flag_no_asm = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_iso = iso;
+  flag_isoc2x = 0;
+  flag_isoc11 = 1;
+  flag_isoc99 = 1;
+  flag_isoc94 = 1;
+  lang_hooks.name = "GNU C17";
+}
+
+/* Set the C 2X standard (without GNU extensions if ISO).  */
+static void
+set_std_c2x (int iso)
+{
+  cpp_set_lang (parse_in, iso ? CLK_STDC2X: CLK_GNUC2X);
+  flag_no_asm = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_iso = iso;
+  flag_isoc2x = 1;
+  flag_isoc11 = 1;
+  flag_isoc99 = 1;
+  flag_isoc94 = 1;
+  lang_hooks.name = "GNU C2X";
+}
+
+
 /* Set the C++ 98 standard (without GNU extensions if ISO).  */
 static void
 set_std_cxx98 (int iso)
@@ -1519,6 +1690,8 @@ set_std_cxx98 (int iso)
   flag_no_gnu_keywords = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
+  flag_isoc94 = 0;
+  flag_isoc99 = 0;
   cxx_dialect = cxx98;
   lang_hooks.name = "GNU C++98";
 }
@@ -1538,7 +1711,7 @@ set_std_cxx11 (int iso)
   lang_hooks.name = "GNU C++11";
 }
 
-/* Set the C++ 2014 draft standard (without GNU extensions if ISO).  */
+/* Set the C++ 2014 standard (without GNU extensions if ISO).  */
 static void
 set_std_cxx14 (int iso)
 {
@@ -1546,29 +1719,45 @@ set_std_cxx14 (int iso)
   flag_no_gnu_keywords = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
-  /* C++11 includes the C99 standard library.  */
+  /* C++14 includes the C99 standard library.  */
   flag_isoc94 = 1;
   flag_isoc99 = 1;
   cxx_dialect = cxx14;
   lang_hooks.name = "GNU C++14";
 }
 
-/* Set the C++ 201z draft standard (without GNU extensions if ISO).  */
+/* Set the C++ 2017 standard (without GNU extensions if ISO).  */
 static void
-set_std_cxx1z (int iso)
+set_std_cxx17 (int iso)
 {
-  cpp_set_lang (parse_in, iso ? CLK_CXX1Z: CLK_GNUCXX1Z);
+  cpp_set_lang (parse_in, iso ? CLK_CXX17: CLK_GNUCXX17);
   flag_no_gnu_keywords = iso;
   flag_no_nonansi_builtin = iso;
   flag_iso = iso;
-  /* C++11 includes the C99 standard library.  */
+  /* C++17 includes the C11 standard library.  */
+  flag_isoc94 = 1;
+  flag_isoc99 = 1;
+  flag_isoc11 = 1;
+  cxx_dialect = cxx17;
+  lang_hooks.name = "GNU C++17";
+}
+
+/* Set the C++ 2020 standard (without GNU extensions if ISO).  */
+static void
+set_std_cxx20 (int iso)
+{
+  cpp_set_lang (parse_in, iso ? CLK_CXX20: CLK_GNUCXX20);
+  flag_no_gnu_keywords = iso;
+  flag_no_nonansi_builtin = iso;
+  flag_iso = iso;
+  /* C++17 includes the C11 standard library.  */
   flag_isoc94 = 1;
   flag_isoc99 = 1;
-  /* Enable concepts by default. */
-  flag_concepts = 1;
   flag_isoc11 = 1;
-  cxx_dialect = cxx1z;
-  lang_hooks.name = "GNU C++14"; /* Pretend C++14 till standarization.  */
+  /* C++20 includes coroutines. */
+  flag_coroutines = true;
+  cxx_dialect = cxx20;
+  lang_hooks.name = "GNU C++20";
 }
 
 /* Args to -d specify what to dump.  Silently ignore