re PR c++/24924 (front end and preprocessor pedantic_errors settings should agree)
authorManuel López-Ibáñez <manu@gcc.gnu.org>
Sun, 2 Mar 2008 15:45:29 +0000 (15:45 +0000)
committerManuel López-Ibáñez <manu@gcc.gnu.org>
Sun, 2 Mar 2008 15:45:29 +0000 (15:45 +0000)
2008-03-02  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>

PR 24924
* c-common.c (flag_permissive): Delete.
(constant_expression_warnings): Check flags first.
(constant_expression_error): New.
* c-common.h (flag_permissive): Delete.
(constant_expression_error): Declare.
* flags.h (flag_permissive): Declare. Update description.
* diagnostic.c (pedwarn): Update.
(permerror): New.
* diagnostic.h: (pedantic_error_kind): Rename as pedantic_warning_kind.
(permissive_error_kind): New.
* toplev.c (flag_permissive): Define. Update description.
* toplev.h (permissive_error_kind): Declare.
* c-errors.c (pedwarn_c99): Use pedantic_warning_kind.
(pedwarn_c90): Use pedantic_warning_kind.
* c-opts.c (c_common_post_options): flag_permissive does not affect
flag_pedantic_errors.
cp/
* class.c (finish_struct_anon): Use permerror instead of pedwarn.
(check_field_decls): Likewise.
(note_name_declared_in_class): Likewise.
* call.c (build_new_op): Likewise.
(convert_like_real): Likewise.
(build_over_call): Likewise.
* lex.c (unqualified_fn_lookup_error): Likewise.
* parser.c (cp_parser_template_id): Likewise.
* cvt.c (warn_ref_binding): Likewise.
(convert_to_reference): Likewise.
(ocp_convert): Likewise.
(convert_to_void): Use error instead of pedwarn.
* error.c (cp_cpp_error): Use pedantic_warning_kind.
* decl.c (compute_array_index_type): Use constant_expression_error.
testsuite/
* g++.dg/cpp/string-2.C: This is a warning now.
* g++.dg/cpp/pedantic-errors.C: -pedantic-errors is not enabled by
default, so add it.

From-SVN: r132817

21 files changed:
gcc/ChangeLog
gcc/c-common.c
gcc/c-common.h
gcc/c-errors.c
gcc/c-opts.c
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/error.c
gcc/cp/lex.c
gcc/cp/parser.c
gcc/diagnostic.c
gcc/diagnostic.h
gcc/flags.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp/pedantic-errors.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp/string-2.C
gcc/toplev.c
gcc/toplev.h

