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]

[Patch] Conversion warnings when truncating 64-bit types (v1)


When porting applications to 64-bit platforms, code is often found
to use the wrong types, in particular, to use int or long to represent
the sizes and offsets (e.g. results from sizeof/strlen). If the actual
size exceeds the range of the target type, gcc will silently truncate
the result.

To detect such errors better, this patch introduces a new type
attribute, __w64__, and a new command line option, -Wp64 (64-bit
portability warnings). The attribute can be attached to any type
intended to hold the size of a memory block (or an offset into it);
what these types are depends on the C library and the application
(typically, size_t should be declared to be __w64__, at a minimum).

Then, if a conversion is attempted from a __w64__ type to a type
shorter than 64 bits, a warning is issued if the -Wp64 flag was
passed to the compiler. This warning is not active by default,
as it can produce many false positives (e.g. for writing
  int x = sizeof(struct stat); where struct stat is known to fit
into 2**32 bytes on all relevant systems).

By default, only the builtin size_t-ish types are marked as w64 with
this patch: size_type_node (signed/unsigned), and ptrdiff_type_node.

Please let me know what you think.

Regards,
Martin

2006-10-24 Martin von Löwis <loewis@hpi.uni-potsdam.de>

	* c.opt: Add Wp64.
	* c-common.c (handle_w64_attribute): New.
	(c_common_attribute_table): Add "w64".
	(convert_and_check): Test for w64 attribute.
	(c_common_nodes_and_builtins): Add w64 attribute to
	size_type_node, signed_size_type_node, ptrdiff_type_node,
	unsigned_ptrdiff_type_node
	* extend.texi (Type Attributes: Document w64.
	* invoke.texi (-Wp64): Document.
	* testsuite/gcc.dg/Wp64-1.c: New.
	* testsuite/gcc.dg/Wp64-2.c: New.
Index: doc/extend.texi
===================================================================
--- doc/extend.texi	(Revision 117999)
+++ doc/extend.texi	(Arbeitskopie)
@@ -3570,6 +3570,14 @@ You may only specify this attribute on t
 @code{struct} or @code{union}, not on a @code{typedef} which does not
 also define the enumerated type, structure or union.

+@item w64
+This attribute, attached to an integral type, indicates that the
+type might use 64-bits on some architectures, even if it doesn't
+on the current architecture.  It is most commonly used for types
+representing the size of memory, or offsets in memory. Truncating
+a type that is marked with @code{w64} will cause a warning if the
+program is compiled with the @option{-Wp64} option.
+
 @item transparent_union
 This attribute, attached to a @code{union} type definition, indicates
 that any function parameter having that union type causes calls to that
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(Revision 117999)
+++ doc/invoke.texi	(Arbeitskopie)
@@ -224,7 +224,7 @@ Objective-C and Objective-C++ Dialects}.
 @gccoptlist{-fsyntax-only  -pedantic  -pedantic-errors @gol
 -w  -Wextra  -Wall  -Waggregate-return -Walways-true -Wno-attributes @gol
 -Wc++-compat -Wcast-align  -Wcast-qual  -Wchar-subscripts  -Wcomment @gol
--Wconversion  -Wno-deprecated-declarations @gol
+-Wconversion  -Wp64  -Wno-deprecated-declarations @gol
 -Wdisabled-optimization  -Wno-div-by-zero  -Wno-endif-labels @gol
 -Werror  -Werror-* -Werror-implicit-function-declaration @gol
 -Wfatal-errors  -Wfloat-equal  -Wformat  -Wformat=2 @gol
@@ -3140,6 +3140,13 @@ converted to an unsigned type.  For exam
 @code{x = -1} if @code{x} is unsigned.  But do not warn about explicit
 casts like @code{(unsigned) -1}.

+@item -Wp64
+@opindex Wp64
+Warn if a potential 64-bit type is truncated to a narrower
+type. Potential 64-bit types are the builtin size types, and types
+marked with the w64 attribute (@pxref{Type Attributes}). Whether or
+not size_t is marked as such a type depends on the C library.
+
@item -Wsign-compare
@opindex Wsign-compare
@cindex warning for comparison of signed and unsigned values
Index: testsuite/gcc.dg/Wp64-2.c
===================================================================
--- testsuite/gcc.dg/Wp64-2.c (Revision 0)
+++ testsuite/gcc.dg/Wp64-2.c (Revision 0)
@@ -0,0 +1,12 @@
+/* Test -Wp64: no warning is emitted when -Wp64 is not given */
+/* Origin: Martin v. Loewis <martin@v.loewis.de> */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+typedef __attribute__((w64)) int size_t_ish;
+
+int
+f (size_t_ish x)
+{
+ return x;
+}
Index: testsuite/gcc.dg/Wp64-1.c
===================================================================
--- testsuite/gcc.dg/Wp64-1.c (Revision 0)
+++ testsuite/gcc.dg/Wp64-1.c (Revision 0)
@@ -0,0 +1,12 @@
+/* Test -Wp64 */
+/* Origin: Martin v. Loewis <martin@v.loewis.de> */
+/* { dg-do compile } */
+/* { dg-options "-Wp64" } */
+
+typedef __attribute__((w64)) int size_t_ish;
+
+int
+f (size_t_ish x)
+{
+ return x; /* { dg-warning "warning: possible truncation of 64-bit value" } */
+}
Index: c.opt
===================================================================
--- c.opt (Revision 117999)
+++ c.opt (Arbeitskopie)
@@ -323,6 +323,10 @@ Woverride-init
C ObjC Var(warn_override_init) Init(-1)
Warn about overriding initializers without side effects


+Wp64
+C ObjC C++ ObjC++ Var(warn_p64)
+Warn about truncations from 64-bit quantities
+
Wparentheses
C ObjC C++ ObjC++ Var(warn_parentheses)
Warn about possibly missing parentheses
Index: c-common.c
===================================================================
--- c-common.c (Revision 117999)
+++ c-common.c (Arbeitskopie)
@@ -516,6 +516,7 @@ static tree handle_transparent_union_att
static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
+static tree handle_w64_attribute (tree *, tree, tree, int, bool *);
static tree handle_section_attribute (tree *, tree, tree, int, bool *);
static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
@@ -592,6 +593,8 @@ const struct attribute_spec c_common_att
handle_destructor_attribute },
{ "mode", 1, 1, false, true, false,
handle_mode_attribute },
+ { "w64", 0, 0, false, true, false,
+ handle_w64_attribute },
{ "section", 1, 1, true, false, false,
handle_section_attribute },
{ "aligned", 0, 1, false, false, false,
@@ -1103,6 +1106,18 @@ convert_and_check (tree type, tree expr)
else
unsigned_conversion_warning (t, expr);
}
+ /* Warn if a w64, size, or pointer type is converted to a type
+ with less then 64 bits. */
+ if (TREE_CODE (type) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ && TYPE_PRECISION (type) < 64
+ && (lookup_attribute ("w64", TYPE_ATTRIBUTES (TREE_TYPE (expr)))
+ || TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
+ || (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+ && TYPE_IS_SIZETYPE (TREE_TYPE (expr)))))
+ {
+ warning (OPT_Wp64, "possible truncation of 64-bit value");
+ }
return t;
}

