Warnings in the C++ Front-End and GCC in General

Mark Mitchell mark@markmitchell.com
Mon Sep 7 04:07:00 GMT 1998


First, two prefatory notes:

  o This message is being sent to both egcs and egcs-patches.  The
    reason is that while it *is* a patch, it is also about a topic
    that bears more general discussion amongst GCC users as well as
    GCC developers.  Therefore, if you are a GCC user, you should 
    read on, stopping when the discussion of the actual changes
    begins.

  o This message does not contain the complete patch checked in to the
    C++ front-end.  The reason is that the patch is very large, and
    much of it is very repetitive.  Therefore, only the "interesting"
    portions, and representative samples of the "boring" pieces, are
    included.  You should *not* try to apply this patch to your
    source-tree, as you will not get the complete set of changes.

This patch addresses a long-standing need in GCC: the ability to
disable individual warnings.  Until now, we have had the coarse
-W/-Wall/-w switches, and the -Wno- switches for controlling certain
categories of warnings.  However, some warnings have not been under
the control of individual switches.  In fact, it does not make sense
to add individual switches for each of the literally hundreds
(thousands?) of diagnostics GCC can issue!

But, never-the-less, their are indeed situations where one would like
to disable a particular warning, without disabling all warnings.
Sometimes the warning is badly designed; at other times it is
well-designed, but, for whatever reason, you have written code that
causes it to complain (unjustly).  One such occasion is in header
files; you would like clients to be able to include a header file
using any warning option they like, but you may have to use constructs
about which GCC would normally warn.

This patch provides, for every C++ warning/error message, a unique
number.  You can see the numbers for diagnostics by using -fdiag-codes
when compiling.  You can disable a warning on a translation unit by
translation unit basis with -Wno-number-N where N is the number of the
warning.  For example, this C++ program:

  class C {
    C();
  };

yields

  test.C:3: warning: [62] all member functions in class `C' are private

when copmiled with -fdiag-codes.  (Without -fdiag-codes the `[62]' is
omitted.)  Compiling with `-fdiag-codes -Wno-number-62' disables the
warning.

As of yet, there is no way to turn off warnings in a particular block
of code, although this was the main motivation for this work.  The
reason is that I believe the logical way to do this is via `#pragma',
e.g.:
   
  #pragma gcc_diable_warn (62)
  ...
  #pragma gcc_enable_warn (62)

However, I did *not* implement this (although it will now be trivial),
because GCC has traditionally eschewed #pragma.  In fact, the GCC
manual says:

  It is basically a mistake to use `#pragma' for *anything*.

I believe this to be an over-statement.  For this particular
situation, I think `#pragma' is the way to go.  If I do not hear
violent disagreement in the next few days, I will go ahead and
implement this.

The following section discusses GCC internals, and is not important if
you are a GCC user, bot not a developer.

This patch collects the various error messages together in a single
file, and provides enumeration constants corresponding to each one.
(Not really very revolutionary, that.)  This should make
internatiationalization of the messages easier, should anyone care to
do so.

One interesting feature (basically unused at this point) is that
various warnings can be marked as equivalent.  (See cp-error.def for
how to do this).  Thus, in a message like:

   warning: `f' is bad.  You maybe meant one of:
   warning:   `g'
   warning:   `h'

all the messages can be given the same code, so that they can all be
disabled with one fell swoop.  Similarly, we could mark all `pointer
arithmetic' messages as equivalent, and then make -Wpointer-arith
synonymous with some -Wnumber-X for appropriate X.

Although the patch provided here works only on the C++ front-end, the
general mechanism could be extended to the other front-ends and the
back-end as well.  The conversion can be largely automated; I have the
elisp that I used for the C++ front-end, and am happy to share it with
anyone who is interested.  Ideally, I think we should use these
mechanisms universally.

