attribs.c (register_attribute): Use CONST_CAST.
authorIan Lance Taylor <iant@google.com>
Mon, 1 Jun 2009 16:35:01 +0000 (16:35 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Mon, 1 Jun 2009 16:35:01 +0000 (16:35 +0000)
./: * attribs.c (register_attribute): Use CONST_CAST.
* collect2.c (main): Use CONST_CAST2.
(scan_prog_file): Likewise.
* gcc.c (process_command, main): Likewise.
* toplev.c (toplev_main): Likewise.

* c-typeck.c (handle_warn_cast_qual): New static function,
partially broken out of build_c_cast.
(build_c_cast): Call handle_warn_cast_qual.
* doc/invoke.texi (Warning Options): Document new effect of
-Wcast-qual.
./java: * jcf-io.c (find_class): Use CONST_CAST.
./testsuite: * gcc.dg/cast-qual-3.c: New testcase.
* g++.dg/warn/Wcast-qual2.C: New testcase.

From-SVN: r148053

12 files changed:
gcc/ChangeLog
gcc/attribs.c
gcc/c-typeck.c
gcc/collect2.c
gcc/doc/invoke.texi
gcc/gcc.c
gcc/java/ChangeLog
gcc/java/jcf-io.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/warn/Wcast-qual2.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/cast-qual-3.c [new file with mode: 0644]
gcc/toplev.c

index 9789c01..d9f67d8 100644 (file)
@@ -1,3 +1,17 @@
+2009-06-01  Ian Lance Taylor  <iant@google.com>
+
+       * attribs.c (register_attribute): Use CONST_CAST.
+       * collect2.c (main): Use CONST_CAST2.
+       (scan_prog_file): Likewise.
+       * gcc.c (process_command, main): Likewise.
+       * toplev.c (toplev_main): Likewise.
+
+       * c-typeck.c (handle_warn_cast_qual): New static function,
+       partially broken out of build_c_cast.
+       (build_c_cast): Call handle_warn_cast_qual.
+       * doc/invoke.texi (Warning Options): Document new effect of
+       -Wcast-qual.
+
 2009-06-01  Aldy Hernandez  <aldyh@redhat.com>
 
        * diagnostic.c (diagnostic_build_prefix): Always print columns.
index 5b18aa3..5ae462e 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions dealing with attribute handling, used by most front ends.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+   2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -195,15 +195,15 @@ void
 register_attribute (const struct attribute_spec *attr) 
 {
   struct substring str;
-  const void **slot;
+  void **slot;
 
   str.str = attr->name;
   str.length = strlen (str.str);
-  slot = (const void **)htab_find_slot_with_hash (attribute_hash, &str,
-                                                  substring_hash (str.str, str.length),
-                                                  INSERT);
+  slot = htab_find_slot_with_hash (attribute_hash, &str,
+                                  substring_hash (str.str, str.length),
+                                  INSERT);
   gcc_assert (!*slot);
-  *slot = attr;
+  *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
 }
 
 /* Return the spec for the attribute named NAME.  */
index 43cb6f3..28fb8b8 100644 (file)
@@ -4055,6 +4055,93 @@ build_compound_expr (tree expr1, tree expr2)
   return ret;
 }
 
