зеркало из https://github.com/microsoft/clang-1.git
Propagate alignment on lvalues through EmitLValueForField. PR12395.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154789 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
c5086f08be
Коммит
377ecc7996
|
@ -464,13 +464,12 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
|
|||
llvm::Function::arg_iterator AI) {
|
||||
assert(LV.isSimple() &&
|
||||
"Unexpected non-simple lvalue during struct expansion.");
|
||||
llvm::Value *Addr = LV.getAddress();
|
||||
|
||||
if (const ConstantArrayType *AT = getContext().getAsConstantArrayType(Ty)) {
|
||||
unsigned NumElts = AT->getSize().getZExtValue();
|
||||
QualType EltTy = AT->getElementType();
|
||||
for (unsigned Elt = 0; Elt < NumElts; ++Elt) {
|
||||
llvm::Value *EltAddr = Builder.CreateConstGEP2_32(Addr, 0, Elt);
|
||||
llvm::Value *EltAddr = Builder.CreateConstGEP2_32(LV.getAddress(), 0, Elt);
|
||||
LValue LV = MakeAddrLValue(EltAddr, EltTy);
|
||||
AI = ExpandTypeFromArgs(EltTy, LV, AI);
|
||||
}
|
||||
|
@ -495,8 +494,8 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
|
|||
}
|
||||
if (LargestFD) {
|
||||
// FIXME: What are the right qualifiers here?
|
||||
LValue LV = EmitLValueForField(Addr, LargestFD, 0);
|
||||
AI = ExpandTypeFromArgs(LargestFD->getType(), LV, AI);
|
||||
LValue SubLV = EmitLValueForField(LV, LargestFD);
|
||||
AI = ExpandTypeFromArgs(LargestFD->getType(), SubLV, AI);
|
||||
}
|
||||
} else {
|
||||
for (RecordDecl::field_iterator i = RD->field_begin(), e = RD->field_end();
|
||||
|
@ -505,15 +504,15 @@ CodeGenFunction::ExpandTypeFromArgs(QualType Ty, LValue LV,
|
|||
QualType FT = FD->getType();
|
||||
|
||||
// FIXME: What are the right qualifiers here?
|
||||
LValue LV = EmitLValueForField(Addr, FD, 0);
|
||||
AI = ExpandTypeFromArgs(FT, LV, AI);
|
||||
LValue SubLV = EmitLValueForField(LV, FD);
|
||||
AI = ExpandTypeFromArgs(FT, SubLV, AI);
|
||||
}
|
||||
}
|
||||
} else if (const ComplexType *CT = Ty->getAs<ComplexType>()) {
|
||||
QualType EltTy = CT->getElementType();
|
||||
llvm::Value *RealAddr = Builder.CreateStructGEP(Addr, 0, "real");
|
||||
llvm::Value *RealAddr = Builder.CreateStructGEP(LV.getAddress(), 0, "real");
|
||||
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(RealAddr, EltTy));
|
||||
llvm::Value *ImagAddr = Builder.CreateStructGEP(Addr, 1, "imag");
|
||||
llvm::Value *ImagAddr = Builder.CreateStructGEP(LV.getAddress(), 1, "imag");
|
||||
EmitStoreThroughLValue(RValue::get(AI++), MakeAddrLValue(ImagAddr, EltTy));
|
||||
} else {
|
||||
EmitStoreThroughLValue(RValue::get(AI), LV);
|
||||
|
@ -1808,7 +1807,7 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
|
|||
} else if (const RecordType *RT = Ty->getAs<RecordType>()) {
|
||||
RecordDecl *RD = RT->getDecl();
|
||||
assert(RV.isAggregate() && "Unexpected rvalue during struct expansion");
|
||||
llvm::Value *Addr = RV.getAggregateAddr();
|
||||
LValue LV = MakeAddrLValue(RV.getAggregateAddr(), Ty);
|
||||
|
||||
if (RD->isUnion()) {
|
||||
const FieldDecl *LargestFD = 0;
|
||||
|
@ -1826,7 +1825,7 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
|
|||
}
|
||||
}
|
||||
if (LargestFD) {
|
||||
RValue FldRV = EmitRValueForField(Addr, LargestFD);
|
||||
RValue FldRV = EmitRValueForField(LV, LargestFD);
|
||||
ExpandTypeToArgs(LargestFD->getType(), FldRV, Args, IRFuncTy);
|
||||
}
|
||||
} else {
|
||||
|
@ -1834,7 +1833,7 @@ void CodeGenFunction::ExpandTypeToArgs(QualType Ty, RValue RV,
|
|||
i != e; ++i) {
|
||||
FieldDecl *FD = *i;
|
||||
|
||||
RValue FldRV = EmitRValueForField(Addr, FD);
|
||||
RValue FldRV = EmitRValueForField(LV, FD);
|
||||
ExpandTypeToArgs(FD->getType(), FldRV, Args, IRFuncTy);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -555,15 +555,17 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
|
|||
QualType FieldType = Field->getType();
|
||||
|
||||
llvm::Value *ThisPtr = CGF.LoadCXXThis();
|
||||
QualType RecordTy = CGF.getContext().getTypeDeclType(ClassDecl);
|
||||
LValue LHS;
|
||||
|
||||
|
||||
// If we are initializing an anonymous union field, drill down to the field.
|
||||
if (MemberInit->isIndirectMemberInitializer()) {
|
||||
LHS = CGF.EmitLValueForAnonRecordField(ThisPtr,
|
||||
MemberInit->getIndirectMember(), 0);
|
||||
FieldType = MemberInit->getIndirectMember()->getAnonField()->getType();
|
||||
} else {
|
||||
LHS = CGF.EmitLValueForFieldInitialization(ThisPtr, Field, 0);
|
||||
LValue ThisLHSLV = CGF.MakeNaturalAlignAddrLValue(ThisPtr, RecordTy);
|
||||
LHS = CGF.EmitLValueForFieldInitialization(ThisLHSLV, Field);
|
||||
}
|
||||
|
||||
// Special case: if we are in a copy or move constructor, and we are copying
|
||||
|
@ -585,7 +587,8 @@ static void EmitMemberInitializer(CodeGenFunction &CGF,
|
|||
unsigned SrcArgIndex = Args.size() - 1;
|
||||
llvm::Value *SrcPtr
|
||||
= CGF.Builder.CreateLoad(CGF.GetAddrOfLocalVar(Args[SrcArgIndex]));
|
||||
LValue Src = CGF.EmitLValueForFieldInitialization(SrcPtr, Field, 0);
|
||||
LValue ThisRHSLV = CGF.MakeNaturalAlignAddrLValue(SrcPtr, RecordTy);
|
||||
LValue Src = CGF.EmitLValueForFieldInitialization(ThisRHSLV, Field);
|
||||
|
||||
// Copy the aggregate.
|
||||
CGF.EmitAggregateCopy(LHS.getAddress(), Src.getAddress(), FieldType,
|
||||
|
@ -978,7 +981,9 @@ namespace {
|
|||
void Emit(CodeGenFunction &CGF, Flags flags) {
|
||||
// Find the address of the field.
|
||||
llvm::Value *thisValue = CGF.LoadCXXThis();
|
||||
LValue LV = CGF.EmitLValueForField(thisValue, field, /*CVRQualifiers=*/0);
|
||||
QualType RecordTy = CGF.getContext().getTagDeclType(field->getParent());
|
||||
LValue ThisLV = CGF.MakeAddrLValue(thisValue, RecordTy);
|
||||
LValue LV = CGF.EmitLValueForField(ThisLV, field);
|
||||
assert(LV.isSimple());
|
||||
|
||||
CGF.emitDestroy(LV.getAddress(), field->getType(), destroyer,
|
||||
|
|
|
@ -399,8 +399,8 @@ EmitExprForReferenceBinding(CodeGenFunction &CGF, const Expr *E,
|
|||
break;
|
||||
|
||||
case SubobjectAdjustment::FieldAdjustment: {
|
||||
LValue LV =
|
||||
CGF.EmitLValueForField(Object, Adjustment.Field, 0);
|
||||
LValue LV = CGF.MakeAddrLValue(Object, E->getType());
|
||||
LV = CGF.EmitLValueForField(LV, Adjustment.Field);
|
||||
if (LV.isSimple()) {
|
||||
Object = LV.getAddress();
|
||||
break;
|
||||
|
@ -1570,8 +1570,12 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
|
|||
|
||||
// Use special handling for lambdas.
|
||||
if (!V) {
|
||||
if (FieldDecl *FD = LambdaCaptureFields.lookup(VD))
|
||||
return EmitLValueForField(CXXABIThisValue, FD, 0);
|
||||
if (FieldDecl *FD = LambdaCaptureFields.lookup(VD)) {
|
||||
QualType LambdaTagType = getContext().getTagDeclType(FD->getParent());
|
||||
LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue,
|
||||
LambdaTagType);
|
||||
return EmitLValueForField(LambdaLV, FD);
|
||||
}
|
||||
|
||||
assert(isa<BlockDecl>(CurCodeDecl) && E->refersToEnclosingLocal());
|
||||
CharUnits alignment = getContext().getDeclAlign(VD);
|
||||
|
@ -1966,32 +1970,19 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
|
|||
}
|
||||
|
||||
LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
|
||||
bool isNonGC = false;
|
||||
Expr *BaseExpr = E->getBase();
|
||||
llvm::Value *BaseValue = NULL;
|
||||
Qualifiers BaseQuals;
|
||||
|
||||
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
|
||||
if (E->isArrow()) {
|
||||
BaseValue = EmitScalarExpr(BaseExpr);
|
||||
const PointerType *PTy =
|
||||
BaseExpr->getType()->getAs<PointerType>();
|
||||
BaseQuals = PTy->getPointeeType().getQualifiers();
|
||||
} else {
|
||||
LValue BaseLV = EmitLValue(BaseExpr);
|
||||
if (BaseLV.isNonGC())
|
||||
isNonGC = true;
|
||||
// FIXME: this isn't right for bitfields.
|
||||
BaseValue = BaseLV.getAddress();
|
||||
QualType BaseTy = BaseExpr->getType();
|
||||
BaseQuals = BaseTy.getQualifiers();
|
||||
}
|
||||
LValue BaseLV;
|
||||
if (E->isArrow())
|
||||
BaseLV = MakeNaturalAlignAddrLValue(EmitScalarExpr(BaseExpr),
|
||||
BaseExpr->getType()->getPointeeType());
|
||||
else
|
||||
BaseLV = EmitLValue(BaseExpr);
|
||||
|
||||
NamedDecl *ND = E->getMemberDecl();
|
||||
if (FieldDecl *Field = dyn_cast<FieldDecl>(ND)) {
|
||||
LValue LV = EmitLValueForField(BaseValue, Field,
|
||||
BaseQuals.getCVRQualifiers());
|
||||
LV.setNonGC(isNonGC);
|
||||
LValue LV = EmitLValueForField(BaseLV, Field);
|
||||
setObjCGCLValueClass(getContext(), E, LV);
|
||||
return LV;
|
||||
}
|
||||
|
@ -2025,8 +2016,10 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
|
|||
IndirectFieldDecl::chain_iterator I = Field->chain_begin(),
|
||||
IEnd = Field->chain_end();
|
||||
while (true) {
|
||||
LValue LV = EmitLValueForField(BaseValue, cast<FieldDecl>(*I),
|
||||
CVRQualifiers);
|
||||
QualType RecordTy =
|
||||
getContext().getTypeDeclType(cast<FieldDecl>(*I)->getParent());
|
||||
LValue LV = EmitLValueForField(MakeAddrLValue(BaseValue, RecordTy),
|
||||
cast<FieldDecl>(*I));
|
||||
if (++I == IEnd) return LV;
|
||||
|
||||
assert(LV.isSimple());
|
||||
|
@ -2035,19 +2028,25 @@ LValue CodeGenFunction::EmitLValueForAnonRecordField(llvm::Value *BaseValue,
|
|||
}
|
||||
}
|
||||
|
||||
LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
|
||||
const FieldDecl *field,
|
||||
unsigned cvr) {
|
||||
LValue CodeGenFunction::EmitLValueForField(LValue base,
|
||||
const FieldDecl *field) {
|
||||
if (field->isBitField())
|
||||
return EmitLValueForBitfield(baseAddr, field, cvr);
|
||||
return EmitLValueForBitfield(base.getAddress(), field,
|
||||
base.getVRQualifiers());
|
||||
|
||||
const RecordDecl *rec = field->getParent();
|
||||
QualType type = field->getType();
|
||||
CharUnits alignment = getContext().getDeclAlign(field);
|
||||
|
||||
// FIXME: It should be impossible to have an LValue without alignment for a
|
||||
// complete type.
|
||||
if (!base.getAlignment().isZero())
|
||||
alignment = std::min(alignment, base.getAlignment());
|
||||
|
||||
bool mayAlias = rec->hasAttr<MayAliasAttr>();
|
||||
|
||||
llvm::Value *addr = baseAddr;
|
||||
llvm::Value *addr = base.getAddress();
|
||||
unsigned cvr = base.getVRQualifiers();
|
||||
if (rec->isUnion()) {
|
||||
// For unions, there is no pointer adjustment.
|
||||
assert(!type->isReferenceType() && "union has reference member");
|
||||
|
@ -2110,30 +2109,33 @@ LValue CodeGenFunction::EmitLValueForField(llvm::Value *baseAddr,
|
|||
}
|
||||
|
||||
LValue
|
||||
CodeGenFunction::EmitLValueForFieldInitialization(llvm::Value *BaseValue,
|
||||
const FieldDecl *Field,
|
||||
unsigned CVRQualifiers) {
|
||||
CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
|
||||
const FieldDecl *Field) {
|
||||
QualType FieldType = Field->getType();
|
||||
|
||||
if (!FieldType->isReferenceType())
|
||||
return EmitLValueForField(BaseValue, Field, CVRQualifiers);
|
||||
return EmitLValueForField(Base, Field);
|
||||
|
||||
const CGRecordLayout &RL =
|
||||
CGM.getTypes().getCGRecordLayout(Field->getParent());
|
||||
unsigned idx = RL.getLLVMFieldNo(Field);
|
||||
llvm::Value *V = Builder.CreateStructGEP(BaseValue, idx);
|
||||
llvm::Value *V = Builder.CreateStructGEP(Base.getAddress(), idx);
|
||||
assert(!FieldType.getObjCGCAttr() && "fields cannot have GC attrs");
|
||||
|
||||
|
||||
// Make sure that the address is pointing to the right type. This is critical
|
||||
// for both unions and structs. A union needs a bitcast, a struct element
|
||||
// will need a bitcast if the LLVM type laid out doesn't match the desired
|
||||
// type.
|
||||
llvm::Type *llvmType = ConvertTypeForMem(FieldType);
|
||||
unsigned AS = cast<llvm::PointerType>(V->getType())->getAddressSpace();
|
||||
V = Builder.CreateBitCast(V, llvmType->getPointerTo(AS));
|
||||
|
||||
V = EmitBitCastOfLValueToProperType(*this, V, llvmType, Field->getName());
|
||||
|
||||
CharUnits Alignment = getContext().getDeclAlign(Field);
|
||||
|
||||
// FIXME: It should be impossible to have an LValue without alignment for a
|
||||
// complete type.
|
||||
if (!Base.getAlignment().isZero())
|
||||
Alignment = std::min(Alignment, Base.getAlignment());
|
||||
|
||||
return MakeAddrLValue(V, FieldType, Alignment);
|
||||
}
|
||||
|
||||
|
@ -2371,18 +2373,18 @@ LValue CodeGenFunction::EmitMaterializeTemporaryExpr(
|
|||
return MakeAddrLValue(RV.getScalarVal(), E->getType());
|
||||
}
|
||||
|
||||
RValue CodeGenFunction::EmitRValueForField(llvm::Value *Addr,
|
||||
RValue CodeGenFunction::EmitRValueForField(LValue LV,
|
||||
const FieldDecl *FD) {
|
||||
QualType FT = FD->getType();
|
||||
// FIXME: What are the right qualifiers here?
|
||||
LValue LV = EmitLValueForField(Addr, FD, 0);
|
||||
LValue FieldLV = EmitLValueForField(LV, FD);
|
||||
if (FT->isAnyComplexType())
|
||||
// FIXME: Volatile?
|
||||
return RValue::getComplex(LoadComplexFromAddr(LV.getAddress(), false));
|
||||
return RValue::getComplex(
|
||||
LoadComplexFromAddr(FieldLV.getAddress(),
|
||||
FieldLV.isVolatileQualified()));
|
||||
else if (CodeGenFunction::hasAggregateLLVMType(FT))
|
||||
return LV.asAggregateRValue();
|
||||
return FieldLV.asAggregateRValue();
|
||||
|
||||
return EmitLoadOfLValue(LV);
|
||||
return EmitLoadOfLValue(FieldLV);
|
||||
}
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
|
|
@ -348,7 +348,8 @@ void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
|
|||
CGF.ErrorUnsupported(initList, "weird std::initializer_list");
|
||||
return;
|
||||
}
|
||||
LValue start = CGF.EmitLValueForFieldInitialization(destPtr, *field, 0);
|
||||
LValue DestLV = CGF.MakeNaturalAlignAddrLValue(destPtr, initList->getType());
|
||||
LValue start = CGF.EmitLValueForFieldInitialization(DestLV, *field);
|
||||
llvm::Value *arrayStart = Builder.CreateStructGEP(alloc, 0, "arraystart");
|
||||
CGF.EmitStoreThroughLValue(RValue::get(arrayStart), start);
|
||||
++field;
|
||||
|
@ -357,7 +358,7 @@ void AggExprEmitter::EmitStdInitializerList(llvm::Value *destPtr,
|
|||
CGF.ErrorUnsupported(initList, "weird std::initializer_list");
|
||||
return;
|
||||
}
|
||||
LValue endOrLength = CGF.EmitLValueForFieldInitialization(destPtr, *field, 0);
|
||||
LValue endOrLength = CGF.EmitLValueForFieldInitialization(DestLV, *field);
|
||||
if (ctx.hasSameType(field->getType(), elementPtr)) {
|
||||
// End pointer.
|
||||
llvm::Value *arrayEnd = Builder.CreateStructGEP(alloc,numInits, "arrayend");
|
||||
|
@ -912,7 +913,9 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
|||
return;
|
||||
}
|
||||
|
||||
llvm::Value *DestPtr = EnsureSlot(E->getType()).getAddr();
|
||||
AggValueSlot Dest = EnsureSlot(E->getType());
|
||||
LValue DestLV = CGF.MakeAddrLValue(Dest.getAddr(), E->getType(),
|
||||
Dest.getAlignment());
|
||||
|
||||
// Handle initialization of an array.
|
||||
if (E->getType()->isArrayType()) {
|
||||
|
@ -923,11 +926,11 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
|||
CGF.getContext().getAsArrayType(E->getType())->getElementType();
|
||||
|
||||
llvm::PointerType *APType =
|
||||
cast<llvm::PointerType>(DestPtr->getType());
|
||||
cast<llvm::PointerType>(Dest.getAddr()->getType());
|
||||
llvm::ArrayType *AType =
|
||||
cast<llvm::ArrayType>(APType->getElementType());
|
||||
|
||||
EmitArrayInit(DestPtr, AType, elementType, E);
|
||||
EmitArrayInit(Dest.getAddr(), AType, elementType, E);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -960,7 +963,7 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
|||
// FIXME: volatility
|
||||
FieldDecl *Field = E->getInitializedFieldInUnion();
|
||||
|
||||
LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestPtr, Field, 0);
|
||||
LValue FieldLoc = CGF.EmitLValueForFieldInitialization(DestLV, Field);
|
||||
if (NumInitElements) {
|
||||
// Store the initializer into the field
|
||||
EmitInitializationToLValue(E->getInit(0), FieldLoc);
|
||||
|
@ -998,8 +1001,8 @@ void AggExprEmitter::VisitInitListExpr(InitListExpr *E) {
|
|||
CGF.getTypes().isZeroInitializable(E->getType()))
|
||||
break;
|
||||
|
||||
// FIXME: volatility
|
||||
LValue LV = CGF.EmitLValueForFieldInitialization(DestPtr, *field, 0);
|
||||
|
||||
LValue LV = CGF.EmitLValueForFieldInitialization(DestLV, *field);
|
||||
// We never generate write-barries for initialized fields.
|
||||
LV.setNonGC(true);
|
||||
|
||||
|
|
|
@ -1815,13 +1815,16 @@ llvm::Value *CodeGenFunction::EmitDynamicCast(llvm::Value *Value,
|
|||
|
||||
void CodeGenFunction::EmitLambdaExpr(const LambdaExpr *E, AggValueSlot Slot) {
|
||||
RunCleanupsScope Scope(*this);
|
||||
LValue SlotLV = MakeAddrLValue(Slot.getAddr(), E->getType(),
|
||||
Slot.getAlignment());
|
||||
|
||||
CXXRecordDecl::field_iterator CurField = E->getLambdaClass()->field_begin();
|
||||
for (LambdaExpr::capture_init_iterator i = E->capture_init_begin(),
|
||||
e = E->capture_init_end();
|
||||
i != e; ++i, ++CurField) {
|
||||
// Emit initialization
|
||||
LValue LV = EmitLValueForFieldInitialization(Slot.getAddr(), *CurField, 0);
|
||||
|
||||
LValue LV = EmitLValueForFieldInitialization(SlotLV, *CurField);
|
||||
ArrayRef<VarDecl *> ArrayIndexes;
|
||||
if (CurField->getType()->isArrayType())
|
||||
ArrayIndexes = E->getCaptureInitIndexVars(i);
|
||||
|
|
|
@ -362,8 +362,12 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy,
|
|||
LambdaThisCaptureField);
|
||||
if (LambdaThisCaptureField) {
|
||||
// If this lambda captures this, load it.
|
||||
LValue ThisLValue = EmitLValueForField(CXXABIThisValue,
|
||||
LambdaThisCaptureField, 0);
|
||||
QualType LambdaTagType =
|
||||
getContext().getTagDeclType(LambdaThisCaptureField->getParent());
|
||||
LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue,
|
||||
LambdaTagType);
|
||||
LValue ThisLValue = EmitLValueForField(LambdaLV,
|
||||
LambdaThisCaptureField);
|
||||
CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -2105,7 +2105,7 @@ public:
|
|||
LValue EmitMaterializeTemporaryExpr(const MaterializeTemporaryExpr *E);
|
||||
LValue EmitOpaqueValueLValue(const OpaqueValueExpr *e);
|
||||
|
||||
RValue EmitRValueForField(llvm::Value *Addr, const FieldDecl *FD);
|
||||
RValue EmitRValueForField(LValue LV, const FieldDecl *FD);
|
||||
|
||||
class ConstantEmission {
|
||||
llvm::PointerIntPair<llvm::Constant*, 1, bool> ValueAndIsReference;
|
||||
|
@ -2146,15 +2146,13 @@ public:
|
|||
LValue EmitLValueForAnonRecordField(llvm::Value* Base,
|
||||
const IndirectFieldDecl* Field,
|
||||
unsigned CVRQualifiers);
|
||||
LValue EmitLValueForField(llvm::Value* Base, const FieldDecl* Field,
|
||||
unsigned CVRQualifiers);
|
||||
LValue EmitLValueForField(LValue Base, const FieldDecl* Field);
|
||||
|
||||
/// EmitLValueForFieldInitialization - Like EmitLValueForField, except that
|
||||
/// if the Field is a reference, this will return the address of the reference
|
||||
/// and not the address of the value stored in the reference.
|
||||
LValue EmitLValueForFieldInitialization(llvm::Value* Base,
|
||||
const FieldDecl* Field,
|
||||
unsigned CVRQualifiers);
|
||||
LValue EmitLValueForFieldInitialization(LValue Base,
|
||||
const FieldDecl* Field);
|
||||
|
||||
LValue EmitLValueForIvar(QualType ObjectTy,
|
||||
llvm::Value* Base, const ObjCIvarDecl *Ivar,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
// RUN: %clang_cc1 %s -triple x86_64-apple-macosx10.7.2 -emit-llvm -o - | FileCheck %s
|
||||
// <rdar://problem/10463337>
|
||||
|
||||
struct X { int x[6]; };
|
||||
struct Y { char x[13]; struct X y; } __attribute((packed));
|
||||
struct Y g;
|
||||
void f(struct X);
|
||||
|
||||
// <rdar://problem/10463337>
|
||||
struct X test1() {
|
||||
// CHECK: @test1
|
||||
// CHECK: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
|
||||
|
@ -24,8 +24,16 @@ void test3(struct X a) {
|
|||
g.y = a;
|
||||
}
|
||||
|
||||
// <rdar://problem/10530444>
|
||||
void test4() {
|
||||
// CHECK: @test4
|
||||
// FIXME: call void @llvm.memcpy.p0i8.p0i8.i64(i8* {{.*}}, i8* bitcast (%struct.X* getelementptr inbounds (%struct.Y* @g, i32 0, i32 1) to i8*), i64 24, i32 1, i1 false)
|
||||
f(g.y);
|
||||
}
|
||||
|
||||
// PR12395
|
||||
int test5() {
|
||||
// CHECK: @test5
|
||||
// CHECK: load i32* getelementptr inbounds (%struct.Y* @g, i32 0, i32 1, i32 0, i64 0), align 1
|
||||
return g.y.x[0];
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче