Commit c30b4add by Mark Mitchell Committed by Mark Mitchell

re PR c++/16338 (ICE when throwing a compound literal)

	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.

	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.

From-SVN: r85421
parent 112ccb83
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 Gabriel Dos Reis <gdr@integrable-solutions.net> 2004-08-01 Gabriel Dos Reis <gdr@integrable-solutions.net>
* call.c (z_candidate::template_decl): Rename from template. * call.c (z_candidate::template_decl): Rename from template.
......
...@@ -429,6 +429,9 @@ struct z_candidate { ...@@ -429,6 +429,9 @@ struct z_candidate {
z_candidate *next; z_candidate *next;
}; };
/* Returns true iff T is a null pointer constant in the sense of
[conv.ptr]. */
bool bool
null_ptr_cst_p (tree t) null_ptr_cst_p (tree t)
{ {
...@@ -436,13 +439,14 @@ null_ptr_cst_p (tree t) ...@@ -436,13 +439,14 @@ null_ptr_cst_p (tree t)
A null pointer constant is an integral constant expression A null pointer constant is an integral constant expression
(_expr.const_) rvalue of integer type that evaluates to zero. */ (_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 if (t == null_node
|| (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))) || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
return true; return true;
return false; return false;
} }
/* Returns nonzero if PARMLIST consists of only default parms and/or /* Returns nonzero if PARMLIST consists of only default parms and/or
ellipsis. */ ellipsis. */
......
...@@ -1821,6 +1821,23 @@ struct lang_decl GTY(()) ...@@ -1821,6 +1821,23 @@ struct lang_decl GTY(())
#define DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P(NODE) \ #define DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P(NODE) \
(TREE_LANG_FLAG_2 (VAR_DECL_CHECK (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, /* Nonzero if the DECL was initialized in the class definition itself,
rather than outside the class. This is used for both static member rather than outside the class. This is used for both static member
VAR_DECLS, and FUNTION_DECLS that are defined in the class. */ VAR_DECLS, and FUNTION_DECLS that are defined in the class. */
......
...@@ -1407,19 +1407,32 @@ duplicate_decls (tree newdecl, tree olddecl) ...@@ -1407,19 +1407,32 @@ duplicate_decls (tree newdecl, tree olddecl)
/* One of the declarations is a template instantiation, and the /* One of the declarations is a template instantiation, and the
other is not a template at all. That's OK. */ other is not a template at all. That's OK. */
return NULL_TREE; return NULL_TREE;
else if (TREE_CODE (newdecl) == NAMESPACE_DECL 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 [namespace.alias] we have:
In a declarative region, a namespace-alias-definition can be
In a declarative region, a namespace-alias-definition can be used to redefine a namespace-alias declared in that declarative
used to redefine a namespace-alias declared in that declarative region to refer only to the namespace to which it already
region to refer only to the namespace to which it already refers.
refers.
Therefore, if we encounter a second alias directive for the same
Therefore, if we encounter a second alias directive for the same alias, we can just ignore the second directive. */
alias, we can just ignore the second directive. */ if (DECL_NAMESPACE_ALIAS (newdecl)
return olddecl; && (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 else
{ {
const char *errmsg = redeclaration_error_message (newdecl, olddecl); const char *errmsg = redeclaration_error_message (newdecl, olddecl);
......
...@@ -3233,9 +3233,7 @@ convert_nontype_argument (tree type, tree expr) ...@@ -3233,9 +3233,7 @@ convert_nontype_argument (tree type, tree expr)
will not return the initializer. Handle that special case will not return the initializer. Handle that special case
here. */ here. */
if (expr == const_expr if (expr == const_expr
&& TREE_CODE (expr) == VAR_DECL && DECL_INTEGRAL_CONSTANT_VAR_P (expr)
&& 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 /* DECL_INITIAL can be NULL if we are processing a
variable initialized to an expression involving itself. variable initialized to an expression involving itself.
We know it is initialized to a constant -- but not what We know it is initialized to a constant -- but not what
......
...@@ -2564,25 +2564,15 @@ finish_id_expression (tree id_expression, ...@@ -2564,25 +2564,15 @@ finish_id_expression (tree id_expression,
/* Only certain kinds of names are allowed in constant /* Only certain kinds of names are allowed in constant
expression. Enumerators and template parameters expression. Enumerators and template parameters
have already been handled above. */ have already been handled above. */
if (integral_constant_expression_p) if (integral_constant_expression_p
&& !DECL_INTEGRAL_CONSTANT_VAR_P (decl))
{ {
/* Const variables or static data members of integral or if (!allow_non_integral_constant_expression_p)
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;
error ("`%D' cannot appear in a constant-expression", decl);
return error_mark_node;
}
*non_integral_constant_expression_p = true;
} }
*non_integral_constant_expression_p = true;
} }
if (TREE_CODE (decl) == NAMESPACE_DECL) if (TREE_CODE (decl) == NAMESPACE_DECL)
......
...@@ -5463,7 +5463,10 @@ build_ptrmemfunc (tree type, tree pfn, int force) ...@@ -5463,7 +5463,10 @@ build_ptrmemfunc (tree type, tree pfn, int force)
} }
/* Just adjust the DELTA field. */ /* Just adjust the DELTA field. */
my_friendly_assert (TREE_TYPE (delta) == ptrdiff_type_node, 20030727); 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) if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node); n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
delta = cp_build_binary_op (PLUS_EXPR, delta, n); delta = cp_build_binary_op (PLUS_EXPR, delta, n);
......
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.
2004-08-02 Ben Elliston <bje@au.ibm.com> 2004-08-02 Ben Elliston <bje@au.ibm.com>
PR target/16155 PR target/16155
......
// 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)();
}
// PR c++/16338
const int NULL = 0;
int main() {
double* p = NULL;
}
// PR c++/16489
namespace m {} // { dg-error "" }
namespace n {
namespace m {}
}
namespace m = n::m; // { dg-error "" }
...@@ -5,4 +5,4 @@ ...@@ -5,4 +5,4 @@
volatile const int a = 5; volatile const int a = 5;
template <int> struct K; template <int> struct K;
template struct K<a>; // { dg-error "non-constant" } template struct K<a>; // { dg-error "" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment