Skip to content

Commit 3a604fd

Browse files
[Clang][CFG] check children statements of asm goto
When performing CFG based analyses, don't forget to check the child statements of an asm goto, such as the expressions used for inputs+outputs. Fixes: #51024 Fixes: ClangBuiltLinux/linux#1439 Reviewed By: void, jyknight, jyu2, efriedma Differential Revision: https://reviews.llvm.org/D116059
1 parent f388735 commit 3a604fd

File tree

5 files changed

+74
-25
lines changed

5 files changed

+74
-25
lines changed

clang/lib/Analysis/CFG.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3352,7 +3352,7 @@ CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
33523352
// Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is
33533353
// used to avoid adding "Succ" again.
33543354
BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
3355-
return Block;
3355+
return VisitChildren(G);
33563356
}
33573357

33583358
CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {

clang/lib/Analysis/UninitializedValues.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -819,12 +819,11 @@ void TransferFunctions::VisitGCCAsmStmt(GCCAsmStmt *as) {
819819
while (const auto *UO = dyn_cast<UnaryOperator>(Ex))
820820
Ex = stripCasts(C, UO->getSubExpr());
821821

822+
// Mark the variable as potentially uninitialized for those cases where
823+
// it's used on an indirect path, where it's not guaranteed to be
824+
// defined.
822825
if (const VarDecl *VD = findVar(Ex).getDecl())
823-
if (vals[VD] != Initialized)
824-
// If the variable isn't initialized by the time we get here, then we
825-
// mark it as potentially uninitialized for those cases where it's used
826-
// on an indirect path, where it's not guaranteed to be defined.
827-
vals[VD] = MayUninitialized;
826+
vals[VD] = MayUninitialized;
828827
}
829828
}
830829

clang/test/Analysis/asm-goto.cpp

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_analyze_cc1 -triple i386-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
2-
// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
1+
// RUN: %clang_analyze_cc1 -triple i386-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
2+
// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
33

44
int foo(int cond)
55
{
@@ -17,11 +17,12 @@ int foo(int cond)
1717
// CHECK-NEXT: Succs (1): B0
1818

1919
// CHECK-LABEL: label_true
20-
// CHECK-NEXT: asm goto
20+
// CHECK-NEXT: cond
21+
// CHECK-NEXT: [B3.1]
22+
// CHECK-NEXT: T: asm goto
2123
// CHECK-NEXT: Preds (2): B3 B4
2224
// CHECK-NEXT: Succs (3): B2 B3 B1
2325

24-
2526
int bar(int cond)
2627
{
2728
asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::L1, L2);
@@ -32,7 +33,9 @@ int bar(int cond)
3233
}
3334

3435
// CHECK: [B4]
35-
// CHECK-NEXT: asm goto
36+
// CHECK-NEXT: cond
37+
// CHECK-NEXT: [B4.1]
38+
// CHECK-NEXT: T: asm goto
3639
// CHECK-NEXT: Preds (1): B5
3740
// CHECK-NEXT: Succs (3): B3 B2 B1
3841

@@ -48,6 +51,20 @@ int zoo(int n)
4851
}
4952

5053
// CHECK-LABEL: A1
51-
// CHECK-NEXT: asm goto
54+
// CHECK-NEXT: n
55+
// CHECK-NEXT: [B4.1]
56+
// CHECK-NEXT: T: asm goto
5257
// CHECK-NEXT: Preds (2): B5 B4
5358
// CHECK-NEXT: Succs (5): B3 B4 B2 B1 B5
59+
60+
void baz(void)
61+
{
62+
asm goto("" :: "r"(1 ? 2 : 0 << -1) :: error);
63+
error:;
64+
}
65+
66+
// CHECK: [B2]
67+
// CHECK-NEXT: 1: [B5.2] ? [B3.1] : [B4.4]
68+
// CHECK-NEXT: T: asm goto ("" : : "r" ([B2.1]) : : error);
69+
// CHECK-NEXT: Preds (2): B3 B4
70+
// CHECK-NEXT: Succs (1): B1

clang/test/Analysis/uninit-asm-goto.cpp

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@
33
// test1: Expect no diagnostics
44
int test1(int x) {
55
int y;
6-
asm goto("nop" : "=r"(y) : "r"(x) : : err);
6+
asm goto("" : "=r"(y) : "r"(x) : : err);
77
return y;
88
err:
99
return -1;
1010
}
1111