index 41e35e298a71b42a6d1b71f7281f611b88f8f65d..c2200cb0a3a7c05a1482e7480ccb4d4045b4eb52 100644 (file)
@@ -1,3 +1,23 @@
+2008-03-02  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
+
+       PR 24924
+       * c-common.c (flag_permissive): Delete.
+       (constant_expression_warnings): Check flags first.
+       (constant_expression_error): New.
+       * c-common.h (flag_permissive): Delete.
+       (constant_expression_error): Declare.
+       * flags.h (flag_permissive): Declare. Update description.
+       * diagnostic.c (pedwarn): Update.
+       (permerror): New.
+       * diagnostic.h: (pedantic_error_kind): Rename as pedantic_warning_kind.
+       (permissive_error_kind): New.
+       * toplev.c (flag_permissive): Define. Update description.
+       * toplev.h (permissive_error_kind): Declare.
+       * c-errors.c (pedwarn_c99): Use pedantic_warning_kind.
+       (pedwarn_c90): Use pedantic_warning_kind.
+       * c-opts.c (c_common_post_options): flag_permissive does not affect
+       flag_pedantic_errors.
+
 2008-03-02  Joseph Myers  <joseph@codesourcery.com>
 
        * libgcc2.c (__addvSI3, __addvsi3, __addvDI3, __subvSI3,
index 9706d874456137251b73e31407319accbd247a7a..f3de12a7359611c1498178cd2540a24299533388 100644 (file)
@@ -443,11 +443,6 @@ int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
 
 int flag_use_cxa_get_exception_ptr = 2;
 
-/* Nonzero means make the default pedwarns warnings instead of errors.
-   The value of this flag is ignored if -pedantic is specified.  */
-
-int flag_permissive;
-
 /* Nonzero means to implement standard semantics for exception
    specifications, calling unexpected if an exception is thrown that
    doesn't match the specification.  Zero means to treat them as
@@ -926,15 +921,26 @@ fix_string_type (tree value)
 
 void
 constant_expression_warning (tree value)
+{
+  if (warn_overflow && pedantic 
+      && (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
+         || TREE_CODE (value) == FIXED_CST
+         || TREE_CODE (value) == VECTOR_CST
+         || TREE_CODE (value) == COMPLEX_CST)
+      && TREE_OVERFLOW (value))
+    pedwarn ("overflow in constant expression");
+}
+
+/* The same as above but print an unconditional error.  */
+void
+constant_expression_error (tree value)
 {
   if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
        || TREE_CODE (value) == FIXED_CST
        || TREE_CODE (value) == VECTOR_CST
        || TREE_CODE (value) == COMPLEX_CST)
-      && TREE_OVERFLOW (value)
-      && warn_overflow
-      && pedantic)
-    pedwarn ("overflow in constant expression");
+      && TREE_OVERFLOW (value))
+    error ("overflow in constant expression");
 }
 
 /* Print a warning if an expression had overflow in folding and its
index 99209c71ce39e287daf67a1c03a81ecb0c01c936..a072710c9ab6fcecac3290003d5c2b9423bee568 100644 (file)
@@ -584,11 +584,6 @@ extern int flag_use_cxa_atexit;
 
 extern int flag_use_cxa_get_exception_ptr;
 
-/* Nonzero means make the default pedwarns warnings instead of errors.
-   The value of this flag is ignored if -pedantic is specified.  */
-
-extern int flag_permissive;
-
 /* Nonzero means to implement standard semantics for exception
    specifications, calling unexpected if an exception is thrown that
    doesn't match the specification.  Zero means to treat them as
@@ -688,6 +683,7 @@ extern void binary_op_error (enum tree_code, tree, tree);
 extern tree fix_string_type (tree);
 struct varray_head_tag;
 extern void constant_expression_warning (tree);
+extern void constant_expression_error (tree);
 extern bool strict_aliasing_warning (tree, tree, tree);
 extern void empty_if_body_warning (tree, tree);
 extern void warnings_for_convert_and_check (tree, tree, tree);
index c85d397833015b5fa943c3b9b50358ac65bdb7e4..dc47b764f39c6b6fee4bb8074b031d5aed672e55 100644 (file)
@@ -38,7 +38,7 @@ pedwarn_c99 (const char *gmsgid, ...)
 
   va_start (ap, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location,
-                      flag_isoc99 ? pedantic_error_kind () : DK_WARNING);
+                      flag_isoc99 ? pedantic_warning_kind () : DK_WARNING);
   report_diagnostic (&diagnostic);
   va_end (ap);
 }
@@ -56,7 +56,7 @@ pedwarn_c90 (const char *gmsgid, ...)
 
   va_start (ap, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location,
-                      flag_isoc99 ? DK_WARNING : pedantic_error_kind ());
+                      flag_isoc99 ? DK_WARNING : pedantic_warning_kind ());
   report_diagnostic (&diagnostic);
   va_end (ap);
 }
index d7409adcccc31905bcdf2b4dc49609b8f647a60f..69c4d5448853c245cbf00d01d1436c22b77c94ac 100644 (file)
@@ -1107,18 +1107,6 @@ c_common_post_options (const char **pfilename)
   /* Adjust various flags for C++ based on command-line settings.  */
   if (c_dialect_cxx ())
     {
-      if (!flag_permissive)
-       {
-         flag_pedantic_errors = 1;
-         /* FIXME: For consistency pedantic_errors should have the
-            same value in the front-end and in CPP. However, this
-            will break existing applications. The right fix is
-            disentagle flag_permissive from flag_pedantic_errors,
-            create a new diagnostic function permerror that is
-            controlled by flag_permissive and convert most C++
-            pedwarns to this new function.
-         cpp_opts->pedantic_errors = 1;  */
-       }
       if (!flag_no_inline)
        {
          flag_inline_trees = 1;
index 6f612621e28a4b9ef6e92f94fbec2bba43478a49..3c79d1dd91028f199a4c2928cee0fe75fc31e8c0 100644 (file)
@@ -1,3 +1,21 @@
+2008-03-02  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
+
+       PR 24924
+       * class.c (finish_struct_anon): Use permerror instead of pedwarn.
+       (check_field_decls): Likewise.
+       (note_name_declared_in_class): Likewise.
+       * call.c (build_new_op): Likewise.
+       (convert_like_real): Likewise.
+       (build_over_call): Likewise.
+       * lex.c (unqualified_fn_lookup_error): Likewise.
+       * parser.c (cp_parser_template_id): Likewise.
+       * cvt.c (warn_ref_binding): Likewise.
+       (convert_to_reference): Likewise.
+       (ocp_convert): Likewise.
+       (convert_to_void): Use error instead of pedwarn.
+       * error.c (cp_cpp_error): Use pedantic_warning_kind.
+       * decl.c (compute_array_index_type): Use constant_expression_error.
+       
 2008-03-01  Douglas Gregor  <doug.gregor@gmail.com>
 
        * parser.c (cp_lexer_next_token_is_decl_specifier_keyword): Note
index a61638cfe458cb8cd705025b7209bec8c3e39933..2ee82371f68baaf7674eef58bf5de1f29ebde1a0 100644 (file)
@@ -3857,10 +3857,10 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
          /* Look for an `operator++ (int)'.  If they didn't have
             one, then we fall back to the old way of doing things.  */
          if (flags & LOOKUP_COMPLAIN)
-           pedwarn ("no %<%D(int)%> declared for postfix %qs, "
-                    "trying prefix operator instead",
-                    fnname,
-                    operator_name_info[code].name);
+           permerror ("no %<%D(int)%> declared for postfix %qs, "
+                      "trying prefix operator instead",
+                      fnname,
+                      operator_name_info[code].name);
          if (code == POSTINCREMENT_EXPR)
            code = PREINCREMENT_EXPR;
          else
@@ -4343,9 +4343,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
          else if (t->kind == ck_identity)
            break;
        }
-      pedwarn ("invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
+      permerror ("invalid conversion from %qT to %qT", TREE_TYPE (expr), totype);
       if (fn)
-       pedwarn ("  initializing argument %P of %qD", argnum, fn);
+       permerror ("  initializing argument %P of %qD", argnum, fn);
       return cp_convert (totype, expr);
     }
 
@@ -4955,7 +4955,7 @@ build_over_call (struct z_candidate *cand, int flags)
       tree base_binfo;
 
       if (convs[i]->bad_p)
-       pedwarn ("passing %qT as %<this%> argument of %q#D discards qualifiers",
+       permerror ("passing %qT as %<this%> argument of %q#D discards qualifiers",
                 TREE_TYPE (argtype), fn);
 
       /* [class.mfct.nonstatic]: If a nonstatic member function of a class
index 1a76816c2294c445a559eab0547d729b740db117..500ddaac635b3780d5f094b1f98f1ebc74319f9f 100644 (file)
@@ -2493,27 +2493,27 @@ finish_struct_anon (tree t)
              if (TREE_CODE (elt) != FIELD_DECL)
                {
                  if (is_union)
-                   pedwarn ("%q+#D invalid; an anonymous union can "
-                            "only have non-static data members", elt);
+                   permerror ("%q+#D invalid; an anonymous union can "
+                              "only have non-static data members", elt);
                  else
-                   pedwarn ("%q+#D invalid; an anonymous struct can "
-                            "only have non-static data members", elt);
+                   permerror ("%q+#D invalid; an anonymous struct can "
+                              "only have non-static data members", elt);
                  continue;
                }
 
              if (TREE_PRIVATE (elt))
                {
                  if (is_union)
-                   pedwarn ("private member %q+#D in anonymous union", elt);
+                   permerror ("private member %q+#D in anonymous union", elt);
                  else
-                   pedwarn ("private member %q+#D in anonymous struct", elt);
+                   permerror ("private member %q+#D in anonymous struct", elt);
                }
              else if (TREE_PROTECTED (elt))
                {
                  if (is_union)
-                   pedwarn ("protected member %q+#D in anonymous union", elt);
+                   permerror ("protected member %q+#D in anonymous union", elt);
                  else
-                   pedwarn ("protected member %q+#D in anonymous struct", elt);
+                   permerror ("protected member %q+#D in anonymous struct", elt);
                }
 
              TREE_PRIVATE (elt) = TREE_PRIVATE (field);
@@ -3044,7 +3044,7 @@ check_field_decls (tree t, tree *access_decls,
         user-defined constructor.  */
       if (constructor_name_p (DECL_NAME (x), t)
          && TYPE_HAS_USER_CONSTRUCTOR (t))
-       pedwarn ("field %q+#D with same name as class", x);
+       permerror ("field %q+#D with same name as class", x);
 
       /* We set DECL_C_BIT_FIELD in grokbitfield.
         If the type and width are valid, we'll also set DECL_BIT_FIELD.  */
@@ -6072,10 +6072,10 @@ resolve_address_of_overloaded_function (tree target_type,
       if (!(flags & tf_error))
        return error_mark_node;
 
-      pedwarn ("assuming pointer to member %qD", fn);
+      permerror ("assuming pointer to member %qD", fn);
       if (!explained)
        {
-         pedwarn ("(a pointer to member can only be formed with %<&%E%>)", fn);
+         inform ("(a pointer to member can only be formed with %<&%E%>)", fn);
          explained = 1;
        }
     }
@@ -6435,8 +6435,8 @@ note_name_declared_in_class (tree name, tree decl)
         A name N used in a class S shall refer to the same declaration
         in its context and when re-evaluated in the completed scope of
         S.  */
-      pedwarn ("declaration of %q#D", decl);
-      pedwarn ("changes meaning of %qD from %q+#D",
+      permerror ("declaration of %q#D", decl);
+      permerror ("changes meaning of %qD from %q+#D",
               DECL_NAME (OVL_CURRENT (decl)), (tree) n->value);
     }
 }
index a75036f53c115353bcc1d9d41a5dd14517a52efd..ee5759d6b4f18d33ef6b8951c5ca90405b0a4947 100644 (file)
@@ -379,7 +379,7 @@ warn_ref_binding (tree reftype, tree intype, tree decl)
          msg = "conversion to non-const reference type %q#T from"
            " rvalue of type %qT";
 
-      pedwarn (msg, reftype, intype);
+      permerror (msg, reftype, intype);
     }
 }
 
