/* Process source files and output type information.
- Copyright (C) 2006, 2007, 2010, 2012 Free Software Foundation, Inc.
+ Copyright (C) 2006-2015 Free Software Foundation, Inc.
This file is part of GCC.
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-#ifdef GENERATOR_FILE
-#include "bconfig.h"
-#else
+#ifdef HOST_GENERATOR_FILE
#include "config.h"
+#define GENERATOR_FILE 1
+#else
+#include "bconfig.h"
#endif
#include "system.h"
#include "gengtype.h"
"union",
"struct",
"enum",
- "VEC",
"...",
"ptr_alias",
"nested_ptr",
return v;
}
+/* As per require, but do not advance. */
+static const char *
+require_without_advance (int t)
+{
+ int u = token ();
+ const char *v = T.value;
+ if (u != t)
+ {
+ parse_error ("expected %s, have %s",
+ print_token (t, 0), print_token (u, v));
+ return 0;
+ }
+ return v;
+}
+
/* If the next token does not have one of the codes T1 or T2, report a
parse error; otherwise return the token's value. */
static const char *
return v;
}
+/* If the next token does not have one of the codes T1, T2, T3 or T4, report a
+ parse error; otherwise return the token's value. */
+static const char *
+require4 (int t1, int t2, int t3, int t4)
+{
+ int u = token ();
+ const char *v = advance ();
+ if (u != t1 && u != t2 && u != t3 && u != t4)
+ {
+ parse_error ("expected %s, %s, %s or %s, have %s",
+ print_token (t1, 0), print_token (t2, 0),
+ print_token (t3, 0), print_token (t4, 0),
+ print_token (u, v));
+ return 0;
+ }
+ return v;
+}
+
/* Near-terminals. */
/* C-style string constant concatenation: STRING+
/* The caller has detected a template declaration that starts
with TMPL_NAME. Parse up to the closing '>'. This recognizes
- simple template declarations of the form ID<ID1,ID2,...,IDn>.
+ simple template declarations of the form ID<ID1,ID2,...,IDn>,
+ potentially with a single level of indirection e.g.
+ ID<ID1 *, ID2, ID3 *, ..., IDn>.
It does not try to parse anything more sophisticated than that.
Returns the template declaration string "ID<ID1,ID2,...,IDn>". */
require_template_declaration (const char *tmpl_name)
{
char *str;
+ int num_indirections = 0;
/* Recognize the opening '<'. */
require ('<');
str = concat (tmpl_name, "<", (char *) 0);
/* Read the comma-separated list of identifiers. */
- while (token () != '>')
+ int depth = 1;
+ while (depth > 0)
{
- const char *id = require2 (ID, ',');
+ if (token () == ENUM)
+ {
+ advance ();
+ str = concat (str, "enum ", (char *) 0);
+ continue;
+ }
+ if (token () == NUM
+ || token () == ':'
+ || token () == '+')
+ {
+ str = concat (str, advance (), (char *) 0);
+ continue;
+ }
+ if (token () == '<')
+ {
+ advance ();
+ str = concat (str, "<", (char *) 0);
+ depth += 1;
+ continue;
+ }
+ if (token () == '>')
+ {
+ advance ();
+ str = concat (str, ">", (char *) 0);
+ depth -= 1;
+ continue;
+ }
+ const char *id = require4 (SCALAR, ID, '*', ',');
if (id == NULL)
- id = ",";
+ {
+ if (T.code == '*')
+ {
+ id = "*";
+ if (num_indirections++)
+ parse_error ("only one level of indirection is supported"
+ " in template arguments");
+ }
+ else
+ id = ",";
+ }
+ else
+ num_indirections = 0;
str = concat (str, id, (char *) 0);
}
-
- /* Recognize the closing '>'. */
- require ('>');
- str = concat (str, ">", (char *) 0);
-
return str;
}
-/* 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);
/* One GTY(()) option:
ID str_optvalue_opt
| PTR_ALIAS type_optvalue
- | PARAM_IS type_optvalue
| NESTED_PTR nestedptr_optvalue
*/
static options_p
advance ();
return type_optvalue (prev, "ptr_alias");
- case PARAM_IS:
- return type_optvalue (prev, advance ());
-
case NESTED_PTR:
advance ();
return nestedptr_optvalue (prev);
(
type bitfield ';'
| type declarator bitfield? ( ',' declarator bitfield? )+ ';'
- )+
+ )*
Knows that such declarations must end with a close brace (or,
erroneously, at EOF).
const char *name;
bool another;
- do
+ while (token () != '}' && token () != EOF_TOKEN)
{
ty = type (&opts, true);
+ /* Ignore access-control keywords ("public:" etc). */
+ while (!ty && token () == IGNORABLE_CXX_KEYWORD)
+ {
+ const char *keyword = advance ();
+ if (strcmp (keyword, "public:") != 0
+ && strcmp (keyword, "private:") != 0
+ && strcmp (keyword, "protected:") != 0)
+ break;
+ ty = type (&opts, true);
+ }
+
if (!ty || token () == ':')
{
consume_until_eos ();
}
while (another);
}
- while (token () != '}' && token () != EOF_TOKEN);
return nreverse_pairs (f);
}
/* Return true if OPTS contain the option named STR. */
-static bool
+bool
opts_have (options_p opts, const char *str)
{
for (options_p opt = opts; opt; opt = opt->next)
return create_scalar_type (s);
case ID:
- case VEC_TOKEN:
s = typedef_name ();
return resolve_typedef (s, &lexer_line);
case STRUCT:
case UNION:
{
+ type_p base_class = NULL;
options_p opts = 0;
/* GTY annotations follow attribute syntax
GTY_BEFORE_ID is for union/struct declarations
opts = gtymarker_opt ();
}
+ bool is_user_gty = opts_have (opts, "user");
+
if (token () == ':')
{
- /* Skip over C++ inheritance specification. */
- while (token () != '{')
- advance ();
+ if (is_gty && !is_user_gty)
+ {
+ /* For GTY-marked types that are not "user", parse some C++
+ inheritance specifications.
+ We require single-inheritance from a non-template type. */
+ advance ();
+ const char *basename = require (ID);
+ /* This may be either an access specifier, or the base name. */
+ if (0 == strcmp (basename, "public")
+ || 0 == strcmp (basename, "protected")
+ || 0 == strcmp (basename, "private"))
+ basename = require (ID);
+ base_class = find_structure (basename, TYPE_STRUCT);
+ if (!base_class)
+ parse_error ("unrecognized base class: %s", basename);
+ require_without_advance ('{');
+ }
+ else
+ {
+ /* For types lacking GTY-markings, skip over C++ inheritance
+ specification (and thus avoid having to parse e.g. template
+ types). */
+ while (token () != '{')
+ advance ();
+ }
}
if (is_gty)
{
- bool is_user_gty = opts_have (opts, "user");
if (token () == '{')
{
pair_p fields;
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);
+ return new_structure (s, kind, &lexer_line, fields, opts,
+ base_class);
}
}
else if (token () == '{')