This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix cp_parser_direct_declarator (PR c++/29886)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Mark Mitchell <mark at codesourcery dot com>, Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Thu, 23 Nov 2006 11:26:00 -0500
- Subject: [C++ PATCH] Fix cp_parser_direct_declarator (PR c++/29886)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
cp_parser_direct_declarator is used even in tentative parsing, but
is unconditionally issuing error, which breaks the attached testcase.
I don't see any machiner in cp/parser.c which would allow to queue
non-parsing errors and emit them only when we definitely commit
to parse it. The following patch instead moves the diagnostic
emitting to grokdeclarator. As array.bounds == NULL_TREE is used for
[] arrays and there might be other reason why error_mark_node would be
stored in array.bounds, I chose just to stick a pointer to the error
message string into an otherwise unused padding in struct cp_declarator
(u.array is smaller than other union fields) instead of always emitting
a hardcoded error message when array.bounds == error_mark_node
or coming up with another special value for array.bounds.
As explained elsewhere in parser.c, we need to record somewhere
whether the array bounds were non_constant_p or not, that information
can't be deduced from whether bounds is INTEGER_CST or not.
Ok for 4.1/4.2/4.3?
2006-11-23 Jakub Jelinek <jakub@redhat.com>
PR c++/29886
* cp-tree.h (struct cp_declarator): Add array.error_msg field.
* parser.c: Include intl.h.
(make_array_declarator): Add error_msg argument, set array.error_msg.
(cp_parser_direct_new_declarator): Adjust caller.
(cp_parser_direct_declarator): Instead of issuing error message about
non-constant bounds pass the error message string to
make_array_declarator.
* decl.c (grokdeclarator): If array.error_msg is non-NULL, issue
diagnostics.
* Makefile.in (cp/parser.o): Depend on intl.h.
* g++.dg/parse/array1.C: New test.
--- gcc/cp/cp-tree.h.jj 2006-11-23 10:23:51.000000000 +0100
+++ gcc/cp/cp-tree.h 2006-11-23 16:08:52.000000000 +0100
@@ -3762,6 +3762,9 @@ struct cp_declarator {
struct {
/* The bounds to the array. */
tree bounds;
+ /* Error message about array bounds that should be emitted if
+ non-NULL. */
+ const char *error_msg;
} array;
/* For cdk_pointer, cdk_reference, and cdk_ptrmem. */
struct {
--- gcc/cp/parser.c.jj 2006-11-23 10:23:51.000000000 +0100
+++ gcc/cp/parser.c 2006-11-23 16:23:37.000000000 +0100
@@ -38,6 +38,7 @@
#include "target.h"
#include "cgraph.h"
#include "c-common.h"
+#include "intl.h"
/* The lexer. */
@@ -820,7 +821,7 @@ clear_decl_specs (cp_decl_specifier_seq
static cp_declarator *make_call_declarator
(cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree);
static cp_declarator *make_array_declarator
- (cp_declarator *, tree);
+ (cp_declarator *, tree, const char *);
static cp_declarator *make_pointer_declarator
(cp_cv_quals, cp_declarator *);
static cp_declarator *make_reference_declarator
@@ -970,16 +971,19 @@ make_call_declarator (cp_declarator *tar
}
/* Make a declarator for an array of BOUNDS elements, each of which is
- defined by ELEMENT. */
+ defined by ELEMENT. ERROR_MSG is an error message that should be
+ emitted if any when creating the trees. */
cp_declarator *
-make_array_declarator (cp_declarator *element, tree bounds)
+make_array_declarator (cp_declarator *element, tree bounds,
+ const char *error_msg)
{
cp_declarator *declarator;
declarator = make_declarator (cdk_array);
declarator->declarator = element;
declarator->u.array.bounds = bounds;
+ declarator->u.array.error_msg = error_msg;
return declarator;
}
@@ -5399,7 +5403,7 @@ cp_parser_direct_new_declarator (cp_pars
cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
/* Add this bound to the declarator. */
- declarator = make_array_declarator (declarator, expression);
+ declarator = make_array_declarator (declarator, expression, NULL);
/* If the next token is not a `[', then there are no more
bounds. */
@@ -11672,6 +11676,7 @@ cp_parser_direct_declarator (cp_parser*
{
/* Parse an array-declarator. */
tree bounds;
+ const char *error_msg = NULL;
if (ctor_dtor_or_conv_p)
*ctor_dtor_or_conv_p = 0;
@@ -11700,7 +11705,7 @@ cp_parser_direct_declarator (cp_parser*
in function scopes. */
else if (!at_function_scope_p ())
{
- error ("array bound is not an integer constant");
+ error_msg = N_("array bound is not an integer constant");
bounds = error_mark_node;
}
}
@@ -11713,7 +11718,7 @@ cp_parser_direct_declarator (cp_parser*
break;
}
- declarator = make_array_declarator (declarator, bounds);
+ declarator = make_array_declarator (declarator, bounds, error_msg);
}
else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
{
--- gcc/cp/decl.c.jj 2006-11-23 10:23:51.000000000 +0100
+++ gcc/cp/decl.c 2006-11-23 16:22:58.000000000 +0100
@@ -7525,6 +7525,8 @@ grokdeclarator (const cp_declarator *dec
switch (declarator->kind)
{
case cdk_array:
+ if (declarator->u.array.error_msg)
+ error (declarator->u.array.error_msg);
type = create_array_type_for_decl (dname, type,
declarator->u.array.bounds);
break;
--- gcc/cp/Make-lang.in.jj 2006-11-20 21:11:41.000000000 +0100
+++ gcc/cp/Make-lang.in 2006-11-20 21:11:41.000000000 +0100
@@ -287,7 +287,7 @@ cp/optimize.o: cp/optimize.c $(CXX_TREE_
cp/mangle.o: cp/mangle.c $(CXX_TREE_H) $(TM_H) toplev.h $(REAL_H) \
gt-cp-mangle.h $(TARGET_H) $(TM_P_H)
cp/parser.o: cp/parser.c $(CXX_TREE_H) $(TM_H) $(DIAGNOSTIC_H) gt-cp-parser.h \
- output.h $(TARGET_H)
+ output.h $(TARGET_H) intl.h
cp/cp-gimplify.o: cp/cp-gimplify.c $(CXX_TREE_H) toplev.h $(C_COMMON_H) \
$(TM_H) coretypes.h pointer-set.h
--- gcc/testsuite/g++.dg/parse/array1.C.jj 2006-11-23 16:36:07.000000000 +0100
+++ gcc/testsuite/g++.dg/parse/array1.C 2006-11-23 16:34:53.000000000 +0100
@@ -0,0 +1,24 @@
+// PR c++/29886
+// { dg-do compile }
+
+struct A
+{
+ static int x[2];
+};
+int y[2];
+struct B
+{
+ static int z[2];
+};
+int A::z[(3, 2)]; // { dg-error "array bound is not an integer constant" }
+
+void
+foo (int i)
+{
+ int j = int (A::x[i]);
+ switch (int (A::x[i])) {}
+ if (int (A::x[i])) {}
+ j = int (y[i]);
+ switch (int (y[i])) {}
+ if (int (y[i])) {}
+}
Jakub