-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[Clang] Add -fwrapv-pointer flag #122486
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Clang] Add -fwrapv-pointer flag #122486
Changes from all commits
925f74c
da97931
609188c
dc8be66
b9a34dc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4311,14 +4311,14 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, | |
// GEP indexes are signed, and scaling an index isn't permitted to | ||
// signed-overflow, so we use the same semantics for our explicit | ||
// multiply. We suppress this if overflow is not undefined behavior. | ||
if (getLangOpts().isSignedOverflowDefined()) { | ||
if (getLangOpts().PointerOverflowDefined) { | ||
Idx = Builder.CreateMul(Idx, numElements); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like a gap in the pointer-overflow sanitizer: we should trigger the sanitizer if the multiply overflows. Same issue pops up in a few other places. But you don't need to fix this in this patch, I guess. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Opened #124358 . |
||
} else { | ||
Idx = Builder.CreateNSWMul(Idx, numElements); | ||
} | ||
|
||
Addr = emitArraySubscriptGEP(*this, Addr, Idx, vla->getElementType(), | ||
!getLangOpts().isSignedOverflowDefined(), | ||
!getLangOpts().PointerOverflowDefined, | ||
SignedIndices, E->getExprLoc()); | ||
|
||
} else if (const ObjCObjectType *OIT = E->getType()->getAs<ObjCObjectType>()){ | ||
|
@@ -4408,7 +4408,7 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, | |
QualType arrayType = Array->getType(); | ||
Addr = emitArraySubscriptGEP( | ||
*this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, | ||
E->getType(), !getLangOpts().isSignedOverflowDefined(), SignedIndices, | ||
E->getType(), !getLangOpts().PointerOverflowDefined, SignedIndices, | ||
E->getExprLoc(), &arrayType, E->getBase()); | ||
EltBaseInfo = ArrayLV.getBaseInfo(); | ||
EltTBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, E->getType()); | ||
|
@@ -4417,10 +4417,9 @@ LValue CodeGenFunction::EmitArraySubscriptExpr(const ArraySubscriptExpr *E, | |
Addr = EmitPointerWithAlignment(E->getBase(), &EltBaseInfo, &EltTBAAInfo); | ||
auto *Idx = EmitIdxAfterBase(/*Promote*/true); | ||
QualType ptrType = E->getBase()->getType(); | ||
Addr = emitArraySubscriptGEP(*this, Addr, Idx, E->getType(), | ||
!getLangOpts().isSignedOverflowDefined(), | ||
SignedIndices, E->getExprLoc(), &ptrType, | ||
E->getBase()); | ||
Addr = emitArraySubscriptGEP( | ||
*this, Addr, Idx, E->getType(), !getLangOpts().PointerOverflowDefined, | ||
SignedIndices, E->getExprLoc(), &ptrType, E->getBase()); | ||
} | ||
|
||
LValue LV = MakeAddrLValue(Addr, E->getType(), EltBaseInfo, EltTBAAInfo); | ||
|
@@ -4565,11 +4564,11 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E, | |
: llvm::ConstantInt::get(IntPtrTy, ConstLength); | ||
Idx = Builder.CreateAdd(LowerBoundVal, LengthVal, "lb_add_len", | ||
/*HasNUW=*/false, | ||
!getLangOpts().isSignedOverflowDefined()); | ||
!getLangOpts().PointerOverflowDefined); | ||
if (Length && LowerBound) { | ||
Idx = Builder.CreateSub( | ||
Idx, llvm::ConstantInt::get(IntPtrTy, /*V=*/1), "idx_sub_1", | ||
/*HasNUW=*/false, !getLangOpts().isSignedOverflowDefined()); | ||
/*HasNUW=*/false, !getLangOpts().PointerOverflowDefined); | ||
} | ||
} else | ||
Idx = llvm::ConstantInt::get(IntPtrTy, ConstLength + ConstLowerBound); | ||
|
@@ -4595,7 +4594,7 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E, | |
Length->getType()->hasSignedIntegerRepresentation()); | ||
Idx = Builder.CreateSub( | ||
LengthVal, llvm::ConstantInt::get(IntPtrTy, /*V=*/1), "len_sub_1", | ||
/*HasNUW=*/false, !getLangOpts().isSignedOverflowDefined()); | ||
/*HasNUW=*/false, !getLangOpts().PointerOverflowDefined); | ||
} else { | ||
ConstLength = ConstLength.zextOrTrunc(PointerWidthInBits); | ||
--ConstLength; | ||
|
@@ -4622,12 +4621,12 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E, | |
// GEP indexes are signed, and scaling an index isn't permitted to | ||
// signed-overflow, so we use the same semantics for our explicit | ||
// multiply. We suppress this if overflow is not undefined behavior. | ||
if (getLangOpts().isSignedOverflowDefined()) | ||
if (getLangOpts().PointerOverflowDefined) | ||
Idx = Builder.CreateMul(Idx, NumElements); | ||
else | ||
Idx = Builder.CreateNSWMul(Idx, NumElements); | ||
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, VLA->getElementType(), | ||
!getLangOpts().isSignedOverflowDefined(), | ||
!getLangOpts().PointerOverflowDefined, | ||
/*signedIndices=*/false, E->getExprLoc()); | ||
} else if (const Expr *Array = isSimpleArrayDecayOperand(E->getBase())) { | ||
// If this is A[i] where A is an array, the frontend will have decayed the | ||
|
@@ -4647,7 +4646,7 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E, | |
// Propagate the alignment from the array itself to the result. | ||
EltPtr = emitArraySubscriptGEP( | ||
*this, ArrayLV.getAddress(), {CGM.getSize(CharUnits::Zero()), Idx}, | ||
ResultExprTy, !getLangOpts().isSignedOverflowDefined(), | ||
ResultExprTy, !getLangOpts().PointerOverflowDefined, | ||
/*signedIndices=*/false, E->getExprLoc()); | ||
BaseInfo = ArrayLV.getBaseInfo(); | ||
TBAAInfo = CGM.getTBAAInfoForSubobject(ArrayLV, ResultExprTy); | ||
|
@@ -4656,7 +4655,7 @@ LValue CodeGenFunction::EmitArraySectionExpr(const ArraySectionExpr *E, | |
emitOMPArraySectionBase(*this, E->getBase(), BaseInfo, TBAAInfo, BaseTy, | ||
ResultExprTy, IsLowerBound); | ||
EltPtr = emitArraySubscriptGEP(*this, Base, Idx, ResultExprTy, | ||
!getLangOpts().isSignedOverflowDefined(), | ||
!getLangOpts().PointerOverflowDefined, | ||
/*signedIndices=*/false, E->getExprLoc()); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT | ||
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fwrapv | FileCheck %s --check-prefix=DEFAULT | ||
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -ftrapv | FileCheck %s --check-prefix=DEFAULT | ||
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fwrapv-pointer | FileCheck %s --check-prefix=FWRAPV-POINTER | ||
|
||
void test(void) { | ||
// -fwrapv-pointer should turn off inbounds for GEP's | ||
extern int* P; | ||
++P; | ||
// DEFAULT: getelementptr inbounds nuw i32, ptr | ||
// FWRAPV-POINTER: getelementptr i32, ptr | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,20 @@ | ||
// RUN: %clang -### -S -fwrapv -fno-wrapv -fwrapv %s 2>&1 | FileCheck -check-prefix=CHECK1 %s | ||
// CHECK1: -fwrapv | ||
// RUN: %clang -### -S -fwrapv -fno-wrapv -fwrapv -Werror %s 2>&1 | FileCheck -check-prefix=CHECK1 %s | ||
// CHECK1: "-fwrapv" | ||
// | ||
// RUN: %clang -### -S -fstrict-overflow -fno-strict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK2 %s | ||
// CHECK2: -fwrapv | ||
// RUN: %clang -### -S -fwrapv-pointer -fno-wrapv-pointer -fwrapv-pointer -Werror %s 2>&1 | FileCheck -check-prefix=CHECK1-POINTER %s | ||
// CHECK1-POINTER: "-fwrapv-pointer" | ||
// | ||
// RUN: %clang -### -S -fwrapv -fstrict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK3 %s | ||
// CHECK3: -fwrapv | ||
// RUN: %clang -### -S -fstrict-overflow -fno-strict-overflow -Werror %s 2>&1 | FileCheck -check-prefix=CHECK2 %s | ||
// CHECK2: "-fwrapv"{{.*}}"-fwrapv-pointer" | ||
// | ||
// RUN: %clang -### -S -fno-wrapv -fno-strict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK4 %s | ||
// CHECK4-NOT: -fwrapv | ||
// RUN: %clang -### -S -fwrapv -fstrict-overflow -Werror -Werror %s 2>&1 | FileCheck -check-prefix=CHECK3 %s --implicit-check-not="-fwrapv-pointer" | ||
// CHECK3: "-fwrapv" | ||
// | ||
// RUN: %clang -### -S -fwrapv-pointer -fstrict-overflow -Werror %s 2>&1 | FileCheck -check-prefix=CHECK3-POINTER %s --implicit-check-not="-fwrapv" | ||
// CHECK3-POINTER: "-fwrapv-pointer" | ||
// | ||
// RUN: %clang -### -S -fno-wrapv -fno-strict-overflow -Werror %s 2>&1 | FileCheck -check-prefix=CHECK4 %s --implicit-check-not="-fwrapv" | ||
// CHECK4: "-fwrapv-pointer" | ||
// | ||
// RUN: %clang -### -S -fno-wrapv-pointer -fno-strict-overflow -Werror %s 2>&1 | FileCheck -check-prefix=CHECK4-POINTER %s --implicit-check-not="-fwrapv-pointer" | ||
// CHECK4-POINTER: "-fwrapv" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Curiously enough, we only ever documented the signed integer overflow behavior, not the pointer overflow: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fwrapv