}
}
+RValue CodeGenFunction::EmitDelegateCallArg(const VarDecl *Param) {
+ // StartFunction converted the ABI-lowered parameter(s) into a
+ // local alloca. We need to turn that into an r-value suitable
+ // for EmitCall.
+ llvm::Value *Local = GetAddrOfLocalVar(Param);
+
+ QualType ArgType = Param->getType();
+
+ // For the most part, we just need to load the alloca, except:
+ // 1) aggregate r-values are actually pointers to temporaries, and
+ // 2) references to aggregates are pointers directly to the aggregate.
+ // I don't know why references to non-aggregates are different here.
+ if (const ReferenceType *RefType = ArgType->getAs<ReferenceType>()) {
+ if (hasAggregateLLVMType(RefType->getPointeeType()))
+ return RValue::getAggregate(Local);
+
+ // Locals which are references to scalars are represented
+ // with allocas holding the pointer.
+ return RValue::get(Builder.CreateLoad(Local));
+ }
+
+ if (ArgType->isAnyComplexType())
+ return RValue::getComplex(LoadComplexFromAddr(Local, /*volatile*/ false));
+
+ if (hasAggregateLLVMType(ArgType))
+ return RValue::getAggregate(Local);
+
+ return RValue::get(EmitLoadOfScalar(Local, false, ArgType));
+}
+
RValue CodeGenFunction::EmitCallArg(const Expr *E, QualType ArgType) {
if (ArgType->isReferenceType())
return EmitReferenceBindingToExpr(E);
// Explicit arguments.
for (; I != E; ++I) {
-
const VarDecl *Param = I->first;
QualType ArgType = Param->getType(); // because we're passing it to itself
-
- // StartFunction converted the ABI-lowered parameter(s) into a
- // local alloca. We need to turn that into an r-value suitable
- // for EmitCall.
- llvm::Value *Local = GetAddrOfLocalVar(Param);
- RValue Arg;
-
- // For the most part, we just need to load the alloca, except:
- // 1) aggregate r-values are actually pointers to temporaries, and
- // 2) references to aggregates are pointers directly to the aggregate.
- // I don't know why references to non-aggregates are different here.
- if (ArgType->isReferenceType()) {
- const ReferenceType *RefType = ArgType->getAs<ReferenceType>();
- if (hasAggregateLLVMType(RefType->getPointeeType()))
- Arg = RValue::getAggregate(Local);
- else
- // Locals which are references to scalars are represented
- // with allocas holding the pointer.
- Arg = RValue::get(Builder.CreateLoad(Local));
- } else {
- if (hasAggregateLLVMType(ArgType))
- Arg = RValue::getAggregate(Local);
- else
- Arg = RValue::get(EmitLoadOfScalar(Local, false, ArgType));
- }
+ RValue Arg = EmitDelegateCallArg(Param);
DelegateArgs.push_back(std::make_pair(Arg, ArgType));
}
E = MD->param_end(); I != E; ++I) {
ParmVarDecl *Param = *I;
QualType ArgType = Param->getType();
-
- // Load the argument corresponding to this parameter.
- RValue Arg;
- if (ArgType->isReferenceType() ||
- (hasAggregateLLVMType(ArgType) && !ArgType->isAnyComplexType()))
- Arg = RValue::get(Builder.CreateLoad(LocalDeclMap[Param]));
- else
- Arg = RValue::get(EmitLoadOfScalar(LocalDeclMap[Param], false, ArgType));
+ RValue Arg = EmitDelegateCallArg(Param);
CallArgs.push_back(std::make_pair(Arg, ArgType));
}
/// EmitCallArg - Emit a single call argument.
RValue EmitCallArg(const Expr *E, QualType ArgType);
+ /// EmitDelegateCallArg - We are performing a delegate call; that
+ /// is, the current function is delegating to another one. Produce
+ /// a r-value suitable for passing the given parameter.
+ RValue EmitDelegateCallArg(const VarDecl *Param);
+
private:
void EmitReturnOfRValue(RValue RV, QualType Ty);
void testD() { D d; }
}
+namespace Test8 {
+ struct NonPOD { ~NonPOD(); int x, y, z; };
+ struct A { virtual void foo(); };
+ struct B { virtual void bar(NonPOD); };
+ struct C : A, B { virtual void bar(NonPOD); static void helper(NonPOD); };
+
+ // CHECK: define void @_ZN5Test81C6helperENS_6NonPODE([[NONPODTYPE:%.*]]*
+ void C::helper(NonPOD var) {}
+
+ // CHECK: define void @_ZThn8_N5Test81C3barENS_6NonPODE(
+ // CHECK-NOT: load [[NONPODTYPE]]*
+ // CHECK-NOT: memcpy
+ // CHECK: ret void
+ void C::bar(NonPOD var) {}
+}
+
+/**** The following has to go at the end of the file ****/
+
// This is from Test5:
// CHECK: define linkonce_odr void @_ZTv0_n24_N5Test51B1fEv
// CHECK: define internal void @_ZThn8_N12_GLOBAL__N_11C1fEv(