+/* Issue -Wcast-qual warnings when appropriate.  TYPE is the type to
+   which we are casting.  OTYPE is the type of the expression being
+   cast.  Both TYPE and OTYPE are pointer types.  -Wcast-qual appeared
+   on the command line.  */
+
+static void
+handle_warn_cast_qual (tree type, tree otype)
+{
+  tree in_type = type;
+  tree in_otype = otype;
+  int added = 0;
+  int discarded = 0;
+  bool is_const;
+
+  /* Check that the qualifiers on IN_TYPE are a superset of the
+     qualifiers of IN_OTYPE.  The outermost level of POINTER_TYPE
+     nodes is uninteresting and we stop as soon as we hit a
+     non-POINTER_TYPE node on either type.  */
+  do
+    {
+      in_otype = TREE_TYPE (in_otype);
+      in_type = TREE_TYPE (in_type);
+
+      /* GNU C allows cv-qualified function types.  'const' means the
+        function is very pure, 'volatile' means it can't return.  We
+        need to warn when such qualifiers are added, not when they're
+        taken away.  */
+      if (TREE_CODE (in_otype) == FUNCTION_TYPE
+         && TREE_CODE (in_type) == FUNCTION_TYPE)
+       added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
+      else
+       discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+    }
+  while (TREE_CODE (in_type) == POINTER_TYPE
+        && TREE_CODE (in_otype) == POINTER_TYPE);
+
+  if (added)
+    warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+
+  if (discarded)
+    /* There are qualifiers present in IN_OTYPE that are not present
+       in IN_TYPE.  */
+    warning (OPT_Wcast_qual,
+            "cast discards qualifiers from pointer target type");
+
+  if (added || discarded)
+    return;
+
+  /* A cast from **T to const **T is unsafe, because it can cause a
+     const value to be changed with no additional warning.  We only
+     issue this warning if T is the same on both sides, and we only
+     issue the warning if there are the same number of pointers on
+     both sides, as otherwise the cast is clearly unsafe anyhow.  A
+     cast is unsafe when a qualifier is added at one level and const
+     is not present at all outer levels.
+
+     To issue this warning, we check at each level whether the cast
+     adds new qualifiers not already seen.  We don't need to special
+     case function types, as they won't have the same
+     TYPE_MAIN_VARIANT.  */
+
+  if (TYPE_MAIN_VARIANT (in_type) != TYPE_MAIN_VARIANT (in_otype))
+    return;
+  if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE)
+    return;
+
+  in_type = type;
+  in_otype = otype;
+  is_const = TYPE_READONLY (TREE_TYPE (in_type));
+  do
+    {
+      in_type = TREE_TYPE (in_type);
+      in_otype = TREE_TYPE (in_otype);
+      if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
+         && !is_const)
+       {
+         warning (OPT_Wcast_qual,
+                  ("new qualifiers in middle of multi-level non-const cast "
+                   "are unsafe"));
+         break;
+       }
+      if (is_const)
+       is_const = TYPE_READONLY (in_type);
+    }
+  while (TREE_CODE (in_type) == POINTER_TYPE);
+}
+
 /* Build an expression representing a cast to type TYPE of expression EXPR.  */
 
 tree
@@ -4139,46 +4226,10 @@ build_c_cast (tree type, tree expr)
       otype = TREE_TYPE (value);
 
       /* Optionally warn about potentially worrisome casts.  */
-
       if (warn_cast_qual
          && TREE_CODE (type) == POINTER_TYPE
          && TREE_CODE (otype) == POINTER_TYPE)