@@ -449,8 +449,8 @@ convert_to_reference (tree reftype, tree expr, int convtype,
 
          if (! (convtype & CONV_CONST)
                   && !at_least_as_qualified_p (ttl, ttr))
-           pedwarn ("conversion from %qT to %qT discards qualifiers",
-                    ttr, reftype);
+           permerror ("conversion from %qT to %qT discards qualifiers",
+                      ttr, reftype);
        }
 
       return build_up_reference (reftype, expr, flags, decl);
@@ -646,9 +646,9 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
              || TREE_CODE (intype) == POINTER_TYPE))
        {
          if (flags & LOOKUP_COMPLAIN)
-           pedwarn ("conversion from %q#T to %q#T", intype, type);
+           permerror ("conversion from %q#T to %q#T", intype, type);
 
-         if (flag_pedantic_errors)
+         if (!flag_permissive)
            return error_mark_node;
        }
       if (IS_AGGR_TYPE (intype))
@@ -892,8 +892,8 @@ convert_to_void (tree expr, const char *implicit)
       {
        /* [over.over] enumerates the places where we can take the address
           of an overloaded function, and this is not one of them.  */
-       pedwarn ("%s cannot resolve address of overloaded function",
-                   implicit ? implicit : "void cast");
+       error ("%s cannot resolve address of overloaded function",
+              implicit ? implicit : "void cast");
        expr = void_zero_node;
       }
     else if (implicit && probe == expr && is_overloaded_fn (probe))
