diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h index 2271a4e6bb34..832f83ca73c3 100644 --- a/clang/include/clang/AST/Expr.h +++ b/clang/include/clang/AST/Expr.h @@ -533,7 +533,12 @@ public: const char *getStrData() const { return StrData; } unsigned getByteLength() const { return ByteLength; } bool isWide() const { return IsWide; } - + bool containsNonAscii() const { + for (unsigned i = 0; i < getByteLength(); ++i) + if (!isascii(getStrData()[i])) + return true; + return false; + } /// getNumConcatenated - Get the number of string literal tokens that were /// concatenated in translation phase #6 to form this string literal. unsigned getNumConcatenated() const { return NumConcatenated; } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index 3f52175745f2..89b331950c12 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -417,9 +417,7 @@ public: return CGM.GetAddrOfConstantStringFromObjCEncode(cast(E)); case Expr::ObjCStringLiteralClass: { ObjCStringLiteral* SL = cast(E); - std::string S(SL->getString()->getStrData(), - SL->getString()->getByteLength()); - llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(S); + llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(SL); return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); } case Expr::PredefinedExprClass: { @@ -445,6 +443,7 @@ public: const Expr *Arg = CE->getArg(0)->IgnoreParenCasts(); const StringLiteral *Literal = cast(Arg); std::string S(Literal->getStrData(), Literal->getByteLength()); + // FIXME: need to deal with UCN conversion issues. return CGM.GetAddrOfConstantCFString(S); } case Expr::BlockExprClass: { diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index 2467a8290aa8..4db29ce05d08 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -26,9 +26,7 @@ using namespace CodeGen; /// Emits an instance of NSConstantString representing the object. llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E) { - std::string String(E->getString()->getStrData(), - E->getString()->getByteLength()); - llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(String); + llvm::Constant *C = CGM.getObjCRuntime().GenerateConstantString(E); // FIXME: This bitcast should just be made an invariant on the Runtime. return llvm::ConstantExpr::getBitCast(C, ConvertType(E->getType())); } diff --git a/clang/lib/CodeGen/CGObjCGNU.cpp b/clang/lib/CodeGen/CGObjCGNU.cpp index e6ca536c66bf..bc713bd8cc29 100644 --- a/clang/lib/CodeGen/CGObjCGNU.cpp +++ b/clang/lib/CodeGen/CGObjCGNU.cpp @@ -94,7 +94,7 @@ private: std::vector &V, const std::string &Name=""); public: CGObjCGNU(CodeGen::CodeGenModule &cgm); - virtual llvm::Constant *GenerateConstantString(const std::string &String); + virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *); virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF, QualType ResultType, @@ -252,7 +252,9 @@ llvm::Constant *CGObjCGNU::MakeGlobal(const llvm::ArrayType *Ty, //TODO: In case there are any crazy people still using the GNU runtime without //an OpenStep implementation, this should let them select their own class for //constant strings. -llvm::Constant *CGObjCGNU::GenerateConstantString(const std::string &Str) { +llvm::Constant *CGObjCGNU::GenerateConstantString(const ObjCStringLiteral *SL) { + std::string Str(SL->getString()->getStrData(), + SL->getString()->getByteLength()); std::vector Ivars; Ivars.push_back(NULLPtr); Ivars.push_back(MakeConstantString(Str)); diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp index 05d81eaf0f1f..f688029fb23a 100644 --- a/clang/lib/CodeGen/CGObjCMac.cpp +++ b/clang/lib/CodeGen/CGObjCMac.cpp @@ -487,7 +487,7 @@ public: CGObjCCommonMac(CodeGen::CodeGenModule &cgm) : CGM(cgm) { } - virtual llvm::Constant *GenerateConstantString(const std::string &String); + virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *SL); virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD, const ObjCContainerDecl *CD=0); @@ -899,8 +899,13 @@ llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel) { */ llvm::Constant *CGObjCCommonMac::GenerateConstantString( - const std::string &String) { - return CGM.GetAddrOfConstantCFString(String); + const ObjCStringLiteral *SL) { + std::string Str(SL->getString()->getStrData(), + SL->getString()->getByteLength()); + if (SL->getString()->containsNonAscii()) { + // FIXME: Convert from UTF-8 to UTF-16. + } + return CGM.GetAddrOfConstantCFString(Str); } /// Generates a message send where the super is the receiver. This is diff --git a/clang/lib/CodeGen/CGObjCRuntime.h b/clang/lib/CodeGen/CGObjCRuntime.h index 7c66ff6f7b3d..65bf52c5e205 100644 --- a/clang/lib/CodeGen/CGObjCRuntime.h +++ b/clang/lib/CodeGen/CGObjCRuntime.h @@ -48,6 +48,7 @@ namespace CodeGen { class ObjCProtocolDecl; class Selector; class ObjCIvarDecl; + class ObjCStringLiteral; namespace CodeGen { class CodeGenModule; @@ -72,7 +73,7 @@ public: Selector Sel) = 0; /// Generate a constant string object. - virtual llvm::Constant *GenerateConstantString(const std::string &String) = 0; + virtual llvm::Constant *GenerateConstantString(const ObjCStringLiteral *) = 0; /// Generate a category. A category contains a list of methods (and /// accompanying metadata) and a list of protocols.