@@ -4738,6 +4738,10 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
4738
4738
}
4739
4739
4740
4740
Expr *BaseExpr = E->getBase ();
4741
+ Expr *UnderlyingBaseExpr = BaseExpr;
4742
+ while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr))
4743
+ UnderlyingBaseExpr = BaseMemberExpr->getBase ();
4744
+ bool IsBaseConstantNull = getContext ().isSentinelNullExpr (UnderlyingBaseExpr);
4741
4745
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
4742
4746
LValue BaseLV;
4743
4747
if (E->isArrow ()) {
@@ -4759,7 +4763,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
4759
4763
4760
4764
NamedDecl *ND = E->getMemberDecl ();
4761
4765
if (auto *Field = dyn_cast<FieldDecl>(ND)) {
4762
- LValue LV = EmitLValueForField (BaseLV, Field);
4766
+ LValue LV = EmitLValueForField (BaseLV, Field, IsBaseConstantNull );
4763
4767
setObjCGCLValueClass (getContext (), E, LV);
4764
4768
if (getLangOpts ().OpenMP ) {
4765
4769
// If the member was explicitly marked as nontemporal, mark it as
@@ -4845,12 +4849,15 @@ unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec,
4845
4849
// / Get the address of a zero-sized field within a record. The resulting
4846
4850
// / address doesn't necessarily have the right type.
4847
4851
static Address emitAddrOfZeroSizeField (CodeGenFunction &CGF, Address Base,
4848
- const FieldDecl *Field) {
4852
+ const FieldDecl *Field,
4853
+ bool IsBaseConstantNull) {
4849
4854
CharUnits Offset = CGF.getContext ().toCharUnitsFromBits (
4850
4855
CGF.getContext ().getFieldOffset (Field));
4851
4856
if (Offset.isZero ())
4852
4857
return Base;
4853
4858
Base = Base.withElementType (CGF.Int8Ty );
4859
+ if (IsBaseConstantNull)
4860
+ return CGF.Builder .CreateConstByteGEP (Base, Offset);
4854
4861
return CGF.Builder .CreateConstInBoundsByteGEP (Base, Offset);
4855
4862
}
4856
4863
@@ -4859,15 +4866,18 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
4859
4866
// /
4860
4867
// / The resulting address doesn't necessarily have the right type.
4861
4868
static Address emitAddrOfFieldStorage (CodeGenFunction &CGF, Address base,
4862
- const FieldDecl *field) {
4869
+ const FieldDecl *field,
4870
+ bool IsBaseConstantNull) {
4863
4871
if (isEmptyFieldForLayout (CGF.getContext (), field))
4864
- return emitAddrOfZeroSizeField (CGF, base, field);
4872
+ return emitAddrOfZeroSizeField (CGF, base, field, IsBaseConstantNull );
4865
4873
4866
4874
const RecordDecl *rec = field->getParent ();
4867
4875
4868
4876
unsigned idx =
4869
4877
CGF.CGM .getTypes ().getCGRecordLayout (rec).getLLVMFieldNo (field);
4870
4878
4879
+ if (IsBaseConstantNull)
4880
+ return CGF.Builder .CreateConstGEP (base, idx, field->getName ());
4871
4881
return CGF.Builder .CreateStructGEP (base, idx, field->getName ());
4872
4882
}
4873
4883
@@ -4903,8 +4913,8 @@ static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
4903
4913
return false ;
4904
4914
}
4905
4915
4906
- LValue CodeGenFunction::EmitLValueForField (LValue base,
4907
- const FieldDecl *field ) {
4916
+ LValue CodeGenFunction::EmitLValueForField (LValue base, const FieldDecl *field,
4917
+ bool IsBaseConstantNull ) {
4908
4918
LValueBaseInfo BaseInfo = base.getBaseInfo ();
4909
4919
4910
4920
if (field->isBitField ()) {
@@ -5036,7 +5046,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
5036
5046
if (!IsInPreservedAIRegion &&
5037
5047
(!getDebugInfo () || !rec->hasAttr <BPFPreserveAccessIndexAttr>()))
5038
5048
// For structs, we GEP to the field that the record layout suggests.
5039
- addr = emitAddrOfFieldStorage (*this , addr, field);
5049
+ addr = emitAddrOfFieldStorage (*this , addr, field, IsBaseConstantNull );
5040
5050
else
5041
5051
// Remember the original struct field index
5042
5052
addr = emitPreserveStructAccess (*this , base, addr, field);
@@ -5080,7 +5090,8 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
5080
5090
if (!FieldType->isReferenceType ())
5081
5091
return EmitLValueForField (Base, Field);
5082
5092
5083
- Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field);
5093
+ Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field,
5094
+ /* IsBaseConstantNull=*/ false );
5084
5095
5085
5096
// Make sure that the address is pointing to the right type.
5086
5097
llvm::Type *llvmType = ConvertTypeForMem (FieldType);
0 commit comments