From b8363a243d4778afbdcc3794c86a7e08eb076f76 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Sun, 1 Jul 2001 18:48:13 +0000 Subject: [PATCH] c-common.h (enum rid): Add RID_FIRST_AT, RID_LAST_AT, RID_LAST_PQ. * c-common.h (enum rid): Add RID_FIRST_AT, RID_LAST_AT, RID_LAST_PQ. Move RID_FIRST_PQ down with the other FIRST/LAST enumerators. (OBJC_IS_AT_KEYWORD, OBJC_IS_PQ_KEYWORD): New macros. * c-parse.in (OBJC_STRING): Kill. (objc_string): Decompose to [objc_string] '@' STRING. (reswords): Take the leading '@' off all the Objective C keywords. (objc_rid_sans_at): Kill. (init_reswords): Don't initialize it. (yylexname): Use OBJC_IS_AT_KEYWORD and OBJC_IS_PQ_KEYWORD. (_yylex): Kill reconsider label. Look ahead one token after an '@'; if we get an identifier, check whether it's an Objective C @-keyword. If so, return the keyword. Otherwise, put back the token and return the '@' as a terminal. * cpplib.c (lex_macro_node): Remove unnecessary check for leading '@' on identifier. Clarify control flow and commentary. From-SVN: r43674 --- gcc/ChangeLog | 21 ++++++++++ gcc/c-common.h | 17 +++++++- gcc/c-parse.in | 104 +++++++++++++++++++++---------------------------- gcc/cpplib.c | 34 +++++++++------- 4 files changed, 100 insertions(+), 76 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 45be5e87fa7..6077e458524 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2001-07-01 Zack Weinberg + + * c-common.h (enum rid): Add RID_FIRST_AT, RID_LAST_AT, + RID_LAST_PQ. Move RID_FIRST_PQ down with the other FIRST/LAST + enumerators. + (OBJC_IS_AT_KEYWORD, OBJC_IS_PQ_KEYWORD): New macros. + + * c-parse.in (OBJC_STRING): Kill. + (objc_string): Decompose to [objc_string] '@' STRING. + (reswords): Take the leading '@' off all the Objective C keywords. + (objc_rid_sans_at): Kill. + (init_reswords): Don't initialize it. + (yylexname): Use OBJC_IS_AT_KEYWORD and OBJC_IS_PQ_KEYWORD. + (_yylex): Kill reconsider label. Look ahead one token after + an '@'; if we get an identifier, check whether it's an + Objective C @-keyword. If so, return the keyword. Otherwise, + put back the token and return the '@' as a terminal. + + * cpplib.c (lex_macro_node): Remove unnecessary check for + leading '@' on identifier. Clarify control flow and commentary. + Sun Jul 1 11:53:52 2001 Richard Kenner * cse.c (new_label_ref): Variable deleted. diff --git a/gcc/c-common.h b/gcc/c-common.h index 05350c12fa2..95ead542441 100644 --- a/gcc/c-common.h +++ b/gcc/c-common.h @@ -63,7 +63,7 @@ enum rid RID_FRIEND, RID_VIRTUAL, RID_EXPLICIT, RID_EXPORT, RID_MUTABLE, /* ObjC */ - RID_FIRST_PQ, RID_IN = RID_FIRST_PQ, RID_OUT, RID_INOUT, RID_BYCOPY, RID_BYREF, RID_ONEWAY, + RID_IN, RID_OUT, RID_INOUT, RID_BYCOPY, RID_BYREF, RID_ONEWAY, /* C */ RID_INT, RID_CHAR, RID_FLOAT, RID_DOUBLE, RID_VOID, @@ -107,9 +107,22 @@ enum rid RID_MAX, RID_FIRST_MODIFIER = RID_STATIC, - RID_LAST_MODIFIER = RID_ONEWAY + RID_LAST_MODIFIER = RID_ONEWAY, + + RID_FIRST_AT = RID_AT_ENCODE, + RID_LAST_AT = RID_AT_IMPLEMENTATION, + RID_FIRST_PQ = RID_IN, + RID_LAST_PQ = RID_ONEWAY }; +#define OBJC_IS_AT_KEYWORD(rid) \ + ((unsigned int)(rid) >= (unsigned int)RID_FIRST_AT && \ + (unsigned int)(rid) <= (unsigned int)RID_LAST_AT) + +#define OBJC_IS_PQ_KEYWORD(rid) \ + ((unsigned int)(rid) >= (unsigned int)RID_FIRST_PQ && \ + (unsigned int)(rid) <= (unsigned int)RID_LAST_PQ) + /* The elements of `ridpointers' are identifier nodes for the reserved type names and storage classes. It is indexed by a RID_... value. */ extern tree *ridpointers; diff --git a/gcc/c-parse.in b/gcc/c-parse.in index 45b04dab71a..9a7fe1cd34f 100644 --- a/gcc/c-parse.in +++ b/gcc/c-parse.in @@ -157,11 +157,6 @@ end ifc %token INTERFACE IMPLEMENTATION END SELECTOR DEFS ENCODE %token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS -/* Objective-C string constants in raw form. - yylval is an STRING_CST node. */ -%token OBJC_STRING - - %type unop %type ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT %type BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF @@ -231,7 +226,7 @@ ifobjc %type selectorarg keywordnamelist keywordname objcencodeexpr %type objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr -%type CLASSNAME OBJC_STRING OBJECTNAME +%type CLASSNAME OBJECTNAME end ifobjc %{ @@ -767,9 +762,10 @@ ifobjc /* Produces an STRING_CST with perhaps more STRING_CSTs chained onto it, which is to be read as an ObjC string object. */ objc_string: - OBJC_STRING - | objc_string OBJC_STRING - { $$ = chainon ($1, $2); } + '@' STRING + { $$ = $2; } + | objc_string '@' STRING + { $$ = chainon ($1, $3); } ; end ifobjc @@ -3407,19 +3403,25 @@ static const struct resword reswords[] = { "volatile", RID_VOLATILE, D_TRAD }, { "while", RID_WHILE, 0 }, ifobjc - { "@class", RID_AT_CLASS, D_OBJC }, - { "@compatibility_alias", RID_AT_ALIAS, D_OBJC }, - { "@defs", RID_AT_DEFS, D_OBJC }, - { "@encode", RID_AT_ENCODE, D_OBJC }, - { "@end", RID_AT_END, D_OBJC }, - { "@implementation", RID_AT_IMPLEMENTATION, D_OBJC }, - { "@interface", RID_AT_INTERFACE, D_OBJC }, - { "@private", RID_AT_PRIVATE, D_OBJC }, - { "@protected", RID_AT_PROTECTED, D_OBJC }, - { "@protocol", RID_AT_PROTOCOL, D_OBJC }, - { "@public", RID_AT_PUBLIC, D_OBJC }, - { "@selector", RID_AT_SELECTOR, D_OBJC }, { "id", RID_ID, D_OBJC }, + + /* These objc keywords are recognized only immediately after + an '@'. */ + { "class", RID_AT_CLASS, D_OBJC }, + { "compatibility_alias", RID_AT_ALIAS, D_OBJC }, + { "defs", RID_AT_DEFS, D_OBJC }, + { "encode", RID_AT_ENCODE, D_OBJC }, + { "end", RID_AT_END, D_OBJC }, + { "implementation", RID_AT_IMPLEMENTATION, D_OBJC }, + { "interface", RID_AT_INTERFACE, D_OBJC }, + { "private", RID_AT_PRIVATE, D_OBJC }, + { "protected", RID_AT_PROTECTED, D_OBJC }, + { "protocol", RID_AT_PROTOCOL, D_OBJC }, + { "public", RID_AT_PUBLIC, D_OBJC }, + { "selector", RID_AT_SELECTOR, D_OBJC }, + + /* These are recognized only in protocol-qualifier context + (see above) */ { "bycopy", RID_BYCOPY, D_OBJC }, { "byref", RID_BYREF, D_OBJC }, { "in", RID_IN, D_OBJC }, @@ -3568,13 +3570,6 @@ static const short rid_to_yy[RID_MAX] = /* RID_AT_IMPLEMENTATION */ IMPLEMENTATION }; -ifobjc -/* Lookup table for ObjC keywords beginning with '@'. Crude but - hopefully effective. */ -#define N_at_reswords ((int) RID_AT_IMPLEMENTATION - (int)RID_AT_ENCODE + 1) -static tree objc_rid_sans_at[N_at_reswords]; -end ifobjc - static void init_reswords () { @@ -3602,16 +3597,6 @@ init_reswords () C_RID_CODE (id) = reswords[i].rid; C_IS_RESERVED_WORD (id) = 1; ridpointers [(int) reswords[i].rid] = id; - -ifobjc - /* Enter ObjC @-prefixed keywords into the "sans" table - _without_ their leading at-sign. Again, all these - identifiers are reachable by the get_identifer table, so it's - not necessary to make objc_rid_sans_at a GC root. */ - if (reswords[i].word[0] == '@') - objc_rid_sans_at[(int) reswords[i].rid - (int) RID_AT_ENCODE] - = get_identifier (reswords[i].word + 1); -end ifobjc } } @@ -3680,8 +3665,8 @@ yylexname () enum rid rid_code = C_RID_CODE (yylval.ttype); ifobjc - if (!((unsigned int) rid_code - (unsigned int) RID_FIRST_PQ < 6) - || objc_pq_context) + if (!OBJC_IS_AT_KEYWORD (rid_code) + && (!OBJC_IS_PQ_KEYWORD (rid_code) || objc_pq_context)) end ifobjc { int yycode = rid_to_yy[(int) rid_code]; @@ -3730,9 +3715,6 @@ _yylex () { get_next: last_token = c_lex (&yylval.ttype); -ifobjc - reconsider: -end ifobjc switch (last_token) { case CPP_EQ: return '='; @@ -3809,23 +3791,27 @@ end ifobjc token special significance. */ case CPP_ATSIGN: ifobjc - last_token = c_lex (&yylval.ttype); - if (last_token == CPP_STRING) - return OBJC_STRING; - else if (last_token == CPP_NAME) - { - int i; - for (i = 0; i < N_at_reswords; i++) - if (objc_rid_sans_at[i] == yylval.ttype) - { - int rid_code = i + (int) RID_AT_ENCODE; - yylval.ttype = ridpointers[rid_code]; - return rid_to_yy[rid_code]; - } - } - error ("syntax error at '@' token"); - goto reconsider; + { + tree after_at; + enum cpp_ttype after_at_type; + + cpp_start_lookahead (parse_in); + after_at_type = c_lex (&after_at); + + if (after_at_type == CPP_NAME + && C_IS_RESERVED_WORD (after_at) + && OBJC_IS_AT_KEYWORD (C_RID_CODE (after_at))) + { + cpp_stop_lookahead (parse_in, 1); /* accept this token */ + yylval.ttype = after_at; + last_token = after_at_type; + return rid_to_yy [(int) C_RID_CODE (after_at)]; + } + cpp_stop_lookahead (parse_in, 0); /* put back this token */ + return '@'; + } end ifobjc + /* These tokens are C++ specific (and will not be generated in C mode, but let's be cautious). */ case CPP_SCOPE: diff --git a/gcc/cpplib.c b/gcc/cpplib.c index cb493105ae9..e0f61247c46 100644 --- a/gcc/cpplib.c +++ b/gcc/cpplib.c @@ -438,14 +438,17 @@ lex_macro_node (pfile) cpp_reader *pfile; { cpp_token token; + cpp_hashnode *node; /* Lex the macro name directly. */ _cpp_lex_token (pfile, &token); /* The token immediately after #define must be an identifier. That - identifier is not allowed to be "defined". See predefined macro - names (6.10.8.4). In C++, it is not allowed to be any of the - macro names (which are keywords in C++) either. */ + identifier may not be "defined", per C99 6.10.8p4. + In C++, it may not be any of the "named operators" either, + per C++98 [lex.digraph], [lex.key]. + Finally, the identifier may not have been poisoned. (In that case + the lexer has issued the error message for us.) */ if (token.type != CPP_NAME) { @@ -454,25 +457,26 @@ lex_macro_node (pfile) pfile->directive->name); else if (token.flags & NAMED_OP) cpp_error (pfile, - "\"%s\" cannot be used as a macro name as it is an operator in C++", + "\"%s\" cannot be used as a macro name as it is an operator in C++", NODE_NAME (token.val.node)); else cpp_error (pfile, "macro names must be identifiers"); + + return 0; } - else + + node = token.val.node; + if (node->flags & NODE_POISONED) + return 0; + + if (node == pfile->spec_nodes.n_defined) { - cpp_hashnode *node = token.val.node; - - /* In Objective C, some keywords begin with '@', but general - identifiers do not, and you're not allowed to #define them. */ - if (node == pfile->spec_nodes.n_defined || NODE_NAME (node)[0] == '@') - cpp_error (pfile, "\"%s\" cannot be used as a macro name", - NODE_NAME (node)); - else if (!(node->flags & NODE_POISONED)) - return node; + cpp_error (pfile, "\"%s\" cannot be used as a macro name", + NODE_NAME (node)); + return 0; } - return 0; + return node; } /* Process a #define directive. Most work is done in cppmacro.c. */ -- 2.30.2