@@ -4778,6 +4778,10 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
4778
4778
}
4779
4779
4780
4780
Expr *BaseExpr = E->getBase ();
4781
+ Expr *UnderlyingBaseExpr = BaseExpr;
4782
+ while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr))
4783
+ UnderlyingBaseExpr = BaseMemberExpr->getBase ();
4784
+ bool IsBaseConstantNull = getContext ().isSentinelNullExpr (UnderlyingBaseExpr);
4781
4785
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
4782
4786
LValue BaseLV;
4783
4787
if (E->isArrow ()) {
@@ -4799,7 +4803,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
4799
4803
4800
4804
NamedDecl *ND = E->getMemberDecl ();
4801
4805
if (auto *Field = dyn_cast<FieldDecl>(ND)) {
4802
- LValue LV = EmitLValueForField (BaseLV, Field);
4806
+ LValue LV = EmitLValueForField (BaseLV, Field, IsBaseConstantNull );
4803
4807
setObjCGCLValueClass (getContext (), E, LV);
4804
4808
if (getLangOpts ().OpenMP ) {
4805
4809
// If the member was explicitly marked as nontemporal, mark it as
@@ -4885,12 +4889,15 @@ unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec,
4885
4889
// / Get the address of a zero-sized field within a record. The resulting
4886
4890
// / address doesn't necessarily have the right type.
4887
4891
static Address emitAddrOfZeroSizeField (CodeGenFunction &CGF, Address Base,
4888
- const FieldDecl *Field) {
4892
+ const FieldDecl *Field,
4893
+ bool IsBaseConstantNull) {
4889
4894
CharUnits Offset = CGF.getContext ().toCharUnitsFromBits (
4890
4895
CGF.getContext ().getFieldOffset (Field));
4891
4896
if (Offset.isZero ())
4892
4897
return Base;
4893
4898
Base = Base.withElementType (CGF.Int8Ty );
4899
+ if (IsBaseConstantNull)
4900
+ return CGF.Builder .CreateConstByteGEP (Base, Offset);
4894
4901
return CGF.Builder .CreateConstInBoundsByteGEP (Base, Offset);
4895
4902
}
4896
4903
@@ -4899,15 +4906,18 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
4899
4906
// /
4900
4907
// / The resulting address doesn't necessarily have the right type.
4901
4908
static Address emitAddrOfFieldStorage (CodeGenFunction &CGF, Address base,
4902
- const FieldDecl *field) {
4909
+ const FieldDecl *field,
4910
+ bool IsBaseConstantNull) {
4903
4911
if (isEmptyFieldForLayout (CGF.getContext (), field))
4904
- return emitAddrOfZeroSizeField (CGF, base, field);
4912
+ return emitAddrOfZeroSizeField (CGF, base, field, IsBaseConstantNull );
4905
4913
4906
4914
const RecordDecl *rec = field->getParent ();
4907
4915
4908
4916
unsigned idx =
4909
4917
CGF.CGM .getTypes ().getCGRecordLayout (rec).getLLVMFieldNo (field);
4910
4918
4919
+ if (IsBaseConstantNull)
4920
+ return CGF.Builder .CreateConstGEP (base, idx, field->getName ());
4911
4921
return CGF.Builder .CreateStructGEP (base, idx, field->getName ());
4912
4922
}
4913
4923
@@ -4943,8 +4953,8 @@ static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
4943
4953
return false ;
4944
4954
}
4945
4955
4946
- LValue CodeGenFunction::EmitLValueForField (LValue base,
4947
- const FieldDecl *field ) {
4956
+ LValue CodeGenFunction::EmitLValueForField (LValue base, const FieldDecl *field,
4957
+ bool IsBaseConstantNull ) {
4948
4958
LValueBaseInfo BaseInfo = base.getBaseInfo ();
4949
4959
4950
4960
if (field->isBitField ()) {
@@ -5076,7 +5086,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
5076
5086
if (!IsInPreservedAIRegion &&
5077
5087
(!getDebugInfo () || !rec->hasAttr <BPFPreserveAccessIndexAttr>()))
5078
5088
// For structs, we GEP to the field that the record layout suggests.
5079
- addr = emitAddrOfFieldStorage (*this , addr, field);
5089
+ addr = emitAddrOfFieldStorage (*this , addr, field, IsBaseConstantNull );
5080
5090
else
5081
5091
// Remember the original struct field index
5082
5092
addr = emitPreserveStructAccess (*this , base, addr, field);
@@ -5120,7 +5130,8 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
5120
5130
if (!FieldType->isReferenceType ())
5121
5131
return EmitLValueForField (Base, Field);
5122
5132
5123
- Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field);
5133
+ Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field,
5134
+ /* IsBaseConstantNull=*/ false );
5124
5135
5125
5136
// Make sure that the address is pointing to the right type.
5126
5137
llvm::Type *llvmType = ConvertTypeForMem (FieldType);
0 commit comments