Skip to content

Commit b98a0c7

Browse files
committed
[clang][CodeGen] Implicit Conversion Sanitizer: handle increment/decrement (PR44054)(take 2)
Summary: Implicit Conversion Sanitizer is *almost* feature complete. There aren't *that* much unsanitized things left, two major ones are increment/decrement (this patch) and bit fields. As it was discussed in [[ https://bugs.llvm.org/show_bug.cgi?id=39519 | PR39519 ]], unlike `CompoundAssignOperator` (which is promoted internally), or `BinaryOperator` (for which we always have promotion/demotion in AST) or parts of `UnaryOperator` (we have promotion/demotion but only for certain operations), for inc/dec, clang omits promotion/demotion altogether, under as-if rule. This is technically correct: https://rise4fun.com/Alive/zPgD As it can be seen in `InstCombineCasts.cpp` `canEvaluateTruncated()`, `add`/`sub`/`mul`/`and`/`or`/`xor` operators can all arbitrarily be extended or truncated: https://github.com/llvm/llvm-project/blob/901cd3b3f62d0c700e5d2c3f97eff97d634bec5e/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp#L1320-L1334 But that has serious implications: 1. Since we no longer model implicit casts, do we pessimise their AST representation and everything that uses it? 2. There is no demotion, so lossy demotion sanitizer does not trigger :] Now, i'm not going to argue about the first problem here, but the second one **needs** to be addressed. As it was stated in the report, this is done intentionally, so changing this in all modes would be considered a penalization/regression. Which means, the sanitization-less codegen must not be altered. It was also suggested to not change the sanitized codegen to the one with demotion, but i quite strongly believe that will not be the wise choice here: 1. One will need to re-engineer the check that the inc/dec was lossy in terms of `@llvm.{u,s}{add,sub}.with.overflow` builtins 2. We will still need to compute the result we would lossily demote. (i.e. the result of wide `add`ition/`sub`traction) 3. I suspect it would need to be done right here, in sanitization. Which kinda defeats the point of using `@llvm.{u,s}{add,sub}.with.overflow` builtins: we'd have two `add`s with basically the same arguments, one of which is used for check+error-less codepath and other one for the error reporting. That seems worse than a single wide op+check. 4. OR, we would need to do that in the compiler-rt handler. Which means we'll need a whole new handler. But then what about the `CompoundAssignOperator`, it would also be applicable for it. So this also doesn't really seem like the right path to me. 5. At least X86 (but likely others) pessimizes all sub-`i32` operations (due to partial register stalls), so even if we avoid promotion+demotion, the computations will //likely// be performed in `i32` anyways. So i'm not really seeing much benefit of not doing the straight-forward thing. While looking into this, i have noticed a few more LLVM middle-end missed canonicalizations, and filed [[ https://bugs.llvm.org/show_bug.cgi?id=44100 | PR44100 ]], [[ https://bugs.llvm.org/show_bug.cgi?id=44102 | PR44102 ]]. Those are not specific to inc/dec, we also have them for `CompoundAssignOperator`, and it can happen for normal arithmetics, too. But if we take some other path in the patch, it will not be applicable here, and we will have most likely played ourselves. TLDR: front-end should emit canonical, easy-to-optimize yet un-optimized code. It is middle-end's job to make it optimal. I'm really hoping reviewers agree with my personal assessment of the path this patch should take.. This originally landed in 9872ea4 but got immediately reverted in cbfa237 because the assertion was faulty. That fault ended up being caused by the enum - while there will be promotion, both types are unsigned, with same width. So we still don't need to sanitize non-signed cases. So far. Maybe the assert will tell us this isn't so. Fixes [[ https://bugs.llvm.org/show_bug.cgi?id=44054 | PR44054 ]]. Refs. google/sanitizers#940 Reviewers: rjmccall, erichkeane, rsmith, vsk Reviewed By: erichkeane Subscribers: mehdi_amini, dexonsmith, cfe-commits, #sanitizers, llvm-commits, aaron.ballman, t.p.northover, efriedma, regehr Tags: #llvm, #clang, #sanitizers Differential Revision: https://reviews.llvm.org/D70539
1 parent ebfff46 commit b98a0c7

15 files changed

+1979
-5
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ Non-comprehensive list of changes in this release
7878
been extended to detect these cases, so that code relying on them can be
7979
detected and fixed.
8080

81+
* The Implicit Conversion Sanitizer (``-fsanitize=implicit-conversion``) has
82+
learned to sanitize pre/post increment/decrement of types with bit width
83+
smaller than ``int``.
84+
8185
- For X86 target, -march=skylake-avx512, -march=icelake-client,
8286
-march=icelake-server, -march=cascadelake, -march=cooperlake will default to
8387
not using 512-bit zmm registers in vectorized code unless 512-bit intrinsics

clang/lib/CodeGen/CGExprScalar.cpp

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -976,6 +976,11 @@ EmitIntegerTruncationCheckHelper(Value *Src, QualType SrcType, Value *Dst,
976976
return std::make_pair(Kind, std::make_pair(Check, Mask));
977977
}
978978

979+
static bool PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(
980+
QualType SrcType, QualType DstType) {
981+
return SrcType->isIntegerType() && DstType->isIntegerType();
982+
}
983+
979984
void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
980985
Value *Dst, QualType DstType,
981986
SourceLocation Loc) {
@@ -984,7 +989,8 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value *Src, QualType SrcType,
984989

985990
// We only care about int->int conversions here.
986991
// We ignore conversions to/from pointer and/or bool.
987-
if (!(SrcType->isIntegerType() && DstType->isIntegerType()))
992+
if (!PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(SrcType,
993+
DstType))
988994
return;
989995

990996
unsigned SrcBits = Src->getType()->getScalarSizeInBits();
@@ -1095,7 +1101,8 @@ void ScalarExprEmitter::EmitIntegerSignChangeCheck(Value *Src, QualType SrcType,
10951101

10961102
// We only care about int->int conversions here.
10971103
// We ignore conversions to/from pointer and/or bool.
1098-
if (!(SrcType->isIntegerType() && DstType->isIntegerType()))
1104+
if (!PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(SrcType,
1105+
DstType))
10991106
return;
11001107

11011108
bool SrcSigned = SrcType->isSignedIntegerOrEnumerationType();
@@ -2419,9 +2426,51 @@ ScalarExprEmitter::EmitScalarPrePostIncDec(const UnaryOperator *E, LValue LV,
24192426

24202427
// Most common case by far: integer increment.
24212428
} else if (type->isIntegerType()) {
2422-
// Note that signed integer inc/dec with width less than int can't
2423-
// overflow because of promotion rules; we're just eliding a few steps here.
2424-
if (E->canOverflow() && type->isSignedIntegerOrEnumerationType()) {
2429+
QualType promotedType;
2430+
bool canPerformLossyDemotionCheck = false;
2431+
if (type->isPromotableIntegerType()) {
2432+
promotedType = CGF.getContext().getPromotedIntegerType(type);
2433+
assert(promotedType != type && "Shouldn't promote to the same type.");
2434+
canPerformLossyDemotionCheck = true;
2435+
canPerformLossyDemotionCheck &=
2436+
CGF.getContext().getCanonicalType(type) !=
2437+
CGF.getContext().getCanonicalType(promotedType);
2438+
canPerformLossyDemotionCheck &=
2439+
PromotionIsPotentiallyEligibleForImplicitIntegerConversionCheck(
2440+
type, promotedType);
2441+
assert((!canPerformLossyDemotionCheck ||
2442+
type->isSignedIntegerOrEnumerationType() ||
2443+
promotedType->isSignedIntegerOrEnumerationType() ||
2444+
ConvertType(type)->getScalarSizeInBits() ==
2445+
ConvertType(promotedType)->getScalarSizeInBits()) &&
2446+
"The following check expects that if we do promotion to different "
2447+
"underlying canonical type, at least one of the types (either "
2448+
"base or promoted) will be signed, or the bitwidths will match.");
2449+
}
2450+
if (CGF.SanOpts.hasOneOf(
2451+
SanitizerKind::ImplicitIntegerArithmeticValueChange) &&
2452+
canPerformLossyDemotionCheck) {
2453+
// While `x += 1` (for `x` with width less than int) is modeled as
2454+
// promotion+arithmetics+demotion, and we can catch lossy demotion with
2455+
// ease; inc/dec with width less than int can't overflow because of
2456+
// promotion rules, so we omit promotion+demotion, which means that we can
2457+
// not catch lossy "demotion". Because we still want to catch these cases
2458+
// when the sanitizer is enabled, we perform the promotion, then perform
2459+
// the increment/decrement in the wider type, and finally
2460+
// perform the demotion. This will catch lossy demotions.
2461+
2462+
value = EmitScalarConversion(value, type, promotedType, E->getExprLoc());
2463+
Value *amt = llvm::ConstantInt::get(value->getType(), amount, true);
2464+
value = Builder.CreateAdd(value, amt, isInc ? "inc" : "dec");
2465+
// Do pass non-default ScalarConversionOpts so that sanitizer check is
2466+
// emitted.
2467+
value = EmitScalarConversion(value, promotedType, type, E->getExprLoc(),
2468+
ScalarConversionOpts(CGF.SanOpts));
2469+
2470+
// Note that signed integer inc/dec with width less than int can't
2471+
// overflow because of promotion rules; we're just eliding a few steps
2472+
// here.
2473+
} else if (E->canOverflow() && type->isSignedIntegerOrEnumerationType()) {
24252474
value = EmitIncDecConsiderOverflowBehavior(E, value, isInc);
24262475
} else if (E->canOverflow() && type->isUnsignedIntegerType() &&
24272476
CGF.SanOpts.has(SanitizerKind::UnsignedIntegerOverflow)) {
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
2+
3+
// If we have an enum, it will be promoted to an unsigned integer.
4+
// But both types are unsigned, and have same bitwidth.
5+
// So we should not emit any sanitization. Also, for inc/dec we currently assume
6+
// (assert) that we will only have cases where at least one of the types
7+
// is signed, which isn't the case here.
8+
typedef enum { a } b;
9+
b t0(b c) {
10+
c--;
11+
return c;
12+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// RUN: %clang_cc1 -fsanitize=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-unsigned-integer-truncation,implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
2+
3+
// CHECK-DAG: @[[INT:.*]] = {{.*}} c"'int'\00" }
4+
// CHECK-DAG: @[[UNSIGNED_SHORT:.*]] = {{.*}} c"'unsigned short'\00" }
5+
// CHECK-DAG: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
6+
// CHECK-DAG: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
7+
// CHECK-DAG: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
8+
// CHECK-DAG: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
9+
// CHECK-DAG: @[[SHORT:.*]] = {{.*}} c"'short'\00" }
10+
// CHECK-DAG: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
11+
// CHECK-DAG: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
12+
// CHECK-DAG: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
13+
// CHECK-DAG: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
14+
// CHECK-DAG: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
15+
// CHECK-DAG: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
16+
// CHECK-DAG: @[[LINE_1000:.*]] = {{.*}}, i32 1000, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
17+
// CHECK-DAG: @[[LINE_1100:.*]] = {{.*}}, i32 1100, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
18+
// CHECK-DAG: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
19+
// CHECK-DAG: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
20+
// CHECK-DAG: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
21+
// CHECK-DAG: @[[LINE_1400:.*]] = {{.*}}, i32 1400, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
22+
// CHECK-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
23+
// CHECK-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
24+
25+
// CHECK-LABEL: @t0(
26+
unsigned short t0(unsigned short x) {
27+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*)
28+
#line 100
29+
x++;
30+
return x;
31+
}
32+
// CHECK-LABEL: @t1(
33+
unsigned short t1(unsigned short x) {
34+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*)
35+
#line 200
36+
x--;
37+
return x;
38+
}
39+
// CHECK-LABEL: @t2(
40+
unsigned short t2(unsigned short x) {
41+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*)
42+
#line 300
43+
++x;
44+
return x;
45+
}
46+
// CHECK-LABEL: @t3(
47+
unsigned short t3(unsigned short x) {
48+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*)
49+
#line 400
50+
--x;
51+
return x;
52+
}
53+
54+
// CHECK-LABEL: @t4(
55+
signed short t4(signed short x) {
56+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*)
57+
#line 500
58+
x++;
59+
return x;
60+
}
61+
// CHECK-LABEL: @t5(
62+
signed short t5(signed short x) {
63+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600]] to i8*)
64+
#line 600
65+
x--;
66+
return x;
67+
}
68+
// CHECK-LABEL: @t6(
69+
signed short t6(signed short x) {
70+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700]] to i8*)
71+
#line 700
72+
++x;
73+
return x;
74+
}
75+
// CHECK-LABEL: @t7(
76+
signed short t7(signed short x) {
77+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800]] to i8*)
78+
#line 800
79+
--x;
80+
return x;
81+
}
82+
83+
// CHECK-LABEL: @t8(
84+
unsigned char t8(unsigned char x) {
85+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900]] to i8*)
86+
#line 900
87+
x++;
88+
return x;
89+
}
90+
// CHECK-LABEL: @t9(
91+
unsigned char t9(unsigned char x) {
92+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000]] to i8*)
93+
#line 1000
94+
x--;
95+
return x;
96+
}
97+
// CHECK-LABEL: @t10(
98+
unsigned char t10(unsigned char x) {
99+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100]] to i8*)
100+
#line 1100
101+
++x;
102+
return x;
103+
}
104+
// CHECK-LABEL: @t11(
105+
unsigned char t11(unsigned char x) {
106+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200]] to i8*)
107+
#line 1200
108+
--x;
109+
return x;
110+
}
111+
112+
// CHECK-LABEL: @t12(
113+
signed char t12(signed char x) {
114+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300]] to i8*)
115+
#line 1300
116+
x++;
117+
return x;
118+
}
119+
// CHECK-LABEL: @t13(
120+
signed char t13(signed char x) {
121+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400]] to i8*)
122+
#line 1400
123+
x--;
124+
return x;
125+
}
126+
// CHECK-LABEL: @t14(
127+
signed char t14(signed char x) {
128+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500]] to i8*)
129+
#line 1500
130+
++x;
131+
return x;
132+
}
133+
// CHECK-LABEL: @t15(
134+
signed char t15(signed char x) {
135+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600]] to i8*)
136+
#line 1600
137+
--x;
138+
return x;
139+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
// RUN: %clang_cc1 -fsanitize=implicit-signed-integer-truncation,implicit-integer-sign-change -fsanitize-recover=implicit-signed-integer-truncation,implicit-integer-sign-change -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s -implicit-check-not="call void @__ubsan_handle_implicit_conversion" --check-prefixes=CHECK
2+
3+
// CHECK-DAG: @[[INT:.*]] = {{.*}} c"'int'\00" }
4+
// CHECK-DAG: @[[UNSIGNED_SHORT:.*]] = {{.*}} c"'unsigned short'\00" }
5+
// CHECK-DAG: @[[LINE_100:.*]] = {{.*}}, i32 100, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
6+
// CHECK-DAG: @[[LINE_200:.*]] = {{.*}}, i32 200, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
7+
// CHECK-DAG: @[[LINE_300:.*]] = {{.*}}, i32 300, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
8+
// CHECK-DAG: @[[LINE_400:.*]] = {{.*}}, i32 400, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_SHORT]], i8 2 }
9+
// CHECK-DAG: @[[SHORT:.*]] = {{.*}} c"'short'\00" }
10+
// CHECK-DAG: @[[LINE_500:.*]] = {{.*}}, i32 500, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
11+
// CHECK-DAG: @[[LINE_600:.*]] = {{.*}}, i32 600, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
12+
// CHECK-DAG: @[[LINE_700:.*]] = {{.*}}, i32 700, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
13+
// CHECK-DAG: @[[LINE_800:.*]] = {{.*}}, i32 800, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SHORT]], i8 2 }
14+
// CHECK-DAG: @[[UNSIGNED_CHAR:.*]] = {{.*}} c"'unsigned char'\00" }
15+
// CHECK-DAG: @[[LINE_900:.*]] = {{.*}}, i32 900, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
16+
// CHECK-DAG: @[[LINE_1000:.*]] = {{.*}}, i32 1000, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
17+
// CHECK-DAG: @[[LINE_1100:.*]] = {{.*}}, i32 1100, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
18+
// CHECK-DAG: @[[LINE_1200:.*]] = {{.*}}, i32 1200, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[UNSIGNED_CHAR]], i8 2 }
19+
// CHECK-DAG: @[[SIGNED_CHAR:.*]] = {{.*}} c"'signed char'\00" }
20+
// CHECK-DAG: @[[LINE_1300:.*]] = {{.*}}, i32 1300, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
21+
// CHECK-DAG: @[[LINE_1400:.*]] = {{.*}}, i32 1400, i32 4 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
22+
// CHECK-DAG: @[[LINE_1500:.*]] = {{.*}}, i32 1500, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
23+
// CHECK-DAG: @[[LINE_1600:.*]] = {{.*}}, i32 1600, i32 3 }, {{.*}}* @[[INT]], {{.*}}* @[[SIGNED_CHAR]], i8 2 }
24+
25+
// CHECK-LABEL: @t0(
26+
unsigned short t0(unsigned short x) {
27+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_100]] to i8*)
28+
#line 100
29+
x++;
30+
return x;
31+
}
32+
// CHECK-LABEL: @t1(
33+
unsigned short t1(unsigned short x) {
34+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_200]] to i8*)
35+
#line 200
36+
x--;
37+
return x;
38+
}
39+
// CHECK-LABEL: @t2(
40+
unsigned short t2(unsigned short x) {
41+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_300]] to i8*)
42+
#line 300
43+
++x;
44+
return x;
45+
}
46+
// CHECK-LABEL: @t3(
47+
unsigned short t3(unsigned short x) {
48+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_400]] to i8*)
49+
#line 400
50+
--x;
51+
return x;
52+
}
53+
54+
// CHECK-LABEL: @t4(
55+
signed short t4(signed short x) {
56+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_500]] to i8*)
57+
#line 500
58+
x++;
59+
return x;
60+
}
61+
// CHECK-LABEL: @t5(
62+
signed short t5(signed short x) {
63+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_600]] to i8*)
64+
#line 600
65+
x--;
66+
return x;
67+
}
68+
// CHECK-LABEL: @t6(
69+
signed short t6(signed short x) {
70+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_700]] to i8*)
71+
#line 700
72+
++x;
73+
return x;
74+
}
75+
// CHECK-LABEL: @t7(
76+
signed short t7(signed short x) {
77+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_800]] to i8*)
78+
#line 800
79+
--x;
80+
return x;
81+
}
82+
83+
// CHECK-LABEL: @t8(
84+
unsigned char t8(unsigned char x) {
85+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_900]] to i8*)
86+
#line 900
87+
x++;
88+
return x;
89+
}
90+
// CHECK-LABEL: @t9(
91+
unsigned char t9(unsigned char x) {
92+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1000]] to i8*)
93+
#line 1000
94+
x--;
95+
return x;
96+
}
97+
// CHECK-LABEL: @t10(
98+
unsigned char t10(unsigned char x) {
99+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1100]] to i8*)
100+
#line 1100
101+
++x;
102+
return x;
103+
}
104+
// CHECK-LABEL: @t11(
105+
unsigned char t11(unsigned char x) {
106+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1200]] to i8*)
107+
#line 1200
108+
--x;
109+
return x;
110+
}
111+
112+
// CHECK-LABEL: @t12(
113+
signed char t12(signed char x) {
114+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1300]] to i8*)
115+
#line 1300
116+
x++;
117+
return x;
118+
}
119+
// CHECK-LABEL: @t13(
120+
signed char t13(signed char x) {
121+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1400]] to i8*)
122+
#line 1400
123+
x--;
124+
return x;
125+
}
126+
// CHECK-LABEL: @t14(
127+
signed char t14(signed char x) {
128+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1500]] to i8*)
129+
#line 1500
130+
++x;
131+
return x;
132+
}
133+
// CHECK-LABEL: @t15(
134+
signed char t15(signed char x) {
135+
// CHECK: call void @__ubsan_handle_implicit_conversion(i8* bitcast ({ {{{.*}}}, {{{.*}}}*, {{{.*}}}*, i8 }* @[[LINE_1600]] to i8*)
136+
#line 1600
137+
--x;
138+
return x;
139+
}

0 commit comments

Comments
 (0)