This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR 16338, 16489, 16810
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 1 Aug 2004 19:00:01 -0700
- Subject: C++ PATCH: PR 16338, 16489, 16810
- Reply-to: mark at codesourcery dot com
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 "" }