summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog17
-rw-r--r--gcc/cp/call.c6
-rw-r--r--gcc/cp/cp-tree.h17
-rw-r--r--gcc/cp/decl.c39
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/cp/semantics.c22
-rw-r--r--gcc/cp/typeck.c5
-rw-r--r--gcc/testsuite/ChangeLog12
-rw-r--r--gcc/testsuite/g++.dg/inherit/ptrmem2.C25
-rw-r--r--gcc/testsuite/g++.dg/init/null1.C6
-rw-r--r--gcc/testsuite/g++.dg/parse/namespace10.C9
-rw-r--r--gcc/testsuite/g++.dg/tc1/dr76.C2
12 files changed, 129 insertions, 35 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6122d57b95a..da833d1762a 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a6bfc729352..a34eb271001 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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. */
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8d14911235d..cdb67063f3a 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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. */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c84c4be7687..c4755c0c7b0 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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:
-
- 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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0ecbda0fa15..ad489104974 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 152d75ca1f0..606fe5fc3f6 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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)
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index cad077a13e2..bc458cad8d6 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 69ef9dc680e..c6ae76c8923 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/inherit/ptrmem2.C b/gcc/testsuite/g++.dg/inherit/ptrmem2.C
new file mode 100644
index 00000000000..a13705576a4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/inherit/ptrmem2.C
@@ -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)();
+}
+
diff --git a/gcc/testsuite/g++.dg/init/null1.C b/gcc/testsuite/g++.dg/init/null1.C
new file mode 100644
index 00000000000..37a9a3e3680
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/null1.C
@@ -0,0 +1,6 @@
+// PR c++/16338
+
+const int NULL = 0;
+int main() {
+ double* p = NULL;
+}
diff --git a/gcc/testsuite/g++.dg/parse/namespace10.C b/gcc/testsuite/g++.dg/parse/namespace10.C
new file mode 100644
index 00000000000..aeaae615bc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/namespace10.C
@@ -0,0 +1,9 @@
+// PR c++/16489
+
+namespace m {} // { dg-error "" }
+
+namespace n {
+ namespace m {}
+}
+
+namespace m = n::m; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/tc1/dr76.C b/gcc/testsuite/g++.dg/tc1/dr76.C
index 6d3d1c12a04..0859b0c730e 100644
--- a/gcc/testsuite/g++.dg/tc1/dr76.C
+++ b/gcc/testsuite/g++.dg/tc1/dr76.C
@@ -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 "" }