-       {
-         tree in_type = type;
-         tree in_otype = otype;
-         int added = 0;
-         int discarded = 0;
-
-         /* Check that the qualifiers on IN_TYPE are a superset of
-            the qualifiers of IN_OTYPE.  The outermost level of
-            POINTER_TYPE nodes is uninteresting and we stop as soon
-            as we hit a non-POINTER_TYPE node on either type.  */
-         do
-           {
-             in_otype = TREE_TYPE (in_otype);
-             in_type = TREE_TYPE (in_type);
-
-             /* GNU C allows cv-qualified function types.  'const'
-                means the function is very pure, 'volatile' means it
-                can't return.  We need to warn when such qualifiers
-                are added, not when they're taken away.  */
-             if (TREE_CODE (in_otype) == FUNCTION_TYPE
-                 && TREE_CODE (in_type) == FUNCTION_TYPE)
-               added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
-             else
-               discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
-           }
-         while (TREE_CODE (in_type) == POINTER_TYPE
-                && TREE_CODE (in_otype) == POINTER_TYPE);
-
-         if (added)
-           warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
-
-         if (discarded)
-           /* There are qualifiers present in IN_OTYPE that are not
-              present in IN_TYPE.  */
-           warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type");
-       }
+       handle_warn_cast_qual (type, otype);
 
       /* Warn about possible alignment problems.  */
       if (STRICT_ALIGNMENT
index 277ddd6..d15a81a 100644 (file)
@@ -857,9 +857,12 @@ main (int argc, char **argv)
   /* Do not invoke xcalloc before this point, since locale needs to be
      set first, in case a diagnostic is issued.  */
 
-  ld1 = (const char **)(ld1_argv = XCNEWVEC (char *, argc+4));
-  ld2 = (const char **)(ld2_argv = XCNEWVEC (char *, argc+11));
-  object = (const char **)(object_lst = XCNEWVEC (char *, argc));
+  ld1_argv = XCNEWVEC (char *, argc + 4);
+  ld1 = CONST_CAST2 (const char **, char **, ld1_argv);
+  ld2_argv = XCNEWVEC (char *, argc + 11);
+  ld2 = CONST_CAST2 (const char **, char **, ld2_argv);
+  object_lst = XCNEWVEC (char *, argc);
+  object = CONST_CAST2 (const char **, char **, object_lst);
 
 #ifdef DEBUG
   debug = 1;
@@ -904,7 +907,8 @@ main (int argc, char **argv)
      -fno-exceptions -w */
   num_c_args += 5;
 
-  c_ptr = (const char **) (c_argv = XCNEWVEC (char *, num_c_args));
+  c_argv = XCNEWVEC (char *, num_c_args);
+  c_ptr = CONST_CAST2 (const char **, char **, c_argv);
 
   if (argc < 2)
     fatal ("no arguments");
@@ -1406,7 +1410,8 @@ main (int argc, char **argv)
       if (strip_flag)
        {
          char **real_strip_argv = XCNEWVEC (char *, 3);
-         const char ** strip_argv = (const char **) real_strip_argv;
+         const char ** strip_argv = CONST_CAST2 (const char **, char **,
+                                                 real_strip_argv);
 
          strip_argv[0] = strip_file_name;
          strip_argv[1] = output_file;
@@ -2090,7 +2095,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass)
   void (*quit_handler) (int);
 #endif
   char *real_nm_argv[4];
-  const char **nm_argv = (const char **) real_nm_argv;
+  const char **nm_argv = CONST_CAST2 (const char **, char**, real_nm_argv);
   int argc = 0;
   struct pex_obj *pex;
   const char *errmsg;
index df831e3..85b3ae8 100644 (file)
@@ -3694,6 +3694,19 @@ Warn whenever a pointer is cast so as to remove a type qualifier from
 the target type.  For example, warn if a @code{const char *} is cast
 to an ordinary @code{char *}.
 
+Also warn when making a cast which introduces a type qualifier in an
+unsafe way.  For example, casting @code{char **} to @code{const char **}
+is unsafe, as in this example:
+
+@smallexample
+  /* p is char ** value.  */
+  const char **q = (const char **) p;
+  /* Assignment of readonly string to const char * is OK.  */
+  *q = "string";
+  /* Now char** pointer points to read-only memory.  */
+  **p = 'b';
+@end smallexample
+
 @item -Wcast-align
 @opindex Wcast-align
 @opindex Wno-cast-align
index 9168a34..538be05 100644 (file)
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -3636,10 +3636,15 @@ process_command (int argc, const char **argv)
     }
 
   /* Convert new-style -- options to old-style.  */
-  translate_options (&argc, (const char *const **) &argv);
+  translate_options (&argc,
+                    CONST_CAST2 (const char *const **, const char ***,
+                                 &argv));
 
   /* Do language-specific adjustment/addition of flags.  */
-  lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
+  lang_specific_driver (&argc,
+                       CONST_CAST2 (const char *const **, const char ***,
+                                    &argv),
+                       &added_libraries);
 
   /* Scan argv twice.  Here, the first time, just count how many switches
      there will be in their vector, and how many input files in theirs.
@@ -6466,7 +6471,7 @@ main (int argc, char **argv)
      Make a table of specified input files (infiles, n_infiles).
      Decode switches that are handled locally.  */
 
-  process_command (argc, (const char **) argv);
+  process_command (argc, CONST_CAST2 (const char **, char **, argv));
 
   /* Initialize the vector of specs to just the default.
      This means one element containing 0s, as a terminator.  */
index 16fbfea..6754403 100644 (file)
@@ -1,3 +1,7 @@
+2009-06-01  Ian Lance Taylor  <iant@google.com>
+
+       * jcf-io.c (find_class): Use CONST_CAST.
+
 2009-05-27  Ian Lance Taylor  <iant@google.com>
 
        * Make-lang.in ($(XGCJ)$(exeext)): Change $(COMPILER) to
index b968214..28a48bb 100644 (file)
@@ -1,6 +1,6 @@
 /* Utility routines for finding and reading Java(TM) .class files.
    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
-   2006, 2007, 2008 Free Software Foundation, Inc.
+   2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -399,9 +399,8 @@ find_class (const char *classname, int classname_length, JCF *jcf)
 
   /* Remember that this class could not be found so that we do not
      have to look again.  */
-  *(const void **)htab_find_slot_with_hash (memoized_class_lookups,
-                                           classname, hash, INSERT)
-    = classname;
+  *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
+    = (void *) CONST_CAST (char *, classname);
 
   return NULL;
  found:
index 9e10c59..f76815a 100644 (file)
@@ -1,3 +1,8 @@
+2009-06-01  Ian Lance Taylor  <iant@google.com>
+
+       * gcc.dg/cast-qual-3.c: New testcase.
+       * g++.dg/warn/Wcast-qual2.C: New testcase.
+
 2009-06-01  Aldy Hernandez  <aldyh@redhat.com>
 
        * lib/gcc-dg.exp (dg-bogus): Override dg-bogus.
diff --git a/gcc/testsuite/g++.dg/warn/Wcast-qual2.C b/gcc/testsuite/g++.dg/warn/Wcast-qual2.C
new file mode 100644 (file)
index 0000000..88fdcfb
--- /dev/null
@@ -0,0 +1,167 @@
+/* { dg-do compile } */
+/* { dg-options "-Wcast-qual" } */
+
+/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
+   duals.  they are intended to show that gcc -Wcast-qual and g++
+   -Wcast-qual emit warnings in the same cases.  If you change this
+   file, please also change the other one.  */
+
+void
+f1 (void *bar)
+{
+  const void *p1 = (const void *) bar;
+  const char *p2 = (const char *) bar;
+  const void **p3 = (const void **) bar;
+  const char **p4 = (const char **) bar;
+  const void * const *p5 = (const void * const *) bar;
+  const char * const *p6 = (const char * const *) bar;
+  void * const *p7 = (void * const *) bar;
+  char * const *p8 = (char * const *) bar;
+  const void ***p9 = (const void ***) bar;
+  const char ***p10 = (const char ***) bar;
+  void * const **p11 = (void * const **) bar;
+  char * const **p12 = (char * const **) bar;
+  void ** const *p13 = (void ** const *) bar;
+  char ** const *p14 = (char ** const *) bar;
+  const void * const **p15 = (const void * const **) bar;
+  const char * const **p16 = (const char * const **) bar;
+  const void ** const *p17 = (const void ** const *) bar;
+  const char ** const *p18 = (const char ** const *) bar;
+  void * const * const * p19 = (void * const * const *) bar;
+  char * const * const * p20 = (char * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+  const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f2 (void **bar)
+{
+  const void *p1 = (const void *) bar;
+  const char *p2 = (const char *) bar;
+  const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
+  const char **p4 = (const char **) bar;
+  const void * const *p5 = (const void * const *) bar;
+  const char * const *p6 = (const char * const *) bar;
+  void * const *p7 = (void * const *) bar;
+  char * const *p8 = (char * const *) bar;
+  const void ***p9 = (const void ***) bar;
+  const char ***p10 = (const char ***) bar;
+  void * const **p11 = (void * const **) bar;
+  char * const **p12 = (char * const **) bar;
+  void ** const *p13 = (void ** const *) bar;
+  char ** const *p14 = (char ** const *) bar;
+  const void * const **p15 = (const void * const **) bar;
+  const char * const **p16 = (const char * const **) bar;
+  const void ** const *p17 = (const void ** const *) bar;
+  const char ** const *p18 = (const char ** const *) bar;
+  void * const * const * p19 = (void * const * const *) bar;
+  char * const * const * p20 = (char * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+  const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f3 (void ***bar)
+{
+  const void *p1 = (const void *) bar;
+  const char *p2 = (const char *) bar;
+  const void **p3 = (const void **) bar;
+  const char **p4 = (const char **) bar;
+  const void * const *p5 = (const void * const *) bar;
+  const char * const *p6 = (const char * const *) bar;
+  void * const *p7 = (void * const *) bar;
+  char * const *p8 = (char * const *) bar;
+  const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+  const char ***p10 = (const char ***) bar;
+  void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
+  char * const **p12 = (char * const **) bar;
+  void ** const *p13 = (void ** const *) bar;
+  char ** const *p14 = (char ** const *) bar;
+  const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+  const char * const **p16 = (const char * const **) bar;
+  const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+  const char ** const *p18 = (const char ** const *) bar;
+  void * const * const * p19 = (void * const * const *) bar;
+  char * const * const * p20 = (char * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+  const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f4 (void * const **bar)
+{
+  const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+  void * const **p11 = (void * const **) bar;
+  void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
+  const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+  const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+  void * const * const * p19 = (void * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+}
+
+void
+f5 (char ***bar)
+{
+  volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
+  volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
+  volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
+  volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
+  volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
+  volatile char * const * const * p19 = (volatile char * const * const *) bar;
+  volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
+}
+
+void
+f6 (char ***bar)
+{
+  const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
+  char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
+  char * volatile * const *p13 = (char * volatile * const *) bar;
+  const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
+  const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
+  char * volatile const * const * p19 = (char * volatile const * const *) bar;
+  const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
+}
+
+void
+f7 (char ***bar)
+{
+  const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
+  char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
+  char ** volatile const *p13 = (char ** volatile const *) bar;
+  const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
+  const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
+  char * const * volatile const * p19 = (char * const * volatile const *) bar;
+  const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
+}
+
+typedef int (intfn) (int);
+typedef intfn *pintfn;
+typedef const intfn *constfn;
+
+void
+f8 (constfn ***bar)
+{
+  const constfn *p1 = (const constfn *) bar;
+  const pintfn *p2 = (const pintfn *) bar;
+  const constfn **p3 = (const constfn **) bar;
+  const pintfn **p4 = (const pintfn **) bar;
+  const constfn * const *p5 = (const constfn * const *) bar;
+  const pintfn * const *p6 = (const pintfn * const *) bar;
+  constfn * const *p7 = (constfn * const *) bar;
+  pintfn * const *p8 = (pintfn * const *) bar;
+  const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
+  const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
+  constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
+  pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
+  constfn ** const *p13 = (constfn ** const *) bar;
+  pintfn ** const *p14 = (pintfn ** const *) bar;
+  const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
+  const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
+  const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
+  const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
+  constfn * const * const * p19 = (constfn * const * const *) bar;
+  pintfn * const * const * p20 = (pintfn * const * const *) bar;
+  const constfn * const * const *p21 = (const constfn * const * const *) bar;
+  const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
+}
diff --git a/gcc/testsuite/gcc.dg/cast-qual-3.c b/gcc/testsuite/gcc.dg/cast-qual-3.c
new file mode 100644 (file)
index 0000000..88fdcfb
--- /dev/null
@@ -0,0 +1,167 @@
+/* { dg-do compile } */
+/* { dg-options "-Wcast-qual" } */
+
+/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
+   duals.  they are intended to show that gcc -Wcast-qual and g++
+   -Wcast-qual emit warnings in the same cases.  If you change this
+   file, please also change the other one.  */
+
+void
+f1 (void *bar)
+{
+  const void *p1 = (const void *) bar;
+  const char *p2 = (const char *) bar;
+  const void **p3 = (const void **) bar;
+  const char **p4 = (const char **) bar;
+  const void * const *p5 = (const void * const *) bar;
+  const char * const *p6 = (const char * const *) bar;
+  void * const *p7 = (void * const *) bar;
+  char * const *p8 = (char * const *) bar;
+  const void ***p9 = (const void ***) bar;
+  const char ***p10 = (const char ***) bar;
+  void * const **p11 = (void * const **) bar;
+  char * const **p12 = (char * const **) bar;
+  void ** const *p13 = (void ** const *) bar;
+  char ** const *p14 = (char ** const *) bar;
+  const void * const **p15 = (const void * const **) bar;
+  const char * const **p16 = (const char * const **) bar;
+  const void ** const *p17 = (const void ** const *) bar;
+  const char ** const *p18 = (const char ** const *) bar;
+  void * const * const * p19 = (void * const * const *) bar;
+  char * const * const * p20 = (char * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+  const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f2 (void **bar)
+{
+  const void *p1 = (const void *) bar;
+  const char *p2 = (const char *) bar;
+  const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
+  const char **p4 = (const char **) bar;
+  const void * const *p5 = (const void * const *) bar;
+  const char * const *p6 = (const char * const *) bar;
+  void * const *p7 = (void * const *) bar;
+  char * const *p8 = (char * const *) bar;
+  const void ***p9 = (const void ***) bar;
+  const char ***p10 = (const char ***) bar;
+  void * const **p11 = (void * const **) bar;
+  char * const **p12 = (char * const **) bar;
+  void ** const *p13 = (void ** const *) bar;
+  char ** const *p14 = (char ** const *) bar;
+  const void * const **p15 = (const void * const **) bar;
+  const char * const **p16 = (const char * const **) bar;
+  const void ** const *p17 = (const void ** const *) bar;
+  const char ** const *p18 = (const char ** const *) bar;
+  void * const * const * p19 = (void * const * const *) bar;
+  char * const * const * p20 = (char * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+  const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f3 (void ***bar)
+{
+  const void *p1 = (const void *) bar;
+  const char *p2 = (const char *) bar;
+  const void **p3 = (const void **) bar;
+  const char **p4 = (const char **) bar;
+  const void * const *p5 = (const void * const *) bar;
+  const char * const *p6 = (const char * const *) bar;
+  void * const *p7 = (void * const *) bar;
+  char * const *p8 = (char * const *) bar;
+  const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+  const char ***p10 = (const char ***) bar;
+  void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
+  char * const **p12 = (char * const **) bar;
+  void ** const *p13 = (void ** const *) bar;
+  char ** const *p14 = (char ** const *) bar;
+  const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+  const char * const **p16 = (const char * const **) bar;
+  const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+  const char ** const *p18 = (const char ** const *) bar;
+  void * const * const * p19 = (void * const * const *) bar;
+  char * const * const * p20 = (char * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+  const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f4 (void * const **bar)
+{
+  const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+  void * const **p11 = (void * const **) bar;
+  void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
+  const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+  const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+  void * const * const * p19 = (void * const * const *) bar;
+  const void * const * const *p21 = (const void * const * const *) bar;
+}
+
+void
+f5 (char ***bar)
+{
+  volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
+  volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
+  volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
+  volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
+  volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
+  volatile char * const * const * p19 = (volatile char * const * const *) bar;
+  volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
+}
+
+void
+f6 (char ***bar)
+{
+  const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
+  char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
+  char * volatile * const *p13 = (char * volatile * const *) bar;
+  const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
+  const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
+  char * volatile const * const * p19 = (char * volatile const * const *) bar;
+  const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
+}
+
+void
+f7 (char ***bar)
+{
+  const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
+  char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
+  char ** volatile const *p13 = (char ** volatile const *) bar;
+  const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
+  const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
+  char * const * volatile const * p19 = (char * const * volatile const *) bar;
+  const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
+}
+
+typedef int (intfn) (int);
+typedef intfn *pintfn;
+typedef const intfn *constfn;
+
+void
+f8 (constfn ***bar)
+{
+  const constfn *p1 = (const constfn *) bar;
+  const pintfn *p2 = (const pintfn *) bar;
+  const constfn **p3 = (const constfn **) bar;
+  const pintfn **p4 = (const pintfn **) bar;
+  const constfn * const *p5 = (const constfn * const *) bar;
+  const pintfn * const *p6 = (const pintfn * const *) bar;
+  constfn * const *p7 = (constfn * const *) bar;
+  pintfn * const *p8 = (pintfn * const *) bar;
+  const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
+  const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
+  constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
+  pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
+  constfn ** const *p13 = (constfn ** const *) bar;
+  pintfn ** const *p14 = (pintfn ** const *) bar;
+  const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
+  const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
+  const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
+  const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
+  constfn * const * const * p19 = (constfn * const * const *) bar;
+  pintfn * const * const * p20 = (pintfn * const * const *) bar;
+  const constfn * const * const *p21 = (const constfn * const * const *) bar;
+  const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
+}
index 346887b..eb47d99 100644 (file)
@@ -1,6 +1,6 @@
 /* Top level of GCC compilers (cc1, cc1plus, etc.)
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -2349,14 +2349,14 @@ toplev_main (int argc, char **argv)
 {
   expandargv (&argc, &argv);
 
-  save_argv = (const char **) argv;
+  save_argv = CONST_CAST2 (const char **, char **, argv);
 
   /* Initialization of GCC's environment, and diagnostics.  */
   general_init (argv[0]);
 
   /* Parse the options and do minimal processing; basically just
      enough to default flags appropriately.  */
-  decode_options (argc, (const char **) argv);
+  decode_options (argc, CONST_CAST2 (const char **, char **, argv));
 
   init_local_tick ();