@@ -3180,7 +3195,16 @@ c_common_nodes_and_builtins (void)
and this must agree, even if long and int are the same size. */
size_type_node =
TREE_TYPE (identifier_global_value (get_identifier (SIZE_TYPE)));
+ /* Apply w64 attribute */
+ size_type_node =
+ build_type_attribute_variant (size_type_node,
+ tree_cons (get_identifier ("w64"),
+ NULL_TREE, NULL_TREE));
signed_size_type_node = c_common_signed_type (size_type_node);
+ signed_size_type_node =
+ build_type_attribute_variant (signed_size_type_node,
+ tree_cons (get_identifier ("w64"),
+ NULL_TREE, NULL_TREE));
set_sizetype (size_type_node);


pid_type_node =
@@ -3284,7 +3308,15 @@ c_common_nodes_and_builtins (void)
default_function_type = build_function_type (integer_type_node, NULL_TREE);
ptrdiff_type_node
= TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
+ ptrdiff_type_node =
+ build_type_attribute_variant (ptrdiff_type_node,
+ tree_cons (get_identifier ("w64"),
+ NULL_TREE, NULL_TREE));
unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
+ unsigned_ptrdiff_type_node =
+ build_type_attribute_variant (unsigned_ptrdiff_type_node,
+ tree_cons (get_identifier ("w64"),
+ NULL_TREE, NULL_TREE));


   lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
@@ -4607,6 +4639,15 @@ handle_mode_attribute (tree *node, tree
   return NULL_TREE;
 }

+static tree
+handle_w64_attribute (tree *ARG_UNUSED(node), tree ARG_UNUSED(name),
+		      tree ARG_UNUSED(args),
+		      int ARG_UNUSED (flags), bool *ARG_UNUSED(no_add_attrs))
+{
+  /* Nothing to do yet */
+  return NULL_TREE;
+}
+
 /* Handle a "section" attribute; arguments as in
    struct attribute_spec.handler.  */



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