Skip to content

[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

Merged
merged 5 commits into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,15 @@ code bases.
Undefined behavior due to pointer addition overflow can be reliably detected
using ``-fsanitize=pointer-overflow``. It is also possible to use
``-fno-strict-overflow`` to opt-in to a language dialect where signed integer
and pointer overflow are well-defined.
and pointer overflow are well-defined. Since Clang 20, it is also possible
to use ``-fwrapv-pointer`` to only make pointer overflow well-defined, while
not affecting the behavior of signed integer overflow.

- The ``-fwrapv`` flag now only makes signed integer overflow well-defined,
Copy link
Collaborator

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

without affecting pointer overflow, which is controlled by a new
``-fwrapv-pointer`` flag. The ``-fno-strict-overflow`` flag now implies
both ``-fwrapv`` and ``-fwrapv-pointer`` and as such retains its old meaning.
The new behavior matches GCC.

C/C++ Language Potentially Breaking Changes
-------------------------------------------
Expand Down Expand Up @@ -500,6 +508,11 @@ New Compiler Flags
- clang-cl and clang-dxc now support ``-fdiagnostics-color=[auto|never|always]``
in addition to ``-f[no-]color-diagnostics``.

- The new ``-fwrapv-pointer`` flag opts-in to a language dialect where pointer
overflow is well-defined. The ``-fwrapv`` flag previously implied
``-fwrapv-pointer`` as well, but no longer does. ``-fno-strict-overflow``
implies ``-fwrapv -fwrapv-pointer``. The flags now match GCC.

Deprecated Compiler Flags
-------------------------

Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/Basic/LangOptions.def
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,7 @@ VALUE_LANGOPT(TrivialAutoVarInitMaxSize, 32, 0,
"stop trivial automatic variable initialization if var size exceeds the specified size (in bytes). Must be greater than 0.")
ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined,
"signed integer overflow handling")
LANGOPT(PointerOverflowDefined, 1, 0, "make pointer overflow defined")
ENUM_LANGOPT(ThreadModel , ThreadModelKind, 2, ThreadModelKind::POSIX, "Thread Model")

