@@ -4772,13 +4772,25 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
4772
4772
Base.getBaseInfo (), TBAAAccessInfo ());
4773
4773
}
4774
4774
4775
+ bool CodeGenFunction::isUnderlyingBasePointerConstantNull (const Expr *E) {
4776
+ const Expr *UnderlyingBaseExpr = E->IgnoreParens ();
4777
+ while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr))
4778
+ UnderlyingBaseExpr = BaseMemberExpr->getBase ()->IgnoreParens ();
4779
+ return getContext ().isSentinelNullExpr (UnderlyingBaseExpr);
4780
+ }
4781
+
4775
4782
LValue CodeGenFunction::EmitMemberExpr (const MemberExpr *E) {
4776
4783
if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr (*this , E)) {
4777
4784
EmitIgnoredExpr (E->getBase ());
4778
4785
return EmitDeclRefLValue (DRE);
4779
4786
}
4780
4787
4781
4788
Expr *BaseExpr = E->getBase ();
4789
+ // Check whether the underlying base pointer is a constant null.
4790
+ // If so, we do not set inbounds flag for GEP to avoid breaking some
4791
+ // old-style offsetof idioms.
4792
+ bool IsInBounds = !getLangOpts ().PointerOverflowDefined &&
4793
+ !isUnderlyingBasePointerConstantNull (BaseExpr);
4782
4794
// If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
4783
4795
LValue BaseLV;
4784
4796
if (E->isArrow ()) {
@@ -4800,7 +4812,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
4800
4812
4801
4813
NamedDecl *ND = E->getMemberDecl ();
4802
4814
if (auto *Field = dyn_cast<FieldDecl>(ND)) {
4803
- LValue LV = EmitLValueForField (BaseLV, Field);
4815
+ LValue LV = EmitLValueForField (BaseLV, Field, IsInBounds );
4804
4816
setObjCGCLValueClass (getContext (), E, LV);
4805
4817
if (getLangOpts ().OpenMP ) {
4806
4818
// If the member was explicitly marked as nontemporal, mark it as
@@ -4886,12 +4898,15 @@ unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec,
4886
4898
// / Get the address of a zero-sized field within a record. The resulting
4887
4899
// / address doesn't necessarily have the right type.
4888
4900
static Address emitAddrOfZeroSizeField (CodeGenFunction &CGF, Address Base,
4889
- const FieldDecl *Field) {
4901
+ const FieldDecl *Field,
4902
+ bool IsInBounds) {
4890
4903
CharUnits Offset = CGF.getContext ().toCharUnitsFromBits (
4891
4904
CGF.getContext ().getFieldOffset (Field));
4892
4905
if (Offset.isZero ())
4893
4906
return Base;
4894
4907
Base = Base.withElementType (CGF.Int8Ty );
4908
+ if (!IsInBounds)
4909
+ return CGF.Builder .CreateConstByteGEP (Base, Offset);
4895
4910
return CGF.Builder .CreateConstInBoundsByteGEP (Base, Offset);
4896
4911
}
4897
4912
@@ -4900,16 +4915,16 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
4900
4915
// /
4901
4916
// / The resulting address doesn't necessarily have the right type.
4902
4917
static Address emitAddrOfFieldStorage (CodeGenFunction &CGF, Address base,
4903
- const FieldDecl *field) {
4918
+ const FieldDecl *field, bool IsInBounds ) {
4904
4919
if (isEmptyFieldForLayout (CGF.getContext (), field))
4905
- return emitAddrOfZeroSizeField (CGF, base, field);
4920
+ return emitAddrOfZeroSizeField (CGF, base, field, IsInBounds );
4906
4921
4907
4922
const RecordDecl *rec = field->getParent ();
4908
4923
4909
4924
unsigned idx =
4910
4925
CGF.CGM .getTypes ().getCGRecordLayout (rec).getLLVMFieldNo (field);
4911
4926
4912
- if (CGF. getLangOpts (). PointerOverflowDefined )
4927
+ if (!IsInBounds )
4913
4928
return CGF.Builder .CreateConstGEP2_32 (base, 0 , idx, field->getName ());
4914
4929
4915
4930
return CGF.Builder .CreateStructGEP (base, idx, field->getName ());
@@ -4947,8 +4962,8 @@ static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
4947
4962
return false ;
4948
4963
}
4949
4964
4950
- LValue CodeGenFunction::EmitLValueForField (LValue base,
4951
- const FieldDecl *field ) {
4965
+ LValue CodeGenFunction::EmitLValueForField (LValue base, const FieldDecl *field,
4966
+ bool IsInBounds ) {
4952
4967
LValueBaseInfo BaseInfo = base.getBaseInfo ();
4953
4968
4954
4969
if (field->isBitField ()) {
@@ -4971,7 +4986,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
4971
4986
(!getDebugInfo () || !rec->hasAttr <BPFPreserveAccessIndexAttr>())) {
4972
4987
if (Idx != 0 ) {
4973
4988
// For structs, we GEP to the field that the record layout suggests.
4974
- if (getLangOpts (). PointerOverflowDefined )
4989
+ if (!IsInBounds )
4975
4990
Addr = Builder.CreateConstGEP2_32 (Addr, 0 , Idx, field->getName ());
4976
4991
else
4977
4992
Addr = Builder.CreateStructGEP (Addr, Idx, field->getName ());
@@ -5084,7 +5099,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
5084
5099
if (!IsInPreservedAIRegion &&
5085
5100
(!getDebugInfo () || !rec->hasAttr <BPFPreserveAccessIndexAttr>()))
5086
5101
// For structs, we GEP to the field that the record layout suggests.
5087
- addr = emitAddrOfFieldStorage (*this , addr, field);
5102
+ addr = emitAddrOfFieldStorage (*this , addr, field, IsInBounds );
5088
5103
else
5089
5104
// Remember the original struct field index
5090
5105
addr = emitPreserveStructAccess (*this , base, addr, field);
@@ -5128,7 +5143,9 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
5128
5143
if (!FieldType->isReferenceType ())
5129
5144
return EmitLValueForField (Base, Field);
5130
5145
5131
- Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field);
5146
+ Address V = emitAddrOfFieldStorage (
5147
+ *this , Base.getAddress (), Field,
5148
+ /* IsInBounds=*/ !getLangOpts ().PointerOverflowDefined );
5132
5149
5133
5150
// Make sure that the address is pointing to the right type.
5134
5151
llvm::Type *llvmType = ConvertTypeForMem (FieldType);
0 commit comments