Doing so would require:

  o Extending the main error/warning functions with the ability to 
    call a language-dependent hook to do some format substitutions.
    (For example the C++ front-end's cp_error function uses 
     `%D' as a format specifier for a declaration.)  Doing just this
    would be backward-compatible; we wouldn't have to make any other
    changes. 

  o Move the warning enabling/disabling and code-printing code
    to GCC, from the G++ front-end.  If we create new error-handling
    routines (error_with_code, warning_with_code, etc.) at this point, 
    this is still backward-compatible.  At first, only the C++
    front-end would use the new interface.

  o Convert everything else to use error_code's rather than format
    strings.  (This is where the elisp comes in handy, and could be
    done a file at a time.)

I have little intention of tackling al of this time-consuming, and
somewhat tedious task; my motivation was C++-specific.  But, I
endeavored to make the mechanism general, and I'd be happy to help
anyone who was interested.  I would be willing to do steps 1 and 2
above, if Jeff agrees that this is a reasonable approach.  Step 3 task
is something that could, in my opinion, be tackled by a motivated and
careful volunteer with little knowledge of GCC internals.

Here are the changes.  See the decl2.c diffs to see how cp_error and
friends are now called.  Corresponding changes for the other files are
omitted.  The C++ front-end now makes almost no direct calls to the
GCC warning/error functions; the only calls to those functions come
from errfn.c, after the C++-specific formatting has been accomplished.

-- 
Mark Mitchell 			mark@markmitchell.com
Mark Mitchell Consulting	http://www.markmitchell.com

1998-09-06  Mark Mitchell  <mark@markmitchell.com>

	* cp-error.def: New file.
	* Make-lang.in (cc1plus): Add dependency on it.
	* Makefile.in (CXX_TREE_H): Likewise.
	* cp-tree.h (error_code): New type.
	Include cp-error.def to get error codes.  Make it possible to
	include cp-tree.h in errfn.c.
	(enable_warning): New function.
	(flag_diag_codes): New variable.
	* errfn.c: Include cp-tree.h.
	(cp_err_msg): New type.  Include cp-error.def to define it.
	(err_msgs): New variable.
	(is_warning_enabled): New function.
	(cp_thing): Take an error_code, not a format string.  Output the
	diagnostic code if flag_diag_codes.
	(cp_error, cp_compiler_error, cp_sprintf, cp_error_at): Take
	error_codes, not format strings.
	(cp_warning, cp_pedwarn, cp_warning_at, cp_pedwarn_at): Likewise.
	Call is_warning_enabled.
	* decl2.c (flag_diag_codes): New variable.
	(lang_decode_option): Handle -fdiag-codes and -Wnumber.
	* lang-options.h: Add -fdiag-codes, -fno-diag-codes, and
	-W-number-, and -Wno-number.
	
	* class.c: Update all calls to error-functions.
	* cvt.c: Likewise.
	* decl.c: Likewise.
	* decl2.c: Likewise.
	* except.c: Likewise.
	* expr.c: Likewise.
	* friend.c: Likewise.
	* lex.c: Likewise.
	* parse.y: Likewise.
	* pt.c: Likewise.
	* repo.c: Likewise.
	* rtti.c: Likewise.
	* search.c: Likewise.
	* semantics.c: Likewise.
	* sig.c: Likewise.
	* tree.c: Likewise.
	* typeck.c: Likewise.
	* typeck2.c: Likewise.
	* xref.c: Likewise.
	
Index: invoke.texi
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/invoke.texi,v
retrieving revision 1.63
diff -c -p -r1.63 invoke.texi
*** invoke.texi	1998/09/03 16:09:01	1.63
--- invoke.texi	1998/09/07 01:38:22
*************** in the following sections.
*** 108,114 ****
  -fname-mangling-version-@var{n}  -fno-default-inline  
  -fno-gnu-keywords -fnonnull-objects -fguiding-decls
  -foperator-names  -fno-optional-diags -fstrict-prototype  -fthis-is-variable
! -ftemplate-depth-@var{n}  -nostdinc++  -traditional  +e@var{n}
  @end smallexample
  
  @item Warning Options
--- 108,114 ----
  -fname-mangling-version-@var{n}  -fno-default-inline  
  -fno-gnu-keywords -fnonnull-objects -fguiding-decls
  -foperator-names  -fno-optional-diags -fstrict-prototype  -fthis-is-variable
! -ftemplate-depth-@var{n} -fdiag-codes -nostdinc++  -traditional  +e@var{n}
  @end smallexample
  
  @item Warning Options
*************** in the following sections.
*** 129,135 ****
  -Wreturn-type -Wshadow  -Wsign-compare  -Wstrict-prototypes  
  -Wswitch -Wsynth  -Wtemplate-debugging  -Wtraditional  
  -Wtrigraphs -Wundef  -Wuninitialized  -Wunused  -Wwrite-strings
! -Wunknown-pragmas
  @end smallexample
  
  @item Debugging Options
--- 129,135 ----
  -Wreturn-type -Wshadow  -Wsign-compare  -Wstrict-prototypes  
  -Wswitch -Wsynth  -Wtemplate-debugging  -Wtraditional  
  -Wtrigraphs -Wundef  -Wuninitialized  -Wunused  -Wwrite-strings
! -Wunknown-pragmas -Wnumber-@var{n}
  @end smallexample
  
  @item Debugging Options
*************** A limit on the template instantiation de
*** 1165,1170 ****
--- 1165,1183 ----
  endless recursions during template class instantiation. ANSI/ISO C++
  conforming programs must not rely on a maximum depth greater than 17.
  
+ @item -fdiag-codes
+ When printing a diagnostic, also print the corresponding diagnostic
+ code.  The code is printed in square brackets, before the message
+ itself.  For example, you might see something like:
+ 
+ @smallexample
+ test.C:3: warning: [62] all member functions in class `C' are private
+ @end smallexample
+ 
+ which indicates that this is warning number 62.  Some diagnostics do not
+ (yet) have corresponding code numbers.  This option is useful in
+ conjuction with @samp{-Wnumber-@var{n}}.
+ 
  @item -nostdinc++
  Do not search for header files in the standard directories specific to
  C++, but do still search the other standard directories.  (This option
*************** Do not assume @samp{inline} for function
*** 1189,1194 ****
--- 1202,1208 ----
  @item -Wold-style-cast
  @itemx -Woverloaded-virtual
  @itemx -Wtemplate-debugging
+ @itemx -Wnumber-@var{n}
  Warnings that apply only to C++ programs.  @xref{Warning
  Options,,Options to Request or Suppress Warnings}.
  
*************** conformant compiler code but disables th
*** 1696,1701 ****
--- 1710,1720 ----
  @item -Winline
  Warn if a function can not be inlined, and either it was declared as inline,
  or else the @samp{-finline-functions} option was given.
+ 
+ @item -Wnumber-@var{n} (C++ only)
+ Enable warning number @var{n}.  (Or, more often, with
+ @samp{-Wno-number-@var{n}}, disable that warning.)  To obtain the
+ appropriate numbers, use @samp{-fdiag-codes}.
  
  @item -Wold-style-cast
  Warn if an old-style (C-style) cast is used within a program.
Index: testsuite/g++.old-deja/g++.other/warn2.C
===================================================================
RCS file: warn2.C
diff -N warn2.C
*** /dev/null	Mon Dec 31 20:00:00 1979
--- warn2.C	Sun Sep  6 18:25:27 1998
***************
*** 0 ****
--- 1,6 ----
+ // Build don't link:
+ // Special g++ Options: -Wno-number-62
+ 
+ class C {
+   C();
+ };
Index: cp/Make-lang.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Make-lang.in,v
retrieving revision 1.17
diff -c -p -r1.17 Make-lang.in
*** Make-lang.in	1998/08/17 11:42:20	1.17
--- Make-lang.in	1998/09/07 01:26:13
*************** CXX_SRCS = $(srcdir)/cp/call.c $(srcdir)
*** 125,131 ****
   $(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
  
  cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
! 	$(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def
  	cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext)
  #
  # Build hooks:
--- 125,131 ----
   $(srcdir)/cp/repo.c $(srcdir)/cp/semantics.c
  
  cc1plus$(exeext): $(P) $(CXX_SRCS) $(LIBDEPS) stamp-objlist c-common.o c-pragma.o \
! 	$(srcdir)/cp/cp-tree.h $(srcdir)/cp/cp-tree.def $(srcdir)/cp/cp-error.def
  	cd cp; $(MAKE) $(FLAGS_TO_PASS) $(CXX_FLAGS_TO_PASS) ../cc1plus$(exeext)
  #
  # Build hooks:
Index: cp/Makefile.in
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/Makefile.in,v
retrieving revision 1.33
diff -c -p -r1.33 Makefile.in
*** Makefile.in	1998/09/05 23:02:22	1.33
--- Makefile.in	1998/09/07 01:26:14
*************** RTL_H = $(srcdir)/../rtl.h $(srcdir)/../
*** 208,214 ****
  	$(srcdir)/../machmode.h $(srcdir)/../machmode.def
  TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \
  	$(srcdir)/../machmode.h $(srcdir)/../machmode.def
! CXX_TREE_H = $(TREE_H) cp-tree.h cp-tree.def
  PARSE_H = $(srcdir)/parse.h
  PARSE_C = $(srcdir)/parse.c
  EXPR_H = $(srcdir)/../expr.h ../insn-codes.h
--- 208,214 ----
  	$(srcdir)/../machmode.h $(srcdir)/../machmode.def
  TREE_H = $(srcdir)/../tree.h $(srcdir)/../real.h $(srcdir)/../tree.def \
  	$(srcdir)/../machmode.h $(srcdir)/../machmode.def
! CXX_TREE_H = $(TREE_H) cp-tree.h cp-tree.def cp-error.def
  PARSE_H = $(srcdir)/parse.h
  PARSE_C = $(srcdir)/parse.c
  EXPR_H = $(srcdir)/../expr.h ../insn-codes.h
Index: cp/cp-error.def
===================================================================
RCS file: cp-error.def
diff -N cp-error.def
*** /dev/null	Mon Dec 31 20:00:00 1979
--- cp-error.def Sun Sep  6 18:41:14 1998
***************
*** 0 ****
--- 1,2469 ----
+ /* C++ error messages.
+    Copyright (C) 1998 Free Software Foundation, Inc.
+    Written by Mark Mitchell (mark@markmitchell.com)
+ 
+    This file is part of GNU CC.
+    
+    GNU CC is free software; you can redistribute it and/or modify it
+    under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2, or (at your option)
+    any later version.
+    
+    GNU CC is distributed in the hope that it will be useful, but
+    WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    General Public License for more details.
+    
+    You should have received a copy of the GNU General Public License
+    along with GNU CC; see the file COPYING.  If not, write to the Free
+    Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+    02111-1307, USA.  */
+ 
+ /* This file contains descriptions for the warning and error messages
+    issued by the C++ front-end.  Each message is defined by the use of 
+    the DEFERROR macro.  There are two arguments to this macro.  The
+    first is the "code" for the macro.  These codes become enumeration
+    constants of the enumeration type cp_error_code defined in
+    cp-tree.h.  The second argument is the message text itself, which
+    may contain the format specifiers (like "%D") handled by cp_thing. 
+ 
+    Some messages are defined with the DEFERRORNUM macro.  The first
+    two arguments to this macro are as for DEFERROR, but the third
+    argument is a code for another error.  The implication is that the
+    new error is "the same as" the previous error; i.e., that turning
+    off one should turn off both.  There's no point in using this for
+    messages that are always errors; those messages will always be
+    emitted.
+ 
+    Users may control what warnings are emitted by use by numeric codes
+    assigned automatically to the error messages.  Therefore, when an
+    error message is removed, it should *not* be removed from this
+    list.  (That will change the numeric codes assigned to all
+    subsequent error messages).  Instead, just make the string the
+    constant 0; this will automatically cause an internal error if that
+    error code is ever used again.  It is also safe to change the name
+    of the code, as you see fit.  Similarly, you should *not* insert
+    new error codes in the middle of this list; only at the end.
+ 
+    There is no need to have separate message codes if the same message
+    is used as an error in some places and as a warning in others.  It
+    is the use of cp_error vs. cp_warning vs ... that makes that
+    distinction.  
+ 
+    Be careful when introducing new format specifiers into an error
+    message that you change all uses of that error code, and not just
+    the one you are looking at.  The same error code may be used in
+    multiple places.  */
+ 
+ DEFERROR(ec_this_has_no_member_named,
+ 	 "`this' has no member named `%D'")
+ DEFERROR(ec_qualified_type_does_not_match_destructor_name,
+ 	 "qualified type `%T' does not match destructor name `~%T'")
+ DEFERROR(ec_type_of_does_not_match_destructor_type_type_was,
+ 	 "type of `%E' does not match destructor type `%T' (type was `%T')")
+ DEFERROR(ec_base_object_of_scoped_method_call_is_of_nonaggregate_type,
+ 	 "base object `%E' of scoped method call is of non-aggregate type `%T'")

< Lots more DEFERRORs omitted>

Index: cp/cp-tree.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/cp-tree.h,v
retrieving revision 1.134
diff -c -p -r1.134 cp-tree.h
*** cp-tree.h	1998/09/05 20:14:13	1.134
--- cp-tree.h	1998/09/07 01:26:54
*************** enum cplus_tree_code {
*** 493,498 ****
--- 493,508 ----
  };
  #undef DEFTREECODE
  
+ /* Error codes.  */
+ typedef enum error_code {
+ #undef DEFERROR
+ #undef DEFERRORNUM
+ #define DEFERROR(code, string) code,
+ #define DEFERRORNUM(code, string, num) DEFERROR(code, string)
+ #include "cp-error.def"
+   ec_last_error_code
+ } error_code;
+ 
  enum languages { lang_c, lang_cplusplus, lang_java };
  
  /* Macros to make error reporting functions' lives easier.  */
*************** extern int flag_new_abi;
*** 2240,2245 ****
--- 2250,2258 ----
  
  extern int flag_honor_std;
  
+ /* Nonzero means show diagnostic codes when printing error messages.  */
+ extern int flag_diag_codes;
+ 
  /* Nonzero if we're done parsing and into end-of-file activities.  */
  
  extern int at_eof;
*************** extern tree handle_class_head			PROTO((t
*** 2627,2632 ****
--- 2640,2646 ----
  extern tree lookup_arg_dependent                PROTO((tree, tree, tree));
  
  /* in errfn.c */
+ #ifndef NO_CP_ERROR_FNS
  extern void cp_error				();
  extern void cp_error_at				();
  extern void cp_warning				();
*************** extern void cp_pedwarn				();
*** 2635,2640 ****
--- 2649,2656 ----
  extern void cp_pedwarn_at			();
  extern void cp_compiler_error			();
  extern void cp_sprintf				();
+ #endif
+ extern void cp_enable_warning                   PROTO((int, int));
  
  /* in error.c */
  extern void init_error				PROTO((void));
Index: cp/lang-options.h
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/lang-options.h,v
retrieving revision 1.17
diff -c -p -r1.17 lang-options.h
*** lang-options.h	1998/09/03 16:09:59	1.17
--- lang-options.h	1998/09/07 01:54:31
*************** DEFINE_LANG_NAME ("C++")
*** 101,106 ****
--- 101,108 ----
    { "-fno-weak", "" },
    { "-fxref", "Emit cross referencing information" },
    { "-fno-xref", "" },
+   { "-fdiag-codes", "Show code numbers when printing diagnostics" },
+   { "-fno-diag-codes", "" },
  
    { "-Wreturn-type", "Warn about inconsistent return types" },
    { "-Wno-return-type", "" },
*************** DEFINE_LANG_NAME ("C++")
*** 126,129 ****
--- 128,133 ----
    { "-Wno-old-style-cast", "" },
    { "-Wnon-template-friend", "" }, 
    { "-Wno-non-template-friend", "Don't warn when non-templatized friend functions are declared within a template" },
+   { "-Wnumber-" },
+   { "-Wno-number-" },
  
Index: cp/errfn.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/errfn.c,v
retrieving revision 1.14
diff -c -p -r1.14 errfn.c
*** errfn.c	1998/08/26 08:11:46	1.14
--- errfn.c	1998/09/07 01:27:58
*************** Boston, MA 02111-1307, USA.  */
*** 23,28 ****
--- 23,32 ----
  #include "system.h"
  #include "tree.h"
  #include "toplev.h"
+ /* The declarations of cp_error and such here are incompatible with
+    those in cp-tree.h.  */
+ #define NO_CP_ERROR_FNS
+ #include "cp-tree.h"
  
  /* cp_printer is the type of a function which converts an argument into
     a string for digestion by printf.  The cp_printer function should deal
*************** extern cp_printer * cp_printers[256];
*** 37,46 ****
--- 41,76 ----
     when we're computing the conversion costs for a method call.  */
  int cp_silent = 0;
  
+ /* The error messages themselves.  */
+ typedef struct cp_err_msg {
+   /* The format of the error message.  */
+   char* format;
+ 
+   /* The code which we should check when deciding whether or not to
+      issue this message.  Used to indicate that some errors are "the
+      same" even though they have different formats.  */
+   error_code equiv_code;
+ 
+   /* A count of how many more times this warning has been enabled than
+      disabled.  (Ignored for errors.)  */
+   int enabled;
+ } cp_err_msg;
+ 
+ static cp_err_msg err_msgs[] = {
+ #undef DEFERROR
+ #undef DEFERRORNUM
+ #define DEFERROR(code, format) DEFERRORNUM(code, format, code)
+ #define DEFERRORNUM(code, format, equiv_code) \
+   { format, equiv_code, 1 },
+ #include "cp-error.def"
+   { 0, 0, 0 }
+ };
+ 
  typedef void errorfn ();	/* deliberately vague */
  
  extern char* cp_file_of PROTO((tree));
  extern int   cp_line_of PROTO((tree));
+ static int   is_warning_enabled PROTO((error_code));
  
  #define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
  
*************** extern int   cp_line_of PROTO((tree));
*** 49,61 ****
  
  #ifdef __STDC__
  static void
! cp_thing (errorfn *errfn, int atarg1, const char *format, va_list ap)
  #else
  static void
! cp_thing (errfn, atarg1, format, ap)
       errorfn *errfn;
       int atarg1;
!      const char *format;
       va_list ap;
  #endif
  {
--- 79,91 ----
  
  #ifdef __STDC__
  static void
! cp_thing (errorfn *errfn, int atarg1, error_code ec, va_list ap)
  #else
  static void
! cp_thing (errfn, atarg1, ec, ap)
       errorfn *errfn;
       int atarg1;
!      error_code ec;
       va_list ap;
  #endif
  {
*************** cp_thing (errfn, atarg1, format, ap)
*** 66,79 ****
    long offset;
    const char *f;
    tree atarg = 0;
  
!   len = strlen (format) + 1;
    if (len > buflen)
      {
        buflen = len;
        buf = xrealloc (buf, buflen);
      }
!   offset = 0;
  
    for (f = format; *f; ++f)
      {
--- 96,124 ----
    long offset;
    const char *f;
    tree atarg = 0;
+   char* format;
+ 
+   my_friendly_assert ((int) ec >= 0 && (int) ec < ec_last_error_code, 
+ 		      0);
+     
+   format = err_msgs[(int) ec].format;
+ 
+   my_friendly_assert (format != 0, 0);
  
!   len = strlen (format) + 1 /* '\0' */ + 16 /* code number */;
    if (len > buflen)
      {
        buflen = len;
        buf = xrealloc (buf, buflen);
      }
!   if (flag_diag_codes) 
!     {
!       sprintf (buf, "[%d] ", (int) ec);
!       for (offset = 0; buf[offset]; ++offset)
! 	;
!     }
!   else
!     offset = 0;
  
    for (f = format; *f; ++f)
      {
*************** cp_thing (errfn, atarg1, format, ap)
*** 198,207 ****
  }
  
  #ifdef __STDC__
! #define DECLARE(name) void name (const char *format, ...)
! #define INIT va_start (ap, format)
  #else
! #define DECLARE(name) void name (format, va_alist) char *format; va_dcl
  #define INIT va_start (ap)
  #endif
  
--- 243,252 ----
  }
  
  #ifdef __STDC__
! #define DECLARE(name) void name (error_code ec, ...)
! #define INIT va_start (ap, ec)
  #else
! #define DECLARE(name) void name (ec, va_alist) error_code ec; va_dcl
  #define INIT va_start (ap)
  #endif
  
*************** DECLARE (cp_error)
*** 210,216 ****
    va_list ap;
    INIT;
    if (! cp_silent)
!     cp_thing ((errorfn *) error, 0, format, ap);
    va_end (ap);
  }
  
--- 255,261 ----
    va_list ap;
    INIT;
    if (! cp_silent)
!     cp_thing ((errorfn *) error, 0, ec, ap);
    va_end (ap);
  }
  
*************** DECLARE (cp_warning)
*** 218,225 ****
  {
    va_list ap;
    INIT;
!   if (! cp_silent)
!     cp_thing ((errorfn *) warning, 0, format, ap);
    va_end (ap);
  }
  
--- 263,270 ----
  {
    va_list ap;
    INIT;
!   if (! cp_silent && is_warning_enabled (ec))
!     cp_thing ((errorfn *) warning, 0, ec, ap);
    va_end (ap);
  }
  
*************** DECLARE (cp_pedwarn)
*** 227,234 ****
  {
    va_list ap;
    INIT;
!   if (! cp_silent)
!     cp_thing ((errorfn *) pedwarn, 0, format, ap);
    va_end (ap);
  }
  
--- 272,279 ----
  {
    va_list ap;
    INIT;
!   if (! cp_silent && is_warning_enabled (ec))
!     cp_thing ((errorfn *) pedwarn, 0, ec, ap);
    va_end (ap);
  }
  
*************** DECLARE (cp_compiler_error)
*** 238,244 ****
    va_list ap;
    INIT;
    if (! cp_silent)
!     cp_thing (compiler_error, 0, format, ap);
    va_end (ap);
  }
  
--- 283,289 ----
    va_list ap;
    INIT;
    if (! cp_silent)
!     cp_thing (compiler_error, 0, ec, ap);
    va_end (ap);
  }
  
*************** DECLARE (cp_sprintf)
*** 246,252 ****
  {
    va_list ap;
    INIT;
!   cp_thing ((errorfn *) sprintf, 0, format, ap);
    va_end (ap);
  }
  
--- 291,297 ----
  {
    va_list ap;
    INIT;
!   cp_thing ((errorfn *) sprintf, 0, ec, ap);
    va_end (ap);
  }
  
*************** DECLARE (cp_error_at)
*** 255,261 ****
    va_list ap;
    INIT;
    if (! cp_silent)
!     cp_thing ((errorfn *) error_with_file_and_line, 1, format, ap);
    va_end (ap);
  }
  
--- 300,306 ----
    va_list ap;
    INIT;
    if (! cp_silent)
!     cp_thing ((errorfn *) error_with_file_and_line, 1, ec, ap);
    va_end (ap);
  }
  
*************** DECLARE (cp_warning_at)
*** 263,270 ****
  {
    va_list ap;
    INIT;
!   if (! cp_silent)
!     cp_thing ((errorfn *) warning_with_file_and_line, 1, format, ap);
    va_end (ap);
  }
  
--- 308,315 ----
  {
    va_list ap;
    INIT;
!   if (! cp_silent && is_warning_enabled (ec))
!     cp_thing ((errorfn *) warning_with_file_and_line, 1, ec, ap);
    va_end (ap);
  }
  
*************** DECLARE (cp_pedwarn_at)
*** 272,278 ****
  {
    va_list ap;
    INIT;
!   if (! cp_silent)
!     cp_thing ((errorfn *) pedwarn_with_file_and_line, 1, format, ap);
    va_end (ap);
  }
--- 317,358 ----
  {
    va_list ap;
    INIT;
!   if (! cp_silent && is_warning_enabled (ec))
!     cp_thing ((errorfn *) pedwarn_with_file_and_line, 1, ec, ap);
    va_end (ap);
+ }
+ 
+ /* If ON is non-zero, enable the warning with the indicated NUMBER.
+    If OFF is zero, disable it.  Actually, this function manipulates a
+    counter, so that enabling/disabling of warnings can nest
+    appropriately.  */
+ 
+ void 
+ cp_enable_warning (number, on)
+      int number;
+      int on;
+ {
+   if (number < 0 || number > (int) ec_last_error_code)
+     error ("invalid warning number %d", number);
+   else if (on)
+     err_msgs[number].enabled++;
+   else
+     {
+       if (!err_msgs[number].enabled)
+ 	warning ("warning %d not enabled", number);
+       else
+ 	err_msgs[number].enabled--;
+     }
+ }
+ 
+ /* Returns non-zero if EC corresponds to an enabled error message.  */
+ 
+ int
+ is_warning_enabled (ec)
+      error_code ec;
+ {
+   my_friendly_assert ((int) ec >= 0 && (int) ec < ec_last_error_code, 
+ 		      0);
+     
+   return err_msgs[(int) ec].enabled;
  }
Index: cp/decl2.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/decl2.c,v
retrieving revision 1.131
diff -c -p -r1.131 decl2.c
*** decl2.c	1998/09/05 20:14:16	1.131
--- decl2.c	1998/09/07 01:27:58
*************** int flag_init_priority = 1;
*** 181,186 ****
--- 181,189 ----
  int flag_init_priority;
  #endif
  
+ /* Nonzero means show diagnostic codes when printing error messages.  */
+ int flag_diag_codes;
+ 
  /* Nonzero means warn about implicit declarations.  */
  
  int warn_implicit = 1;
*************** static struct { char *string; int *varia
*** 487,493 ****
    {"check-new", &flag_check_new, 1},
    {"repo", &flag_use_repository, 1},
    {"for-scope", &flag_new_for_scope, 2},
!   {"weak", &flag_weak, 1}
  };
  
  /* Decode the string P as a language-specific option.
--- 490,497 ----
    {"check-new", &flag_check_new, 1},
    {"repo", &flag_use_repository, 1},
    {"for-scope", &flag_new_for_scope, 2},
!   {"weak", &flag_weak, 1},
!   {"diag-codes", &flag_diag_codes, 1}
  };
  
  /* Decode the string P as a language-specific option.
*************** lang_decode_option (argc, argv)
*** 530,536 ****
  
        if (!strcmp (p, "handle-exceptions")
  	  || !strcmp (p, "no-handle-exceptions"))
! 	warning ("-fhandle-exceptions has been renamed to -fexceptions (and is now on by default)");
  
        if (!strcmp (p, "memoize-lookups")
  	  || !strcmp (p, "no-memoize-lookups")
--- 534,540 ----
  
        if (!strcmp (p, "handle-exceptions")
  	  || !strcmp (p, "no-handle-exceptions"))
! 	cp_warning (ec_fhandleexceptions_has_been_renamed_to_fexceptions_and_is_now_on_by_default);
  
        if (!strcmp (p, "memoize-lookups")
  	  || !strcmp (p, "no-memoize-lookups")
*************** lang_decode_option (argc, argv)
*** 549,555 ****
  	       || !strcmp (p, "no-nonnull-objects")
  	       || !strcmp (p, "no-ansi-overloading"))
  	{
! 	  warning ("-f%s is no longer supported", p);
  	  found = 1;
  	}
        else if (! strcmp (p, "alt-external-templates"))
--- 553,559 ----
  	       || !strcmp (p, "no-nonnull-objects")
  	       || !strcmp (p, "no-ansi-overloading"))
  	{
! 	  cp_warning (ec_fs_is_no_longer_supported, p);
  	  found = 1;
  	}
        else if (! strcmp (p, "alt-external-templates"))
*************** lang_decode_option (argc, argv)
*** 602,608 ****
  		endp++;
  	      else
  		{
! 		  error ("Invalid option `%s'", p - 2);
  		  goto template_depth_lose;
  		}
  	    }
--- 606,612 ----
  		endp++;
  	      else
  		{
! 		  cp_error (ec_invalid_option_s, p - 2);
  		  goto template_depth_lose;
  		}
  	    }
*************** lang_decode_option (argc, argv)
*** 618,624 ****
  		endp++;
  	      else
  		{
! 		  error ("Invalid option `%s'", p - 2);
  		  goto mangling_version_lose;
  		}
  	    }
--- 622,628 ----
  		endp++;
  	      else
  		{
! 		  cp_error (ec_invalid_option_s, p - 2);
  		  goto mangling_version_lose;
  		}
  	    }
*************** lang_decode_option (argc, argv)
*** 711,716 ****
--- 715,739 ----
  	warn_unknown_pragmas = setting * 2;
        else if (!strcmp (p, "non-template-friend"))
  	warn_nontemplate_friend = setting;
+       else if (!strncmp (p, "number-", strlen ("number-")))
+ 	{
+ 	  char *endp = p + strlen ("number-");
+ 	  while (*endp)
+ 	    {
+ 	      if (*endp >= '0' && *endp <= '9')
+ 		endp++;
+ 	      else 
+ 		{
+ 		  cp_error (ec_invalid_option_s, p - 2);
+ 		  endp = 0;
+ 		}
+ 	    }
+ 	  if (endp)
+ 	    {
+ 	      int warning_number = atoi (p + strlen ("number-"));
+ 	      cp_enable_warning (warning_number, setting);
+ 	    }
+ 	}
        else if (!strcmp (p, "comment"))
  	;			/* cpp handles this one.  */
        else if (!strcmp (p, "comments"))



More information about the Gcc mailing list