From c30b4add62a69bba7271b49d6f31f43187af5cd6 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 2 Aug 2004 01:58:52 +0000 Subject: [PATCH] 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 --- gcc/cp/ChangeLog | 17 +++++++++++ gcc/cp/call.c | 6 +++- gcc/cp/cp-tree.h | 17 +++++++++++ gcc/cp/decl.c | 39 ++++++++++++++++-------- gcc/cp/pt.c | 4 +-- gcc/cp/semantics.c | 22 ++++--------- gcc/cp/typeck.c | 5 ++- gcc/testsuite/ChangeLog | 12 ++++++++ gcc/testsuite/g++.dg/inherit/ptrmem2.C | 25 +++++++++++++++ gcc/testsuite/g++.dg/init/null1.C | 6 ++++ gcc/testsuite/g++.dg/parse/namespace10.C | 9 ++++++ gcc/testsuite/g++.dg/tc1/dr76.C | 2 +- 12 files changed, 129 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/g++.dg/inherit/ptrmem2.C create mode 100644 gcc/testsuite/g++.dg/init/null1.C create mode 100644 gcc/testsuite/g++.dg/parse/namespace10.C 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 + + 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 * 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 + + 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 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 struct K; -template struct K; // { dg-error "non-constant" } +template struct K; // { dg-error "" } -- 2.30.2