Skip to content
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
24 changes: 19 additions & 5 deletions clang/lib/CodeGen/CGExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,8 @@ class ScalarExprEmitter
/// the sign of the value. It is not UB, so we use the value after conversion.
/// NOTE: Src and Dst may be the exact same value! (point to the same thing)
void EmitIntegerSignChangeCheck(Value *Src, QualType SrcType, Value *Dst,
QualType DstType, SourceLocation Loc);
QualType DstType, SourceLocation Loc,
bool OBTrapInvolved = false);

/// Emit a conversion from the specified type to the specified destination
/// type, both of which are LLVM scalar types.
Expand Down Expand Up @@ -1303,8 +1304,10 @@ EmitIntegerSignChangeCheckHelper(Value *Src, QualType SrcType, Value *Dst,

void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
Value *Dst, QualType DstType,
SourceLocation Loc) {
if (!CGF.SanOpts.has(SanitizerKind::SO_ImplicitIntegerSignChange))
SourceLocation Loc,
bool OBTrapInvolved) {
if (!CGF.SanOpts.has(SanitizerKind::SO_ImplicitIntegerSignChange) &&
!OBTrapInvolved)
return;

llvm::Type *SrcTy = Src->getType();
Expand Down Expand Up @@ -1391,6 +1394,16 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
// If the comparison result is 'i1 false', then the truncation was lossy.
}

if (!CGF.SanOpts.has(SanitizerKind::SO_ImplicitIntegerSignChange)) {
if (OBTrapInvolved) {
llvm::Value *Combined = Check.second.first;
for (const auto &C : Checks)
Combined = Builder.CreateAnd(Combined, C.first);
CGF.EmitTrapCheck(Combined, CheckHandler);
}
return;
}

llvm::Constant *StaticArgs[] = {
CGF.EmitCheckSourceLocation(Loc), CGF.EmitCheckTypeDescriptor(SrcType),
CGF.EmitCheckTypeDescriptor(DstType),
Expand Down Expand Up @@ -1828,9 +1841,10 @@ Value *ScalarExprEmitter::EmitScalarConversion(Value *Src, QualType SrcType,
EmitIntegerTruncationCheck(Src, NoncanonicalSrcType, Res,
NoncanonicalDstType, Loc, OBTrapInvolved);

if (Opts.EmitImplicitIntegerSignChangeChecks)
if (Opts.EmitImplicitIntegerSignChangeChecks ||
(OBTrapInvolved && !OBWrapInvolved))
EmitIntegerSignChangeCheck(Src, NoncanonicalSrcType, Res,
NoncanonicalDstType, Loc);
NoncanonicalDstType, Loc, OBTrapInvolved);

return Res;
}
Expand Down
28 changes: 24 additions & 4 deletions clang/test/CodeGen/overflow-behavior-types.c
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -fexperimental-overflow-behavior-types %s \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,implicit-integer-sign-change \
// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT

// RUN: %clang_cc1 -triple x86_64-linux-gnu -fexperimental-overflow-behavior-types %s -ftrapv \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,implicit-integer-sign-change \
// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT

// RUN: %clang_cc1 -triple x86_64-linux-gnu -fexperimental-overflow-behavior-types %s \
// RUN: -ftrapv -ftrapv-handler OVERFLOW_HANDLER \
// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=TRAPV-HANDLER

// RUN: %clang_cc1 -triple x86_64-linux-gnu -fexperimental-overflow-behavior-types %s -fwrapv \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,implicit-integer-sign-change \
// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=DEFAULT

// RUN: %clang_cc1 -triple x86_64-linux-gnu -fexperimental-overflow-behavior-types %s \
// RUN: -fsanitize-undefined-ignore-overflow-pattern=all \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation \
// RUN: -fsanitize=signed-integer-overflow,unsigned-integer-overflow,implicit-signed-integer-truncation,implicit-unsigned-integer-truncation,implicit-integer-sign-change \
// RUN: -emit-llvm -o - | FileCheck %s --check-prefix=EXCL

// RUN: %clang_cc1 -triple x86_64-linux-gnu -fexperimental-overflow-behavior-types %s \
Expand Down Expand Up @@ -174,3 +174,23 @@ int explicit_truncation_cast(__ob_trap unsigned long long result) {
// NOSAN: call void @llvm.ubsantrap(i8 7)
return (int)result;
}

// Make sure __ob_trap types warn on sign change with
// -fsanitize=implicit-integer-sign-change or trap otherwise.
// DEFAULT-LABEL: define {{.*}} @unsigned_to_signed_cast
void unsigned_to_signed_cast(__ob_trap unsigned long long a) {
// DEFAULT: %[[T0:.*]] = load i64, ptr %a.addr
// DEFAULT-NEXT: %[[CONV0:.*]] = trunc i64 %[[T0]] to i8
// DEFAULT-NEXT: %[[NEG:.*]] = icmp slt i8 %[[CONV0]], 0
// DEFAULT-NEXT: %[[SIGN0:.*]] = icmp eq i1 false, %[[NEG]]
// DEFAULT: %[[T1:.*]] = and i1 %[[SIGN0]]
// DEFUALT-NEXT: br i1 %[[T1]], {{.*}}, label %handler.implicit_conversion

// NOSAN: %[[T0:.*]] = load i64, ptr %a.addr
// NOSAN-NEXT: %[[CONV0:.*]] = trunc i64 %[[T0]] to i8
// NOSAN: %[[NEG:.*]] = icmp slt i8 %[[CONV0]], 0
// NOSAN-NEXT: %[[SIGN0:.*]] = icmp eq i1 false, %[[NEG]]
// NOSAN: %[[T1:.*]] = and i1 %[[SIGN0]]
// NOSAN-NEXT: br i1 %[[T1]], {{.*}}, label %trap
(signed char)(a);
}