@@ -4772,13 +4772,25 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
47724772 Base.getBaseInfo (), TBAAAccessInfo ());
47734773}
47744774
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+
47754782LValue CodeGenFunction::EmitMemberExpr (const MemberExpr *E) {
47764783 if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr (*this , E)) {
47774784 EmitIgnoredExpr (E->getBase ());
47784785 return EmitDeclRefLValue (DRE);
47794786 }
47804787
47814788 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);
47824794 // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar.
47834795 LValue BaseLV;
47844796 if (E->isArrow ()) {
@@ -4800,7 +4812,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
48004812
48014813 NamedDecl *ND = E->getMemberDecl ();
48024814 if (auto *Field = dyn_cast<FieldDecl>(ND)) {
4803- LValue LV = EmitLValueForField (BaseLV, Field);
4815+ LValue LV = EmitLValueForField (BaseLV, Field, IsInBounds );
48044816 setObjCGCLValueClass (getContext (), E, LV);
48054817 if (getLangOpts ().OpenMP ) {
48064818 // If the member was explicitly marked as nontemporal, mark it as
@@ -4886,12 +4898,15 @@ unsigned CodeGenFunction::getDebugInfoFIndex(const RecordDecl *Rec,
48864898// / Get the address of a zero-sized field within a record. The resulting
48874899// / address doesn't necessarily have the right type.
48884900static Address emitAddrOfZeroSizeField (CodeGenFunction &CGF, Address Base,
4889- const FieldDecl *Field) {
4901+ const FieldDecl *Field,
4902+ bool IsInBounds) {
48904903 CharUnits Offset = CGF.getContext ().toCharUnitsFromBits (
48914904 CGF.getContext ().getFieldOffset (Field));
48924905 if (Offset.isZero ())
48934906 return Base;
48944907 Base = Base.withElementType (CGF.Int8Ty );
4908+ if (!IsInBounds)
4909+ return CGF.Builder .CreateConstByteGEP (Base, Offset);
48954910 return CGF.Builder .CreateConstInBoundsByteGEP (Base, Offset);
48964911}
48974912
@@ -4900,16 +4915,16 @@ static Address emitAddrOfZeroSizeField(CodeGenFunction &CGF, Address Base,
49004915// /
49014916// / The resulting address doesn't necessarily have the right type.
49024917static Address emitAddrOfFieldStorage (CodeGenFunction &CGF, Address base,
4903- const FieldDecl *field) {
4918+ const FieldDecl *field, bool IsInBounds ) {
49044919 if (isEmptyFieldForLayout (CGF.getContext (), field))
4905- return emitAddrOfZeroSizeField (CGF, base, field);
4920+ return emitAddrOfZeroSizeField (CGF, base, field, IsInBounds );
49064921
49074922 const RecordDecl *rec = field->getParent ();
49084923
49094924 unsigned idx =
49104925 CGF.CGM .getTypes ().getCGRecordLayout (rec).getLLVMFieldNo (field);
49114926
4912- if (CGF. getLangOpts (). PointerOverflowDefined )
4927+ if (!IsInBounds )
49134928 return CGF.Builder .CreateConstGEP2_32 (base, 0 , idx, field->getName ());
49144929
49154930 return CGF.Builder .CreateStructGEP (base, idx, field->getName ());
@@ -4947,8 +4962,8 @@ static bool hasAnyVptr(const QualType Type, const ASTContext &Context) {
49474962 return false ;
49484963}
49494964
4950- LValue CodeGenFunction::EmitLValueForField (LValue base,
4951- const FieldDecl *field ) {
4965+ LValue CodeGenFunction::EmitLValueForField (LValue base, const FieldDecl *field,
4966+ bool IsInBounds ) {
49524967 LValueBaseInfo BaseInfo = base.getBaseInfo ();
49534968
49544969 if (field->isBitField ()) {
@@ -4971,7 +4986,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
49714986 (!getDebugInfo () || !rec->hasAttr <BPFPreserveAccessIndexAttr>())) {
49724987 if (Idx != 0 ) {
49734988 // For structs, we GEP to the field that the record layout suggests.
4974- if (getLangOpts (). PointerOverflowDefined )
4989+ if (!IsInBounds )
49754990 Addr = Builder.CreateConstGEP2_32 (Addr, 0 , Idx, field->getName ());
49764991 else
49774992 Addr = Builder.CreateStructGEP (Addr, Idx, field->getName ());
@@ -5084,7 +5099,7 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
50845099 if (!IsInPreservedAIRegion &&
50855100 (!getDebugInfo () || !rec->hasAttr <BPFPreserveAccessIndexAttr>()))
50865101 // 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 );
50885103 else
50895104 // Remember the original struct field index
50905105 addr = emitPreserveStructAccess (*this , base, addr, field);
@@ -5128,7 +5143,9 @@ CodeGenFunction::EmitLValueForFieldInitialization(LValue Base,
51285143 if (!FieldType->isReferenceType ())
51295144 return EmitLValueForField (Base, Field);
51305145
5131- Address V = emitAddrOfFieldStorage (*this , Base.getAddress (), Field);
5146+ Address V = emitAddrOfFieldStorage (
5147+ *this , Base.getAddress (), Field,
5148+ /* IsInBounds=*/ !getLangOpts ().PointerOverflowDefined );
51325149
51335150 // Make sure that the address is pointing to the right type.
51345151 llvm::Type *llvmType = ConvertTypeForMem (FieldType);
0 commit comments