aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog22
-rw-r--r--gcc/cp/cp-tree.h29
-rw-r--r--gcc/cp/decl.c101
-rw-r--r--gcc/cp/semantics.c6
-rw-r--r--gcc/cp/typeck.c3
-rw-r--r--gcc/testsuite/ChangeLog14
-rw-r--r--gcc/testsuite/g++.dg/ext/complit7.C4
-rw-r--r--gcc/testsuite/g++.dg/init/array21.C7
-rw-r--r--gcc/testsuite/g++.dg/parse/ptrmem5.C9
-rw-r--r--gcc/testsuite/g++.dg/template/static25.C14
10 files changed, 159 insertions, 50 deletions
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 <mark@codesourcery.com>
+
+ 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 <reichelt@igpm.rwth-aachen.de>
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 <mark@codesourcery.com>
+
+ 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 <roger@eyesopen.com>
Andrew Pinski <pinskia@physics.uc.edu>
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<int> struct B
+{
+ static const int j = A::i;
+ int x[int(j)];
+};
+
+B<0> b;