diff options
author | marcel <marcel@FreeBSD.org> | 2004-06-20 18:26:14 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2004-06-20 18:26:14 +0000 |
commit | ddb504ee412e85d02695ae9f3deef7f220b77beb (patch) | |
tree | a49f8af771ff0bf61cc4f75dc6b9537c0bd683e7 /contrib/gdb/gdb/c-exp.y | |
parent | c6cc8e4a1eb2de942258fa7cd28b9c4f9e5c6277 (diff) | |
download | FreeBSD-src-ddb504ee412e85d02695ae9f3deef7f220b77beb.zip FreeBSD-src-ddb504ee412e85d02695ae9f3deef7f220b77beb.tar.gz |
Import of GDB version 6.1.1 (stripped; see FREEBSD-Xlist rev. 1.6).
Diffstat (limited to 'contrib/gdb/gdb/c-exp.y')
-rw-r--r-- | contrib/gdb/gdb/c-exp.y | 369 |
1 files changed, 219 insertions, 150 deletions
diff --git a/contrib/gdb/gdb/c-exp.y b/contrib/gdb/gdb/c-exp.y index 3d2d1aa..f11b93e 100644 --- a/contrib/gdb/gdb/c-exp.y +++ b/contrib/gdb/gdb/c-exp.y @@ -1,6 +1,6 @@ /* YACC parser for C expressions, for GDB. Copyright 1986, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, - 1998, 1999, 2000 + 1998, 1999, 2000, 2003, 2004 Free Software Foundation, Inc. This file is part of GDB. @@ -49,6 +49,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "bfd.h" /* Required by objfiles.h. */ #include "symfile.h" /* Required by objfiles.h. */ #include "objfiles.h" /* For have_full_symbols and have_partial_symbols */ +#include "charset.h" +#include "block.h" +#include "cp-support.h" /* Flag indicating we're dealing with HP-compiled objects */ extern int hp_som_som_object_present; @@ -89,6 +92,8 @@ extern int hp_som_som_object_present; #define yylloc c_lloc #define yyreds c_reds /* With YYDEBUG defined */ #define yytoks c_toks /* With YYDEBUG defined */ +#define yyname c_name /* With YYDEBUG defined */ +#define yyrule c_rule /* With YYDEBUG defined */ #define yylhs c_yylhs #define yylen c_yylen #define yydefred c_yydefred @@ -100,9 +105,11 @@ extern int hp_som_som_object_present; #define yycheck c_yycheck #ifndef YYDEBUG -#define YYDEBUG 0 /* Default to no yydebug support */ +#define YYDEBUG 1 /* Default to yydebug support */ #endif +#define YYFPRINTF parser_fprintf + int yyparse (void); static int yylex (void); @@ -147,7 +154,7 @@ static int parse_number (char *, int, int, YYSTYPE *); %type <voidval> exp exp1 type_exp start variable qualified_name lcurly %type <lval> rcurly -%type <tval> type typebase +%type <tval> type typebase qualified_type %type <tvec> nonempty_typelist /* %type <bval> block */ @@ -194,7 +201,6 @@ static int parse_number (char *, int, int, YYSTYPE *); %token <opcode> ASSIGN_MODIFY /* C++ */ -%token THIS %token TRUEKEYWORD %token FALSEKEYWORD @@ -243,9 +249,11 @@ exp1 : exp /* Expressions, not including the comma operator. */ exp : '*' exp %prec UNARY { write_exp_elt_opcode (UNOP_IND); } + ; exp : '&' exp %prec UNARY { write_exp_elt_opcode (UNOP_ADDR); } + ; exp : '-' exp %prec UNARY { write_exp_elt_opcode (UNOP_NEG); } @@ -527,11 +535,6 @@ exp : STRING ; /* C++. */ -exp : THIS - { write_exp_elt_opcode (OP_THIS); - write_exp_elt_opcode (OP_THIS); } - ; - exp : TRUEKEYWORD { write_exp_elt_opcode (OP_LONG); write_exp_elt_type (builtin_type_bool); @@ -565,7 +568,7 @@ block : BLOCKNAME block : block COLONCOLON name { struct symbol *tem = lookup_symbol (copy_name ($3), $1, - VAR_NAMESPACE, (int *) NULL, + VAR_DOMAIN, (int *) NULL, (struct symtab **) NULL); if (!tem || SYMBOL_CLASS (tem) != LOC_BLOCK) error ("No function \"%s\" in specified context.", @@ -576,7 +579,7 @@ block : block COLONCOLON name variable: block COLONCOLON name { struct symbol *sym; sym = lookup_symbol (copy_name ($3), $1, - VAR_NAMESPACE, (int *) NULL, + VAR_DOMAIN, (int *) NULL, (struct symtab **) NULL); if (sym == 0) error ("No symbol \"%s\" in specified context.", @@ -593,7 +596,8 @@ qualified_name: typebase COLONCOLON name { struct type *type = $1; if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION) + && TYPE_CODE (type) != TYPE_CODE_UNION + && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) error ("`%s' is not defined as an aggregate type.", TYPE_NAME (type)); @@ -607,7 +611,8 @@ qualified_name: typebase COLONCOLON name struct type *type = $1; struct stoken tmp_token; if (TYPE_CODE (type) != TYPE_CODE_STRUCT - && TYPE_CODE (type) != TYPE_CODE_UNION) + && TYPE_CODE (type) != TYPE_CODE_UNION + && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) error ("`%s' is not defined as an aggregate type.", TYPE_NAME (type)); @@ -635,7 +640,7 @@ variable: qualified_name sym = lookup_symbol (name, (const struct block *) NULL, - VAR_NAMESPACE, (int *) NULL, + VAR_DOMAIN, (int *) NULL, (struct symtab **) NULL); if (sym) { @@ -699,7 +704,7 @@ variable: name_not_typename else { struct minimal_symbol *msymbol; - register char *arg = copy_name ($1.stoken); + char *arg = copy_name ($1.stoken); msymbol = lookup_minimal_symbol (arg, NULL, NULL); @@ -780,7 +785,7 @@ array_mod: '[' ']' func_mod: '(' ')' { $$ = 0; } | '(' nonempty_typelist ')' - { free ((PTR)$2); $$ = 0; } + { free ($2); $$ = 0; } ; /* We used to try to recognize more pointer to member types here, but @@ -807,24 +812,50 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ { $$ = builtin_type_short; } | LONG INT_KEYWORD { $$ = builtin_type_long; } + | LONG SIGNED_KEYWORD INT_KEYWORD + { $$ = builtin_type_long; } + | LONG SIGNED_KEYWORD + { $$ = builtin_type_long; } + | SIGNED_KEYWORD LONG INT_KEYWORD + { $$ = builtin_type_long; } | UNSIGNED LONG INT_KEYWORD { $$ = builtin_type_unsigned_long; } + | LONG UNSIGNED INT_KEYWORD + { $$ = builtin_type_unsigned_long; } + | LONG UNSIGNED + { $$ = builtin_type_unsigned_long; } | LONG LONG { $$ = builtin_type_long_long; } | LONG LONG INT_KEYWORD { $$ = builtin_type_long_long; } + | LONG LONG SIGNED_KEYWORD INT_KEYWORD + { $$ = builtin_type_long_long; } + | LONG LONG SIGNED_KEYWORD + { $$ = builtin_type_long_long; } + | SIGNED_KEYWORD LONG LONG + { $$ = builtin_type_long_long; } + | SIGNED_KEYWORD LONG LONG INT_KEYWORD + { $$ = builtin_type_long_long; } | UNSIGNED LONG LONG { $$ = builtin_type_unsigned_long_long; } | UNSIGNED LONG LONG INT_KEYWORD { $$ = builtin_type_unsigned_long_long; } - | SIGNED_KEYWORD LONG LONG - { $$ = lookup_signed_typename ("long long"); } - | SIGNED_KEYWORD LONG LONG INT_KEYWORD - { $$ = lookup_signed_typename ("long long"); } + | LONG LONG UNSIGNED + { $$ = builtin_type_unsigned_long_long; } + | LONG LONG UNSIGNED INT_KEYWORD + { $$ = builtin_type_unsigned_long_long; } | SHORT INT_KEYWORD { $$ = builtin_type_short; } + | SHORT SIGNED_KEYWORD INT_KEYWORD + { $$ = builtin_type_short; } + | SHORT SIGNED_KEYWORD + { $$ = builtin_type_short; } | UNSIGNED SHORT INT_KEYWORD { $$ = builtin_type_unsigned_short; } + | SHORT UNSIGNED + { $$ = builtin_type_unsigned_short; } + | SHORT UNSIGNED INT_KEYWORD + { $$ = builtin_type_unsigned_short; } | DOUBLE_KEYWORD { $$ = builtin_type_double; } | LONG DOUBLE_KEYWORD @@ -860,6 +891,77 @@ typebase /* Implements (approximately): (type-qualifier)* type-specifier */ { $$ = follow_types ($2); } | typebase const_or_volatile_or_space_identifier_noopt { $$ = follow_types ($1); } + | qualified_type + ; + +/* FIXME: carlton/2003-09-25: This next bit leads to lots of + reduce-reduce conflicts, because the parser doesn't know whether or + not to use qualified_name or qualified_type: the rules are + identical. If the parser is parsing 'A::B::x', then, when it sees + the second '::', it knows that the expression to the left of it has + to be a type, so it uses qualified_type. But if it is parsing just + 'A::B', then it doesn't have any way of knowing which rule to use, + so there's a reduce-reduce conflict; it picks qualified_name, since + that occurs earlier in this file than qualified_type. + + There's no good way to fix this with the grammar as it stands; as + far as I can tell, some of the problems arise from ambiguities that + GDB introduces ('start' can be either an expression or a type), but + some of it is inherent to the nature of C++ (you want to treat the + input "(FOO)" fairly differently depending on whether FOO is an + expression or a type, and if FOO is a complex expression, this can + be hard to determine at the right time). Fortunately, it works + pretty well in most cases. For example, if you do 'ptype A::B', + where A::B is a nested type, then the parser will mistakenly + misidentify it as an expression; but evaluate_subexp will get + called with 'noside' set to EVAL_AVOID_SIDE_EFFECTS, and everything + will work out anyways. But there are situations where the parser + will get confused: the most common one that I've run into is when + you want to do + + print *((A::B *) x)" + + where the parser doesn't realize that A::B has to be a type until + it hits the first right paren, at which point it's too late. (The + workaround is to type "print *(('A::B' *) x)" instead.) (And + another solution is to fix our symbol-handling code so that the + user never wants to type something like that in the first place, + because we get all the types right without the user's help!) + + Perhaps we could fix this by making the lexer smarter. Some of + this functionality used to be in the lexer, but in a way that + worked even less well than the current solution: that attempt + involved having the parser sometimes handle '::' and having the + lexer sometimes handle it, and without a clear division of + responsibility, it quickly degenerated into a big mess. Probably + the eventual correct solution will give more of a role to the lexer + (ideally via code that is shared between the lexer and + decode_line_1), but I'm not holding my breath waiting for somebody + to get around to cleaning this up... */ + +qualified_type: typebase COLONCOLON name + { + struct type *type = $1; + struct type *new_type; + char *ncopy = alloca ($3.length + 1); + + memcpy (ncopy, $3.ptr, $3.length); + ncopy[$3.length] = '\0'; + + if (TYPE_CODE (type) != TYPE_CODE_STRUCT + && TYPE_CODE (type) != TYPE_CODE_UNION + && TYPE_CODE (type) != TYPE_CODE_NAMESPACE) + error ("`%s' is not defined as an aggregate type.", + TYPE_NAME (type)); + + new_type = cp_lookup_nested_type (type, ncopy, + expression_context_block); + if (new_type == NULL) + error ("No type \"%s\" within class or namespace \"%s\".", + ncopy, TYPE_NAME (type)); + + $$ = new_type; + } ; typename: TYPENAME @@ -942,20 +1044,20 @@ name_not_typename : NAME static int parse_number (p, len, parsed_float, putithere) - register char *p; - register int len; + char *p; + int len; int parsed_float; YYSTYPE *putithere; { /* FIXME: Shouldn't these be unsigned? We don't deal with negative values here, and we do kind of silly things like cast to unsigned. */ - register LONGEST n = 0; - register LONGEST prevn = 0; + LONGEST n = 0; + LONGEST prevn = 0; ULONGEST un; - register int i = 0; - register int c; - register int base = input_radix; + int i = 0; + int c; + int base = input_radix; int unsigned_p = 0; /* Number of "L" suffixes encountered. */ @@ -1218,12 +1320,24 @@ yylex () retry: + /* Check if this is a macro invocation that we need to expand. */ + if (! scanning_macro_expansion ()) + { + char *expanded = macro_expand_next (&lexptr, + expression_macro_lookup_func, + expression_macro_lookup_baton); + + if (expanded) + scan_macro_expansion (expanded); + } + + prev_lexptr = lexptr; unquoted_expr = 1; tokstart = lexptr; /* See if it is a special token of length 3. */ for (i = 0; i < sizeof tokentab3 / sizeof tokentab3[0]; i++) - if (STREQN (tokstart, tokentab3[i].operator, 3)) + if (strncmp (tokstart, tokentab3[i].operator, 3) == 0) { lexptr += 3; yylval.opcode = tokentab3[i].opcode; @@ -1232,7 +1346,7 @@ yylex () /* See if it is a special token of length 2. */ for (i = 0; i < sizeof tokentab2 / sizeof tokentab2[0]; i++) - if (STREQN (tokstart, tokentab2[i].operator, 2)) + if (strncmp (tokstart, tokentab2[i].operator, 2) == 0) { lexptr += 2; yylval.opcode = tokentab2[i].opcode; @@ -1242,7 +1356,17 @@ yylex () switch (c = *tokstart) { case 0: - return 0; + /* If we were just scanning the result of a macro expansion, + then we need to resume scanning the original text. + Otherwise, we were already scanning the original text, and + we're really done. */ + if (scanning_macro_expansion ()) + { + finished_macro_expansion (); + goto retry; + } + else + return 0; case ' ': case '\t': @@ -1260,6 +1384,15 @@ yylex () c = parse_escape (&lexptr); else if (c == '\'') error ("Empty character constant."); + else if (! host_char_to_target (c, &c)) + { + int toklen = lexptr - tokstart + 1; + char *tok = alloca (toklen + 1); + memcpy (tok, tokstart, toklen); + tok[toklen] = '\0'; + error ("There is no character corresponding to %s in the target " + "character set `%s'.", tok, target_charset ()); + } yylval.typed_val_int.val = c; yylval.typed_val_int.type = builtin_type_char; @@ -1295,7 +1428,9 @@ yylex () return c; case ',': - if (comma_terminates && paren_depth == 0) + if (comma_terminates + && paren_depth == 0 + && ! scanning_macro_expansion ()) return 0; lexptr++; return c; @@ -1319,7 +1454,7 @@ yylex () { /* It's a number. */ int got_dot = 0, got_e = 0, toktype; - register char *p = tokstart; + char *p = tokstart; int hex = input_radix > 10; if (c == '0' && (p[1] == 'x' || p[1] == 'X')) @@ -1408,6 +1543,8 @@ yylex () tempbufindex = 0; do { + char *char_start_pos = tokptr; + /* Grow the static temp buffer if necessary, including allocating the first one on demand. */ if (tempbufindex + 1 >= tempbufsize) @@ -1430,7 +1567,19 @@ yylex () tempbuf[tempbufindex++] = c; break; default: - tempbuf[tempbufindex++] = *tokptr++; + c = *tokptr++; + if (! host_char_to_target (c, &c)) + { + int len = tokptr - char_start_pos; + char *copy = alloca (len + 1); + memcpy (copy, char_start_pos, len); + copy[len] = '\0'; + + error ("There is no character corresponding to `%s' " + "in the target character set `%s'.", + copy, target_charset ()); + } + tempbuf[tempbufindex++] = c; break; } } while ((*tokptr != '"') && (*tokptr != '\0')); @@ -1474,9 +1623,13 @@ yylex () c = tokstart[++namelen]; } - /* The token "if" terminates the expression and is NOT - removed from the input stream. */ - if (namelen == 2 && tokstart[0] == 'i' && tokstart[1] == 'f') + /* The token "if" terminates the expression and is NOT removed from + the input stream. It doesn't count if it appears in the + expansion of a macro. */ + if (namelen == 2 + && tokstart[0] == 'i' + && tokstart[1] == 'f' + && ! scanning_macro_expansion ()) { return 0; } @@ -1489,63 +1642,52 @@ yylex () switch (namelen) { case 8: - if (STREQN (tokstart, "unsigned", 8)) + if (strncmp (tokstart, "unsigned", 8) == 0) return UNSIGNED; if (current_language->la_language == language_cplus - && STREQN (tokstart, "template", 8)) + && strncmp (tokstart, "template", 8) == 0) return TEMPLATE; - if (STREQN (tokstart, "volatile", 8)) + if (strncmp (tokstart, "volatile", 8) == 0) return VOLATILE_KEYWORD; break; case 6: - if (STREQN (tokstart, "struct", 6)) + if (strncmp (tokstart, "struct", 6) == 0) return STRUCT; - if (STREQN (tokstart, "signed", 6)) + if (strncmp (tokstart, "signed", 6) == 0) return SIGNED_KEYWORD; - if (STREQN (tokstart, "sizeof", 6)) + if (strncmp (tokstart, "sizeof", 6) == 0) return SIZEOF; - if (STREQN (tokstart, "double", 6)) + if (strncmp (tokstart, "double", 6) == 0) return DOUBLE_KEYWORD; break; case 5: if (current_language->la_language == language_cplus) { - if (STREQN (tokstart, "false", 5)) + if (strncmp (tokstart, "false", 5) == 0) return FALSEKEYWORD; - if (STREQN (tokstart, "class", 5)) + if (strncmp (tokstart, "class", 5) == 0) return CLASS; } - if (STREQN (tokstart, "union", 5)) + if (strncmp (tokstart, "union", 5) == 0) return UNION; - if (STREQN (tokstart, "short", 5)) + if (strncmp (tokstart, "short", 5) == 0) return SHORT; - if (STREQN (tokstart, "const", 5)) + if (strncmp (tokstart, "const", 5) == 0) return CONST_KEYWORD; break; case 4: - if (STREQN (tokstart, "enum", 4)) + if (strncmp (tokstart, "enum", 4) == 0) return ENUM; - if (STREQN (tokstart, "long", 4)) + if (strncmp (tokstart, "long", 4) == 0) return LONG; if (current_language->la_language == language_cplus) { - if (STREQN (tokstart, "true", 4)) + if (strncmp (tokstart, "true", 4) == 0) return TRUEKEYWORD; - - if (STREQN (tokstart, "this", 4)) - { - static const char this_name[] = - { CPLUS_MARKER, 't', 'h', 'i', 's', '\0' }; - - if (lookup_symbol (this_name, expression_context_block, - VAR_NAMESPACE, (int *) NULL, - (struct symtab **) NULL)) - return THIS; - } } break; case 3: - if (STREQN (tokstart, "int", 3)) + if (strncmp (tokstart, "int", 3) == 0) return INT_KEYWORD; break; default: @@ -1565,7 +1707,13 @@ yylex () string to get a reasonable class/namespace spec or a fully-qualified name. This is a kludge to get around the HP aCC compiler's generation of symbol names with embedded - colons for namespace and nested classes. */ + colons for namespace and nested classes. */ + + /* NOTE: carlton/2003-09-24: I don't entirely understand the + HP-specific code, either here or in linespec. Having said that, + I suspect that we're actually moving towards their model: we want + symbols whose names are fully qualified, which matches the + description above. */ if (unquoted_expr) { /* Only do it if not inside single quotes */ @@ -1591,7 +1739,7 @@ yylex () int hextype; sym = lookup_symbol (tmp, expression_context_block, - VAR_NAMESPACE, + VAR_DOMAIN, current_language->la_language == language_cplus ? &is_a_field_of_this : (int *) NULL, (struct symtab **) NULL); @@ -1619,92 +1767,10 @@ yylex () if (sym && SYMBOL_CLASS (sym) == LOC_TYPEDEF) { -#if 1 - /* Despite the following flaw, we need to keep this code enabled. - Because we can get called from check_stub_method, if we don't - handle nested types then it screws many operations in any - program which uses nested types. */ - /* In "A::x", if x is a member function of A and there happens - to be a type (nested or not, since the stabs don't make that - distinction) named x, then this code incorrectly thinks we - are dealing with nested types rather than a member function. */ - - char *p; - char *namestart; - struct symbol *best_sym; - - /* Look ahead to detect nested types. This probably should be - done in the grammar, but trying seemed to introduce a lot - of shift/reduce and reduce/reduce conflicts. It's possible - that it could be done, though. Or perhaps a non-grammar, but - less ad hoc, approach would work well. */ - - /* Since we do not currently have any way of distinguishing - a nested type from a non-nested one (the stabs don't tell - us whether a type is nested), we just ignore the - containing type. */ - - p = lexptr; - best_sym = sym; - while (1) - { - /* Skip whitespace. */ - while (*p == ' ' || *p == '\t' || *p == '\n') - ++p; - if (*p == ':' && p[1] == ':') - { - /* Skip the `::'. */ - p += 2; - /* Skip whitespace. */ - while (*p == ' ' || *p == '\t' || *p == '\n') - ++p; - namestart = p; - while (*p == '_' || *p == '$' || (*p >= '0' && *p <= '9') - || (*p >= 'a' && *p <= 'z') - || (*p >= 'A' && *p <= 'Z')) - ++p; - if (p != namestart) - { - struct symbol *cur_sym; - /* As big as the whole rest of the expression, which is - at least big enough. */ - char *ncopy = alloca (strlen (tmp)+strlen (namestart)+3); - char *tmp1; - - tmp1 = ncopy; - memcpy (tmp1, tmp, strlen (tmp)); - tmp1 += strlen (tmp); - memcpy (tmp1, "::", 2); - tmp1 += 2; - memcpy (tmp1, namestart, p - namestart); - tmp1[p - namestart] = '\0'; - cur_sym = lookup_symbol (ncopy, expression_context_block, - VAR_NAMESPACE, (int *) NULL, - (struct symtab **) NULL); - if (cur_sym) - { - if (SYMBOL_CLASS (cur_sym) == LOC_TYPEDEF) - { - best_sym = cur_sym; - lexptr = p; - } - else - break; - } - else - break; - } - else - break; - } - else - break; - } - - yylval.tsym.type = SYMBOL_TYPE (best_sym); -#else /* not 0 */ + /* NOTE: carlton/2003-09-25: There used to be code here to + handle nested types. It didn't work very well. See the + comment before qualified_type for more info. */ yylval.tsym.type = SYMBOL_TYPE (sym); -#endif /* not 0 */ return TYPENAME; } if ((yylval.tsym.type = lookup_primitive_typename (tmp)) != 0) @@ -1738,5 +1804,8 @@ void yyerror (msg) char *msg; { + if (prev_lexptr) + lexptr = prev_lexptr; + error ("A %s in expression, near `%s'.", (msg ? msg : "error"), lexptr); } |