summaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/CGObjC.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2015-07-05 14:23:59 +0000
committerdim <dim@FreeBSD.org>2015-07-05 14:23:59 +0000
commite7bcad327814a78ecb8d5f5545d2e3df84c67a5c (patch)
treeac719b5984165053bf83d71142e4d96b609b9784 /lib/CodeGen/CGObjC.cpp
parent9dd834653b811ad20382e98a87dff824980c9916 (diff)
downloadFreeBSD-src-e7bcad327814a78ecb8d5f5545d2e3df84c67a5c.zip
FreeBSD-src-e7bcad327814a78ecb8d5f5545d2e3df84c67a5c.tar.gz
Vendor import of clang trunk r241361:
https://llvm.org/svn/llvm-project/cfe/trunk@241361
Diffstat (limited to 'lib/CodeGen/CGObjC.cpp')
-rw-r--r--lib/CodeGen/CGObjC.cpp34
1 files changed, 32 insertions, 2 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp
index 9981fcc..747326e 100644
--- a/lib/CodeGen/CGObjC.cpp
+++ b/lib/CodeGen/CGObjC.cpp
@@ -55,13 +55,15 @@ llvm::Value *CodeGenFunction::EmitObjCStringLiteral(const ObjCStringLiteral *E)
/// EmitObjCBoxedExpr - This routine generates code to call
/// the appropriate expression boxing method. This will either be
-/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:].
+/// one of +[NSNumber numberWith<Type>:], or +[NSString stringWithUTF8String:],
+/// or [NSValue valueWithBytes:objCType:].
///
llvm::Value *
CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
// Generate the correct selector for this literal's concrete type.
// Get the method.
const ObjCMethodDecl *BoxingMethod = E->getBoxingMethod();
+ const Expr *SubExpr = E->getSubExpr();
assert(BoxingMethod && "BoxingMethod is null");
assert(BoxingMethod->isClassMethod() && "BoxingMethod must be a class method");
Selector Sel = BoxingMethod->getSelector();
@@ -74,7 +76,35 @@ CodeGenFunction::EmitObjCBoxedExpr(const ObjCBoxedExpr *E) {
llvm::Value *Receiver = Runtime.GetClass(*this, ClassDecl);
CallArgList Args;
- EmitCallArgs(Args, BoxingMethod, E->arg_begin(), E->arg_end());
+ const ParmVarDecl *ArgDecl = *BoxingMethod->param_begin();
+ QualType ArgQT = ArgDecl->getType().getUnqualifiedType();
+
+ // ObjCBoxedExpr supports boxing of structs and unions
+ // via [NSValue valueWithBytes:objCType:]
+ const QualType ValueType(SubExpr->getType().getCanonicalType());
+ if (ValueType->isObjCBoxableRecordType()) {
+ // Emit CodeGen for first parameter
+ // and cast value to correct type
+ llvm::Value *Temporary = CreateMemTemp(SubExpr->getType());
+ EmitAnyExprToMem(SubExpr, Temporary, Qualifiers(), /*isInit*/ true);
+ llvm::Value *BitCast = Builder.CreateBitCast(Temporary,
+ ConvertType(ArgQT));
+ Args.add(RValue::get(BitCast), ArgQT);
+
+ // Create char array to store type encoding
+ std::string Str;
+ getContext().getObjCEncodingForType(ValueType, Str);
+ llvm::GlobalVariable *GV = CGM.GetAddrOfConstantCString(Str);
+
+ // Cast type encoding to correct type
+ const ParmVarDecl *EncodingDecl = BoxingMethod->parameters()[1];
+ QualType EncodingQT = EncodingDecl->getType().getUnqualifiedType();
+ llvm::Value *Cast = Builder.CreateBitCast(GV, ConvertType(EncodingQT));
+
+ Args.add(RValue::get(Cast), EncodingQT);
+ } else {
+ Args.add(EmitAnyExpr(SubExpr), ArgQT);
+ }
RValue result = Runtime.GenerateMessageSend(
*this, ReturnValueSlot(), BoxingMethod->getReturnType(), Sel, Receiver,
OpenPOWER on IntegriCloud