From dcba9b0fab084c394cbc664809868cbd8071b92e Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Tue, 10 Dec 2002 07:11:46 +0000 Subject: [PATCH] re PR c++/8153 (ICE with static const member in class) PR c++/8153 PR c++/8036 * NEWS: Document removal of in-class initialization extension for static data members of non-arithmetic, non-enumeration type. * decl.c (check_static_variable_definition): Do not allow that extension. * decl2.c (grokfield): Do not call digest_init when processing templates. PR c++/8153 PR c++/8036 * g++.dg/template/static1.C: New test. * g++.dg/template/static2.C: New test. * g++.old-deja/g++.ext/memconst.C: New test. From-SVN: r59980 --- gcc/cp/ChangeLog | 9 ++++ gcc/cp/NEWS | 22 +++++++++ gcc/cp/decl.c | 4 +- gcc/cp/decl2.c | 46 ++++++++++--------- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/template/static1.C | 4 ++ gcc/testsuite/g++.dg/template/static2.C | 17 +++++++ gcc/testsuite/g++.old-deja/g++.ext/memconst.C | 2 +- 8 files changed, 85 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/static1.C create mode 100644 gcc/testsuite/g++.dg/template/static2.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 8d600ac74d0..28bdb17b51e 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2002-12-09 Mark Mitchell + + * NEWS: Document removal of in-class initialization extension for + static data members of non-arithmetic, non-enumeration type. + * decl.c (check_static_variable_definition): Do not allow that + extension. + * decl2.c (grokfield): Do not call digest_init when processing + templates. + 2002-12-05 Kaveh R. Ghazi * error.c (dump_expr): Fix format specifier warning. diff --git a/gcc/cp/NEWS b/gcc/cp/NEWS index 85642b587d9..36720c60443 100644 --- a/gcc/cp/NEWS +++ b/gcc/cp/NEWS @@ -2,6 +2,28 @@ * The "new X = 3" extension has been removed; you must now use "new X(3)". +* G++ no longer allows in-class initializations of static data members + that do not have arithmetic or enumeration type. For example: + + struct S { + static const char* const p = "abc"; + }; + + is no longer accepted. + + Use the standards-conformant form: + + struct S { + static const char* const p; + }; + + const char* const S::p = "abc"; + + instead. + + (ISO C++ is even stricter; it does not allow in-class + initializations of floating-point types.) + *** Changes in GCC 3.1: * -fhonor-std and -fno-honor-std have been removed. -fno-honor-std was diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d881b832a80..e68c06447e1 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -9616,10 +9616,10 @@ check_static_variable_definition (decl, type) the definition, but not both. If it appears in the class, the member is a member constant. The file-scope definition is always required. */ - if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE) + if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE) { error ("invalid in-class initialization of static data member of non-integral type `%T'", - type); + type); /* If we just return the declaration, crashes will sometimes occur. We therefore return void_type_node, as if this was a friend declaration, to cause callers to completely ignore diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 61efb5832ff..248fa2d6725 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -979,30 +979,32 @@ grokfield (declarator, declspecs, init, asmspec_tree, attrlist) else init = digest_init (TREE_TYPE (value), init, (tree *)0); } - - if (TREE_CODE (init) == CONST_DECL) - init = DECL_INITIAL (init); - else if (TREE_READONLY_DECL_P (init)) - init = decl_constant_value (init); - else if (TREE_CODE (init) == CONSTRUCTOR) - init = digest_init (TREE_TYPE (value), init, (tree *)0); - if (init == error_mark_node) - /* We must make this look different than `error_mark_node' - because `decl_const_value' would mis-interpret it - as only meaning that this VAR_DECL is defined. */ - init = build1 (NOP_EXPR, TREE_TYPE (value), init); - else if (processing_template_decl) - ; - else if (! TREE_CONSTANT (init)) + + if (!processing_template_decl) { - /* We can allow references to things that are effectively - static, since references are initialized with the address. */ - if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE - || (TREE_STATIC (init) == 0 - && (!DECL_P (init) || DECL_EXTERNAL (init) == 0))) + if (TREE_CODE (init) == CONST_DECL) + init = DECL_INITIAL (init); + else if (TREE_READONLY_DECL_P (init)) + init = decl_constant_value (init); + else if (TREE_CODE (init) == CONSTRUCTOR) + init = digest_init (TREE_TYPE (value), init, (tree *)0); + if (init == error_mark_node) + /* We must make this look different than `error_mark_node' + because `decl_const_value' would mis-interpret it + as only meaning that this VAR_DECL is defined. */ + init = build1 (NOP_EXPR, TREE_TYPE (value), init); + else if (! TREE_CONSTANT (init)) { - error ("field initializer is not constant"); - init = error_mark_node; + /* We can allow references to things that are effectively + static, since references are initialized with the + address. */ + if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE + || (TREE_STATIC (init) == 0 + && (!DECL_P (init) || DECL_EXTERNAL (init) == 0))) + { + error ("field initializer is not constant"); + init = error_mark_node; + } } } } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b74a2a106b1..ca9c2a6af05 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2002-12-09 Mark Mitchell + + * g++.dg/template/static1.C: New test. + * g++.dg/template/static2.C: New test. + * g++.old-deja/g++.ext/memconst.C: New test. + 2002-12-08 Kaveh R. Ghazi * g++.dg/special/conpr-2.C: Expect failure on solaris2. diff --git a/gcc/testsuite/g++.dg/template/static1.C b/gcc/testsuite/g++.dg/template/static1.C new file mode 100644 index 00000000000..f01d0322e99 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/static1.C @@ -0,0 +1,4 @@ +template struct A +{ + static const int t[1][1]={{0}}; // { dg-error "in-class" } +}; diff --git a/gcc/testsuite/g++.dg/template/static2.C b/gcc/testsuite/g++.dg/template/static2.C new file mode 100644 index 00000000000..d18c1a7fb4e --- /dev/null +++ b/gcc/testsuite/g++.dg/template/static2.C @@ -0,0 +1,17 @@ +class A; + +template +class B +{ +public: + static int A::* const p = P; // { dg-error "in-class" } +}; + +class A +{ +public: + +int dummy; + +B<&A::dummy> d; +}; diff --git a/gcc/testsuite/g++.old-deja/g++.ext/memconst.C b/gcc/testsuite/g++.old-deja/g++.ext/memconst.C index a49d3a05898..a47a45ca8f6 100644 --- a/gcc/testsuite/g++.old-deja/g++.ext/memconst.C +++ b/gcc/testsuite/g++.old-deja/g++.ext/memconst.C @@ -12,7 +12,7 @@ public: class foo { private: - static const unsigned char * const dummy_key = (unsigned char*)"ThisIs a dummy!"; + static const unsigned char * const dummy_key = (unsigned char*)"ThisIs a dummy!"; // { dg-error "in-class" } public: void bar ();