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
This commit is contained in:
parent
128e8aa952
commit
b8363a243d
4 changed files with 100 additions and 76 deletions
|
@ -1,3 +1,24 @@
|
|||
2001-07-01 Zack Weinberg <zackw@stanford.edu>
|
||||
|
||||
* 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 <kenner@vlsi1.ultra.nyu.edu>
|
||||
|
||||
* cse.c (new_label_ref): Variable deleted.
|
||||
|
|
|
@ -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;
|
||||
|
|
104
gcc/c-parse.in
104
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 <code> unop
|
||||
%type <ttype> ENUM STRUCT UNION IF ELSE WHILE DO FOR SWITCH CASE DEFAULT
|
||||
%type <ttype> BREAK CONTINUE RETURN GOTO ASM_KEYWORD SIZEOF TYPEOF ALIGNOF
|
||||
|
@ -231,7 +226,7 @@ ifobjc
|
|||
%type <ttype> selectorarg keywordnamelist keywordname objcencodeexpr
|
||||
%type <ttype> objc_string non_empty_protocolrefs protocolrefs identifier_list objcprotocolexpr
|
||||
|
||||
%type <ttype> CLASSNAME OBJC_STRING OBJECTNAME
|
||||
%type <ttype> 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:
|
||||
|
|
34
gcc/cpplib.c
34
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
|
||||
<iso646.h> 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. */
|
||||
|
|
Loading…
Add table
Reference in a new issue