c-common.h (enum rid): Add RID_FIRST_AT, RID_LAST_AT, RID_LAST_PQ.
authorZack Weinberg <zackw@stanford.edu>
Sun, 1 Jul 2001 18:48:13 +0000 (18:48 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Sun, 1 Jul 2001 18:48:13 +0000 (18:48 +0000)
* 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
gcc/c-common.h
gcc/c-parse.in
gcc/cpplib.c

index 45be5e87fa7180e3bcee4c51b002012e8b0056ae..6077e4585240944a13c16279a42b02b39565c438 100644 (file)
@@ -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.
index 05350c12fa2a40d4605f5602920a57e7d52d916f..95ead5424412b96da3291b6c97a7b1c08679757f 100644 (file)
@@ -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;
index 45b04dab71addd2759a38433339d81f7b1b54ff2..9a7fe1cd34f9338ef1d088ff43f500b726c98ee0 100644 (file)
@@ -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
 \f
 %{
@@ -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:
index cb493105ae94e2461cd3dbe975e3bed40e0fee82..e0f61247c466fdff3ae280e4491226d669790fb1 100644 (file)
@@ -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.  */