Commit ba89d661 by Zack Weinberg

cpplex.c (parse_name): Might have to glue a CPP_OTHER token before the name.

	* cpplex.c (parse_name): Might have to glue a CPP_OTHER token
	before the name.
	(lex_line): Glue @ onto the beginning of identifiers and
	string constants, in Objective-C mode.
	(output_token, spell_token): Handle CPP_OSTRING.
	(can_paste, maybe_paste_with_next): Handle pasting @ onto the
	beginning of a NAME or a STRING, in objc mode.

	* cpplib.c (get_define_node): Do not permit identifiers that
	begin with @ to be #defined.
	* cppmacro.c (CAN_PASTE_AFTER): Add CPP_OTHER.
	* cpplib.h (TTYPE_TABLE): Add CPP_OSTRING.

	* c-lang.c, objc/objc-act.c (build_objc_string): Delete.
	* c-tree.h (build_objc_string): Delete prototype.
	* objc/objc-tree.def: Delete OBJC_STRING_CST.
	* c-lex.c (yylex): Use build_string for all three kinds of strings.

	* gcc.dg/cpp/20000625-2.c: Don't expect a warning on line 4.

From-SVN: r35470
parent d31772ca
2000-08-03 Zack Weinberg <zack@wolery.cumb.org>
* cpplex.c (parse_name): Might have to glue a CPP_OTHER token
before the name.
(lex_line): Glue @ onto the beginning of identifiers and
string constants, in Objective-C mode.
(output_token, spell_token): Handle CPP_OSTRING.
(can_paste, maybe_paste_with_next): Handle pasting @ onto the
beginning of a NAME or a STRING, in objc mode.
* cpplib.c (get_define_node): Do not permit identifiers that
begin with @ to be #defined.
* cppmacro.c (CAN_PASTE_AFTER): Add CPP_OTHER.
* cpplib.h (TTYPE_TABLE): Add CPP_OSTRING.
* c-lang.c, objc/objc-act.c (build_objc_string): Delete.
* c-tree.h (build_objc_string): Delete prototype.
* objc/objc-tree.def: Delete OBJC_STRING_CST.
* c-lex.c (yylex): Use build_string for all three kinds of strings.
* c-parse.in, objc/objc-act.c: Update commentary.
2000-08-03 Mark Mitchell <mark@codesourcery.com> 2000-08-03 Mark Mitchell <mark@codesourcery.com>
* extend.texi: Fix typo in last change. * extend.texi: Fix typo in last change.
......
...@@ -171,15 +171,6 @@ recognize_objc_keyword () ...@@ -171,15 +171,6 @@ recognize_objc_keyword ()
return 0; return 0;
} }
tree
build_objc_string (len, str)
int len ATTRIBUTE_UNUSED;
const char *str ATTRIBUTE_UNUSED;
{
abort ();
return NULL_TREE;
}
/* Used by c-typeck.c (build_external_ref), but only for objc. */ /* Used by c-typeck.c (build_external_ref), but only for objc. */
tree tree
......
...@@ -2268,25 +2268,19 @@ yylex () ...@@ -2268,25 +2268,19 @@ yylex ()
/* We have read the entire constant. /* We have read the entire constant.
Construct a STRING_CST for the result. */ Construct a STRING_CST for the result. */
yylval.ttype = build_string (p - (token_buffer + 1), token_buffer + 1);
if (wide_flag) if (wide_flag)
{ {
yylval.ttype = build_string (p - (token_buffer + 1),
token_buffer + 1);
TREE_TYPE (yylval.ttype) = wchar_array_type_node; TREE_TYPE (yylval.ttype) = wchar_array_type_node;
value = STRING; value = STRING;
} }
else if (objc_flag) else if (objc_flag)
{ {
/* Return an Objective-C @"..." constant string object. */
yylval.ttype = build_objc_string (p - (token_buffer + 1),
token_buffer + 1);
TREE_TYPE (yylval.ttype) = char_array_type_node; TREE_TYPE (yylval.ttype) = char_array_type_node;
value = OBJC_STRING; value = OBJC_STRING;
} }
else else
{ {
yylval.ttype = build_string (p - (token_buffer + 1),
token_buffer + 1);
TREE_TYPE (yylval.ttype) = char_array_type_node; TREE_TYPE (yylval.ttype) = char_array_type_node;
value = STRING; value = STRING;
} }
......
...@@ -150,7 +150,7 @@ end ifc ...@@ -150,7 +150,7 @@ end ifc
%token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS %token CLASSNAME PUBLIC PRIVATE PROTECTED PROTOCOL OBJECTNAME CLASS ALIAS
/* Objective-C string constants in raw form. /* Objective-C string constants in raw form.
yylval is an OBJC_STRING_CST node. */ yylval is an STRING_CST node. */
%token OBJC_STRING %token OBJC_STRING
...@@ -753,8 +753,8 @@ end ifc ...@@ -753,8 +753,8 @@ end ifc
; ;
ifobjc ifobjc
/* Produces an OBJC_STRING_CST with perhaps more OBJC_STRING_CSTs chained /* Produces an STRING_CST with perhaps more STRING_CSTs chained
onto it. */ onto it, which is to be read as an ObjC string object. */
objc_string: objc_string:
OBJC_STRING OBJC_STRING
| objc_string OBJC_STRING | objc_string OBJC_STRING
......
...@@ -142,7 +142,6 @@ extern int maybe_objc_comptypes PARAMS ((tree, tree, int)); ...@@ -142,7 +142,6 @@ extern int maybe_objc_comptypes PARAMS ((tree, tree, int));
extern tree maybe_building_objc_message_expr PARAMS ((void)); extern tree maybe_building_objc_message_expr PARAMS ((void));
extern tree maybe_objc_method_name PARAMS ((tree)); extern tree maybe_objc_method_name PARAMS ((tree));
extern int recognize_objc_keyword PARAMS ((void)); extern int recognize_objc_keyword PARAMS ((void));
extern tree build_objc_string PARAMS ((int, const char *));
extern tree lookup_objc_ivar PARAMS ((tree)); extern tree lookup_objc_ivar PARAMS ((tree));
/* in c-parse.in */ /* in c-parse.in */
......
...@@ -1008,15 +1008,27 @@ parse_name (pfile, tok, cur, rlimit) ...@@ -1008,15 +1008,27 @@ parse_name (pfile, tok, cur, rlimit)
} }
len = cur - name; len = cur - name;
if (tok->val.node == 0) if (tok->type == CPP_NAME && tok->val.node == 0)
tok->val.node = _cpp_lookup_with_hash (pfile, name, len, r); tok->val.node = _cpp_lookup_with_hash (pfile, name, len, r);
else else
{ {
unsigned int oldlen = tok->val.node->length; unsigned int oldlen;
U_CHAR *newname = alloca (oldlen + len); U_CHAR *newname;
if (tok->type == CPP_NAME)
oldlen = tok->val.node->length;
else
oldlen = 1;
newname = alloca (oldlen + len);
if (tok->type == CPP_NAME)
memcpy (newname, tok->val.node->name, oldlen); memcpy (newname, tok->val.node->name, oldlen);
else
newname[0] = tok->val.aux;
memcpy (newname + oldlen, name, len); memcpy (newname + oldlen, name, len);
tok->val.node = cpp_lookup (pfile, newname, len + oldlen); tok->val.node = cpp_lookup (pfile, newname, len + oldlen);
tok->type = CPP_NAME;
} }
return cur; return cur;
...@@ -1373,8 +1385,16 @@ lex_line (pfile, list) ...@@ -1373,8 +1385,16 @@ lex_line (pfile, list)
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'Y': case 'Z': case 'Y': case 'Z':
cur--; /* Backup character. */ cur--; /* Backup character. */
/* In Objective C, '@' may begin certain keywords. */
if (CPP_OPTION (pfile, objc) && cur_token[-1].type == CPP_OTHER
&& cur_token[-1].val.aux == '@' && IMMED_TOKEN ())
cur_token--;
else
{
cur_token->val.node = 0; cur_token->val.node = 0;
cur_token->type = CPP_NAME; /* Identifier, macro etc. */ cur_token->type = CPP_NAME; /* Identifier, macro etc. */
}
continue_name: continue_name:
cur = parse_name (pfile, cur_token, cur, buffer->rlimit); cur = parse_name (pfile, cur_token, cur, buffer->rlimit);
...@@ -1394,12 +1414,21 @@ lex_line (pfile, list) ...@@ -1394,12 +1414,21 @@ lex_line (pfile, list)
break; break;
case '\'': case '\'':
cur_token->type = CPP_CHAR;
if (cur_token[-1].type == CPP_NAME && IMMED_TOKEN ()
&& cur_token[-1].val.node == pfile->spec_nodes->n_L)
BACKUP_TOKEN (CPP_WCHAR);
goto do_parse_string;
case '\"': case '\"':
cur_token->type = c == '\'' ? CPP_CHAR : CPP_STRING; cur_token->type = CPP_STRING;
/* Do we have a wide string? */
if (cur_token[-1].type == CPP_NAME && IMMED_TOKEN () if (cur_token[-1].type == CPP_NAME && IMMED_TOKEN ()
&& cur_token[-1].val.node == pfile->spec_nodes->n_L) && cur_token[-1].val.node == pfile->spec_nodes->n_L)
BACKUP_TOKEN (c == '\'' ? CPP_WCHAR : CPP_WSTRING); BACKUP_TOKEN (CPP_WSTRING);
else if (CPP_OPTION (pfile, objc)
&& cur_token[-1].type == CPP_OTHER && IMMED_TOKEN ()
&& cur_token[-1].val.aux == '@')
BACKUP_TOKEN (CPP_OSTRING);
do_parse_string: do_parse_string:
/* Here c is one of ' " or >. */ /* Here c is one of ' " or >. */
...@@ -1883,20 +1912,21 @@ output_token (pfile, fp, token, prev, white) ...@@ -1883,20 +1912,21 @@ output_token (pfile, fp, token, prev, white)
case SPELL_STRING: case SPELL_STRING:
{ {
if (token->type == CPP_WSTRING || token->type == CPP_WCHAR) int left, right, tag;
putc ('L', fp); switch (token->type)
{
if (token->type == CPP_STRING || token->type == CPP_WSTRING) case CPP_STRING: left = '"'; right = '"'; tag = '\0'; break;
putc ('"', fp); case CPP_WSTRING: left = '"'; right = '"'; tag = 'L'; break;
if (token->type == CPP_CHAR || token->type == CPP_WCHAR) case CPP_OSTRING: left = '"'; right = '"'; tag = '@'; break;
putc ('\'', fp); case CPP_CHAR: left = '\''; right = '\''; tag = '\0'; break;
case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break;
case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break;
default: left = '\0'; right = '\0'; tag = '\0'; break;
}
if (tag) putc (tag, fp);
if (left) putc (left, fp);
fwrite (token->val.str.text, 1, token->val.str.len, fp); fwrite (token->val.str.text, 1, token->val.str.len, fp);
if (right) putc (right, fp);
if (token->type == CPP_STRING || token->type == CPP_WSTRING)
putc ('"', fp);
if (token->type == CPP_CHAR || token->type == CPP_WCHAR)
putc ('\'', fp);
} }
break; break;
...@@ -1999,21 +2029,22 @@ spell_token (pfile, token, buffer) ...@@ -1999,21 +2029,22 @@ spell_token (pfile, token, buffer)
case SPELL_STRING: case SPELL_STRING:
{ {
if (token->type == CPP_WSTRING || token->type == CPP_WCHAR) int left, right, tag;
*buffer++ = 'L'; switch (token->type)
{
if (token->type == CPP_STRING || token->type == CPP_WSTRING) case CPP_STRING: left = '"'; right = '"'; tag = '\0'; break;
*buffer++ = '"'; case CPP_WSTRING: left = '"'; right = '"'; tag = 'L'; break;
if (token->type == CPP_CHAR || token->type == CPP_WCHAR) case CPP_OSTRING: left = '"'; right = '"'; tag = '@'; break;
*buffer++ = '\''; case CPP_CHAR: left = '\''; right = '\''; tag = '\0'; break;
case CPP_WCHAR: left = '\''; right = '\''; tag = 'L'; break;
case CPP_HEADER_NAME: left = '<'; right = '>'; tag = '\0'; break;
default: left = '\0'; right = '\0'; tag = '\0'; break;
}
if (tag) *buffer++ = tag;
if (left) *buffer++ = left;
memcpy (buffer, token->val.str.text, token->val.str.len); memcpy (buffer, token->val.str.text, token->val.str.len);
buffer += token->val.str.len; buffer += token->val.str.len;
if (right) *buffer++ = right;
if (token->type == CPP_STRING || token->type == CPP_WSTRING)
*buffer++ = '"';
if (token->type == CPP_CHAR || token->type == CPP_WCHAR)
*buffer++ = '\'';
} }
break; break;
...@@ -2700,6 +2731,13 @@ can_paste (pfile, token1, token2, digraph) ...@@ -2700,6 +2731,13 @@ can_paste (pfile, token1, token2, digraph)
return CPP_NUMBER; return CPP_NUMBER;
break; break;
case CPP_OTHER:
if (CPP_OPTION (pfile, objc) && token1->val.aux == '@')
{
if (b == CPP_NAME) return CPP_NAME;
if (b == CPP_STRING) return CPP_OSTRING;
}
default: default:
break; break;
} }
...@@ -2789,7 +2827,8 @@ maybe_paste_with_next (pfile, token) ...@@ -2789,7 +2827,8 @@ maybe_paste_with_next (pfile, token)
pasted->val.str.len = end - buf; pasted->val.str.len = end - buf;
} }
} }
else if (type == CPP_WCHAR || type == CPP_WSTRING) else if (type == CPP_WCHAR || type == CPP_WSTRING
|| type == CPP_OSTRING)
pasted = duplicate_token (pfile, second); pasted = duplicate_token (pfile, second);
else else
{ {
......
...@@ -242,6 +242,16 @@ get_define_node (pfile) ...@@ -242,6 +242,16 @@ get_define_node (pfile)
return 0; return 0;
} }
/* In Objective C, some keywords begin with '@', but general identifiers
do not, and you're not allowed to #define them. */
if (token->val.node->name[0] == '@')
{
cpp_error_with_line (pfile, token->line, token->col,
"\"%s\" cannot be used as a macro name",
token->val.node->name);
return 0;
}
/* Check for poisoned identifiers now. */ /* Check for poisoned identifiers now. */
if (token->val.node->type == T_POISON) if (token->val.node->type == T_POISON)
{ {
......
...@@ -123,6 +123,7 @@ typedef struct cpp_hashnode cpp_hashnode; ...@@ -123,6 +123,7 @@ typedef struct cpp_hashnode cpp_hashnode;
\ \
TK(CPP_STRING, SPELL_STRING) /* "string" */ \ TK(CPP_STRING, SPELL_STRING) /* "string" */ \
TK(CPP_WSTRING, SPELL_STRING) /* L"string" */ \ TK(CPP_WSTRING, SPELL_STRING) /* L"string" */ \
TK(CPP_OSTRING, SPELL_STRING) /* @"string" - Objective C */ \
TK(CPP_HEADER_NAME, SPELL_STRING) /* <stdio.h> in #include */ \ TK(CPP_HEADER_NAME, SPELL_STRING) /* <stdio.h> in #include */ \
\ \
TK(CPP_COMMENT, SPELL_STRING) /* Only if output comments. */ \ TK(CPP_COMMENT, SPELL_STRING) /* Only if output comments. */ \
......
...@@ -55,12 +55,14 @@ static cpp_toklist * alloc_macro PARAMS ((cpp_reader *, struct macro_info *)); ...@@ -55,12 +55,14 @@ static cpp_toklist * alloc_macro PARAMS ((cpp_reader *, struct macro_info *));
/* These are all the tokens that can have something pasted after them. /* These are all the tokens that can have something pasted after them.
Comma is included in the list only to support the GNU varargs extension Comma is included in the list only to support the GNU varargs extension
(where you write a ## b and a disappears if b is an empty rest argument). */ (where you write a ## b and a disappears if b is an empty rest argument).
CPP_OTHER is included because of Objective C's use of '@'. */
#define CAN_PASTE_AFTER(type) \ #define CAN_PASTE_AFTER(type) \
((type) <= CPP_LAST_EQ || (type) == CPP_COLON || (type) == CPP_HASH \ ((type) <= CPP_LAST_EQ || (type) == CPP_COLON || (type) == CPP_HASH \
|| (type) == CPP_DEREF || (type) == CPP_DOT || (type) == CPP_NAME \ || (type) == CPP_DEREF || (type) == CPP_DOT || (type) == CPP_NAME \
|| (type) == CPP_INT || (type) == CPP_FLOAT || (type) == CPP_NUMBER \ || (type) == CPP_INT || (type) == CPP_FLOAT || (type) == CPP_NUMBER \
|| (type) == CPP_MACRO_ARG || (type) == CPP_PLACEMARKER || (type) == CPP_COMMA) || (type) == CPP_MACRO_ARG || (type) == CPP_PLACEMARKER \
|| (type) == CPP_COMMA || (type) == CPP_OTHER)
/* Scans for a given token, returning the parameter number if found, /* Scans for a given token, returning the parameter number if found,
or 0 if not found. Scans from FIRST to TOKEN - 1 or the first or 0 if not found. Scans from FIRST to TOKEN - 1 or the first
......
...@@ -1410,22 +1410,7 @@ my_build_string (len, str) ...@@ -1410,22 +1410,7 @@ my_build_string (len, str)
return a_string; return a_string;
} }
/* Return a newly constructed OBJC_STRING_CST node whose value is /* Given a chain of STRING_CST's, build a static instance of
the LEN characters at STR.
The TREE_TYPE is not initialized. */
tree
build_objc_string (len, str)
int len;
const char *str;
{
tree s = build_string (len, str);
TREE_SET_CODE (s, OBJC_STRING_CST);
return s;
}
/* Given a chain of OBJC_STRING_CST's, build a static instance of
NXConstanString which points at the concatenation of those strings. NXConstanString which points at the concatenation of those strings.
We place the string object in the __string_objects section of the We place the string object in the __string_objects section of the
__OBJC segment. The Objective-C runtime will initialize the isa __OBJC segment. The Objective-C runtime will initialize the isa
...@@ -1451,7 +1436,6 @@ build_objc_string_object (strings) ...@@ -1451,7 +1436,6 @@ build_objc_string_object (strings)
add_class_reference (constant_string_id); add_class_reference (constant_string_id);
/* Combine_strings will work for OBJC_STRING_CST's too. */
string = combine_strings (strings); string = combine_strings (strings);
TREE_SET_CODE (string, STRING_CST); TREE_SET_CODE (string, STRING_CST);
length = TREE_STRING_LENGTH (string) - 1; length = TREE_STRING_LENGTH (string) - 1;
......
...@@ -32,6 +32,3 @@ DEFTREECODE (PROTOCOL_INTERFACE_TYPE, "protocol_interface_type", 't', 0) ...@@ -32,6 +32,3 @@ DEFTREECODE (PROTOCOL_INTERFACE_TYPE, "protocol_interface_type", 't', 0)
DEFTREECODE (KEYWORD_DECL, "keyword_decl", 'd', 0) DEFTREECODE (KEYWORD_DECL, "keyword_decl", 'd', 0)
DEFTREECODE (INSTANCE_METHOD_DECL, "instance_method_decl", 'd', 0) DEFTREECODE (INSTANCE_METHOD_DECL, "instance_method_decl", 'd', 0)
DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", 'd', 0) DEFTREECODE (CLASS_METHOD_DECL, "class_method_decl", 'd', 0)
/* Objective-C constants. */
DEFTREECODE (OBJC_STRING_CST, "objc_string_cst", 'c', 3)
2000-08-03 Zack Weinberg <zack@wolery.cumb.org>
* gcc.dg/cpp/20000625-2.c: Don't expect a warning on line 4.
Thu Aug 3 01:46:33 2000 Jeffrey A Law (law@cygnus.com) Thu Aug 3 01:46:33 2000 Jeffrey A Law (law@cygnus.com)
* gcc.c-torture/compile/20000803-1.c: New test. * gcc.c-torture/compile/20000803-1.c: New test.
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
/* { dg-do run } */ /* { dg-do run } */
#define symbol_version(name, version) name##@##version #define symbol_version(name, version) name##@##version
/* { dg-warning "nothing can be pasted" "" { target *-*-* } 4 } */
#define str(x) xstr(x) #define str(x) xstr(x)
#define xstr(x) #x #define xstr(x) #x
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment