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]

[C++ PATCH] [PR 13005] Warn about casting of incomplete types


This patch is identical to attachment 5429 uploaded to Bugzilla for PR
13005.  I have been asked to post it here, so here it is.

Apply this patch against the mainline snapshot gcc-3.4-20031231.

It adds a warning about the use of a traditional cast to convert an
incomplete type.  The warning happens only in cc1plus, and is on by
default.  The patch also adds an option -Wno-cast-incomplete to turn
off the warning.

Included is an update to the texinfo documentation; I urge you to read
it before looking at the actual code.

P.S.  To reply to me, please take out the trash.


=======================================================================
diff -ur ./ChangeLog ../gcc-3.4-20031231/ChangeLog
--- ./ChangeLog	2003-12-23 10:48:46.000000000 -0800
+++ ../gcc-3.4-20031231/ChangeLog	2004-01-07 16:05:17.000000000 -0800
@@ -1,3 +1,8 @@
+2004-01-07  Stephen Ma  <stephenma@telus.net>
+
+	* Added -Wcast-incomplete, for C++ only.
+	* Updated texinfo documentation accordingly.
+
 2003-12-23  Kazu Hirata  <kazu@cs.umass.edu>
 
 	* MAINTAINERS: Remove the mn10200 maintainer.
diff -ur ./gcc/c-common.c ../gcc-3.4-20031231/gcc/c-common.c
--- ./gcc/c-common.c	2003-12-25 08:21:34.000000000 -0800
+++ ../gcc-3.4-20031231/gcc/c-common.c	2004-01-06 15:34:21.000000000 -0800
@@ -263,6 +263,10 @@
 
 int warn_cast_qual;
 
+/* Warn about old-style casting from/to an incomplete type */
+
+int warn_cast_incomplete = 1;
+
 /* Warn about functions which might be candidates for format attributes.  */
 
 int warn_missing_format_attribute;
diff -ur ./gcc/c-common.h ../gcc-3.4-20031231/gcc/c-common.h
--- ./gcc/c-common.h	2003-12-22 15:57:03.000000000 -0800
+++ ../gcc-3.4-20031231/gcc/c-common.h	2004-01-06 15:56:12.000000000 -0800
@@ -449,6 +449,10 @@
 
 extern int warn_cast_qual;
 
+/* Warn about old-style casting from/to an incomplete type */
+
+extern int warn_cast_incomplete;
+
 /* Warn about functions which might be candidates for format attributes.  */
 
 extern int warn_missing_format_attribute;
diff -ur ./gcc/c-opts.c ../gcc-3.4-20031231/gcc/c-opts.c
--- ./gcc/c-opts.c	2003-12-22 15:57:03.000000000 -0800
+++ ../gcc-3.4-20031231/gcc/c-opts.c	2004-01-07 17:26:08.000000000 -0800
@@ -397,6 +397,10 @@
       warn_cast_qual = value;
       break;
 
+    case OPT_Wcast_incomplete:
+      warn_cast_incomplete = value;
+      break;
+
     case OPT_Wchar_subscripts:
       warn_char_subscripts = value;
       break;
@@ -1108,6 +1112,10 @@
   if (warn_missing_format_attribute && !warn_format)
     warning ("-Wmissing-format-attribute ignored without -Wformat");
 
