]> granicus.if.org Git - clang/commitdiff
Add ObjC parser support for concatenated ObjC strings. Note that
authorChris Lattner <sabre@nondot.org>
Wed, 12 Dec 2007 01:04:12 +0000 (01:04 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 12 Dec 2007 01:04:12 +0000 (01:04 +0000)
this is passed to sema and ignored there, so the second part of the
string will not make it into the AST.  Passing to Fariborz to finish
Sema + AST construction.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44898 91177308-0d34-0410-b5e6-96231b3b80d8

Parse/ParseObjc.cpp
Sema/Sema.h
Sema/SemaExpr.cpp
clang.xcodeproj/project.pbxproj
include/clang/Basic/DiagnosticKinds.def
include/clang/Parse/Action.h
test/Sema/objc-string.m [new file with mode: 0644]

index 05cbabd67c5afd3a81eb2543526ab54aa6af463a..d455a621992aa6efc547fc826440fdd6aec0e13a 100644 (file)
@@ -1190,11 +1190,11 @@ Parser::DeclTy *Parser::ParseObjCMethodDefinition() {
 Parser::ExprResult Parser::ParseObjCAtExpression(SourceLocation AtLoc) {
 
   switch (Tok.getKind()) {
-    case tok::string_literal:    // primary-expression: string-literal
-    case tok::wide_string_literal:
-      return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
-    default:
-      break;
+  case tok::string_literal:    // primary-expression: string-literal
+  case tok::wide_string_literal:
+    return ParsePostfixExpressionSuffix(ParseObjCStringLiteral(AtLoc));
+  default:
+    break;
   }
   
   switch (Tok.getIdentifierInfo()->getObjCKeywordID()) {
@@ -1333,10 +1333,38 @@ Parser::ExprResult Parser::ParseObjCMessageExpression() {
 
 Parser::ExprResult Parser::ParseObjCStringLiteral(SourceLocation AtLoc) {
   ExprResult Res = ParseStringLiteralExpression();
-
   if (Res.isInvalid) return Res;
+  
+  // @"foo" @"bar" is a valid concatenated string.  Eat any subsequent string
+  // expressions.  At this point, we know that the only valid thing that starts
+  // with '@' is an @"".
+  llvm::SmallVector<SourceLocation, 4> AtLocs;
+  llvm::SmallVector<ExprTy*, 4> AtStrings;
+  AtLocs.push_back(AtLoc);
+  AtStrings.push_back(Res.Val);
+  
+  while (Tok.is(tok::at)) {
+    AtLocs.push_back(ConsumeToken()); // eat the @.
+
+    ExprResult Res(true);  // Invalid unless there is a string literal.
+    if (isTokenStringLiteral())
+      Res = ParseStringLiteralExpression();
+    else
+      Diag(Tok, diag::err_objc_concat_string);
+    
+    if (Res.isInvalid) {
+      while (!AtStrings.empty()) {
+        Actions.DeleteExpr(AtStrings.back());
+        AtStrings.pop_back();
+      }
+      return Res;
+    }
+
+    AtStrings.push_back(Res.Val);
+  }
 
-  return Actions.ParseObjCStringLiteral(AtLoc, Res.Val);
+  return Actions.ParseObjCStringLiteral(&AtLocs[0], &AtStrings[0],
+                                        AtStrings.size());
 }
 
 ///    objc-encode-expression:
index 4c9f4788f8e2d2687cd0c4495bd0f4810c016517..d52d49b75c65c8480bac9e4717b9f4b49d49a6d4 100644 (file)
@@ -465,8 +465,9 @@ public:
                                          tok::TokenKind Kind);
   
   // ParseObjCStringLiteral - Parse Objective-C string literals.
-  virtual ExprResult ParseObjCStringLiteral(SourceLocation AtLoc,
-                                            ExprTy *string);
+  virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, 
+                                            ExprTy **Strings,
+                                            unsigned NumStrings);
   virtual ExprResult ParseObjCEncodeExpression(SourceLocation AtLoc,
                                                SourceLocation EncodeLoc,
                                                SourceLocation LParenLoc,
index 808da1e55bcf73ec7565f1c432fd1dfb8cbe71b2..0f5fe8ad0f26ae8120f5eb9115e38129d877d4fb 100644 (file)
@@ -2046,9 +2046,14 @@ Sema::ExprResult Sema::ActOnVAArg(SourceLocation BuiltinLoc,
 }
 
 // TODO: Move this to SemaObjC.cpp
-Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation AtLoc, 
-                                              ExprTy *string) {
-  StringLiteral* S = static_cast<StringLiteral *>(string);
+Sema::ExprResult Sema::ParseObjCStringLiteral(SourceLocation *AtLocs, 
+                                              ExprTy **Strings,
+                                              unsigned NumStrings) {
+  
+  // FIXME: This is passed in an ARRAY of strings which need to be concatenated.
+  // Handle this case here.  For now we just ignore all but the first one.
+  SourceLocation AtLoc = AtLocs[0];
+  StringLiteral* S = static_cast<StringLiteral *>(Strings[0]);
   
   if (CheckBuiltinCFStringArgument(S))
     return true;
index ed2ec876d39cd42735bd374a8a8af302ba9c30a4..789b272fa4e532723e26ed0a8a79e63e292cd980 100644 (file)
                08FB7793FE84155DC02AAC07 /* Project object */ = {
                        isa = PBXProject;
                        buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
-                       compatibilityVersion = "Xcode 2.4";
                        hasScannedForEncodings = 1;
                        mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
                        projectDirPath = "";
index 25f1eea308dbe32ff7f7e21ba36a61c883afc351..7fec38e800d1a0f20f212fe525a4545f6b689690 100644 (file)
@@ -414,6 +414,8 @@ DIAG(err_objc_protocol_optional, ERROR,
      "@optional may be specified in protocols only")
 DIAG(err_missing_catch_finally, ERROR,
      "@try statment without a @catch and @finally clause")
+DIAG(err_objc_concat_string, ERROR,
+     "unexpected token after Objective-C string")
 DIAG(err_undef_superclass, ERROR,
      "cannot find interface declaration for '%0', superclass of '%1'")
 DIAG(err_duplicate_class_def, ERROR,
@@ -465,7 +467,7 @@ DIAG(warn_previous_declaration, WARNING,
 DIAG(err_conflicting_aliasing_type, ERROR,
      "conflicting types for alias %0'")
 DIAG(err_statically_allocated_object, ERROR,
-     "statically allocated Objective-c object '%0'")
+     "statically allocated Objective-C object '%0'")
 DIAG(warn_method_not_found, WARNING,
      "method '%0%1' not found (return type defaults to 'id')")
 
index 5f6a1469e384e3c8ad22faeac4a2b5314b724822..8de9a1901117c7d9608946d4c0d41877c2795bda 100644 (file)
@@ -643,8 +643,10 @@ public:
                                                
                                                
   //===----------------------- Obj-C Expressions --------------------------===//
-  virtual ExprResult ParseObjCStringLiteral(SourceLocation AtLoc, 
-                                            ExprTy *string) {
+
+  virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs, 
+                                            ExprTy **Strings,
+                                            unsigned NumStrings) {
     return 0;
   }
 
diff --git a/test/Sema/objc-string.m b/test/Sema/objc-string.m
new file mode 100644 (file)
index 0000000..4fe4394
--- /dev/null
@@ -0,0 +1,12 @@
+// RUN: clang %s -verify -fsyntax-only
+
+@class NSString;
+@interface NSConstantString;
+@end
+
+
+
+NSString *s = @"123"; // simple
+NSString *t = @"123" @"456"; // concat
+NSString *u = @"123" @ blah; // expected-error: {{unexpected token}}
+