From 76f4a902d7b7bd752506ed7af9cce250252b0474 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Tue, 21 Aug 2007 17:43:55 +0000 Subject: [PATCH] Implement parsing and code generation of Objective-C string literals. llvm-svn: 41238 --- clang/AST/StmtDumper.cpp | 10 ++++++++++ clang/AST/StmtPrinter.cpp | 6 ++++++ clang/CodeGen/CGExpr.cpp | 2 ++ clang/CodeGen/CGObjC.cpp | 28 +++++++++++++++++++++++++++ clang/CodeGen/CodeGenFunction.h | 3 +++ clang/Parse/ParseExpr.cpp | 2 ++ clang/Parse/ParseObjc.cpp | 24 +++++++++++++++++++++++ clang/Sema/Sema.h | 3 +++ clang/Sema/SemaExpr.cpp | 14 ++++++++++++++ clang/clang.xcodeproj/project.pbxproj | 5 +++++ clang/include/clang/AST/Expr.h | 22 +++++++++++++++++++++ clang/include/clang/AST/StmtNodes.def | 6 +++++- clang/include/clang/Parse/Action.h | 6 ++++++ clang/include/clang/Parse/Parser.h | 5 +++++ 14 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 clang/CodeGen/CGObjC.cpp diff --git a/clang/AST/StmtDumper.cpp b/clang/AST/StmtDumper.cpp index 87d4e333b6bb..22af23cc0e0d 100644 --- a/clang/AST/StmtDumper.cpp +++ b/clang/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/clang/AST/StmtPrinter.cpp b/clang/AST/StmtPrinter.cpp index 6387f66301b7..6b2fce874a44 100644 --- a/clang/AST/StmtPrinter.cpp +++ b/clang/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/clang/CodeGen/CGExpr.cpp b/clang/CodeGen/CGExpr.cpp index ee7b47ee2773..cbf92f969c90 100644 --- a/clang/CodeGen/CGExpr.cpp +++ b/clang/CodeGen/CGExpr.cpp @@ -566,6 +566,8 @@ RValue CodeGenFunction::EmitExpr(const Expr *E) { return EmitConditionalOperator(cast(E)); case Expr::ChooseExprClass: return EmitChooseExpr(cast(E)); + case Expr::ObjCStringLiteralClass: + return EmitObjCStringLiteral(cast(E)); } } diff --git a/clang/CodeGen/CGObjC.cpp b/clang/CodeGen/CGObjC.cpp new file mode 100644 index 000000000000..e08fcca0a51e --- /dev/null +++ b/clang/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/clang/CodeGen/CodeGenFunction.h b/clang/CodeGen/CodeGenFunction.h index a0a3c610e8d0..95e3656ed3ab 100644 --- a/clang/CodeGen/CodeGenFunction.h +++ b/clang/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/clang/Parse/ParseExpr.cpp b/clang/Parse/ParseExpr.cpp index 75414f7b076a..aa8ced3bf5c3 100644 --- a/clang/Parse/ParseExpr.cpp +++ b/clang/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/clang/Parse/ParseObjc.cpp b/clang/Parse/ParseObjc.cpp index 192f19990acc..e093f19c2c92 100644 --- a/clang/Parse/ParseObjc.cpp +++ b/clang/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/clang/Sema/Sema.h b/clang/Sema/Sema.h index 0613ee54c69b..42beb84f385b 100644 --- a/clang/Sema/Sema.h +++ b/clang/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/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index 3ca766b3a091..da3bc3d94f9f 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/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(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/clang.xcodeproj/project.pbxproj b/clang/clang.xcodeproj/project.pbxproj index ace6990d6e7b..1509d10db78f 100644 --- a/clang/clang.xcodeproj/project.pbxproj +++ b/clang/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 = ""; }; + 1A7342470C7B57D500122F56 /* CGObjC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGObjC.cpp; path = CodeGen/CGObjC.cpp; sourceTree = ""; }; 1A869A6E0BA2164C008DA07A /* LiteralSupport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LiteralSupport.h; sourceTree = ""; }; 1A869AA70BA21ABA008DA07A /* LiteralSupport.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = LiteralSupport.cpp; sourceTree = ""; }; 1ABC36930C7A4BDC006DB0AB /* CGBuiltin.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CGBuiltin.cpp; path = CodeGen/CGBuiltin.cpp; sourceTree = ""; }; @@ -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/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index d65831d4232a..26d98610d89a 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/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/clang/include/clang/AST/StmtNodes.def b/clang/include/clang/AST/StmtNodes.def index ac1ccacc9d6d..9fa780c314e9 100644 --- a/clang/include/clang/AST/StmtNodes.def +++ b/clang/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/clang/include/clang/Parse/Action.h b/clang/include/clang/Parse/Action.h index 088345cb16d2..668bfb6d016d 100644 --- a/clang/include/clang/Parse/Action.h +++ b/clang/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/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h index ea69da3751c1..cacb78fe11f2 100644 --- a/clang/include/clang/Parse/Parser.h +++ b/clang/include/clang/Parse/Parser.h @@ -323,6 +323,11 @@ private: ExprResult ParseInitializer(); ExprResult ParseInitializerWithPotentialDesignator(); + //===--------------------------------------------------------------------===// + // Objective-C Expressions + ExprResult ParseObjCExpression(); + ExprResult ParseObjCStringLiteral(); + //===--------------------------------------------------------------------===// // C99 6.8: Statements and Blocks.