https://github.com/nikic updated https://github.com/llvm/llvm-project/pull/122486
>From 925f74cad21eb6c46514d1ae543ac202073baf27 Mon Sep 17 00:00:00 2001 From: Nikita Popov <npo...@redhat.com> Date: Fri, 10 Jan 2025 17:01:07 +0100 Subject: [PATCH 1/2] [Clang] Add -fwrapv-pointer flag GCC supports three flags related to overflow behavior: * `-fwrapv`: Makes signed integer overflow well-defined. * `-fwrapv-pointer`: Makes pointer overflow well-defined. * `-fno-strict-overflow`: Implies `-fwrapv -fwrapv-pointer`, making both signed integer overflow and pointer overflow well-defined. Clang currently only supports `-fno-strict-overflow` and `-fwrapv`, but not `-fwrapv-pointer`. This PR proposes to introduce `-fwrapv-pointer` and adjust the semantics of `-fwrapv` to match GCC. This allows signed integer overflow and pointer overflow to be controlled independently, while `-fno-strict-overflow` still exists to control both at the same time (and that option is consistent across GCC and Clang). --- clang/docs/ReleaseNotes.rst | 15 ++++++++++- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/Options.td | 5 ++++ clang/lib/CodeGen/CGBuiltin.cpp | 2 +- clang/lib/CodeGen/CGExpr.cpp | 27 +++++++++---------- clang/lib/CodeGen/CGExprScalar.cpp | 12 ++++----- clang/lib/Driver/SanitizerArgs.cpp | 3 +++ clang/lib/Driver/ToolChains/CommonArgs.cpp | 15 ++++++++--- clang/lib/Frontend/CompilerInvocation.cpp | 4 +++ clang/lib/Sema/SemaExpr.cpp | 2 +- clang/test/CodeGen/integer-overflow.c | 13 ++------- clang/test/CodeGen/pointer-overflow.c | 12 +++++++++ clang/test/Driver/clang_wrapv_opts.c | 15 ++++++++++- .../Sema/tautological-pointer-comparison.c | 2 +- 14 files changed, 88 insertions(+), 40 deletions(-) create mode 100644 clang/test/CodeGen/pointer-overflow.c diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cad17c1b3957b6..12b2893b1eb824 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -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, + 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 ------------------------------------------- @@ -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 ------------------------- diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index a980be853d53e6..1bcec212fd332e 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -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, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 852051e772fc1c..820ed088029f8c 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -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">, diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index f1515347fb816c..ecb1437084006a 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -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 diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 054f8d1eadb8c5..106615ca755c03 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -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); } 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()); } diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index ac499e490ee87e..df850421c72c6c 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -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( @@ -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 = @@ -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( @@ -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( @@ -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 { @@ -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( diff --git a/clang/lib/Driver/SanitizerArgs.cpp b/clang/lib/Driver/SanitizerArgs.cpp index a0d6919c6dc8d0..3420472c0f75eb 100644 --- a/clang/lib/Driver/SanitizerArgs.cpp +++ b/clang/lib/Driver/SanitizerArgs.cpp @@ -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; diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp index f8967890f722cf..8f5c38b38c2f8d 100644 --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -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"); } } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 58658dedbaf1ee..98011398a9d985 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -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; @@ -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)) { diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index d5273d463d7c01..789e3ed576e39f 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -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. diff --git a/clang/test/CodeGen/integer-overflow.c b/clang/test/CodeGen/integer-overflow.c index 9e8cde8b33b16e..9f1eca7e314c26 100644 --- a/clang/test/CodeGen/integer-overflow.c +++ b/clang/test/CodeGen/integer-overflow.c @@ -1,8 +1,8 @@ // 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 -fwrapv | 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 | FileCheck %s --check-prefixes=CATCH_UB +// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=signed-integer-overflow -fwrapv | FileCheck %s --check-prefixes=CATCH_UB // RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -ftrapv -ftrapv-handler foo | FileCheck %s --check-prefix=TRAPV_HANDLER @@ -57,15 +57,6 @@ void test1(void) { // TRAPV_HANDLER: foo( --a; - // -fwrapv should turn off inbounds for GEP's, PR9256 - extern int* P; - ++P; - // DEFAULT: getelementptr inbounds nuw i32, ptr - // WRAPV: getelementptr i32, ptr - // TRAPV: getelementptr inbounds nuw i32, ptr - // CATCH_UB_POINTER: getelementptr inbounds nuw i32, ptr - // NOCATCH_UB_POINTER: getelementptr i32, ptr - // PR9350: char pre-increment never overflows. extern volatile signed char PR9350_char_inc; // DEFAULT: add i8 {{.*}}, 1 diff --git a/clang/test/CodeGen/pointer-overflow.c b/clang/test/CodeGen/pointer-overflow.c new file mode 100644 index 00000000000000..9c7821b841980d --- /dev/null +++ b/clang/test/CodeGen/pointer-overflow.c @@ -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 +} diff --git a/clang/test/Driver/clang_wrapv_opts.c b/clang/test/Driver/clang_wrapv_opts.c index 826468e0678d0b..b0a0935121c769 100644 --- a/clang/test/Driver/clang_wrapv_opts.c +++ b/clang/test/Driver/clang_wrapv_opts.c @@ -1,11 +1,24 @@ // RUN: %clang -### -S -fwrapv -fno-wrapv -fwrapv %s 2>&1 | FileCheck -check-prefix=CHECK1 %s // CHECK1: -fwrapv // +// RUN: %clang -### -S -fwrapv-pointer -fno-wrapv-pointer -fwrapv-pointer %s 2>&1 | FileCheck -check-prefix=CHECK1-POINTER %s +// CHECK1-POINTER: -fwrapv-pointer +// // RUN: %clang -### -S -fstrict-overflow -fno-strict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK2 %s -// CHECK2: -fwrapv +// CHECK2: -fwrapv{{.*}}-fwrapv-pointer // // RUN: %clang -### -S -fwrapv -fstrict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK3 %s // CHECK3: -fwrapv // +// RUN: %clang -### -S -fwrapv-pointer -fstrict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK3-POINTER %s +// CHECK3-POINTER: -fwrapv-pointer +// // RUN: %clang -### -S -fno-wrapv -fno-strict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK4 %s // CHECK4-NOT: -fwrapv +// CHECK4: -fwrapv-pointer +// CHECK4-NOT: -fwrapv +// +// RUN: %clang -### -S -fno-wrapv-pointer -fno-strict-overflow %s 2>&1 | FileCheck -check-prefix=CHECK4-POINTER %s +// CHECK4-POINTER-NOT: -fwrapv-pointer +// CHECK4-POINTER: -fwrapv +// CHECK4-POINTER-NOT: -fwrapv-pointer diff --git a/clang/test/Sema/tautological-pointer-comparison.c b/clang/test/Sema/tautological-pointer-comparison.c index 1c5973b01a30d0..f2a944b5305e4e 100644 --- a/clang/test/Sema/tautological-pointer-comparison.c +++ b/clang/test/Sema/tautological-pointer-comparison.c @@ -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 >From a439c540a6cd4ba33f39e572226a09696e355afb Mon Sep 17 00:00:00 2001 From: Nikita Popov <npo...@redhat.com> Date: Fri, 24 Jan 2025 17:42:54 +0100 Subject: [PATCH 2/2] restore test --- clang/test/CodeGen/integer-overflow.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGen/integer-overflow.c b/clang/test/CodeGen/integer-overflow.c index 9f1eca7e314c26..a12d5867d6499b 100644 --- a/clang/test/CodeGen/integer-overflow.c +++ b/clang/test/CodeGen/integer-overflow.c @@ -1,8 +1,8 @@ // 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 -// RUN: %clang_cc1 -triple x86_64-apple-darwin %s -emit-llvm -o - -fsanitize=signed-integer-overflow -fwrapv | FileCheck %s --check-prefixes=CATCH_UB +// 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 @@ -57,6 +57,14 @@ void test1(void) { // TRAPV_HANDLER: foo( --a; + // -fwrapv should turn off inbounds for GEP's, PR9256 + extern int* P; + ++P; + // DEFAULT: getelementptr inbounds nuw i32, ptr + // WRAPV: getelementptr inbounds nuw i32, ptr + // TRAPV: getelementptr inbounds nuw i32, ptr + // NOCATCH_UB_POINTER: getelementptr inbounds nuw i32, ptr + // PR9350: char pre-increment never overflows. extern volatile signed char PR9350_char_inc; // DEFAULT: add i8 {{.*}}, 1 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits