@@ -116,7 +116,6 @@ CXX_KEYWORD inline|public:|private:|protected:|template|operator|friend
return IGNORABLE_CXX_KEYWORD;
}
"GTY"/{EOID} { return GTY_TOKEN; }
-"VEC"/{EOID} { return VEC_TOKEN; }
"union"/{EOID} { return UNION; }
"struct"/{EOID} { return STRUCT; }
"class"/{EOID} { return STRUCT; }
@@ -163,7 +162,7 @@ CXX_KEYWORD inline|public:|private:|protected:|template|operator|friend
}
"..." { return ELLIPSIS; }
-[(){},*:<>;=%|+-] { return yytext[0]; }
+[(){},*:<>;=%|+\!\?\.-] { return yytext[0]; }
/* ignore pp-directives */
^{HWS}"#"{HWS}[a-z_]+[^\n]*\n {lexer_line.line++;}
@@ -76,7 +76,6 @@ static const char *const token_names[] = {
"union",
"struct",
"enum",
- "VEC",
"...",
"ptr_alias",
"nested_ptr",
@@ -245,31 +244,12 @@ require_template_declaration (const char *tmpl_name)
}
-/* typedef_name: either an ID, or VEC(x,y), or a template type
- specification of the form ID<t1,t2,...,tn>.
-
- FIXME cxx-conversion. VEC(x,y) is currently translated to the
- template 'vec_t<x>'. This is to support the transition to C++ and
- avoid re-writing all the 'VEC(x,y)' declarations in the code. This
- needs to be fixed when the branch is merged into trunk. */
+/* typedef_name: either an ID, or a template type
+ specification of the form ID<t1,t2,...,tn>. */
static const char *
typedef_name (void)
{
- if (token () == VEC_TOKEN)
- {
- const char *c1, *r;
- advance ();
- require ('(');
- c1 = require2 (ID, SCALAR);
- require (',');
- require (ID);
- require (')');
- r = concat ("vec_t<", c1, ">", (char *) 0);
- free (CONST_CAST (char *, c1));
- return r;
- }
-
const char *id = require (ID);
if (token () == '<')
return require_template_declaration (id);
@@ -826,7 +806,6 @@ type (options_p *optsp, bool nested)
return create_scalar_type (s);
case ID:
- case VEC_TOKEN:
s = typedef_name ();
return resolve_typedef (s, &lexer_line);
@@ -907,6 +886,7 @@ type (options_p *optsp, bool nested)
fields = NULL;
kind = TYPE_USER_STRUCT;
consume_balanced ('{', '}');
+ return create_user_defined_type (s, &lexer_line);
}
return new_structure (s, kind, &lexer_line, fields, opts);
@@ -52,6 +52,7 @@ type_lineloc (const_type_p ty)
case TYPE_UNION:
case TYPE_LANG_STRUCT:
case TYPE_USER_STRUCT:
+ case TYPE_UNDEFINED:
return CONST_CAST (struct fileloc*, &ty->u.s.line);
case TYPE_PARAM_STRUCT:
return CONST_CAST (struct fileloc*, &ty->u.param_struct.line);
@@ -770,6 +771,23 @@ write_state_string_type (type_p current)
fatal ("Unexpected type in write_state_string_type");
}
+/* Write an undefined type. */
+static void
+write_state_undefined_type (type_p current)
+{
+ DBGPRINTF ("undefined type @ %p #%d '%s'", (void *) current,
+ current->state_number, current->u.s.tag);
+ fprintf (state_file, "undefined ");
+ gcc_assert (current->gc_used == GC_UNUSED);
+ write_state_common_type_content (current);
+ if (current->u.s.tag != NULL)
+ write_state_a_string (current->u.s.tag);
+ else
+ fprintf (state_file, "nil");
+
+ write_state_fileloc (type_lineloc (current));
+}
+
/* Common code to write structure like types. */
static void
@@ -963,6 +981,9 @@ write_state_type (type_p current)
{
case TYPE_NONE:
gcc_unreachable ();
+ case TYPE_UNDEFINED:
+ write_state_undefined_type (current);
+ break;
case TYPE_STRUCT:
write_state_struct_type (current);
break;
@@ -1345,6 +1366,40 @@ read_state_lang_bitmap (lang_bitmap *bitmap)
}
+/* Read an undefined type. */
+static void
+read_state_undefined_type (type_p type)
+{
+ struct state_token_st *t0;
+
+ type->kind = TYPE_UNDEFINED;
+ read_state_common_type_content (type);
+ t0 = peek_state_token (0);
+ if (state_token_kind (t0) == STOK_STRING)
+ {
+ if (state_token_is_name (t0, "nil"))
+ {
+ type->u.s.tag = NULL;
+ DBGPRINTF ("read anonymous undefined type @%p #%d",
+ (void *) type, type->state_number);
+ }
+ else
+ {
+ type->u.s.tag = xstrdup (t0->stok_un.stok_string);
+ DBGPRINTF ("read undefined type @%p #%d '%s'",
+ (void *) type, type->state_number, type->u.s.tag);
+ }
+
+ next_state_tokens (1);
+ read_state_fileloc (&(type->u.s.line));
+ }
+ else
+ {
+ fatal_reading_state (t0, "Bad tag in undefined type");
+ }
+}
+
+
/* Read a GTY-ed struct type. */
static void
read_state_struct_type (type_p type)
@@ -1673,6 +1728,12 @@ read_state_type (type_p *current)
next_state_tokens (1);
read_state_string_type (current);
}
+ else if (state_token_is_name (t0, "undefined"))
+ {
+ *current = XCNEW (struct type);
+ next_state_tokens (1);
+ read_state_undefined_type (*current);
+ }
else if (state_token_is_name (t0, "struct"))
{
*current = XCNEW (struct type);
@@ -171,13 +171,15 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
int nb_types = 0, nb_scalar = 0, nb_string = 0;
int nb_struct = 0, nb_union = 0, nb_array = 0, nb_pointer = 0;
int nb_lang_struct = 0, nb_param_struct = 0;
- int nb_user_struct = 0;
+ int nb_user_struct = 0, nb_undefined = 0;
type_p p = NULL;
for (p = t; p; p = p->next)
{
nb_types++;
switch (p->kind)
{
+ case TYPE_UNDEFINED:
+ nb_undefined++;
case TYPE_SCALAR:
nb_scalar++;
break;
@@ -205,7 +207,7 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
case TYPE_PARAM_STRUCT:
nb_param_struct++;
break;
- default:
+ case TYPE_NONE:
gcc_unreachable ();
}
}
@@ -222,6 +224,8 @@ dbgprint_count_type_at (const char *fil, int lin, const char *msg, type_p t)
nb_lang_struct, nb_param_struct);
if (nb_user_struct > 0)
fprintf (stderr, "@@%%@@ %d user_structs\n", nb_user_struct);
+ if (nb_undefined > 0)
+ fprintf (stderr, "@@%%@@ %d undefined types\n", nb_undefined);
fprintf (stderr, "\n");
}
#endif /* ENABLE_CHECKING */
@@ -553,7 +557,7 @@ do_scalar_typedef (const char *s, struct fileloc *pos)
/* Define TYPE_NAME to be a user defined type at location POS. */
-static type_p
+type_p
create_user_defined_type (const char *type_name, struct fileloc *pos)
{
type_p ty = find_structure (type_name, TYPE_USER_STRUCT);
@@ -595,20 +599,58 @@ create_user_defined_type (const char *type_name, struct fileloc *pos)
}
-/* Return the type previously defined for S. Use POS to report errors. */
+/* Given a typedef name S, return its associated type. Return NULL if
+ S is not a registered type name. */
-type_p
-resolve_typedef (const char *s, struct fileloc *pos)
+static type_p
+type_for_name (const char *s)
{
pair_p p;
for (p = typedefs; p != NULL; p = p->next)
if (strcmp (p->name, s) == 0)
return p->type;
+ return NULL;
+}
+
+
+/* Create an undefined type with name S and location POS. Return the
+ newly created type. */
+
+static type_p
+create_undefined_type (const char *s, struct fileloc *pos)
+{
+ type_p ty = find_structure (s, TYPE_UNDEFINED);
+ ty->u.s.line = *pos;
+ ty->u.s.bitmap = get_lang_bitmap (pos->file);
+ do_typedef (s, ty, pos);
+ return ty;
+}
+
+
+/* Return the type previously defined for S. Use POS to report errors. */
- /* If we did not find a typedef registered, assume this is a name
- for a user-defined type which will need to provide its own
- marking functions. */
- return create_user_defined_type (s, pos);
+type_p
+resolve_typedef (const char *s, struct fileloc *pos)
+{
+ bool is_template_instance = (strchr (s, '<') != NULL);
+ type_p p = type_for_name (s);
+
+ /* If we did not find a typedef registered, generate a TYPE_UNDEFINED
+ type for regular type identifiers. If the type identifier S is a
+ template instantiation, however, we treat it as a user defined
+ type.
+
+ FIXME, this is actually a limitation in gengtype. Supporting
+ template types and their instances would require keeping separate
+ track of the basic types definition and its instances. This
+ essentially forces all template classes in GC to be marked
+ GTY((user)). */
+ if (!p)
+ p = (is_template_instance)
+ ? create_user_defined_type (s, pos)
+ : create_undefined_type (s, pos);
+
+ return p;
}
@@ -707,7 +749,7 @@ find_structure (const char *name, enum typekind kind)
type_p s;
bool isunion = (kind == TYPE_UNION);
- gcc_assert (union_or_struct_p (kind));
+ gcc_assert (kind == TYPE_UNDEFINED || union_or_struct_p (kind));
for (s = structures; s != NULL; s = s->next)
if (strcmp (name, s->u.s.tag) == 0 && UNION_P (s) == isunion)
@@ -1397,7 +1439,8 @@ adjust_field_type (type_p t, options_p opt)
}
-static void set_gc_used_type (type_p, enum gc_used_enum, type_p *);
+static void set_gc_used_type (type_p, enum gc_used_enum, type_p *,
+ bool = false);
static void set_gc_used (pair_p);
/* Handle OPT for set_gc_used_type. */
@@ -1427,9 +1470,31 @@ process_gc_options (options_p opt, enum gc_used_enum level, int *maybe_undef,
}
-/* Set the gc_used field of T to LEVEL, and handle the types it references. */
+/* Set the gc_used field of T to LEVEL, and handle the types it references.
+
+ If ALLOWED_UNDEFINED_TYPES is true, types of kind TYPE_UNDEFINED
+ are set to GC_UNUSED. Otherwise, an error is emitted for
+ TYPE_UNDEFINED types. This is used to support user-defined
+ template types with non-type arguments.
+
+ For instance, when we parse a template type with enum arguments
+ (e.g. MyType<AnotherType, EnumValue>), the parser created two
+ artificial fields for 'MyType', one for 'AnotherType', the other
+ one for 'EnumValue'.
+
+ At the time that we parse this type we don't know that 'EnumValue'
+ is really an enum value, so the parser creates a TYPE_UNDEFINED
+ type for it. Since 'EnumValue' is never resolved to a known
+ structure, it will stay with TYPE_UNDEFINED.
+
+ Since 'MyType' is a TYPE_USER_STRUCT, we can simply ignore
+ 'EnumValue'. Generating marking code for it would cause
+ compilation failures since the marking routines assumes that
+ 'EnumValue' is a type. */
+
static void
-set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
+set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM],
+ bool allow_undefined_types)
{
if (t->gc_used >= level)
return;
@@ -1445,6 +1510,7 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
pair_p f;
int dummy;
type_p dummy2;
+ bool allow_undefined_field_types = (t->kind == TYPE_USER_STRUCT);
process_gc_options (t->u.s.opt, level, &dummy, &dummy, &dummy, &dummy,
&dummy2);
@@ -1472,11 +1538,21 @@ set_gc_used_type (type_p t, enum gc_used_enum level, type_p param[NUM_PARAM])
else if (skip)
; /* target type is not used through this field */
else
- set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL);
+ set_gc_used_type (f->type, GC_USED, pass_param ? param : NULL,
+ allow_undefined_field_types);
}
break;
}
+ case TYPE_UNDEFINED:
+ if (level > GC_UNUSED)
+ {
+ if (!allow_undefined_types)
+ error_at_line (&t->u.s.line, "undefined type `%s'", t->u.s.tag);
+ t->gc_used = GC_UNUSED;
+ }
+ break;
+
case TYPE_POINTER:
set_gc_used_type (t->u.p, GC_POINTED_TO, NULL);
break;
@@ -2397,7 +2473,7 @@ filter_type_name (const char *type_name)
size_t i;
char *s = xstrdup (type_name);
for (i = 0; i < strlen (s); i++)
- if (s[i] == '<' || s[i] == '>' || s[i] == ':')
+ if (s[i] == '<' || s[i] == '>' || s[i] == ':' || s[i] == ',')
s[i] = '_';
return s;
}
@@ -2417,6 +2493,7 @@ output_mangled_typename (outf_p of, const_type_p t)
switch (t->kind)
{
case TYPE_NONE:
+ case TYPE_UNDEFINED:
gcc_unreachable ();
break;
case TYPE_POINTER:
@@ -3042,7 +3119,8 @@ walk_type (type_p t, struct walk_type_data *d)
d->process_field (t, d);
break;
- default:
+ case TYPE_NONE:
+ case TYPE_UNDEFINED:
gcc_unreachable ();
}
}
@@ -3059,6 +3137,7 @@ write_types_process_field (type_p f, const struct walk_type_data *d)
switch (f->kind)
{
case TYPE_NONE:
+ case TYPE_UNDEFINED:
gcc_unreachable ();
case TYPE_POINTER:
oprintf (d->of, "%*s%s (%s%s", d->indent, "",
@@ -3265,7 +3344,6 @@ write_marker_function_name (outf_p of, type_p s, const char *prefix)
gcc_unreachable ();
}
-
/* Write on OF a user-callable routine to act as an entry point for
the marking routine for S, generated by write_func_for_structure.
PREFIX is the prefix to use to distinguish ggc and pch markers. */
@@ -3429,6 +3507,10 @@ write_func_for_structure (type_p orig_s, type_p s, type_p *param,
oprintf (d.of, " *)x_p;\n");
if (chain_next != NULL)
{
+ /* TYPE_USER_STRUCTs should not occur here. These structures
+ are completely handled by user code. */
+ gcc_assert (orig_s->kind != TYPE_USER_STRUCT);
+
oprintf (d.of, " ");
write_type_decl (d.of, s);
oprintf (d.of, " * xlimit = x;\n");
@@ -3760,7 +3842,9 @@ write_types_local_user_process_field (type_p f, const struct walk_type_data *d)
case TYPE_SCALAR:
break;
- default:
+ case TYPE_ARRAY:
+ case TYPE_NONE:
+ case TYPE_UNDEFINED:
gcc_unreachable ();
}
}
@@ -3843,7 +3927,9 @@ write_types_local_process_field (type_p f, const struct walk_type_data *d)
case TYPE_SCALAR:
break;
- default:
+ case TYPE_ARRAY:
+ case TYPE_NONE:
+ case TYPE_UNDEFINED:
gcc_unreachable ();
}
}
@@ -4063,6 +4149,9 @@ contains_scalar_p (type_p t)
return 0;
case TYPE_ARRAY:
return contains_scalar_p (t->u.a.p);
+ case TYPE_USER_STRUCT:
+ /* User-marked structures will typically contain pointers. */
+ return 0;
default:
/* Could also check for structures that have no non-pointer
fields, but there aren't enough of those to worry about. */
@@ -4313,8 +4402,9 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
break;
case TYPE_USER_STRUCT:
- write_root (f, v, type->u.a.p, name, has_length, line, if_marked,
- emit_pch);
+ error_at_line (line, "`%s' must be a pointer type, because it is "
+ "a GC root and its type is marked with GTY((user))",
+ v->name);
break;
case TYPE_POINTER:
@@ -4384,7 +4474,11 @@ write_root (outf_p f, pair_p v, type_p type, const char *name, int has_length,
case TYPE_SCALAR:
break;
- default:
+ case TYPE_NONE:
+ case TYPE_UNDEFINED:
+ case TYPE_UNION:
+ case TYPE_LANG_STRUCT:
+ case TYPE_PARAM_STRUCT:
error_at_line (line, "global `%s' is unimplemented type", name);
}
}
@@ -4880,7 +4974,9 @@ output_typename (outf_p of, const_type_p t)
output_typename (of, t->u.param_struct.stru);
break;
}
- default:
+ case TYPE_NONE:
+ case TYPE_UNDEFINED:
+ case TYPE_ARRAY:
gcc_unreachable ();
}
}
@@ -4941,6 +5037,9 @@ dump_typekind (int indent, enum typekind kind)
case TYPE_STRUCT:
printf ("TYPE_STRUCT");
break;
+ case TYPE_UNDEFINED:
+ printf ("TYPE_UNDEFINED");
+ break;
case TYPE_USER_STRUCT:
printf ("TYPE_USER_STRUCT");
break;
@@ -134,6 +134,9 @@ extern pair_p variables;
enum typekind {
TYPE_NONE=0, /* Never used, so zeroed memory is invalid. */
+ TYPE_UNDEFINED, /* We have not yet seen a definition for this type.
+ If a type is still undefined when generating code,
+ an error will be generated. */
TYPE_SCALAR, /* Scalar types like char. */
TYPE_STRING, /* The string type. */
TYPE_STRUCT, /* Type for GTY-ed structs. */
@@ -423,6 +426,7 @@ extern type_p resolve_typedef (const char *s, struct fileloc *pos);
extern type_p new_structure (const char *name, enum typekind kind,
struct fileloc *pos, pair_p fields,
options_p o);
+type_p create_user_defined_type (const char *, struct fileloc *);
extern type_p find_structure (const char *s, enum typekind kind);
extern type_p create_scalar_type (const char *name);
extern type_p create_pointer (type_p t);
@@ -457,7 +461,6 @@ enum gty_token
UNION,
STRUCT,
ENUM,
- VEC_TOKEN,
ELLIPSIS,
PTR_ALIAS,
NESTED_PTR,