@@ -4792,6 +4792,10 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
4792
4792
}
4793
4793
4794
4794
Expr *BaseExpr = E->getBase ();
4795
+ Expr *UnderlyingBaseExpr = BaseExpr;
4796
+ while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr))
4797
+ UnderlyingBaseExpr = BaseMemberExpr->getBase ();
4798
+ bool IsBaseConstantNull = getContext ().isSentinelNullExpr (UnderlyingBaseExpr);
4795
4799
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
4796
4800
LValue BaseLV;
4797
4801
if (E->isArrow ()) {
@@ -4813,7 +4817,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
4813
4817
4814
4818
NamedDecl *ND = E->getMemberDecl ();
4815
4819
if (auto *Field = dyn_cast<FieldDecl>(ND)) {
4816
- LValue LV = EmitLValueForField (BaseLV, Field);
4820
+ LValue LV = EmitLValueForField (BaseLV, Field, IsBaseConstantNull );
4817
4821
setObjCGCLValueClass (getContext (), E, LV);
4818
4822
if (getLangOpts ().OpenMP ) {
4819
4823
// If the member was explicitly marked as nontemporal, mark it as
@@ -4899,12 +4903,15 @@ unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec,
4899
4903
// / Get the address of a zero-sized field within a record. The resulting
4900
4904
// / address doesn't necessarily have the right type.
4901
4905
static Address emitAddrOfZeroSizeField (CodeGenFunction &CGF, Address Base,
4902
- const FieldDecl *Field) {
4906
+ const FieldDecl *Field,
4907
+ bool IsBaseConstantNull) {
4903
4908
CharUnits Offset = CGF.getContext ().toCharUnitsFromBits (
4904
4909
CGF.getContext ().getFieldOffset (Field));
4905
4910
if (Offset.isZero ())
4906
4911
return Base;
4907
4912
Base = Base.withElementType (CGF.Int8Ty );
4913
+ if (IsBaseConstantNull)
4914
+ return CGF.Builder .CreateConstByteGEP (Base, Offset);
4908
4915
return CGF.Builder .CreateConstInBoundsByteGEP (Base, Offset);
4909
4916
}
4910
4917
@@ -4913,15 +4920,18 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
4913
4920
// /
4914
4921
// / The resulting address doesn't necessarily have the right type.
4915
4922
static Address emitAddrOfFieldStorage (CodeGenFunction &CGF, Address base,
4916
- const FieldDecl *field) {
4923
+ const FieldDecl *field,
4924
+ bool IsBaseConstantNull) {
4917
4925
if (isEmptyFieldForLayout (CGF.getContext (), field))
4918
- return emitAddrOfZeroSizeField (CGF, base, field);
4926
+ return emitAddrOfZeroSizeField (CGF, base, field, IsBaseConstantNull );
4919
4927
4920
4928
const RecordDecl *rec = field->getParent ();
4921
4929
4922
4930
unsigned idx =
4923
4931
CGF.CGM .getTypes ().getCGRecordLayout (rec).getLLVMFieldNo (field);
4924
4932
4933
+ if (IsBaseConstantNull)
4934
+ return CGF.Builder .CreateConstGEP (base, idx, field->getName ());
4925
4935
return CGF.Builder .CreateStructGEP (base, idx, field->getName ());
4926
4936
}
4927
4937
@@ -4957,8 +4967,8 @@ static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
4957
4967
return false ;
4958
4968
}
4959
4969
4960
- LValue CodeGenFunction::EmitLValueForField (LValue base,
4961
- const FieldDecl *field ) {
4970
+ LValue CodeGenFunction::EmitLValueForField (LValue base, const FieldDecl *field,
4971
+ bool IsBaseConstantNull ) {
4962
4972
LValueBaseInfo BaseInfo = base.getBaseInfo ();
4963
4973
4964
4974
if (field->isBitField ()) {
@@ -5090,7 +5100,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
5090
5100
if (!IsInPreservedAIRegion &&
5091
5101
(!getDebugInfo () || !rec->hasAttr <BPFPreserveAccessIndexAttr>()))
5092
5102
// For structs, we GEP to the field that the record layout suggests.
5093
- addr = emitAddrOfFieldStorage (*this , addr, field);
5103
+ addr = emitAddrOfFieldStorage (*this , addr, field, IsBaseConstantNull );
5094
5104
else
5095
5105
// Remember the original struct field index
5096
5106
addr = emitPreserveStructAccess (*this , base, addr, field);
@@ -5134,7 +5144,8 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
5134
5144
if (!FieldType->isReferenceType ())
5135
5145
return EmitLValueForField (Base, Field);
5136
5146
5137
- Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field);
5147
+ Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field,
5148
+ /* IsBaseConstantNull=*/ false );
5138
5149
5139
5150
// Make sure that the address is pointing to the right type.
5140
5151
llvm::Type *llvmType = ConvertTypeForMem (FieldType);
0 commit comments