index 99078e42edaea1e63f277e978b3d13ef22c0413c..32a0db820ce8b583e6063b450e959302c6173180 100644 (file)
@@ -7028,12 +7028,7 @@ compute_array_index_type (tree name, tree size)
     {
       /* Check to see if the array bound overflowed.  Make that an
         error, no matter how generous we're being.  */
-      int old_flag_pedantic_errors = flag_pedantic_errors;
-      int old_pedantic = pedantic;
-      pedantic = flag_pedantic_errors = 1;
-      constant_expression_warning (size);
-      pedantic = old_pedantic;
-      flag_pedantic_errors = old_flag_pedantic_errors;
+      constant_expression_error (size);
 
       /* An array must have a positive number of elements.  */
       if (INT_CST_LT (size, integer_zero_node))
index 0893f801565d7488660667c9d3b643f7751c5736..97a1785019558772466cf33717dbbe75c13acb7f 100644 (file)
@@ -2651,7 +2651,7 @@ cp_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level,
       dlevel = DK_WARNING;
       break;
     case CPP_DL_PEDWARN:
-      dlevel = pedantic_error_kind ();
+      dlevel = pedantic_warning_kind ();
       break;
     case CPP_DL_ERROR:
       dlevel = DK_ERROR;
index 0b2a37259f4cba292de52b085086edc724958c28..06c0bc2ffe5e66a54e72ff7b2715c92e26190ea8 100644 (file)
@@ -647,16 +647,16 @@ unqualified_fn_lookup_error (tree name)
         Note that we have the exact wording of the following message in
         the manual (trouble.texi, node "Name lookup"), so they need to
         be kept in synch.  */
-      pedwarn ("there are no arguments to %qD that depend on a template "
-              "parameter, so a declaration of %qD must be available",
-              name, name);
+      permerror ("there are no arguments to %qD that depend on a template "
+                "parameter, so a declaration of %qD must be available",
+                name, name);
 
       if (!flag_permissive)
        {
          static bool hint;
          if (!hint)
            {
-             error ("(if you use %<-fpermissive%>, G++ will accept your "
+             inform ("(if you use %<-fpermissive%>, G++ will accept your "
                     "code, but allowing the use of an undeclared name is "
                     "deprecated)");
              hint = true;
index 817a0628987e9c8a91697039b4de67cd612ee4e8..3ffac730a272fed4135e371c55494d31a3c71a31 100644 (file)
@@ -9775,7 +9775,7 @@ cp_parser_template_id (cp_parser *parser,
        }
       /* Otherwise, emit an error about the invalid digraph, but continue
         parsing because we got our argument list.  */
-      pedwarn ("%<<::%> cannot begin a template-argument list");
+      permerror ("%<<::%> cannot begin a template-argument list");
       inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
              "between %<<%> and %<::%>");
       if (!flag_permissive)
index bc4e051b8b5c7d20eb70584f51794da5e5478c92..298890471273fedb7130cca10d306635dd41dfb3 100644 (file)
@@ -544,11 +544,31 @@ pedwarn (const char *gmsgid, ...)
 
   va_start (ap, gmsgid);
   diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location,
-                      pedantic_error_kind ());
+                      pedantic_warning_kind ());
   report_diagnostic (&diagnostic);
   va_end (ap);
 }
 
+/* A "permissive" error: issues an error unless -fpermissive was given
+   on the command line, in which case it issues a warning.  Use this
+   for things that really should be errors but we want to support
+   legacy code.  */
+
+void
+permerror (const char *gmsgid, ...)
+{
+  diagnostic_info diagnostic;
+  va_list ap;
+
+  va_start (ap, gmsgid);
+  diagnostic_set_info (&diagnostic, gmsgid, &ap, input_location,
+                      permissive_error_kind ());
+  diagnostic.option_index = OPT_fpermissive;
+  report_diagnostic (&diagnostic);
+  va_end (ap);
+}
+
+
 /* A hard error: the code is definitely ill-formed, and an object file
    will not be produced.  */
 void
index 992c0c46025056017b0e25bc23cd4b558e6e0109..a249574d4aa432d76f7d8344e992ff7a26641c1e 100644 (file)
@@ -50,7 +50,8 @@ typedef struct diagnostic_info
   int option_index;
 } diagnostic_info;
 
-#define pedantic_error_kind() (flag_pedantic_errors ? DK_ERROR : DK_WARNING)
+#define pedantic_warning_kind() (flag_pedantic_errors ? DK_ERROR : DK_WARNING)
+#define permissive_error_kind() (flag_permissive ? DK_WARNING : DK_ERROR)
 
 
 /*  Forward declarations.  */
