[clang] 3a604fd - [Clang][CFG] check children statements of asm goto

Nick Desaulniers via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 7 14:20:36 PST 2022


Author: Nick Desaulniers
Date: 2022-01-07T14:11:08-08:00
New Revision: 3a604fdbcd5fd9ca41f6659692bb4ad2151c3cf4

URL: https://github.com/llvm/llvm-project/commit/3a604fdbcd5fd9ca41f6659692bb4ad2151c3cf4
DIFF: https://github.com/llvm/llvm-project/commit/3a604fdbcd5fd9ca41f6659692bb4ad2151c3cf4.diff

LOG: [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: https://github.com/llvm/llvm-project/issues/51024
Fixes: https://github.com/ClangBuiltLinux/linux/issues/1439

Reviewed By: void, jyknight, jyu2, efriedma

Differential Revision: https://reviews.llvm.org/D116059

Added: 
    

Modified: 
    clang/lib/Analysis/CFG.cpp
    clang/lib/Analysis/UninitializedValues.cpp
    clang/test/Analysis/asm-goto.cpp
    clang/test/Analysis/uninit-asm-goto.cpp
    clang/test/Sema/array-bounds-ptr-arith.c

Removed: 
    


################################################################################
diff  --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index 9bde034d5e099..8246854dc1b51 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -3352,7 +3352,7 @@ CFGBlock *CFGBuilder::VisitGCCAsmStmt(GCCAsmStmt *G, AddStmtChoice asc) {
   // Save "Succ" in BackpatchBlocks. In the backpatch processing, "Succ" is
   // used to avoid adding "Succ" again.
   BackpatchBlocks.push_back(JumpSource(Succ, ScopePos));
-  return Block;
+  return VisitChildren(G);
 }
 
 CFGBlock *CFGBuilder::VisitForStmt(ForStmt *F) {

diff  --git a/clang/lib/Analysis/UninitializedValues.cpp b/clang/lib/Analysis/UninitializedValues.cpp
index a38ae34f4b811..811146e50b45a 100644
--- a/clang/lib/Analysis/UninitializedValues.cpp
+++ b/clang/lib/Analysis/UninitializedValues.cpp
@@ -819,12 +819,11 @@ void TransferFunctions::VisitGCCAsmStmt(GCCAsmStmt *as) {
     while (const auto *UO = dyn_cast<UnaryOperator>(Ex))
       Ex = stripCasts(C, UO->getSubExpr());
 
+    // Mark the variable as potentially uninitialized for those cases where
+    // it's used on an indirect path, where it's not guaranteed to be
+    // defined.
     if (const VarDecl *VD = findVar(Ex).getDecl())
-      if (vals[VD] != Initialized)
-        // If the variable isn't initialized by the time we get here, then we
-        // mark it as potentially uninitialized for those cases where it's used
-        // on an indirect path, where it's not guaranteed to be defined.
-        vals[VD] = MayUninitialized;
+      vals[VD] = MayUninitialized;
   }
 }
 

diff  --git a/clang/test/Analysis/asm-goto.cpp b/clang/test/Analysis/asm-goto.cpp
index bc212f800401a..75f907a209b2d 100644
--- a/clang/test/Analysis/asm-goto.cpp
+++ b/clang/test/Analysis/asm-goto.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_analyze_cc1  -triple i386-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
-// RUN: %clang_analyze_cc1  -triple x86_64-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
+// RUN: %clang_analyze_cc1 -triple i386-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
+// RUN: %clang_analyze_cc1 -triple x86_64-pc-linux-gnu -analyzer-checker=debug.DumpCFG %s 2>&1 | FileCheck %s
 
 int foo(int cond)
 {
@@ -17,11 +17,12 @@ int foo(int cond)
 // CHECK-NEXT: Succs (1): B0
 
 // CHECK-LABEL: label_true
-// CHECK-NEXT: asm goto
+// CHECK-NEXT: cond
+// CHECK-NEXT: [B3.1]
+// CHECK-NEXT: T: asm goto
 // CHECK-NEXT: Preds (2): B3 B4
 // CHECK-NEXT: Succs (3): B2 B3 B1
 
-
 int bar(int cond)
 {
   asm goto("testl %0, %0; jne %l1;" :: "r"(cond)::L1, L2);
@@ -32,7 +33,9 @@ int bar(int cond)
 }
 
 // CHECK: [B4]
-// CHECK-NEXT: asm goto
+// CHECK-NEXT: cond
+// CHECK-NEXT: [B4.1]
+// CHECK-NEXT: T: asm goto
 // CHECK-NEXT: Preds (1): B5
 // CHECK-NEXT: Succs (3): B3 B2 B1
 
@@ -48,6 +51,20 @@ int zoo(int n)
 }
 
 // CHECK-LABEL: A1
-// CHECK-NEXT: asm goto
+// CHECK-NEXT: n
+// CHECK-NEXT: [B4.1]
+// CHECK-NEXT: T: asm goto
 // CHECK-NEXT: Preds (2): B5 B4
 // CHECK-NEXT: Succs (5): B3 B4 B2 B1 B5
+
+void baz(void)
+{
+  asm goto("" :: "r"(1 ? 2 : 0 << -1) :: error);
+error:;
+}
+
+// CHECK: [B2]
+// CHECK-NEXT: 1: [B5.2] ? [B3.1] : [B4.4]
+// CHECK-NEXT: T: asm goto ("" :  : "r" ([B2.1]) :  : error);
+// CHECK-NEXT: Preds (2): B3 B4
+// CHECK-NEXT: Succs (1): B1

diff  --git a/clang/test/Analysis/uninit-asm-goto.cpp b/clang/test/Analysis/uninit-asm-goto.cpp
index 9da21584ec864..1b9d1689b036f 100644
--- a/clang/test/Analysis/uninit-asm-goto.cpp
+++ b/clang/test/Analysis/uninit-asm-goto.cpp
@@ -3,19 +3,19 @@
 // test1: Expect no diagnostics
 int test1(int x) {
     int y;
-    asm goto("nop" : "=r"(y) : "r"(x) : : err);
+    asm goto("" : "=r"(y) : "r"(x) : : err);
     return y;
   err:
     return -1;
 }
 
 int test2(int x) {
-  int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}} \
-         // expected-note {{initialize the variable}}
+  int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}}
+         // expected-note at -1 {{initialize the variable}}
   if (x < 42)
