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 16338, 16489, 16810


This patch fixes several C++ regressions.  Tested on
i686-pc-linux-gnu, applied on the mainline and on the 3.4 branch.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-08-01  Mark Mitchell  <mark@codesourcery.com>

	PR c++/16338
	* cp-tree.h (DECL_INTEGRAL_CONSTANT_VAR_P): New macro.
	* call.c (null_ptr_cst_p): Handle variables with constant
	initializers.
	* pt.c (convert_nontype_argument): Use
	DECL_INTEGRAL_CONSTANT_VAR_P.
	* semantics.c (finish_id_expression): Likewise.

	PR c++/16489
	* decl.c (duplicate_decls): Reject duplicate namespace
	declarations.

	PR c++/16810
	* typeck.c (build_ptrmemfunc): Loosen assertion.

2004-08-01  Mark Mitchell  <mark@codesourcery.com>

	PR c++/16338
	* g++.dg/init/null1.C: New test.
	* g++.dg/tc1/dr76.C: Adjust error marker.
	
	PR c++/16489
	* g++.dg/parse/namespace10.C: New test.
	
	PR c++/16810
	* g++.dg/inherit/ptrmem2.C: New test.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.495
diff -c -5 -p -r1.495 call.c
*** cp/call.c	18 Jul 2004 05:44:17 -0000	1.495
--- cp/call.c	2 Aug 2004 01:40:33 -0000
*************** struct z_candidate {
*** 427,450 ****
    tree template;
    candidate_warning *warnings;
    z_candidate *next;
  };
  
  bool
  null_ptr_cst_p (tree t)
  {
    /* [conv.ptr]
  
       A null pointer constant is an integral constant expression
       (_expr.const_) rvalue of integer type that evaluates to zero.  */
    if (t == null_node
        || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
      return true;
    return false;
  }
  
- 
  /* Returns nonzero if PARMLIST consists of only default parms and/or
     ellipsis.  */
  
  bool
  sufficient_parms_p (tree parmlist)
--- 427,454 ----
    tree template;
    candidate_warning *warnings;
    z_candidate *next;
  };
  
+ /* Returns true iff T is a null pointer constant in the sense of
+    [conv.ptr].  */
+ 
  bool
  null_ptr_cst_p (tree t)
  {
    /* [conv.ptr]
  
       A null pointer constant is an integral constant expression
       (_expr.const_) rvalue of integer type that evaluates to zero.  */
+   if (DECL_INTEGRAL_CONSTANT_VAR_P (t))
+     t = decl_constant_value (t);
    if (t == null_node
        || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
      return true;
    return false;
  }
  
  /* Returns nonzero if PARMLIST consists of only default parms and/or
     ellipsis.  */
  
  bool
  sufficient_parms_p (tree parmlist)
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1026
diff -c -5 -p -r1.1026 cp-tree.h
*** cp/cp-tree.h	29 Jul 2004 17:59:27 -0000	1.1026
--- cp/cp-tree.h	2 Aug 2004 01:40:33 -0000
*************** struct lang_decl GTY(())
*** 1819,1828 ****
--- 1819,1845 ----
  /* Nonzero for a VAR_DECL that was initialized with a
     constant-expression.  */
  #define DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P(NODE) \
    (TREE_LANG_FLAG_2 (VAR_DECL_CHECK (NODE)))
  
+ /* Nonzero for a VAR_DECL that can be used in an integral constant
+    expression.    
+ 
+       [expr.const]
+ 
+       An integral constant-expression can only involve ... const
+       variables of static or enumeration types initialized with
+       constant expressions ...
+   
+    The standard does not require that the expression be non-volatile.
+    G++ implements the proposed correction in DR 457.  */
+ #define DECL_INTEGRAL_CONSTANT_VAR_P(NODE)		\
+   (TREE_CODE (NODE) == VAR_DECL				\
+    && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (NODE))	\
+    && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (NODE))	\
+    && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (NODE))
+ 
  /* Nonzero if the DECL was initialized in the class definition itself,
     rather than outside the class.  This is used for both static member
     VAR_DECLS, and FUNTION_DECLS that are defined in the class.  */
  #define DECL_INITIALIZED_IN_CLASS_P(DECL) \
   (DECL_LANG_SPECIFIC (DECL)->decl_flags.initialized_in_class)
Index: cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1265
diff -c -5 -p -r1.1265 decl.c
*** cp/decl.c	29 Jul 2004 17:59:27 -0000	1.1265
--- cp/decl.c	2 Aug 2004 01:40:33 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1405,1427 ****
  	       || (DECL_TEMPLATE_INSTANTIATION (newdecl)
  		   && !DECL_USE_TEMPLATE (olddecl))))
      /* One of the declarations is a template instantiation, and the
         other is not a template at all.  That's OK.  */
      return NULL_TREE;
!   else if (TREE_CODE (newdecl) == NAMESPACE_DECL
!            && DECL_NAMESPACE_ALIAS (newdecl)
!            && DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
!     /* In [namespace.alias] we have:
! 
! 	 In a declarative region, a namespace-alias-definition can be
! 	 used to redefine a namespace-alias declared in that declarative
! 	 region to refer only to the namespace to which it already
! 	 refers.
! 
!       Therefore, if we encounter a second alias directive for the same
!       alias, we can just ignore the second directive.  */
!     return olddecl;
    else
      {
        const char *errmsg = redeclaration_error_message (newdecl, olddecl);
        if (errmsg)
  	{
--- 1405,1440 ----
  	       || (DECL_TEMPLATE_INSTANTIATION (newdecl)
  		   && !DECL_USE_TEMPLATE (olddecl))))
      /* One of the declarations is a template instantiation, and the
         other is not a template at all.  That's OK.  */
      return NULL_TREE;
!   else if (TREE_CODE (newdecl) == NAMESPACE_DECL)
!     {
!       /* In [namespace.alias] we have:
! 	 
!            In a declarative region, a namespace-alias-definition can be
! 	   used to redefine a namespace-alias declared in that declarative
! 	   region to refer only to the namespace to which it already
! 	   refers.
! 	   
! 	 Therefore, if we encounter a second alias directive for the same
! 	 alias, we can just ignore the second directive.  */
!       if (DECL_NAMESPACE_ALIAS (newdecl)
! 	  && (DECL_NAMESPACE_ALIAS (newdecl) 
! 	      == DECL_NAMESPACE_ALIAS (olddecl)))
! 	return olddecl;
!       /* [namespace.alias]
! 
!          A namespace-name or namespace-alias shall not be declared as
! 	 the name of any other entity in the same declarative region.
! 	 A namespace-name defined at global scope shall not be
! 	 declared as the name of any other entity in any glogal scope
! 	 of the program.  */
!       error ("declaration of `namespace %D' conflicts with", newdecl);
!       cp_error_at ("previous declaration of `namespace %D' here", olddecl);
!       return error_mark_node;
!     }
    else
      {
        const char *errmsg = redeclaration_error_message (newdecl, olddecl);
        if (errmsg)
  	{
Index: cp/pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.898
diff -c -5 -p -r1.898 pt.c
*** cp/pt.c	29 Jul 2004 17:59:28 -0000	1.898
--- cp/pt.c	2 Aug 2004 01:40:33 -0000
*************** convert_nontype_argument (tree type, tre
*** 3231,3243 ****
  	/* In a template, the initializer for a VAR_DECL may not be
  	   marked as TREE_CONSTANT, in which case decl_constant_value
  	   will not return the initializer.  Handle that special case
  	   here.  */
  	if (expr == const_expr
! 	    && TREE_CODE (expr) == VAR_DECL
! 	    && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr)
! 	    && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr))
  	    /* DECL_INITIAL can be NULL if we are processing a
  	       variable initialized to an expression involving itself.
  	       We know it is initialized to a constant -- but not what
  	       constant, yet.  */
  	    && DECL_INITIAL (expr))
--- 3231,3241 ----
  	/* In a template, the initializer for a VAR_DECL may not be
  	   marked as TREE_CONSTANT, in which case decl_constant_value
  	   will not return the initializer.  Handle that special case
  	   here.  */
  	if (expr == const_expr
! 	    && DECL_INTEGRAL_CONSTANT_VAR_P (expr)
  	    /* DECL_INITIAL can be NULL if we are processing a
  	       variable initialized to an expression involving itself.
  	       We know it is initialized to a constant -- but not what
  	       constant, yet.  */
  	    && DECL_INITIAL (expr))
Index: cp/semantics.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/semantics.c,v
retrieving revision 1.420
diff -c -5 -p -r1.420 semantics.c
*** cp/semantics.c	29 Jul 2004 17:59:28 -0000	1.420
--- cp/semantics.c	2 Aug 2004 01:40:33 -0000
*************** finish_id_expression (tree id_expression
*** 2562,2590 ****
  	}
  
        /* Only certain kinds of names are allowed in constant
         expression.  Enumerators and template parameters 
         have already been handled above.  */
!       if (integral_constant_expression_p)
  	{
! 	    /* Const variables or static data members of integral or
! 	      enumeration types initialized with constant expressions
! 	      are OK.  */
! 	  if (TREE_CODE (decl) == VAR_DECL
! 	      && CP_TYPE_CONST_P (TREE_TYPE (decl))
! 	      && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
! 	      && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
! 	    ;
! 	  else
  	    {
! 	      if (!allow_non_integral_constant_expression_p)
! 		{
! 		  error ("`%D' cannot appear in a constant-expression", decl);
! 		  return error_mark_node;
! 		}
! 	      *non_integral_constant_expression_p = true;
  	    }
  	}
        
        if (TREE_CODE (decl) == NAMESPACE_DECL)
  	{
  	  error ("use of namespace `%D' as expression", decl);
--- 2562,2580 ----
  	}
  
        /* Only certain kinds of names are allowed in constant
         expression.  Enumerators and template parameters 
         have already been handled above.  */
!       if (integral_constant_expression_p
! 	  && !DECL_INTEGRAL_CONSTANT_VAR_P (decl))
  	{
! 	  if (!allow_non_integral_constant_expression_p)
  	    {
! 	      error ("`%D' cannot appear in a constant-expression", decl);
! 	      return error_mark_node;
  	    }
+ 	  *non_integral_constant_expression_p = true;
  	}
        
        if (TREE_CODE (decl) == NAMESPACE_DECL)
  	{
  	  error ("use of namespace `%D' as expression", decl);
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.565
diff -c -5 -p -r1.565 typeck.c
*** cp/typeck.c	27 Jul 2004 23:24:07 -0000	1.565
--- cp/typeck.c	2 Aug 2004 01:40:34 -0000
*************** build_ptrmemfunc (tree type, tree pfn, i
*** 5461,5471 ****
  	  npfn = build_ptrmemfunc_access_expr (pfn, pfn_identifier);
  	  delta = build_ptrmemfunc_access_expr (pfn, delta_identifier);
  	}
  
        /* Just adjust the DELTA field.  */
!       my_friendly_assert (TREE_TYPE (delta) == ptrdiff_type_node, 20030727);
        if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
  	n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
        delta = cp_build_binary_op (PLUS_EXPR, delta, n);
        return build_ptrmemfunc1 (to_type, delta, npfn);
      }
--- 5461,5474 ----
  	  npfn = build_ptrmemfunc_access_expr (pfn, pfn_identifier);
  	  delta = build_ptrmemfunc_access_expr (pfn, delta_identifier);
  	}
  
        /* Just adjust the DELTA field.  */
!       my_friendly_assert 
! 	(same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (delta),
! 						    ptrdiff_type_node), 
! 	 20030727);
        if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
  	n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
        delta = cp_build_binary_op (PLUS_EXPR, delta, n);
        return build_ptrmemfunc1 (to_type, delta, npfn);
      }
