From: Tom Tromey Date: Sun, 16 Nov 2025 21:15:48 +0000 (-0700) Subject: Rewrite the @selector code X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=a0877646e8251393d02957d195f84b2211e0d4ab;p=thirdparty%2Fbinutils-gdb.git Rewrite the @selector code This rewrites the Objective-C @selector implementation in c-exp.y, following a couple general comments in the patch supplied for bug 20503. I suspect something else changed in the Objective-C runtime, though, as most of the examples in that bug still do not work, even though this series (I believe) addresses all the same points. Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20503 --- diff --git a/gdb/c-exp.y b/gdb/c-exp.y index fadd735c517..829058027f3 100644 --- a/gdb/c-exp.y +++ b/gdb/c-exp.y @@ -224,7 +224,7 @@ static void c_print_token (FILE *file, int type, YYSTYPE value); %token STRING %token NSSTRING /* ObjC Foundation "NSString" literal */ -%token SELECTOR /* ObjC "@selector" pseudo-operator */ +%token SELECTOR /* ObjC "@selector" pseudo-operator */ %token CHAR %token NAME /* BLOCKNAME defined below to give it higher precedence. */ %token UNKNOWN_CPP_NAME @@ -918,10 +918,10 @@ exp : DOLLAR_VARIABLE } ; -exp : SELECTOR '(' name ')' +exp : SELECTOR { pstate->push_new - (copy_name ($3)); + (copy_name ($1)); } ; @@ -2664,6 +2664,43 @@ static bool last_was_structop; /* Depth of parentheses. */ static int paren_depth; +/* Lex an Objective-C @selector. Return true if lexed. In this case, + sets the resulting token and updates the lex pointer. Otherwise + returns false and updates nothing. */ + +static bool +lex_selector (const char **lex_ptr, struct stoken *token) +{ + const char *p = *lex_ptr; + + if (!startswith (p, "selector")) + return false; + + p += strlen ("selector"); + p = skip_spaces (p); + if (*p != '(') + return false; + ++p; + + /* The selector name matches [A-Za-z0-9:_-]+. We could probably be + a bit more refined but meh. */ + const char *start = p; + while (c_isalnum (*p) || *p == ':' || *p == '_' || *p == '-') + ++p; + if (p == start) + return false; + const char *end = p; + + p = skip_spaces (p); + if (*p != ')') + return false; + ++p; + + *lex_ptr = p; + *token = { start, (int) (end - start) }; + return true; +} + /* Read one token, getting characters through lexptr. */ static int @@ -2872,12 +2909,11 @@ lex_one_token (struct parser_state *par_state, bool *is_quoted_name) if (par_state->language ()->la_language == language_objc) { - size_t len = strlen ("selector"); - - if (strncmp (p, "selector", len) == 0 - && (p[len] == '\0' || c_isspace (p[len]))) + struct stoken sel_token; + if (lex_selector (&p, &sel_token)) { - pstate->lexptr = p + len; + pstate->lexptr = p; + yylval.sval = sel_token; return SELECTOR; } else if (*p == '"') @@ -3556,6 +3592,7 @@ c_print_token (FILE *file, int type, YYSTYPE value) case NSSTRING: case DOLLAR_VARIABLE: + case SELECTOR: parser_fprintf (file, "sval<%s>", copy_name (value.sval).c_str ()); break;