BENIGN_LANGOPT(ArrowDepth, 32, 256,
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -4299,6 +4299,11 @@ def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>,
HelpText<"Treat signed integer overflow as two's complement">;
def fno_wrapv : Flag<["-"], "fno-wrapv">, Group<f_Group>,
Visibility<[ClangOption, CLOption, FlangOption]>;
def fwrapv_pointer : Flag<["-"], "fwrapv-pointer">, Group<f_Group>,
Visibility<[ClangOption, CLOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Treat pointer overflow as two's complement">;
def fno_wrapv_pointer : Flag<["-"], "fno-wrapv-pointer">, Group<f_Group>,
Visibility<[ClangOption, CLOption, FlangOption]>;
def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>,
Visibility<[ClangOption, CC1Option]>,
HelpText<"Store string literals as writable data">,
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/CodeGen/CGBuiltin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22051,7 +22051,7 @@ RValue CodeGenFunction::EmitBuiltinAlignTo(const CallExpr *E, bool AlignUp) {
// By adding the mask, we ensure that align_up on an already aligned
// value will not change the value.
if (Args.Src->getType()->isPointerTy()) {
if (getLangOpts().isSignedOverflowDefined())
if (getLangOpts().PointerOverflowDefined)
SrcForMask =
Builder.CreateGEP(Int8Ty, SrcForMask, Args.Mask, "over_boundary");
else
Expand Down
27 changes: 13 additions & 14 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.

Copy link
Collaborator

Choose a reason for hiding this comment

The 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>()){
Expand Down Expand Up @@ -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());
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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());
}

Expand Down
12 changes: 6 additions & 6 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3043,7 +3043,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::Value *numElts = CGF.getVLASize(vla).NumElts;
if (!isInc) numElts = Builder.CreateNSWNeg(numElts, "vla.negsize");
llvm::Type *elemTy = CGF.ConvertTypeForMem(vla->getElementType());
if (CGF.getLangOpts().isSignedOverflowDefined())
if (CGF.getLangOpts().PointerOverflowDefined)
value = Builder.CreateGEP(elemTy, value, numElts, "vla.inc");
else
value = CGF.EmitCheckedInBoundsGEP(
Expand All @@ -3054,7 +3054,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
} else if (type->isFunctionType()) {
llvm::Value *amt = Builder.getInt32(amount);

if (CGF.getLangOpts().isSignedOverflowDefined())
if (CGF.getLangOpts().PointerOverflowDefined)
value = Builder.CreateGEP(CGF.Int8Ty, value, amt, "incdec.funcptr");
else
value =
Expand All @@ -3066,7 +3066,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
} else {
llvm::Value *amt = Builder.getInt32(amount);
llvm::Type *elemTy = CGF.ConvertTypeForMem(type);
if (CGF.getLangOpts().isSignedOverflowDefined())
if (CGF.getLangOpts().PointerOverflowDefined)
value = Builder.CreateGEP(elemTy, value, amt, "incdec.ptr");
else
value = CGF.EmitCheckedInBoundsGEP(
Expand Down Expand Up @@ -3179,7 +3179,7 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
llvm::Value *sizeValue =
llvm::ConstantInt::get(CGF.SizeTy, size.getQuantity());

if (CGF.getLangOpts().isSignedOverflowDefined())
if (CGF.getLangOpts().PointerOverflowDefined)
value = Builder.CreateGEP(CGF.Int8Ty, value, sizeValue, "incdec.objptr");
else
value = CGF.EmitCheckedInBoundsGEP(
Expand Down Expand Up @@ -4075,7 +4075,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
// signed-overflow, so we use the same semantics for our explicit
// multiply. We suppress this if overflow is not undefined behavior.
llvm::Type *elemTy = CGF.ConvertTypeForMem(vla->getElementType());
if (CGF.getLangOpts().isSignedOverflowDefined()) {
if (CGF.getLangOpts().PointerOverflowDefined) {
index = CGF.Builder.CreateMul(index, numElements, "vla.index");
pointer = CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr");
} else {
Expand All @@ -4096,7 +4096,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF,
else
elemTy = CGF.ConvertTypeForMem(elementType);

if (CGF.getLangOpts().isSignedOverflowDefined())
if (CGF.getLangOpts().PointerOverflowDefined)
return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr");

return CGF.EmitCheckedInBoundsGEP(
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Driver/SanitizerArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,9 @@ SanitizerArgs::SanitizerArgs(const ToolChain &TC,
options::OPT_fstrict_overflow, false);
if (Args.hasFlagNoClaim(options::OPT_fwrapv, options::OPT_fno_wrapv, S))
Add &= ~SanitizerKind::SignedIntegerOverflow;
if (Args.hasFlagNoClaim(options::OPT_fwrapv_pointer,
options::OPT_fno_wrapv_pointer, S))
Add &= ~SanitizerKind::PointerOverflow;
}
Add &= Supported;

Expand Down
15 changes: 11 additions & 4 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3106,12 +3106,19 @@ void tools::renderCommonIntegerOverflowOptions(const ArgList &Args,
ArgStringList &CmdArgs) {
// -fno-strict-overflow implies -fwrapv if it isn't disabled, but
// -fstrict-overflow won't turn off an explicitly enabled -fwrapv.
bool StrictOverflow = Args.hasFlag(options::OPT_fstrict_overflow,
options::OPT_fno_strict_overflow, true);
if (Arg *A = Args.getLastArg(options::OPT_fwrapv, options::OPT_fno_wrapv)) {
if (A->getOption().matches(options::OPT_fwrapv))
CmdArgs.push_back("-fwrapv");
} else if (Arg *A = Args.getLastArg(options::OPT_fstrict_overflow,
options::OPT_fno_strict_overflow)) {
if (A->getOption().matches(options::OPT_fno_strict_overflow))
CmdArgs.push_back("-fwrapv");
} else if (!StrictOverflow) {
CmdArgs.push_back("-fwrapv");
}
if (Arg *A = Args.getLastArg(options::OPT_fwrapv_pointer,
options::OPT_fno_wrapv_pointer)) {
if (A->getOption().matches(options::OPT_fwrapv_pointer))
CmdArgs.push_back("-fwrapv-pointer");
} else if (!StrictOverflow) {
CmdArgs.push_back("-fwrapv-pointer");
}
}
4 changes: 4 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3721,6 +3721,8 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
} else if (Opts.SignedOverflowBehavior == LangOptions::SOB_Defined) {
GenerateArg(Consumer, OPT_fwrapv);
}
if (Opts.PointerOverflowDefined)
GenerateArg(Consumer, OPT_fwrapv_pointer);

if (Opts.MSCompatibilityVersion != 0) {
unsigned Major = Opts.MSCompatibilityVersion / 10000000;
Expand Down Expand Up @@ -4138,6 +4140,8 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args,
}
else if (Args.hasArg(OPT_fwrapv))
Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
if (Args.hasArg(OPT_fwrapv_pointer))
Opts.PointerOverflowDefined = true;

Opts.MSCompatibilityVersion = 0;
if (const Arg *A = Args.getLastArg(OPT_fms_compatibility_version)) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11793,7 +11793,7 @@ static std::optional<bool> isTautologicalBoundsCheck(Sema &S, const Expr *LHS,
const Expr *RHS,
BinaryOperatorKind Opc) {
if (!LHS->getType()->isPointerType() ||
S.getLangOpts().isSignedOverflowDefined())
S.getLangOpts().PointerOverflowDefined)
return std::nullopt;

// Canonicalize to >= or < predicate.
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CodeGen/integer-overflow.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// 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=WRAPV
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -ftrapv | FileCheck %s --check-prefix=TRAPV
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=signed-integer-overflow | FileCheck %s --check-prefixes=CATCH_UB,CATCH_UB_POINTER
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=signed-integer-overflow | FileCheck %s --check-prefixes=CATCH_UB,NOCATCH_UB_POINTER
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=signed-integer-overflow -fwrapv | FileCheck %s --check-prefixes=CATCH_UB,NOCATCH_UB_POINTER
// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -ftrapv -ftrapv-handler foo | FileCheck %s --check-prefix=TRAPV_HANDLER

Expand Down Expand Up @@ -57,14 +57,14 @@ void test1(void) {
// TRAPV_HANDLER: foo(
--a;

// -fwrapv should turn off inbounds for GEP's, PR9256
// -fwrapv does not affect inbounds for GEP's.
// This is controlled by -fwrapv-pointer instead.
extern int* P;
++P;
// DEFAULT: getelementptr inbounds nuw i32, ptr
// WRAPV: getelementptr i32, ptr
// WRAPV: getelementptr inbounds nuw i32, ptr
// TRAPV: getelementptr inbounds nuw i32, ptr
// CATCH_UB_POINTER: getelementptr inbounds nuw i32, ptr
// NOCATCH_UB_POINTER: getelementptr i32, ptr
// NOCATCH_UB_POINTER: getelementptr inbounds nuw i32, ptr

// PR9350: char pre-increment never overflows.
extern volatile signed char PR9350_char_inc;
Expand Down
12 changes: 12 additions & 0 deletions clang/test/CodeGen/pointer-overflow.c
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
}
25 changes: 17 additions & 8 deletions clang/test/Driver/clang_wrapv_opts.c
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"
2 changes: 1 addition & 1 deletion clang/test/Sema/tautological-pointer-comparison.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -fwrapv -verify=fwrapv %s
// RUN: %clang_cc1 -fsyntax-only -fwrapv-pointer -verify=fwrapv %s

// fwrapv-no-diagnostics

Expand Down
Loading