From 2b643edaf8c711e67a882d4508b114fbf1210233 Mon Sep 17 00:00:00 2001 From: Mark Mitchell Date: Mon, 5 Jun 2006 02:46:38 +0000 Subject: re PR c++/27819 (ICE casting static const variables) PR c++/27819 * decl.c (cp_finish_decl): Process initializers for static data members with non-dependent initializers, even in templates. PR c++/27722 * decl.c (maybe_deduce_size_from_array_init): If the declaration is erroneous, give it an erroneous type. (layout_var_decl): If the type is erroneous, give up. (check_initializer): Likewise. PR c++/27807 * cp-tree.h (TYPE_OBJ_P): New macro. (TYPE_PTROB_P): Use it. (TYPE_REF_OBJ_P): Likewise. * semantics.c (finish_compound_literal): Do not permit compound literals of non-object types. PR c++/27806 * typeck.c (original_type): Robustify. PR c++/27819 * g++.dg/template/static25.C: New test. PR c++/27722 * g++.dg/init/array21.C: New test. PR c++/27807 * g++.dg/ext/complit7.C: New test. PR c++/27806 * g++.dg/parse/ptrmem5.C: New test. From-SVN: r114382 --- gcc/cp/ChangeLog | 22 +++++++ gcc/cp/cp-tree.h | 29 ++++++--- gcc/cp/decl.c | 101 ++++++++++++++++++------------- gcc/cp/semantics.c | 6 ++ gcc/cp/typeck.c | 3 +- gcc/testsuite/ChangeLog | 14 +++++ gcc/testsuite/g++.dg/ext/complit7.C | 4 ++ gcc/testsuite/g++.dg/init/array21.C | 7 +++ gcc/testsuite/g++.dg/parse/ptrmem5.C | 9 +++ gcc/testsuite/g++.dg/template/static25.C | 14 +++++ 10 files changed, 159 insertions(+), 50 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/complit7.C create mode 100644 gcc/testsuite/g++.dg/init/array21.C create mode 100644 gcc/testsuite/g++.dg/parse/ptrmem5.C create mode 100644 gcc/testsuite/g++.dg/template/static25.C (limited to 'gcc') diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 7f118ab..3d0fe7f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,25 @@ +2006-06-04 Mark Mitchell + + PR c++/27819 + * decl.c (cp_finish_decl): Process initializers for static data + members with non-dependent initializers, even in templates. + + PR c++/27722 + * decl.c (maybe_deduce_size_from_array_init): If the declaration + is erroneous, give it an erroneous type. + (layout_var_decl): If the type is erroneous, give up. + (check_initializer): Likewise. + + PR c++/27807 + * cp-tree.h (TYPE_OBJ_P): New macro. + (TYPE_PTROB_P): Use it. + (TYPE_REF_OBJ_P): Likewise. + * semantics.c (finish_compound_literal): Do not permit compound + literals of non-object types. + + PR c++/27806 + * typeck.c (original_type): Robustify. + 2006-06-05 Volker Reichelt PR c++/27804 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 486a90d..9253764 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -2515,30 +2515,43 @@ extern void decl_shadowed_for_var_insert (tree, tree); /* Returns true if NODE is a pointer. */ #define TYPE_PTR_P(NODE) \ (TREE_CODE (NODE) == POINTER_TYPE) + +/* Returns true if NODE is an object type: + + [basic.types] + + An object type is a (possibly cv-qualified) type that is not a + function type, not a reference type, and not a void type. + + Keep these checks in ascending order, for speed. */ +#define TYPE_OBJ_P(NODE) \ + (TREE_CODE (NODE) != REFERENCE_TYPE \ + && TREE_CODE (NODE) != VOID_TYPE \ + && TREE_CODE (NODE) != FUNCTION_TYPE \ + && TREE_CODE (NODE) != METHOD_TYPE) + /* Returns true if NODE is a pointer to an object. Keep these checks in ascending tree code order. */ #define TYPE_PTROB_P(NODE) \ - (TYPE_PTR_P (NODE) \ - && !(TREE_CODE (TREE_TYPE (NODE)) == VOID_TYPE \ - || TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE \ - || TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)) + (TYPE_PTR_P (NODE) && TYPE_OBJ_P (TREE_TYPE (NODE))) + /* Returns true if NODE is a reference to an object. Keep these checks in ascending tree code order. */ #define TYPE_REF_OBJ_P(NODE) \ - (TREE_CODE (NODE) == REFERENCE_TYPE \ - && !(TREE_CODE (TREE_TYPE (NODE)) == VOID_TYPE \ - || TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE \ - || TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)) + (TREE_CODE (NODE) == REFERENCE_TYPE && TYPE_OBJ_P (TREE_TYPE (NODE))) + /* Returns true if NODE is a pointer to an object, or a pointer to void. Keep these checks in ascending tree code order. */ #define TYPE_PTROBV_P(NODE) \ (TYPE_PTR_P (NODE) \ && !(TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE \ || TREE_CODE (TREE_TYPE (NODE)) == METHOD_TYPE)) + /* Returns true if NODE is a pointer to function. */ #define TYPE_PTRFN_P(NODE) \ (TREE_CODE (NODE) == POINTER_TYPE \ && TREE_CODE (TREE_TYPE (NODE)) == FUNCTION_TYPE) + /* Returns true if NODE is a reference to function. */ #define TYPE_REFFN_P(NODE) \ (TREE_CODE (NODE) == REFERENCE_TYPE \ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index bccb438..e005d63 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4111,12 +4111,17 @@ maybe_deduce_size_from_array_init (tree decl, tree init) do_default); if (failure == 1) - error ("initializer fails to determine size of %qD", decl); - - if (failure == 2) + { + error ("initializer fails to determine size of %qD", decl); + TREE_TYPE (decl) = error_mark_node; + } + else if (failure == 2) { if (do_default) - error ("array size missing in %qD", decl); + { + error ("array size missing in %qD", decl); + TREE_TYPE (decl) = error_mark_node; + } /* If a `static' var's size isn't known, make it extern as well as static, so it does not get allocated. If it's not `static', then don't mark it extern; finish_incomplete_decl @@ -4124,9 +4129,11 @@ maybe_deduce_size_from_array_init (tree decl, tree init) else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl)) DECL_EXTERNAL (decl) = 1; } - - if (failure == 3) - error ("zero-size array %qD", decl); + else if (failure == 3) + { + error ("zero-size array %qD", decl); + TREE_TYPE (decl) = error_mark_node; + } cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl); @@ -4140,7 +4147,17 @@ maybe_deduce_size_from_array_init (tree decl, tree init) static void layout_var_decl (tree decl) { - tree type = TREE_TYPE (decl); + tree type; + + if (TREE_STATIC (decl) + && !DECL_ARTIFICIAL (decl) + && current_function_decl + && DECL_CONTEXT (decl) == current_function_decl) + push_local_name (decl); + + type = TREE_TYPE (decl); + if (type == error_mark_node) + return; /* If we haven't already layed out this declaration, do so now. Note that we must not call complete type for an external object @@ -4186,12 +4203,6 @@ layout_var_decl (tree decl) else error ("storage size of %qD isn't constant", decl); } - - if (TREE_STATIC (decl) - && !DECL_ARTIFICIAL (decl) - && current_function_decl - && DECL_CONTEXT (decl) == current_function_decl) - push_local_name (decl); } /* If a local static variable is declared in an inline function, or if @@ -4714,6 +4725,8 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup) array size from the initializer. */ maybe_deduce_size_from_array_init (decl, init); type = TREE_TYPE (decl); + if (type == error_mark_node) + return NULL_TREE; if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type)) { @@ -4977,6 +4990,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, const char *asmspec = NULL; int was_readonly = 0; bool var_definition_p = false; + int saved_processing_template_decl; if (decl == error_mark_node) return; @@ -4988,9 +5002,16 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, } gcc_assert (TREE_CODE (decl) != RESULT_DECL); + /* Parameters are handled by store_parm_decls, not cp_finish_decl. */ + gcc_assert (TREE_CODE (decl) != PARM_DECL); + + type = TREE_TYPE (decl); + if (type == error_mark_node) + return; /* Assume no cleanup is required. */ cleanup = NULL_TREE; + saved_processing_template_decl = processing_template_decl; /* If a name was specified, get the string. */ if (global_scope_p (current_binding_level)) @@ -4998,51 +5019,48 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, if (asmspec_tree) asmspec = TREE_STRING_POINTER (asmspec_tree); - if (init && TREE_CODE (init) == NAMESPACE_DECL) - { - error ("cannot initialize %qD to namespace %qD", decl, init); - init = NULL_TREE; - } - if (current_class_type && CP_DECL_CONTEXT (decl) == current_class_type && TYPE_BEING_DEFINED (current_class_type) && (DECL_INITIAL (decl) || init)) DECL_INITIALIZED_IN_CLASS_P (decl) = 1; - type = TREE_TYPE (decl); - - if (type == error_mark_node) - goto finish_end; - if (processing_template_decl) { + bool type_dependent_p; + /* Add this declaration to the statement-tree. */ if (at_function_scope_p ()) add_decl_expr (decl); - if (init) + type_dependent_p = dependent_type_p (type); + + if (init && init_const_expr_p) { - DECL_INITIAL (decl) = init; - if (init_const_expr_p) - { - DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1; - if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)) - TREE_CONSTANT (decl) = 1; - } + DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1; + if (DECL_INTEGRAL_CONSTANT_VAR_P (decl)) + TREE_CONSTANT (decl) = 1; } - if (TREE_CODE (decl) == VAR_DECL - && !DECL_PRETTY_FUNCTION_P (decl) - && !dependent_type_p (TREE_TYPE (decl))) - maybe_deduce_size_from_array_init (decl, init); + if (!init + || !DECL_CLASS_SCOPE_P (decl) + || !DECL_INTEGRAL_CONSTANT_VAR_P (decl) + || type_dependent_p + || value_dependent_expression_p (init)) + { + if (init) + DECL_INITIAL (decl) = init; + if (TREE_CODE (decl) == VAR_DECL + && !DECL_PRETTY_FUNCTION_P (decl) + && !type_dependent_p) + maybe_deduce_size_from_array_init (decl, init); + goto finish_end; + } - goto finish_end; + init = fold_non_dependent_expr (init); + processing_template_decl = 0; } - /* Parameters are handled by store_parm_decls, not cp_finish_decl. */ - gcc_assert (TREE_CODE (decl) != PARM_DECL); - /* Take care of TYPE_DECLs up front. */ if (TREE_CODE (decl) == TYPE_DECL) { @@ -5236,6 +5254,7 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, push_cleanup (decl, cleanup, false); finish_end: + processing_template_decl = saved_processing_template_decl; if (was_readonly) TREE_READONLY (decl) = 1; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 976005c..06ed52d 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -2021,6 +2021,12 @@ finish_compound_literal (tree type, VEC(constructor_elt,gc) *initializer_list) tree var; tree compound_literal; + if (!TYPE_OBJ_P (type)) + { + error ("compound literal of non-object type %qT", type); + return error_mark_node; + } + /* Build a CONSTRUCTOR for the INITIALIZER_LIST. */ compound_literal = build_constructor (NULL_TREE, initializer_list); if (processing_template_decl) diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 5861f23..7ddbf23 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -228,7 +228,8 @@ commonparms (tree p1, tree p2) static tree original_type (tree t) { - while (TYPE_NAME (t) != NULL_TREE) + while (t != error_mark_node + && TYPE_NAME (t) != NULL_TREE) { tree x = TYPE_NAME (t); if (TREE_CODE (x) != TYPE_DECL) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index b325d67..1396e30 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,17 @@ +2006-06-04 Mark Mitchell + + PR c++/27819 + * g++.dg/template/static25.C: New test. + + PR c++/27722 + * g++.dg/init/array21.C: New test. + + PR c++/27807 + * g++.dg/ext/complit7.C: New test. + + PR c++/27806 + * g++.dg/parse/ptrmem5.C: New test. + 2006-06-04 Roger Sayle Andrew Pinski diff --git a/gcc/testsuite/g++.dg/ext/complit7.C b/gcc/testsuite/g++.dg/ext/complit7.C new file mode 100644 index 0000000..bceb6d1 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/complit7.C @@ -0,0 +1,4 @@ +// PR c++/27807 +// { dg-options "" } + +int i = (int()){0}; // { dg-error "type" } diff --git a/gcc/testsuite/g++.dg/init/array21.C b/gcc/testsuite/g++.dg/init/array21.C new file mode 100644 index 0000000..f41ce86 --- /dev/null +++ b/gcc/testsuite/g++.dg/init/array21.C @@ -0,0 +1,7 @@ +// PR c++/27722 + +void foo() +{ + const int x[] = 0; // { dg-error "size" } + ++x; +} diff --git a/gcc/testsuite/g++.dg/parse/ptrmem5.C b/gcc/testsuite/g++.dg/parse/ptrmem5.C new file mode 100644 index 0000000..1101ad9 --- /dev/null +++ b/gcc/testsuite/g++.dg/parse/ptrmem5.C @@ -0,0 +1,9 @@ +// PR c++/27806 + +struct A {}; + +void foo() +{ + p; // { dg-error "p" } + extern int A::* p; +} diff --git a/gcc/testsuite/g++.dg/template/static25.C b/gcc/testsuite/g++.dg/template/static25.C new file mode 100644 index 0000000..20c0c84 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/static25.C @@ -0,0 +1,14 @@ +// PR c++/27819 + +struct A +{ + static const char i = 1; +}; + +template struct B +{ + static const int j = A::i; + int x[int(j)]; +}; + +B<0> b; -- cgit v1.1