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
This commit is contained in:
Mark Mitchell 2004-08-02 01:58:52 +00:00 committed by Mark Mitchell
parent 112ccb83bb
commit c30b4add62
12 changed files with 128 additions and 34 deletions

View file

@ -1,3 +1,20 @@
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>
* call.c (z_candidate::template_decl): Rename from template.

View file

@ -429,6 +429,9 @@ struct z_candidate {
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)
{
@ -436,13 +439,14 @@ null_ptr_cst_p (tree t)
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. */

View file

@ -1821,6 +1821,23 @@ struct lang_decl GTY(())
#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. */

View file

@ -1407,19 +1407,32 @@ duplicate_decls (tree newdecl, tree 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:
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]
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;
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);

View file

@ -3233,9 +3233,7 @@ convert_nontype_argument (tree type, tree expr)
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_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

View file

@ -2564,25 +2564,15 @@ finish_id_expression (tree id_expression,
/* Only certain kinds of names are allowed in constant
expression. Enumerators and template parameters
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
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)
{
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;
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)

View file

@ -5463,7 +5463,10 @@ build_ptrmemfunc (tree type, tree pfn, int force)
}
/* 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)
n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
delta = cp_build_binary_op (PLUS_EXPR, delta, n);

View file

@ -1,3 +1,15 @@
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>
PR target/16155

View file

@ -0,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)();
}

View file

@ -0,0 +1,6 @@
// PR c++/16338
const int NULL = 0;
int main() {
double* p = NULL;
}

View file

@ -0,0 +1,9 @@
// PR c++/16489
namespace m {} // { dg-error "" }
namespace n {
namespace m {}
}
namespace m = n::m; // { dg-error "" }

View file

@ -5,4 +5,4 @@
volatile const int a = 5;
template <int> struct K;
template struct K<a>; // { dg-error "non-constant" }
template struct K<a>; // { dg-error "" }