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()) {
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:
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,
}
// 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;
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
"@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,
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')")
//===----------------------- Obj-C Expressions --------------------------===//
- virtual ExprResult ParseObjCStringLiteral(SourceLocation AtLoc,
- ExprTy *string) {
+
+ virtual ExprResult ParseObjCStringLiteral(SourceLocation *AtLocs,
+ ExprTy **Strings,
+ unsigned NumStrings) {
return 0;
}
--- /dev/null
+// 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}}
+