-    asm volatile goto("testl %0, %0; testl %1, %2; jne %l3" : "+S"(x), "+D"(y) : "r"(x) :: indirect_1, indirect_2);
+    asm goto("" : "+S"(x), "+D"(y) : "r"(x) :: indirect_1, indirect_2);
   else
-    asm volatile goto("testl %0, %1; testl %2, %3; jne %l5" : "+S"(x), "+D"(y) : "r"(x), "r"(y) :: indirect_1, indirect_2);
+    asm goto("" : "+S"(x), "+D"(y) : "r"(x), "r"(y) :: indirect_1, indirect_2);
   return x + y;
 indirect_1:
   return -42;
@@ -24,9 +24,9 @@ int test2(int x) {
 }
 
 int test3(int x) {
-  int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}} \
-         // expected-note {{initialize the variable}}
-  asm goto("xorl %1, %0; jmp %l2" : "=&r"(y) : "r"(x) : : fail);
+  int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}}
+         // expected-note at -1 {{initialize the variable}}
+  asm goto("" : "=&r"(y) : "r"(x) : : fail);
 normal:
   y += x;
   return y;
@@ -38,20 +38,20 @@ int test3(int x) {
 }
 
 int test4(int x) {
-  int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}} \
-         // expected-note {{initialize the variable}}
+  int y; // expected-warning {{variable 'y' is used uninitialized whenever its declaration is reached}}
+         // expected-note at -1 {{initialize the variable}}
   goto forward;
 backward:
   return y; // expected-note {{uninitialized use occurs here}}
 forward:
-  asm goto("# %0 %1 %2" : "=r"(y) : "r"(x) : : backward);
+  asm goto("" : "=r"(y) : "r"(x) : : backward);
   return y;
 }
 
 // test5: Expect no diagnostics
 int test5(int x) {
   int y;
-  asm volatile goto("testl %0, %0; testl %1, %2; jne %l3" : "+S"(x), "+D"(y) : "r"(x) :: indirect, fallthrough);
+  asm goto("" : "+S"(x), "+D"(y) : "r"(x) :: indirect, fallthrough);
 fallthrough:
   return y;
 indirect:
@@ -63,9 +63,30 @@ int test6(unsigned int *x) {
   unsigned int val;
 
   // See through casts and unary operators.
-  asm goto("nop" : "=r" (*(unsigned int *)(&val)) ::: indirect);
+  asm goto("" : "=r" (*(unsigned int *)(&val)) ::: indirect);
   *x = val;
   return 0;
 indirect:
   return -1;
 }
+
+int test7(int z) {
+    int x; // expected-warning {{variable 'x' is used uninitialized whenever its declaration is reached}}
+           // expected-note at -1 {{initialize the variable 'x' to silence this warning}}
+    if (z)
+      asm goto ("":"=r"(x):::A1,A2);
+    return 0;
+    A1:
+    A2:
+    return x; // expected-note {{uninitialized use occurs here}}
+}
+
+int test8() {
+    int x = 0; // expected-warning {{variable 'x' is used uninitialized whenever its declaration is reached}}
+               // expected-note at -1 {{variable 'x' is declared here}}
+    asm goto ("":"=r"(x):::A1,A2);
+    return 0;
+    A1:
+    A2:
+    return x; // expected-note {{uninitialized use occurs here}}
+}

diff  --git a/clang/test/Sema/array-bounds-ptr-arith.c b/clang/test/Sema/array-bounds-ptr-arith.c
index e3de06a104e47..ac96b896291ac 100644
--- a/clang/test/Sema/array-bounds-ptr-arith.c
+++ b/clang/test/Sema/array-bounds-ptr-arith.c
@@ -37,3 +37,15 @@ void radar11387038() {
   RDar11387038_B *pRDar11387038_B;
   struct RDar11387038* y = &(*pRDar11387038_B->x)->z[4];
 }
+
+void pr51682 (void) {
+  int arr [1];
+  switch (0) {
+    case 0:
+      break;
+    case 1:
+      asm goto (""::"r"(arr[42] >> 1)::failed); // no-warning
+      break;
+  }
+failed:;
+}


        


More information about the cfe-commits mailing list