Implement parsing and code generation of Objective-C string literals.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@41238 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/StmtDumper.cpp b/AST/StmtDumper.cpp
index 87d4e33..22af23c 100644
--- a/AST/StmtDumper.cpp
+++ b/AST/StmtDumper.cpp
@@ -492,6 +492,16 @@
   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 6387f66..6b2fce8 100644
--- a/AST/StmtPrinter.cpp
+++ b/AST/StmtPrinter.cpp
@@ -511,6 +511,12 @@
   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 ee7b47e..cbf92f9 100644
--- a/CodeGen/CGExpr.cpp
+++ b/CodeGen/CGExpr.cpp
@@ -566,6 +566,8 @@
     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 0000000..e08fcca
--- /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 a0a3c61..95e3656 100644
--- a/CodeGen/CodeGenFunction.h
+++ b/CodeGen/CodeGenFunction.h
@@ -61,6 +61,7 @@
   class ConditionalOperator;
   class ChooseExpr;
   class PreDefinedExpr;
+  class ObjCStringLiteral;
   
   class BlockVarDecl;
   class EnumConstantDecl;
@@ -393,6 +394,8 @@
   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 75414f7..aa8ced3 100644
--- a/Parse/ParseExpr.cpp
+++ b/Parse/ParseExpr.cpp
@@ -569,6 +569,8 @@
   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 192f199..e093f19 100644
--- a/Parse/ParseObjc.cpp
+++ b/Parse/ParseObjc.cpp
@@ -310,3 +310,27 @@
 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 0613ee5..42beb84 100644
--- a/Sema/Sema.h
+++ b/Sema/Sema.h
@@ -323,6 +323,9 @@
   /// 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 3ca766b..da3bc3d 100644
--- a/Sema/SemaExpr.cpp
+++ b/Sema/SemaExpr.cpp
@@ -1657,3 +1657,17 @@
   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 ace6990..1509d10 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 d65831d..26d9861 100644
--- a/include/clang/AST/Expr.h
+++ b/include/clang/AST/Expr.h
@@ -811,6 +811,28 @@
   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 ac1ccac..9fa780c 100644
--- a/include/clang/AST/StmtNodes.def
+++ b/include/clang/AST/StmtNodes.def
@@ -73,7 +73,11 @@
 // 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 088345c..668bfb6 100644
--- a/include/clang/Parse/Action.h
+++ b/include/clang/Parse/Action.h
@@ -404,6 +404,12 @@
                                          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 ea69da3..cacb78f 100644
--- a/include/clang/Parse/Parser.h
+++ b/include/clang/Parse/Parser.h
@@ -324,6 +324,11 @@
   ExprResult ParseInitializerWithPotentialDesignator();
   
   //===--------------------------------------------------------------------===//
+  // Objective-C Expressions
+  ExprResult ParseObjCExpression();
+  ExprResult ParseObjCStringLiteral();
+  
+  //===--------------------------------------------------------------------===//
   // C99 6.8: Statements and Blocks.
   
   StmtResult ParseStatement() { return ParseStatementOrDeclaration(true); }