+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.
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)
{
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. */
#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. */
/* 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 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);
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
/* 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)
}
/* 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);
+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
--- /dev/null
+// 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)();
+}
+
--- /dev/null
+// PR c++/16338
+
+const int NULL = 0;
+int main() {
+ double* p = NULL;
+}
--- /dev/null
+// PR c++/16489
+
+namespace m {} // { dg-error "" }
+
+namespace n {
+ namespace m {}
+}
+
+namespace m = n::m; // { dg-error "" }
volatile const int a = 5;
template <int> struct K;
-template struct K<a>; // { dg-error "non-constant" }
+template struct K<a>; // { dg-error "" }