https://github.com/dtcxzyw updated https://github.com/llvm/llvm-project/pull/137849
>From f1db3a540ec1383451955efab62b64ed8d180349 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Wed, 30 Apr 2025 01:26:41 +0800 Subject: [PATCH 1/4] [Clang][CodeGen] Check `isUnderlyingBasePointerConstantNull` in `emitPointerArithmetic` --- clang/lib/CodeGen/CGExprScalar.cpp | 3 ++- .../test/CodeGen/catch-nullptr-and-nonzero-offset.c | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 8dbbcdaef25d8..d214d2af52563 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4238,7 +4238,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, else elemTy = CGF.ConvertTypeForMem(elementType); - if (CGF.getLangOpts().PointerOverflowDefined) + if (CGF.getLangOpts().PointerOverflowDefined || + CGF.isUnderlyingBasePointerConstantNull(pointerOperand)) return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); return CGF.EmitCheckedInBoundsGEP( diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c index 63b6db2c2adeb..c5ae3f8bcc368 100644 --- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c +++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c @@ -431,6 +431,18 @@ char *void_ptr(void *base, unsigned long offset) { return base + offset; } +int *constant_null_add(long offset) { + // CHECK: define{{.*}} ptr @constant_null_add(i64 noundef %[[OFFSET:.*]]) + // CHECK-NEXT: [[ENTRY:.*]]: + // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8 + // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NEXT: %[[ADD_PTR:.*]] = getelementptr i32, ptr null, i64 %[[OFFSET_RELOADED]] + // CHECK-NEXT: ret ptr %[[ADD_PTR]] +#line 1800 + return (int *)0 + offset; +} + #ifdef __cplusplus } #endif >From 2796472ca05332419cade01afbea08d8f9446d76 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Wed, 30 Apr 2025 14:48:54 +0800 Subject: [PATCH 2/4] [Clang][CodeGen] Re-enable ubsan check --- clang/lib/CodeGen/CGExprScalar.cpp | 3 +- .../catch-nullptr-and-nonzero-offset.c | 38 ++++++++++++++----- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index d214d2af52563..96e48d65e8ace 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4239,7 +4239,8 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, elemTy = CGF.ConvertTypeForMem(elementType); if (CGF.getLangOpts().PointerOverflowDefined || - CGF.isUnderlyingBasePointerConstantNull(pointerOperand)) + (!CGF.SanOpts.has(SanitizerKind::PointerOverflow) && + CGF.isUnderlyingBasePointerConstantNull(pointerOperand))) return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); return CGF.EmitCheckedInBoundsGEP( diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c index c5ae3f8bcc368..338f85f2d2fbd 100644 --- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c +++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c @@ -1,9 +1,9 @@ -// RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -x c -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE // RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE // RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER // RUN: %clang_cc1 -x c -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE -// RUN: %clang_cc1 -x c++ -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s +// RUN: %clang_cc1 -x c++ -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,CHECK-NOSANITIZE // RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-NORECOVER,CHECK-SANITIZE-UNREACHABLE // RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-ANYRECOVER,CHECK-SANITIZE-RECOVER // RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fsanitize-trap=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_pointer_overflow" --check-prefixes=CHECK,CHECK-SANITIZE,CHECK-SANITIZE-TRAP,CHECK-SANITIZE-UNREACHABLE @@ -32,6 +32,7 @@ // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1700:.*]] = {{.*}}, i32 1700, i32 15 } } +// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1800:.*]] = {{.*}}, i32 1800, i32 19 } } #ifdef __cplusplus extern "C" { @@ -431,14 +432,33 @@ char *void_ptr(void *base, unsigned long offset) { return base + offset; } -int *constant_null_add(long offset) { +int *constant_null_add(unsigned long offset) { // CHECK: define{{.*}} ptr @constant_null_add(i64 noundef %[[OFFSET:.*]]) - // CHECK-NEXT: [[ENTRY:.*]]: - // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8 - // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8 - // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8 - // CHECK-NEXT: %[[ADD_PTR:.*]] = getelementptr i32, ptr null, i64 %[[OFFSET_RELOADED]] - // CHECK-NEXT: ret ptr %[[ADD_PTR]] + // CHECK-NEXT: [[ENTRY:.*]]: + // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8 + // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8 + // CHECK-NOSANITIZE-NEXT: %[[ADD_PTR:.*]] = getelementptr i32, ptr null, i64 %[[OFFSET_RELOADED]] + // CHECK-SANITIZE-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds nuw i32, ptr null, i64 %[[OFFSET_RELOADED]] + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_AGGREGATE:.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 4, i64 %[[OFFSET_RELOADED]]), !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_OVERFLOWED:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 1, !nosanitize + // CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP:.*]] = add i64 0, %[[COMPUTED_OFFSET]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_NOT_NULL:.*]] = icmp ne i64 %[[COMPUTED_GEP]], 0, !nosanitize + // CHECK-SANITIZE-NEXT: %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL:.*]] = icmp eq i1 false, %[[COMPUTED_GEP_IS_NOT_NULL]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW:.*]] = xor i1 %[[OR_OV]], true, !nosanitize + // CHECK-SANITIZE-NEXT: %[[COMPUTED_GEP_IS_UGE_BASE:.*]] = icmp uge i64 %[[COMPUTED_GEP]], 0, !nosanitize + // CHECK-SANITIZE-NEXT: %[[GEP_DID_NOT_OVERFLOW:.*]] = and i1 %[[COMPUTED_GEP_IS_UGE_BASE]], %[[COMPUTED_OFFSET_DID_NOT_OVERFLOW]], !nosanitize + // CHECK-SANITIZE-NEXT: %[[GEP_IS_OKAY:.*]] = and i1 %[[BOTH_POINTERS_ARE_NULL_OR_BOTH_ARE_NONNULL]], %[[GEP_DID_NOT_OVERFLOW]], !nosanitize + // CHECK-SANITIZE-NEXT: br i1 %[[GEP_IS_OKAY]], label %[[CONT:.*]], label %[[HANDLER_POINTER_OVERFLOW:[^,]+]],{{.*}} !nosanitize + // CHECK-SANITIZE: [[HANDLER_POINTER_OVERFLOW]]: + // CHECK-SANITIZE-NORECOVER-NEXT: call void @__ubsan_handle_pointer_overflow_abort(ptr @[[LINE_1800]], i64 0, i64 %[[COMPUTED_GEP]]) + // CHECK-SANITIZE-RECOVER-NEXT: call void @__ubsan_handle_pointer_overflow(ptr @[[LINE_1800]], i64 0, i64 %[[COMPUTED_GEP]]) + // CHECK-SANITIZE-TRAP-NEXT: call void @llvm.ubsantrap(i8 19){{.*}}, !nosanitize + // CHECK-SANITIZE-UNREACHABLE-NEXT: unreachable, !nosanitize + // CHECK-SANITIZE: [[CONT]]: + // CHECK-NEXT: ret ptr %[[ADD_PTR]] #line 1800 return (int *)0 + offset; } >From 61c7e1d981d85d6ace4b13ca286b91988675dc13 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Thu, 1 May 2025 18:54:58 +0800 Subject: [PATCH 3/4] [Clang][CodeGen] Add comments. NFC. --- clang/lib/CodeGen/CGExprScalar.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 96e48d65e8ace..a9a920b4686f2 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4238,6 +4238,13 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, else elemTy = CGF.ConvertTypeForMem(elementType); + // Some versions of glibc __PTR_ALIGN macro use idioms that add an index to a + // null pointer in order to cast the aligned integer value back to a pointer. + // This is undefined behavior, but we have to add a workaround for it. + // + // Unlike the above check `BinaryOperator::isNullPointerArithmeticExtension`, + // we still generate a GEP with a null-pointer base instead of inttoptr. + // This means that it's also UB to dereference a pointer created that way. if (CGF.getLangOpts().PointerOverflowDefined || (!CGF.SanOpts.has(SanitizerKind::PointerOverflow) && CGF.isUnderlyingBasePointerConstantNull(pointerOperand))) >From 305e5636d99bfb6ce34adfd2a8e2c72a003a1b10 Mon Sep 17 00:00:00 2001 From: Yingwei Zheng <dtcxzyw2...@gmail.com> Date: Sun, 4 May 2025 18:55:44 +0800 Subject: [PATCH 4/4] [Clang][CodeGen] Reuse `isNullPointerArithmeticExtension` --- clang/include/clang/AST/ASTContext.h | 2 ++ clang/lib/AST/ASTContext.cpp | 7 +++++ clang/lib/AST/Expr.cpp | 3 +-- clang/lib/CodeGen/CGExpr.cpp | 14 +++------- clang/lib/CodeGen/CGExprScalar.cpp | 26 ++++++++----------- clang/lib/CodeGen/CodeGenFunction.h | 2 -- .../catch-nullptr-and-nonzero-offset.c | 13 +++++----- 7 files changed, 32 insertions(+), 35 deletions(-) diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h index 3c78833a3f069..e7ae0cdebe300 100644 --- a/clang/include/clang/AST/ASTContext.h +++ b/clang/include/clang/AST/ASTContext.h @@ -3238,6 +3238,8 @@ class ASTContext : public RefCountedBase<ASTContext> { } bool isSentinelNullExpr(const Expr *E); + /// Check whether the underlying base pointer is a constant null. + bool isUnderlyingBasePointerConstantNull(const Expr *E); /// Get the implementation of the ObjCInterfaceDecl \p D, or nullptr if /// none exists. diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index c95e733f30494..3f081629b4e88 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3000,6 +3000,13 @@ bool ASTContext::isSentinelNullExpr(const Expr *E) { return false; } +bool ASTContext::isUnderlyingBasePointerConstantNull(const Expr *E) { + const Expr *UnderlyingBaseExpr = E->IgnoreParens(); + while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr)) + UnderlyingBaseExpr = BaseMemberExpr->getBase()->IgnoreParens(); + return isSentinelNullExpr(UnderlyingBaseExpr); +} + /// Get the implementation of ObjCInterfaceDecl, or nullptr if none /// exists. ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) { diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp index 59c0e47c7c195..243b7587aaebb 100644 --- a/clang/lib/AST/Expr.cpp +++ b/clang/lib/AST/Expr.cpp @@ -2248,8 +2248,7 @@ bool BinaryOperator::isNullPointerArithmeticExtension(ASTContext &Ctx, } // Check that the pointer is a nullptr. - if (!PExp->IgnoreParenCasts() - ->isNullPointerConstant(Ctx, Expr::NPC_ValueDependentIsNotNull)) + if (!Ctx.isUnderlyingBasePointerConstantNull(PExp)) return false; // Check that the pointee type is char-sized. diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index bba7d1e805f3f..80f822cf5328a 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -4816,13 +4816,6 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) { Base.getBaseInfo(), TBAAAccessInfo()); } -bool CodeGenFunction::isUnderlyingBasePointerConstantNull(const Expr *E) { - const Expr *UnderlyingBaseExpr = E->IgnoreParens(); - while (auto *BaseMemberExpr = dyn_cast<MemberExpr>(UnderlyingBaseExpr)) - UnderlyingBaseExpr = BaseMemberExpr->getBase()->IgnoreParens(); - return getContext().isSentinelNullExpr(UnderlyingBaseExpr); -} - LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { if (DeclRefExpr *DRE = tryToConvertMemberExprToDeclRefExpr(*this, E)) { EmitIgnoredExpr(E->getBase()); @@ -4834,7 +4827,7 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { // If so, we do not set inbounds flag for GEP to avoid breaking some // old-style offsetof idioms. bool IsInBounds = !getLangOpts().PointerOverflowDefined && - !isUnderlyingBasePointerConstantNull(BaseExpr); + !getContext().isUnderlyingBasePointerConstantNull(BaseExpr); // If this is s.x, emit s as an lvalue. If it is s->x, emit s as a scalar. LValue BaseLV; if (E->isArrow()) { @@ -6373,8 +6366,9 @@ EmitPointerToDataMemberBinaryExpr(const BinaryOperator *E) { LValueBaseInfo BaseInfo; TBAAAccessInfo TBAAInfo; - bool IsInBounds = !getLangOpts().PointerOverflowDefined && - !isUnderlyingBasePointerConstantNull(E->getLHS()); + bool IsInBounds = + !getLangOpts().PointerOverflowDefined && + !getContext().isUnderlyingBasePointerConstantNull(E->getLHS()); Address MemberAddr = EmitCXXMemberDataPointerAddress( E, BaseAddr, OffsetV, MPT, IsInBounds, &BaseInfo, &TBAAInfo); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index a9a920b4686f2..a15057b1ace16 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -4169,11 +4169,16 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, // The index is not pointer-sized. // The pointer type is not byte-sized. // - if (BinaryOperator::isNullPointerArithmeticExtension(CGF.getContext(), - op.Opcode, - expr->getLHS(), - expr->getRHS())) - return CGF.Builder.CreateIntToPtr(index, pointer->getType()); + // Note that we do not suppress the pointer overflow check in this case. + if (!CGF.SanOpts.has(SanitizerKind::PointerOverflow) && + BinaryOperator::isNullPointerArithmeticExtension( + CGF.getContext(), op.Opcode, expr->getLHS(), expr->getRHS())) { + // isUnderlyingBasePointerConstantNull returns true does not indicate that + // the base pointer is null. + Value *Base = CGF.Builder.CreatePtrToInt(pointer, index->getType()); + Value *PtrAdd = CGF.Builder.CreateAdd(Base, index, "ptr.add"); + return CGF.Builder.CreateIntToPtr(PtrAdd, pointer->getType()); + } if (width != DL.getIndexTypeSizeInBits(PtrTy)) { // Zero-extend or sign-extend the pointer value according to @@ -4238,16 +4243,7 @@ static Value *emitPointerArithmetic(CodeGenFunction &CGF, else elemTy = CGF.ConvertTypeForMem(elementType); - // Some versions of glibc __PTR_ALIGN macro use idioms that add an index to a - // null pointer in order to cast the aligned integer value back to a pointer. - // This is undefined behavior, but we have to add a workaround for it. - // - // Unlike the above check `BinaryOperator::isNullPointerArithmeticExtension`, - // we still generate a GEP with a null-pointer base instead of inttoptr. - // This means that it's also UB to dereference a pointer created that way. - if (CGF.getLangOpts().PointerOverflowDefined || - (!CGF.SanOpts.has(SanitizerKind::PointerOverflow) && - CGF.isUnderlyingBasePointerConstantNull(pointerOperand))) + if (CGF.getLangOpts().PointerOverflowDefined) return CGF.Builder.CreateGEP(elemTy, pointer, index, "add.ptr"); return CGF.EmitCheckedInBoundsGEP( diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 4c5e8a8a44926..756d94702db4a 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4559,8 +4559,6 @@ class CodeGenFunction : public CodeGenTypeCache { const CXXRecordDecl *RD); bool isPointerKnownNonNull(const Expr *E); - /// Check whether the underlying base pointer is a constant null. - bool isUnderlyingBasePointerConstantNull(const Expr *E); /// Create the discriminator from the storage address and the entity hash. llvm::Value *EmitPointerAuthBlendDiscriminator(llvm::Value *StorageAddress, diff --git a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c index 338f85f2d2fbd..6eee33300ef63 100644 --- a/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c +++ b/clang/test/CodeGen/catch-nullptr-and-nonzero-offset.c @@ -32,7 +32,7 @@ // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 15 } } // CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1700:.*]] = {{.*}}, i32 1700, i32 15 } } -// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1800:.*]] = {{.*}}, i32 1800, i32 19 } } +// CHECK-SANITIZE-ANYRECOVER-DAG: @[[LINE_1800:.*]] = {{.*}}, i32 1800, i32 20 } } #ifdef __cplusplus extern "C" { @@ -432,15 +432,16 @@ char *void_ptr(void *base, unsigned long offset) { return base + offset; } -int *constant_null_add(unsigned long offset) { +char *constant_null_add(unsigned long offset) { // CHECK: define{{.*}} ptr @constant_null_add(i64 noundef %[[OFFSET:.*]]) // CHECK-NEXT: [[ENTRY:.*]]: // CHECK-NEXT: %[[OFFSET_ADDR:.*]] = alloca i64, align 8 // CHECK-NEXT: store i64 %[[OFFSET]], ptr %[[OFFSET_ADDR]], align 8 // CHECK-NEXT: %[[OFFSET_RELOADED:.*]] = load i64, ptr %[[OFFSET_ADDR]], align 8 - // CHECK-NOSANITIZE-NEXT: %[[ADD_PTR:.*]] = getelementptr i32, ptr null, i64 %[[OFFSET_RELOADED]] - // CHECK-SANITIZE-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds nuw i32, ptr null, i64 %[[OFFSET_RELOADED]] - // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_AGGREGATE:.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 4, i64 %[[OFFSET_RELOADED]]), !nosanitize + // CHECK-NOSANITIZE-NEXT: %[[PTR_ADD:.*]] = add i64 0, %[[OFFSET_RELOADED]] + // CHECK-NOSANITIZE-NEXT: %[[ADD_PTR:.*]] = inttoptr i64 %[[PTR_ADD]] to ptr + // CHECK-SANITIZE-NEXT: %[[ADD_PTR:.*]] = getelementptr inbounds nuw i8, ptr null, i64 %[[OFFSET_RELOADED]] + // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_AGGREGATE:.*]] = call { i64, i1 } @llvm.smul.with.overflow.i64(i64 1, i64 %[[OFFSET_RELOADED]]), !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET_OVERFLOWED:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 1, !nosanitize // CHECK-SANITIZE-NEXT: %[[OR_OV:.+]] = or i1 %[[COMPUTED_OFFSET_OVERFLOWED]], false, !nosanitize // CHECK-SANITIZE-NEXT: %[[COMPUTED_OFFSET:.*]] = extractvalue { i64, i1 } %[[COMPUTED_OFFSET_AGGREGATE]], 0, !nosanitize @@ -460,7 +461,7 @@ int *constant_null_add(unsigned long offset) { // CHECK-SANITIZE: [[CONT]]: // CHECK-NEXT: ret ptr %[[ADD_PTR]] #line 1800 - return (int *)0 + offset; + return (char *)0 + offset; } #ifdef __cplusplus _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits