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] accept __null as sentinel


Hi,

When annotating some more headers with sentinel attributes (a very usefull
attribute to catch common mistakes calling varargs functions on 64bit
platforms) we noticed that many C++ packages break, because they use a
plain NULL as ending element and hence trigger this warning because in C++
this is no pointer.

While strictly speaking this is indeed not correct (and hence PR19542 was
closed as invalid) we invented the special __null node in C++ (to which
NULL is expanded) exactly to make it possible to write uncasted NULL and
be sure that its size is exactly as large as a pointer type.  So I
consider this a QoI issue regarding the output of needless warning
messages.  The change below makes the warning also recognize this special
node as a correct sentinel.  As the warning is emitted in the common C/C++
code, this either would need a frontend hook for generating the warning,
or simply moving the __null node to the common code, which is easier and
cleaner IMHO.

It adds a testcase checking this.  This is regtested on
{i686,x86_64,ppc,ppc64,s390,s390x,ia64}-linux and additionally in use in
our distri since some time.  I would like to have this in 4.0 and trunk
(where it needs a trivial change, from "warning (" to "warning (0, ")


Ciao,
Michael.
-- 

Changelog:
	PR c++/19542
	* c-common.c (c_common_nodes_and_builtins): Create global null_node.
	(check_function_sentinel): Check for null_node as valid sentinel too.

	* tree.h (tree_index): Added TI_NULL.
	Define null_node as global_tree[TI_NULL].

cp/Changelog:
	PR c++/19542
	* cp-tree.h (cp_tree_index): Remove CPTI_NULL, to be defined in C
	common frontend.
	Removed null_node define.

	* lex.c (cxx_init): Move null_node initialisation to C common frontend.

testsuite/Changelog:
	PR c++/19542
	* g++.dg/warn/sentinel.C: New testcase for __null sentinels added.


*** gcc/cp/cp-tree.h.sentinel	2005-03-30 10:19:52.000000000 +0200
--- gcc/cp/cp-tree.h	2005-04-01 10:16:45.274190351 +0200
*************** enum cp_tree_index
*** 512,518 ****
      CPTI_LANG_NAME_JAVA,
  
      CPTI_EMPTY_EXCEPT_SPEC,
-     CPTI_NULL,
      CPTI_JCLASS,
      CPTI_TERMINATE,
      CPTI_CALL_UNEXPECTED,
--- 512,517 ----
*************** extern GTY(()) tree cp_global_trees[CPTI
*** 608,616 ****
  /* Exception specifier used for throw().  */
  #define empty_except_spec               cp_global_trees[CPTI_EMPTY_EXCEPT_SPEC]
  
- /* The node for `__null'.  */
- #define null_node                       cp_global_trees[CPTI_NULL]
- 
  /* If non-NULL, a POINTER_TYPE equivalent to (java::lang::Class*).  */
  #define jclass_node                     cp_global_trees[CPTI_JCLASS]
  
--- 607,612 ----
*** gcc/cp/lex.c.sentinel	2004-11-25 13:55:47.000000000 +0100
--- gcc/cp/lex.c	2005-04-01 10:26:07.668185370 +0200
*************** cxx_init (void)
*** 348,358 ****
  
    cxx_init_decl_processing ();
  
-   /* Create the built-in __null node.  It is important that this is
-      not shared.  */
-   null_node = make_node (INTEGER_CST);
-   TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
- 
    /* The fact that G++ uses COMDAT for many entities (inline
       functions, template instantiations, virtual tables, etc.) mean
       that it is fundamentally unreliable to try to make decisions
--- 348,353 ----
*** gcc/testsuite/g++.dg/warn/sentinel.C.sentinel	2005-04-01 10:16:45.290186926 +0200
--- gcc/testsuite/g++.dg/warn/sentinel.C	2005-04-01 10:16:45.289187140 +0200
***************
*** 0 ****
--- 1,11 ----
+ /* { dg-do compile } */
+ /* { dg-options "-Wall" } */
+ extern void ex (int i, ...) __attribute__ ((__sentinel__(0)));
+ 
+ void f()
+ {
+   ex (1, 0);		/* { dg-warning "missing sentinel in function call" "" } */
+   ex (1, 0L);		/* { dg-warning "missing sentinel in function call" "" } */
+   ex (1, (void *)0);
+   ex (1, __null);	/* { dg-bogus "sentinel" } */
+ }
*** gcc/c-common.c.sentinel	2005-03-30 10:17:03.000000000 +0200
--- gcc/c-common.c	2005-04-01 10:16:45.250195489 +0200
*************** c_common_nodes_and_builtins (void)
*** 3269,3274 ****
--- 3269,3279 ----
      mudflap_init ();
  
    main_identifier_node = get_identifier ("main");
+ 
+   /* Create the built-in __null node.  It is important that this is
+      not shared.  */
+   null_node = make_node (INTEGER_CST);
+   TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
  }
  
  /* Look up the function in built_in_decls that corresponds to DECL
*************** check_function_sentinel (tree attrs, tre
*** 5115,5122 ****
  	    }
  
  	  /* Validate the sentinel.  */
! 	  if (!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
! 	      || !integer_zerop (TREE_VALUE (sentinel)))
  	    warning ("missing sentinel in function call");
  	}
      }
--- 5120,5132 ----
  	    }
  
  	  /* Validate the sentinel.  */
! 	  if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
! 	       || !integer_zerop (TREE_VALUE (sentinel)))
! 	      /* Although __null (in C++) is only an integer we allow it
! 		 nevertheless, as we are guaranteed that it's exactly
! 		 as wide as a pointer, and we don't want to force
! 		 users to cast the NULL they have written there.  */
! 	      && null_node != TREE_VALUE (sentinel))
  	    warning ("missing sentinel in function call");
  	}
      }
*** gcc/tree.h.sentinel	2005-03-17 07:56:14.000000000 +0100
--- gcc/tree.h	2005-04-01 10:16:45.256194204 +0200
*************** enum tree_index
*** 2595,2600 ****
--- 2595,2602 ----
  
    TI_MAIN_IDENTIFIER,
  
+   TI_NULL,
+ 
    TI_MAX
  };
  
*************** extern GTY(()) tree global_trees[TI_MAX]
*** 2671,2676 ****
--- 2673,2681 ----
  #define main_identifier_node		global_trees[TI_MAIN_IDENTIFIER]
  #define MAIN_NAME_P(NODE) (IDENTIFIER_NODE_CHECK (NODE) == main_identifier_node)
  
+ /* The node for C++ `__null'.  */
+ #define null_node                       global_trees[TI_NULL]
+ 
  /* An enumeration of the standard C integer types.  These must be
     ordered so that shorter types appear before longer ones, and so
     that signed types appear before unsigned ones, for the correct


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