aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Parse/ParseObjc.cpp42
-rw-r--r--Sema/Sema.h5
-rw-r--r--Sema/SemaExpr.cpp11
-rw-r--r--clang.xcodeproj/project.pbxproj1
-rw-r--r--include/clang/Basic/DiagnosticKinds.def4
-rw-r--r--include/clang/Parse/Action.h6
-rw-r--r--test/Sema/objc-string.m12
7 files changed, 65 insertions, 16 deletions
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index 05cbabd67c..d455a62199 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -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:
diff --git a/Sema/Sema.h b/Sema/Sema.h
index 4c9f4788f8..d52d49b75c 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -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,
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 808da1e55b..0f5fe8ad0f 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -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;
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index ed2ec876d3..789b272fa4 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -772,7 +772,6 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
- compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
diff --git a/include/clang/Basic/DiagnosticKinds.def b/include/clang/Basic/DiagnosticKinds.def
index 25f1eea308..7fec38e800 100644
--- a/include/clang/Basic/DiagnosticKinds.def
+++ b/include/clang/Basic/DiagnosticKinds.def
@@ -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')")
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 5f6a1469e3..8de9a19011 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -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
index 0000000000..4fe4394164
--- /dev/null
+++ b/test/Sema/objc-string.m
@@ -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}}
+