Index: testsuite/g++.dg/inherit/ptrmem2.C
===================================================================
RCS file: testsuite/g++.dg/inherit/ptrmem2.C
diff -N testsuite/g++.dg/inherit/ptrmem2.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/inherit/ptrmem2.C	2 Aug 2004 01:40:37 -0000
***************
*** 0 ****
--- 1,25 ----
+ // PR c++/16810
+ 
+ struct C {
+   virtual void f() {}
+ };
+ 
+ struct B {virtual ~B() {} };
+ 
+ class D : public B, public C
+ {
+ public:
+   virtual void f() {}
+ };
+ 
+ typedef void ( C::*FP)();
+ typedef void ( D::*D_f)();
+ 
+ int main() {
+   D *d = new D();
+   C *c = d;
+ 
+   const FP fptr = (FP) &D::f;;
+   (d->* (D_f)fptr)();
+ }
+ 
Index: testsuite/g++.dg/init/null1.C
===================================================================
RCS file: testsuite/g++.dg/init/null1.C
diff -N testsuite/g++.dg/init/null1.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/init/null1.C	2 Aug 2004 01:40:37 -0000
***************
*** 0 ****
--- 1,6 ----
+ // PR c++/16338
+ 
+ const int NULL = 0;
+ int main() { 
+   double* p = NULL; 
+ }
Index: testsuite/g++.dg/parse/namespace10.C
===================================================================
RCS file: testsuite/g++.dg/parse/namespace10.C
diff -N testsuite/g++.dg/parse/namespace10.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- testsuite/g++.dg/parse/namespace10.C	2 Aug 2004 01:40:37 -0000
***************
*** 0 ****
--- 1,9 ----
+ // PR c++/16489
+ 
+ namespace m {} // { dg-error "" }
+ 
+ namespace n {
+   namespace m {}
+ }
+ 
+ namespace m = n::m; // { dg-error "" }
Index: testsuite/g++.dg/tc1/dr76.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/tc1/dr76.C,v
retrieving revision 1.2
diff -c -5 -p -r1.2 dr76.C
*** testsuite/g++.dg/tc1/dr76.C	17 Feb 2004 15:33:49 -0000	1.2
--- testsuite/g++.dg/tc1/dr76.C	2 Aug 2004 01:40:37 -0000
***************
*** 3,8 ****
  // DR76: Are const volatile variables considered "constant expressions"? 
  
  volatile const int a = 5;
  
  template <int> struct K;
! template struct K<a>;	// { dg-error "non-constant" }
--- 3,8 ----
  // DR76: Are const volatile variables considered "constant expressions"? 
  
  volatile const int a = 5;
  
  template <int> struct K;
! template struct K<a>;	// { dg-error "" }


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