aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AST/StmtDumper.cpp10
-rw-r--r--AST/StmtPrinter.cpp6
-rw-r--r--CodeGen/CGExpr.cpp2
-rw-r--r--CodeGen/CGObjC.cpp28
-rw-r--r--CodeGen/CodeGenFunction.h3
-rw-r--r--Parse/ParseExpr.cpp2
-rw-r--r--Parse/ParseObjc.cpp24
-rw-r--r--Sema/Sema.h3
-rw-r--r--Sema/SemaExpr.cpp14
-rw-r--r--clang.xcodeproj/project.pbxproj5
-rw-r--r--include/clang/AST/Expr.h22
-rw-r--r--include/clang/AST/StmtNodes.def6
-rw-r--r--include/clang/Parse/Action.h6
-rw-r--r--include/clang/Parse/Parser.h5
14 files changed, 135 insertions, 1 deletions
diff --git a/AST/StmtDumper.cpp b/AST/StmtDumper.cpp
index 87d4e333b6..22af23cc0e 100644
--- a/AST/StmtDumper.cpp
+++ b/AST/StmtDumper.cpp
@@ -492,6 +492,16 @@ void StmtDumper::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
fprintf(F, " %s)", Node->getValue() ? "true" : "false");
}
+//===----------------------------------------------------------------------===//
+// Obj-C Expressions
+//===----------------------------------------------------------------------===//
+
+void StmtDumper::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
+ DumpExpr(Node);
+ fprintf(F, "\n");
+ DumpSubTree(Node->getString());
+ fprintf(F, ")");
+}
//===----------------------------------------------------------------------===//
// Stmt method implementations
diff --git a/AST/StmtPrinter.cpp b/AST/StmtPrinter.cpp
index 6387f66301..6b2fce874a 100644
--- a/AST/StmtPrinter.cpp
+++ b/AST/StmtPrinter.cpp
@@ -511,6 +511,12 @@ void StmtPrinter::VisitCXXBoolLiteralExpr(CXXBoolLiteralExpr *Node) {
OS << (Node->getValue() ? "true" : "false");
}
+// Obj-C
+
+void StmtPrinter::VisitObjCStringLiteral(ObjCStringLiteral *Node) {
+ OS << "@";
+ VisitStringLiteral(Node->getString());
+}
//===----------------------------------------------------------------------===//
// Stmt method implementations
diff --git a/CodeGen/CGExpr.cpp b/CodeGen/CGExpr.cpp
index ee7b47ee27..cbf92f969c 100644
--- a/CodeGen/CGExpr.cpp
+++ b/CodeGen/CGExpr.cpp
@@ -566,6 +566,8 @@ RValue CodeGenFunction::EmitExpr(const Expr *E) {
return EmitConditionalOperator(cast<ConditionalOperator>(E));
case Expr::ChooseExprClass:
return EmitChooseExpr(cast<ChooseExpr>(E));
+ case Expr::ObjCStringLiteralClass:
+ return EmitObjCStringLiteral(cast<ObjCStringLiteral>(E));
}
}
diff --git a/CodeGen/CGObjC.cpp b/CodeGen/CGObjC.cpp
new file mode 100644
index 0000000000..e08fcca0a5
--- /dev/null
+++ b/CodeGen/CGObjC.cpp
@@ -0,0 +1,28 @@
+//===---- CGBuiltin.cpp - Emit LLVM Code for builtins ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by Anders Carlsson and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code to emit Objective-C code as LLVM code.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CodeGenFunction.h"
+#include "CodeGenModule.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Constant.h"
+
+using namespace clang;
+using namespace CodeGen;
+
+RValue CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral* E)
+{
+ std::string S(E->getString()->getStrData(), E->getString()->getByteLength());
+
+ return RValue::get(CGM.GetAddrOfConstantCFString(S));
+}
+
diff --git a/CodeGen/CodeGenFunction.h b/CodeGen/CodeGenFunction.h
index a0a3c610e8..95e3656ed3 100644
--- a/CodeGen/CodeGenFunction.h
+++ b/CodeGen/CodeGenFunction.h
@@ -61,6 +61,7 @@ namespace clang {
class ConditionalOperator;
class ChooseExpr;
class PreDefinedExpr;
+ class ObjCStringLiteral;
class BlockVarDecl;
class EnumConstantDecl;
@@ -393,6 +394,8 @@ public:
RValue EmitConditionalOperator(const ConditionalOperator *E);
RValue EmitChooseExpr(const ChooseExpr *E);
+ RValue EmitObjCStringLiteral(const ObjCStringLiteral* E);
+
//===--------------------------------------------------------------------===//
// Aggregate Expression Emission
//===--------------------------------------------------------------------===//
diff --git a/Parse/ParseExpr.cpp b/Parse/ParseExpr.cpp
index 75414f7b07..aa8ced3bf5 100644
--- a/Parse/ParseExpr.cpp
+++ b/Parse/ParseExpr.cpp
@@ -569,6 +569,8 @@ Parser::ExprResult Parser::ParseCastExpression(bool isUnaryExpression) {
case tok::kw_reinterpret_cast:
case tok::kw_static_cast:
return ParseCXXCasts();
+ case tok::at:
+ return ParseObjCExpression();
default:
Diag(Tok, diag::err_expected_expression);
return ExprResult(true);
diff --git a/Parse/ParseObjc.cpp b/Parse/ParseObjc.cpp
index 192f19990a..e093f19c2c 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -310,3 +310,27 @@ void Parser::ParseObjCInstanceMethodDeclaration() {
void Parser::ParseObjCClassMethodDeclaration() {
assert(0 && "Unimp");
}
+
+Parser::ExprResult Parser::ParseObjCExpression() {
+ SourceLocation AtLoc = ConsumeToken(); // the "@"
+
+ switch (Tok.getKind()) {
+ case tok::string_literal: // primary-expression: string-literal
+ case tok::wide_string_literal:
+ return ParseObjCStringLiteral();
+ default:
+ Diag(AtLoc, diag::err_unexpected_at);
+ SkipUntil(tok::semi);
+ break;
+ }
+
+ return 0;
+}
+
+Parser::ExprResult Parser::ParseObjCStringLiteral() {
+ ExprResult Res = ParseStringLiteralExpression();
+
+ if (Res.isInvalid) return Res;
+
+ return Actions.ParseObjCStringLiteral(Res.Val);
+}
diff --git a/Sema/Sema.h b/Sema/Sema.h
index 0613ee54c6..42beb84f38 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -323,6 +323,9 @@ public:
/// ParseCXXBoolLiteral - Parse {true,false} literals.
virtual ExprResult ParseCXXBoolLiteral(SourceLocation OpLoc,
tok::TokenKind Kind);
+
+ // ParseObjCStringLiteral - Parse Objective-C string literals.
+ virtual ExprResult ParseObjCStringLiteral(ExprTy *string);
private:
// UsualUnaryConversions - promotes integers (C99 6.3.1.1p2) and converts
// functions and arrays to their respective pointers (C99 6.3.2.1).
diff --git a/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp
index 3ca766b3a0..da3bc3d94f 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1657,3 +1657,17 @@ Sema::ExprResult Sema::ParseChooseExpr(SourceLocation BuiltinLoc, ExprTy *cond,
return new ChooseExpr(BuiltinLoc, CondExpr, LHSExpr, RHSExpr, resType, RPLoc);
}
+// TODO: Move this to SemaObjC.cpp
+Sema::ExprResult Sema::ParseObjCStringLiteral(ExprTy *string)
+{
+ StringLiteral* S = static_cast<StringLiteral *>(string);
+
+ if (CheckBuiltinCFStringArgument(S))
+ return true;
+
+ QualType t = Context.getCFConstantStringType();
+ t = t.getQualifiedType(QualType::Const);
+ t = Context.getPointerType(t);
+
+ return new ObjCStringLiteral(S, t);
+}
diff --git a/clang.xcodeproj/project.pbxproj b/clang.xcodeproj/project.pbxproj
index ace6990d6e..1509d10db7 100644
--- a/clang.xcodeproj/project.pbxproj
+++ b/clang.xcodeproj/project.pbxproj
@@ -8,6 +8,7 @@
/* Begin PBXBuildFile section */
1A30A9E90B93A4C800201A91 /* ExprCXX.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A30A9E80B93A4C800201A91 /* ExprCXX.h */; };
+ 1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A7342470C7B57D500122F56 /* CGObjC.cpp */; };
1A869A700BA2164C008DA07A /* LiteralSupport.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */; };
1A869AA80BA21ABA008DA07A /* LiteralSupport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */; };
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */; };
@@ -196,6 +197,7 @@
/* Begin PBXFileReference section */
1A30A9E80B93A4C800201A91 /* ExprCXX.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = ExprCXX.h; path = clang/AST/ExprCXX.h; sourceTree = "<group>"; };
+ 1A7342470C7B57D500122F56 /* CGObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjC.cpp; path = CodeGen/CGObjC.cpp; sourceTree = "<group>"; };
1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = "<group>"; };
1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = "<group>"; };
1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = CodeGen/CGBuiltin.cpp; sourceTree = "<group>"; };
@@ -437,6 +439,7 @@
DEF2EFF20C6CDD74000C4259 /* CGAggExpr.cpp */,
DE224FF70C7AA98800D370A5 /* CGComplexExpr.cpp */,
DE4772FB0C10EAEC002239E8 /* CGExpr.cpp */,
+ 1A7342470C7B57D500122F56 /* CGObjC.cpp */,
DE4772F90C10EAE5002239E8 /* CGStmt.cpp */,
DE928B120C05659200231DA4 /* ModuleBuilder.cpp */,
);
@@ -616,6 +619,7 @@
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "clang" */;
+ compatibilityVersion = "Xcode 2.4";
hasScannedForEncodings = 1;
mainGroup = 08FB7794FE84155DC02AAC07 /* clang */;
projectDirPath = "";
@@ -692,6 +696,7 @@
DEF2F0100C6CFED5000C4259 /* SemaChecking.cpp in Sources */,
1ABC36940C7A4BDC006DB0AB /* CGBuiltin.cpp in Sources */,
DE224FF80C7AA98800D370A5 /* CGComplexExpr.cpp in Sources */,
+ 1A7342480C7B57D500122F56 /* CGObjC.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h
index d65831d423..26d98610d8 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -811,6 +811,28 @@ public:
static bool classof(const ChooseExpr *) { return true; }
};
+/// ObjCStringLiteral, used for Objective-C string literals
+/// i.e. @"foo".
+class ObjCStringLiteral : public Expr {
+ StringLiteral *String;
+public:
+ ObjCStringLiteral(StringLiteral *SL, QualType T)
+ : Expr(ObjCStringLiteralClass, T), String(SL) {}
+
+ StringLiteral* getString() { return String; }
+
+ const StringLiteral* getString() const { return String; }
+
+ virtual SourceRange getSourceRange() const {
+ return String->getSourceRange();
+ }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == ObjCStringLiteralClass;
+ }
+ static bool classof(const ObjCStringLiteral *) { return true; }
+};
+
} // end namespace clang
#endif
diff --git a/include/clang/AST/StmtNodes.def b/include/clang/AST/StmtNodes.def
index ac1ccacc9d..9fa780c314 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -73,7 +73,11 @@ STMT(53, ChooseExpr , Expr)
// C++ Expressions.
STMT(54, CXXCastExpr , Expr)
STMT(55, CXXBoolLiteralExpr , Expr)
-LAST_EXPR(55)
+
+// Obj-C Expressions.
+STMT(56, ObjCStringLiteral , Expr)
+
+LAST_EXPR(56)
#undef STMT
#undef FIRST_STMT
diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h
index 088345cb16..668bfb6d01 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -404,6 +404,12 @@ public:
tok::TokenKind Kind) {
return 0;
}
+
+ //===----------------------- Obj-C Expressions --------------------------===//
+ virtual ExprResult ParseObjCStringLiteral(ExprTy *string) {
+ return 0;
+ }
+
};
/// MinimalAction - Minimal actions are used by light-weight clients of the
diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h
index ea69da3751..cacb78fe11 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -324,6 +324,11 @@ private:
ExprResult ParseInitializerWithPotentialDesignator();
//===--------------------------------------------------------------------===//
+ // Objective-C Expressions
+ ExprResult ParseObjCExpression();
+ ExprResult ParseObjCStringLiteral();
+
+ //===--------------------------------------------------------------------===//
// C99 6.8: Statements and Blocks.
StmtResult ParseStatement() { return ParseStatementOrDeclaration(true); }