1212
int test2(int x) {
13-
int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}} \
14-
// expected-note {{initialize the variable}}
13+
int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}}
14+
// expected-note@-1 {{initialize the variable}}
1515
if (x < 42)
16-
asm volatile goto("testl %0, %0; testl %1, %2; jne %l3" : "+S"(x), "+D"(y) : "r"(x) :: indirect_1, indirect_2);
16+
asm goto("" : "+S"(x), "+D"(y) : "r"(x) :: indirect_1, indirect_2);
1717
else
18-
asm volatile goto("testl %0, %1; testl %2, %3; jne %l5" : "+S"(x), "+D"(y) : "r"(x), "r"(y) :: indirect_1, indirect_2);
18+
asm goto("" : "+S"(x), "+D"(y) : "r"(x), "r"(y) :: indirect_1, indirect_2);
1919
return x + y;
2020
indirect_1:
2121
return -42;
@@ -24,9 +24,9 @@ int test2(int x) {
2424
}
2525

2626
int test3(int x) {
27-
int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}} \
28-
// expected-note {{initialize the variable}}
29-
asm goto("xorl %1, %0; jmp %l2" : "=&r"(y) : "r"(x) : : fail);
27+
int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}}
28+
// expected-note@-1 {{initialize the variable}}
29+
asm goto("" : "=&r"(y) : "r"(x) : : fail);
3030
normal:
3131
y += x;
3232
return y;
@@ -38,20 +38,20 @@ int test3(int x) {
3838
}
3939

4040
int test4(int x) {
41-
int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}} \
42-
// expected-note {{initialize the variable}}
41+
int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}}
42+
// expected-note@-1 {{initialize the variable}}
4343
goto forward;
4444
backward:
4545
return y; // expected-note {{uninitialized use occurs here}}
4646
forward:
47-
asm goto("# %0 %1 %2" : "=r"(y) : "r"(x) : : backward);
47+
asm goto("" : "=r"(y) : "r"(x) : : backward);
4848
return y;
4949
}
5050

5151
// test5: Expect no diagnostics
5252
int test5(int x) {
5353
int y;
54-
asm volatile goto("testl %0, %0; testl %1, %2; jne %l3" : "+S"(x), "+D"(y) : "r"(x) :: indirect, fallthrough);
54+
asm goto("" : "+S"(x), "+D"(y) : "r"(x) :: indirect, fallthrough);
5555
fallthrough:
5656
return y;
5757
indirect:
@@ -63,9 +63,30 @@ int test6(unsigned int *x) {
6363
unsigned int val;
6464

6565
// See through casts and unary operators.
66-
asm goto("nop" : "=r" (*(unsigned int *)(&val)) ::: indirect);
66+
asm goto("" : "=r" (*(unsigned int *)(&val)) ::: indirect);
6767
*x = val;
6868
return 0;
6969
indirect:
7070
return -1;
7171
}
72+
73+
int test7(int z) {
74+
int x; // expected-warning {{variable 'x' is used uninitialized whenever its declaration is reached}}
75+
// expected-note@-1 {{initialize the variable 'x' to silence this warning}}
76+
if (z)
77+
asm goto ("":"=r"(x):::A1,A2);
78+
return 0;
79+
A1:
80+
A2:
81+
return x; // expected-note {{uninitialized use occurs here}}
82+
}
83+
84+
int test8() {
85+
int x = 0; // expected-warning {{variable 'x' is used uninitialized whenever its declaration is reached}}
86+
// expected-note@-1 {{variable 'x' is declared here}}
87+
asm goto ("":"=r"(x):::A1,A2);
88+
return 0;
89+
A1:
90+
A2:
91+
return x; // expected-note {{uninitialized use occurs here}}
92+
}

clang/test/Sema/array-bounds-ptr-arith.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,15 @@ void radar11387038() {
3737
RDar11387038_B *pRDar11387038_B;
3838
struct RDar11387038* y = &(*pRDar11387038_B->x)->z[4];
3939
}
40+
41+
void pr51682 (void) {
42+
int arr [1];
43+
switch (0) {
44+
case 0:
45+
break;
46+
case 1:
47+
asm goto (""::"r"(arr[42] >> 1)::failed); // no-warning
48+
break;
49+
}
50+
failed:;
51+
}

0 commit comments

Comments
 (0)