index e2041500c149cee314268cdd5cdab96b4819a051..686691c21e07f239ea9f936d6cef57a91a2ef4c9 100644 (file)
@@ -197,6 +197,10 @@ extern int flag_dump_unnumbered;
 
 extern int flag_pedantic_errors;
 
+/* Nonzero means make permerror produce warnings instead of errors.  */
+
+extern int flag_permissive;
+
 /* Nonzero if we are compiling code for a shared library, zero for
    executable.  */
 
index 05b49db777c7fd2cbd8e14fb3a845d5ea5675b3b..b8c03ce38efecbc7b84b49c469a0af2203f11698 100644 (file)
@@ -1,3 +1,10 @@
+2008-03-02  Manuel Lopez-Ibanez  <manu@gcc.gnu.org> 
+
+       PR 24924
+       * g++.dg/cpp/string-2.C: This is a warning now.
+       * g++.dg/cpp/pedantic-errors.C: -pedantic-errors is not enabled by
+       default, so add it.
+       
 2008-03-01  Douglas Gregor  <doug.gregor@gmail.com>
 
        * g++.dg/cpp0x/auto1.C: New.
diff --git a/gcc/testsuite/g++.dg/cpp/pedantic-errors.C b/gcc/testsuite/g++.dg/cpp/pedantic-errors.C
new file mode 100644 (file)
index 0000000..1684749
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do preprocess } */
+/* { dg-options "-std=c++98 -pedantic-errors" } */
+
+#if 1   
+#endif 1 /* { dg-error "error: extra tokens at end of #endif directive" } */
index b947c73eea479d7cbbb94e5afea179f5b3bb68b8..137c3de1931ac7c2734a3e85f7ca86f901dbc13f 100644 (file)
@@ -1,7 +1,6 @@
-// Test diagnostics for interpreting strings: should be an error by
-// default.
+// Test diagnostics for interpreting strings: This is a pedwarn.
 // Origin: Joseph Myers <joseph@codesourcery.com>
 // { dg-do compile }
 // { dg-options "" }
 
-const char *s = "\q"; // { dg-error "error: unknown escape sequence" }
+const char *s = "\q"; // { dg-warning "warning: unknown escape sequence" }
index 5b1600cfeffddca510fbb2b40e08d7313b99a7d9..58c19c5d37db1b5d85cfed517b0d2cc4ddc627ae 100644 (file)
@@ -281,6 +281,10 @@ enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC;
 
 int flag_pedantic_errors = 0;
 
+/* Nonzero means make permerror produce warnings instead of errors.  */
+
+int flag_permissive = 0;
+
 /* -dA causes debug commentary information to be produced in
    the generated assembly code (to make it more readable).  This option
    is generally only of use to those who actually need to read the
index 26a085d0c842963b697ac49113e1ca142c77ac6b..45e464680ff13458e035e40ad18e9f9185c659c4 100644 (file)
@@ -62,6 +62,7 @@ extern void error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern void fatal_error (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2)
      ATTRIBUTE_NORETURN;
 extern void pedwarn (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
+extern void permerror (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern void sorry (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern void inform (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);
 extern void verbatim (const char *, ...) ATTRIBUTE_GCC_DIAG(1,2);