+  /* Make -Wcast-incomplete effective in C++ only */
+  if (c_language != clk_cxx)
+    warn_cast_incomplete = 0;
+
   if (flag_preprocess_only)
     {
       /* Open the output now.  We must do so even if flag_no_output is
diff -ur ./gcc/c.opt ../gcc-3.4-20031231/gcc/c.opt
--- ./gcc/c.opt	2003-09-24 18:25:50.000000000 -0700
+++ ../gcc-3.4-20031231/gcc/c.opt	2004-01-06 14:52:51.000000000 -0800
@@ -156,6 +156,10 @@
 C ObjC
 Warn about casting functions to incompatible types
 
+Wcast-incomplete
+C++
+Warn about casting from/to incomplete types
+
 Wcast-qual
 C ObjC C++ ObjC++
 Warn about casts which discard qualifiers
diff -ur ./gcc/cp/typeck.c ../gcc-3.4-20031231/gcc/cp/typeck.c
--- ./gcc/cp/typeck.c	2003-12-29 09:01:58.000000000 -0800
+++ ../gcc-3.4-20031231/gcc/cp/typeck.c	2004-01-07 15:26:43.000000000 -0800
@@ -4864,6 +4864,10 @@
 
   /* Optionally warn about potentially worrisome casts.  */
 
+  if (warn_cast_incomplete)
+    if (!COMPLETE_TYPE_P (TREE_TYPE (type))  ||  !COMPLETE_TYPE_P (TREE_TYPE (otype)))
+      warning ("casting from/to an incomplete type is risky; see -Wno-cast-incomplete");
+
   if (warn_cast_qual
       && TREE_CODE (type) == POINTER_TYPE
       && TREE_CODE (otype) == POINTER_TYPE
diff -ur ./gcc/doc/invoke.texi ../gcc-3.4-20031231/gcc/doc/invoke.texi
--- ./gcc/doc/invoke.texi	2003-12-31 02:32:57.000000000 -0800
+++ ../gcc-3.4-20031231/gcc/doc/invoke.texi	2004-01-07 15:39:38.000000000 -0800
@@ -211,8 +211,8 @@
 @xref{Warning Options,,Options to Request or Suppress Warnings}.
 @gccoptlist{-fsyntax-only  -pedantic  -pedantic-errors @gol
 -w  -Wextra  -Wall  -Waggregate-return @gol
--Wcast-align  -Wcast-qual  -Wchar-subscripts  -Wcomment @gol
--Wconversion  -Wno-deprecated-declarations @gol
+-Wcast-align  -Wcast-incomplete  -Wcast-qual  -Wchar-subscripts @gol
+-Wcomment  -Wconversion  -Wno-deprecated-declarations @gol
 -Wdisabled-optimization  -Wno-div-by-zero  -Wendif-labels @gol
 -Werror  -Werror-implicit-function-declaration @gol
 -Wfloat-equal  -Wformat  -Wformat=2 @gol
@@ -2794,6 +2794,98 @@
 an @code{int *} on machines where integers can only be accessed at
 two- or four-byte boundaries.
 
+@item -Wno-cast-incomplete
+@opindex Wno-cast-incomplete
+C++ only. Suppress the warnings about the use of an incomplete type as
+either the operand type or the destination type of an old-style cast.
+Using such a cast has always been rather dangerous, but for reasons
+described below is now even riskier; thus the warning.
+@option{-Wcast-incomplete} applies only to the traditional casts
+inherited from C, such as @samp{(int *) p}; there is no effect on
+@samp{static_cast}, @samp{reinterpret_cast}, and so on.
+
+What exactly triggers the warning?  Only one of the following casts
+is accepted quietly by the compiler:
+
+@smallexample
+@group
+class Alpha        *a;   // Incomplete class.
+class Beta;        *b;   // Incomplete class
+class Gamma @{...@}  *c;   // Complete class.
+class Delta @{...@}  *d;   // Complete class.
+
+void foo()
+@{
+  a = (Alpha*) b;   // Incomplete -> incomplete: warning
+  c = (Gamma*) a;   // Incomplete -> complete:   warning
+  b = (Beta*) c;    // Complete -> incomplete:   warning
+  d = (Delta*) c;   // Complete -> complete:     no warning
+@}
+@end group
+@end smallexample
+
+So the best way to avoid the warning is always to use complete types in
+casts.  If you must cast between incomplete types, despite the pitfalls
+outlined below, you can use @samp{reinterpret_cast} in the (hopefully)
+rare locations that require it.  To suppress the warning for an entire
+program, you can use @option{-Wno-cast-incomplete}, but this practice is
+discouraged.
+
+Why is the warning necessary?  Suppose we have an expression like
+@samp{d=(Klass*)o}, where there is an inheritance relationship between
+the pointers @samp{d} and @samp{o}.  In order for the instance variables
+of @samp{o} to still be accessible through @samp{d}, the cast must add
+an adjustment to the value of @samp{o}.  The adjustment is the
+difference between the offset of an instance variable within @samp{*o}
+and the offset of the same variable within @samp{*d}.  Of course, when
+either @samp{o} or @samp{d}, or both, has an incomplete type, the cast
+is unable to determine the adjustment, and has no choice but to use zero
+for it.  Zero is often the wrong value; hence the warning.
+
+The adjustment is most frequently nonzero when @samp{o} and @samp{d} are
+related by multiple inheritance.  But as of @samp{g++ 3.x} it can be
+nonzero even for single inheritance, as the ISO C++ standard gives the
+compiler more latitude in the arrangement of inherited fields within an
+object.  So if you must use an old-style cast, always use it with
+complete types.
+
+When @samp{o} and @samp{d} are not related by inheritance, you are, as
+always, on your own.  The ISO C++ standard does not guarantee that
+@samp{d}, the result of the cast, will be a usable pointer, even if
+@samp{o} and @samp{d} are both complete types, even if you are careful
+to begin @samp{*o} and @samp{*d} with the same instance variables.
+Consider the following subtle trap:
+
+@smallexample
+@group
+class O @{
+  int x;
+@}  *o;
+
+class B @{
+  int x;
+@};
+
+class D: public B @{
+  virtual void mangle();
+@}  *d;
+@end group
+@end smallexample
+
+A cast like @samp{d=(D*)o} or @samp{d=reinterpret_cast<D*>(o)} would
+surely work, wouldn't it?  Since @samp{x} is the first instance variable
+in both @samp{*o} and @samp{*d}, surely @samp{d->x} would be the same
+variable as @samp{o->x}, right?  Well, maybe, if you are lucky.  On some
+older compilers, such as @samp{g++ 2.x}, the cast may work.  However,
+you may be out of luck on newer compilers that follow the ISO C++
+standard, such as @samp{g++ 3.x}.  The reason is that @samp{*d} has a
+vtable pointer, thanks to the virtual function @samp{mangle()}, while
+@samp{*o} does not.  If the compiler chooses to place the vtable pointer
+before @samp{d->x}, as permitted by ISO C++, then @samp{d->x} would
+indeed be different from @samp{o->x}.  So be very careful.
+
+All the cautions above regarding pointers applies equally to references.
+
 @item -Wwrite-strings
 @opindex Wwrite-strings
 When compiling C, give string constants the type @code{const


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]