This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: PATCH RFA: Improve -Wcast-qual warning for C


"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Mon, 25 May 2009, Ian Lance Taylor wrote:
>
>> As discussed at http://gcc.gnu.org/ml/gcc/2009-05/msg00533.html , the
>> C++ compiler issues more warnings for -Wcast-qual than the C compiler
>> does.  After a bit of further discussion on IRC, I think the general
>> consensus is that the C compiler should issue warnings about unsafe
>> casts much as the C++ compiler does.  Recall that this is only when
>> using -Wcast-qual, and that -Wcast-qual is not part of -Wall.
>> 
>> The first patch in this message implements the appropriate warnings.
>> This patch requires approval from the C frontend maintainers.
>
> I do not believe this is implementing the correct semantics.
>
> The requirement for safety in multi-level casts is not that the final 
> qualifier appears at the intermediate levels, it is that "const" appears 
> at all levels before any level at which a qualifier is added; that is, if 
> the C++ rules would permit a qualification conversion with that sequence 
> of qualifiers.  The example
>
> void
> f5 (char ***bar)
> {                                     
>   volatile char * const * const * p19 = bar;
> }
>
> is accepted by the C++ front end as this is a safe implicit conversion, as 
> is the version with a cast when using -Wcast-qual.

You're right, I did misunderstand.  Now fixed.  Thanks.


> I think you should also add a C++ testcase that is essentially identical 
> to the C one to verify that the same semantics are being followed for the 
> option by both front ends.

Done.

Here is the updated patch.  Bootstrapped and tested on
x86_64-unknown-linux-gnu.  The second patch in
   http://gcc.gnu.org/ml/gcc-patches/2009-05/msg01608.html
is unchanged.

Ian


gcc/ChangeLog:

2009-05-29  Ian Lance Taylor  <iant@google.com>

	* 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.

gcc/testsuite/ChangeLog:

2009-05-29  Ian Lance Taylor  <iant@google.com>

	* gcc.dg/cast-qual-3.c: New testcase.
	* g++.dg/warn/Wcast-qual2.C: New testcase.


Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 147842)
+++ gcc/c-typeck.c	(working copy)
@@ -4055,6 +4055,93 @@ build_compound_expr (tree expr1, tree ex
   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: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 147842)
+++ gcc/doc/invoke.texi	(working copy)
@@ -3689,6 +3689,19 @@ Warn whenever a pointer is cast so as to
 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: gcc/testsuite/gcc.dg/cast-qual-3.c
===================================================================
--- gcc/testsuite/gcc.dg/cast-qual-3.c	(revision 0)
+++ gcc/testsuite/gcc.dg/cast-qual-3.c	(revision 0)
@@ -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: gcc/testsuite/g++.dg/warn/Wcast-qual2.C
===================================================================
--- gcc/testsuite/g++.dg/warn/Wcast-qual2.C	(revision 0)
+++ gcc/testsuite/g++.dg/warn/Wcast-qual2.C	(revision 0)
@@ -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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]