From: nicola Date: Mon, 22 Nov 2010 19:27:17 +0000 (+0000) Subject: In gcc/c-family/: X-Git-Url: http://git.sourceforge.jp/view?a=commitdiff_plain;h=b4aa4123af115e2e9b5247d661131d1ccb8f096c;p=pf3gnuchains%2Fgcc-fork.git In gcc/c-family/: 2010-11-22 Nicola Pero PR objc/34033 * c-lex.c (lex_string): Check that each string in an Objective-C string concat sequence starts with either one or zero '@', and that there are no spurious '@' signs at the end. In gcc/testsuite/: 2010-11-22 Nicola Pero PR objc/34033 * objc.dg/strings-1.m: New. * objc.dg/strings-2.m: New. * obj-c++.dg/strings-1.mm: New. * obj-c++.dg/strings-2.mm: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@167048 138bc75d-0d04-0410-961f-82ee72b054a4 --- diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index 86e75ce84c9..fe6fe7ab732 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,10 @@ +2010-11-22 Nicola Pero + + PR objc/34033 + * c-lex.c (lex_string): Check that each string in an Objective-C + string concat sequence starts with either one or zero '@', and + that there are no spurious '@' signs at the end. + 2010-11-20 Joseph Myers * c-pragma.c: Remove conditionals on HANDLE_PRAGMA_PACK, diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c index 68a0fe04a5c..e372954f9ff 100644 --- a/gcc/c-family/c-lex.c +++ b/gcc/c-family/c-lex.c @@ -889,10 +889,12 @@ interpret_fixed (const cpp_token *token, unsigned int flags) /* Convert a series of STRING, WSTRING, STRING16, STRING32 and/or UTF8STRING tokens into a tree, performing string constant - concatenation. TOK is the first of these. VALP is the location - to write the string into. OBJC_STRING indicates whether an '@' token - preceded the incoming token. - Returns the CPP token type of the result (CPP_STRING, CPP_WSTRING, + concatenation. TOK is the first of these. VALP is the location to + write the string into. OBJC_STRING indicates whether an '@' token + preceded the incoming token (in that case, the strings can either + be ObjC strings, preceded by a single '@', or normal strings, not + preceded by '@'. The result will be a CPP_OBJC_STRING). Returns + the CPP token type of the result (CPP_STRING, CPP_WSTRING, CPP_STRING32, CPP_STRING16, CPP_UTF8STRING, or CPP_OBJC_STRING). This is unfortunately more work than it should be. If any of the @@ -918,6 +920,12 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate) cpp_string str = tok->val.str; cpp_string *strs = &str; + /* objc_at_sign_was_seen is only used when doing Objective-C string + concatenation. It is 'true' if we have seen an '@' before the + current string, and 'false' if not. We must see exactly one or + zero '@' before each string. */ + bool objc_at_sign_was_seen = false; + retry: tok = cpp_get_token (parse_in); switch (tok->type) @@ -925,9 +933,12 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate) case CPP_PADDING: goto retry; case CPP_ATSIGN: - if (c_dialect_objc ()) + if (objc_string) { - objc_string = true; + if (objc_at_sign_was_seen) + error ("repeated %<@%> before Objective-C string"); + + objc_at_sign_was_seen = true; goto retry; } /* FALLTHROUGH */ @@ -956,9 +967,15 @@ lex_string (const cpp_token *tok, tree *valp, bool objc_string, bool translate) concats++; obstack_grow (&str_ob, &tok->val.str, sizeof (cpp_string)); + if (objc_string) + objc_at_sign_was_seen = false; goto retry; } + /* It is an error if we saw a '@' with no following string. */ + if (objc_at_sign_was_seen) + error ("stray %<@%> in program"); + /* We have read one more token than we want. */ _cpp_backup_tokens (parse_in, 1); if (concats) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6d9a9d16711..274d4087497 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2010-11-22 Nicola Pero + + PR objc/34033 + * objc.dg/strings-1.m: New. + * objc.dg/strings-2.m: New. + * obj-c++.dg/strings-1.mm: New. + * obj-c++.dg/strings-2.mm: New. + 2010-11-22 Ian Bolton * testsuite/c-c++-common/pr44832.c: Use -fno-short-enums option for diff --git a/gcc/testsuite/obj-c++.dg/strings-1.mm b/gcc/testsuite/obj-c++.dg/strings-1.mm new file mode 100644 index 00000000000..2630220618c --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/strings-1.mm @@ -0,0 +1,33 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include "../objc-obj-c++-shared/Object1.h" +#include "../objc-obj-c++-shared/next-mapping.h" +#ifndef __NEXT_RUNTIME__ +#include +#endif + +/* The following are correct. */ +id test_valid1 = @"test"; +id test_valid2 = @"te" @"st"; +id test_valid3 = @"te" @"s" @"t"; +id test_valid4 = @ "t" @ "e" @ "s" @ "t"; + +/* The following are accepted too; you can concat an ObjC string to a + C string, the result being an ObjC string. */ +id test_valid5 = @"te" "st"; +id test_valid6 = @"te" "s" @"t"; +id test_valid7 = @"te" @"s" "t"; + +/* The following are not correct. */ +id test_invalid1 = @@"test"; /* { dg-error "stray .@. in program" } */ +const char *test_invalid2 = "test"@; /* { dg-error "stray .@. in program" } */ +const char *test_invalid3 = "test"@@; /* { dg-error "stray .@. in program" } */ +const char *test_invalid4 = "te" @"st"; /* { dg-error "expected" } */ +id test_invalid5 = @"te" @@"st"; /* { dg-error "repeated .@. before Objective-C string" } */ +id test_invalid6 = @@"te" @"st"; /* { dg-error "stray .@. in program" } */ +id test_invalid7 = @"te" @"s" @@"t"; /* { dg-error "repeated .@. before Objective-C string" } */ +id test_invalid8 = @"te" @@"s" @"t"; /* { dg-error "repeated .@. before Objective-C string" } */ +id test_invalid9 = @"te" @"s" @"t" @; /* { dg-error "stray .@. in program" } */ +id test_invalidA = @"te" @ st; /* { dg-error "stray .@. in program" } */ + /* { dg-error "expected" "" { target *-*-* } 32 } */ diff --git a/gcc/testsuite/obj-c++.dg/strings-2.mm b/gcc/testsuite/obj-c++.dg/strings-2.mm new file mode 100644 index 00000000000..9b7023a9745 --- /dev/null +++ b/gcc/testsuite/obj-c++.dg/strings-2.mm @@ -0,0 +1,51 @@ +/* Contributed by Nicola Pero , November 2010. */ + +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ +/* { dg-options "-fconstant-string-class=MyTestString" } */ +/* { dg-options "-mno-constant-cfstrings -fconstant-string-class=MyTestString" { target *-*-darwin* } } */ + +/* { dg-additional-sources "../objc-obj-c++-shared/Object1.mm" } */ + +#include "../objc-obj-c++-shared/Object1.h" +#include "../objc-obj-c++-shared/next-mapping.h" + +#include /* For abort() */ + +@interface MyTestString : Object +{ + char *string; + unsigned int len; +} +/* All strings should contain the C string 'test'. Call -check to + test that this is true. */ +- (void) check; +@end + +@implementation MyTestString +- (void) check +{ + if (len != 4 || string[0] != 't' || string[1] != 'e' + || string[2] != 's' || string[3] != 't' || string[4] != '\0') + abort (); +} +@end + +int main (void) +{ + MyTestString *test_valid1 = @"test"; + MyTestString *test_valid2 = @"te" @"st"; + MyTestString *test_valid3 = @"te" @"s" @"t"; + MyTestString *test_valid4 = @ "t" @ "e" @ "s" @ "t"; + MyTestString *test_valid5 = @ "t" "e" "s" "t"; + MyTestString *test_valid6 = @ "t" "e" "s" @ "t"; + + [test_valid1 check]; + [test_valid2 check]; + [test_valid3 check]; + [test_valid4 check]; + [test_valid5 check]; + [test_valid6 check]; + + return 0; +} diff --git a/gcc/testsuite/objc.dg/strings-1.m b/gcc/testsuite/objc.dg/strings-1.m new file mode 100644 index 00000000000..2630220618c --- /dev/null +++ b/gcc/testsuite/objc.dg/strings-1.m @@ -0,0 +1,33 @@ +/* Contributed by Nicola Pero , November 2010. */ +/* { dg-do compile } */ + +#include "../objc-obj-c++-shared/Object1.h" +#include "../objc-obj-c++-shared/next-mapping.h" +#ifndef __NEXT_RUNTIME__ +#include +#endif + +/* The following are correct. */ +id test_valid1 = @"test"; +id test_valid2 = @"te" @"st"; +id test_valid3 = @"te" @"s" @"t"; +id test_valid4 = @ "t" @ "e" @ "s" @ "t"; + +/* The following are accepted too; you can concat an ObjC string to a + C string, the result being an ObjC string. */ +id test_valid5 = @"te" "st"; +id test_valid6 = @"te" "s" @"t"; +id test_valid7 = @"te" @"s" "t"; + +/* The following are not correct. */ +id test_invalid1 = @@"test"; /* { dg-error "stray .@. in program" } */ +const char *test_invalid2 = "test"@; /* { dg-error "stray .@. in program" } */ +const char *test_invalid3 = "test"@@; /* { dg-error "stray .@. in program" } */ +const char *test_invalid4 = "te" @"st"; /* { dg-error "expected" } */ +id test_invalid5 = @"te" @@"st"; /* { dg-error "repeated .@. before Objective-C string" } */ +id test_invalid6 = @@"te" @"st"; /* { dg-error "stray .@. in program" } */ +id test_invalid7 = @"te" @"s" @@"t"; /* { dg-error "repeated .@. before Objective-C string" } */ +id test_invalid8 = @"te" @@"s" @"t"; /* { dg-error "repeated .@. before Objective-C string" } */ +id test_invalid9 = @"te" @"s" @"t" @; /* { dg-error "stray .@. in program" } */ +id test_invalidA = @"te" @ st; /* { dg-error "stray .@. in program" } */ + /* { dg-error "expected" "" { target *-*-* } 32 } */ diff --git a/gcc/testsuite/objc.dg/strings-2.m b/gcc/testsuite/objc.dg/strings-2.m new file mode 100644 index 00000000000..d69967a6871 --- /dev/null +++ b/gcc/testsuite/objc.dg/strings-2.m @@ -0,0 +1,51 @@ +/* Contributed by Nicola Pero , November 2010. */ + +/* { dg-do run } */ +/* { dg-xfail-run-if "Needs OBJC2 ABI" { *-*-darwin* && { lp64 && { ! objc2 } } } { "-fnext-runtime" } { "" } } */ +/* { dg-options "-fconstant-string-class=MyTestString" } */ +/* { dg-options "-mno-constant-cfstrings -fconstant-string-class=MyTestString" { target *-*-darwin* } } */ + +/* { dg-additional-sources "../objc-obj-c++-shared/Object1.m" } */ + +#include "../objc-obj-c++-shared/Object1.h" +#include "../objc-obj-c++-shared/next-mapping.h" + +#include /* For abort() */ + +@interface MyTestString : Object +{ + char *string; + unsigned int len; +} +/* All strings should contain the C string 'test'. Call -check to + test that this is true. */ +- (void) check; +@end + +@implementation MyTestString +- (void) check +{ + if (len != 4 || string[0] != 't' || string[1] != 'e' + || string[2] != 's' || string[3] != 't' || string[4] != '\0') + abort (); +} +@end + +int main (void) +{ + MyTestString *test_valid1 = @"test"; + MyTestString *test_valid2 = @"te" @"st"; + MyTestString *test_valid3 = @"te" @"s" @"t"; + MyTestString *test_valid4 = @ "t" @ "e" @ "s" @ "t"; + MyTestString *test_valid5 = @ "t" "e" "s" "t"; + MyTestString *test_valid6 = @ "t" "e" "s" @ "t"; + + [test_valid1 check]; + [test_valid2 check]; + [test_valid3 check]; + [test_valid4 check]; + [test_valid5 check]; + [test_valid6 check]; + + return 0; +}