summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorGabor Horvath <xazax@google.com>2019-12-11 11:34:44 -0800
committerGabor Horvath <xazax@google.com>2019-12-11 17:15:12 -0800
commit9fdcae7c81f5ff92ad694f5d993a042a525fd6bc (patch)
treefb392a017fd46a9315d0a76abaf0c608a59e5d1a /clang
parent83e1bd36be988ffce4732f400ff6f06442c34011 (diff)
downloadbcm5719-llvm-9fdcae7c81f5ff92ad694f5d993a042a525fd6bc.tar.gz
bcm5719-llvm-9fdcae7c81f5ff92ad694f5d993a042a525fd6bc.zip
[analyzer] Do not cache out on some shared implicit AST nodes
Some AST nodes which stands for implicit initialization is shared. The analyzer will do the same evaluation on the same nodes resulting in the same state. The analyzer will "cache out", i.e. it thinks that it visited an already existing node in the exploded graph. This is not true in this case and we lose coverage. Since these nodes do not really require any processing from the analyzer we just omit them from the CFG. Differential Revision: https://reviews.llvm.org/D71371
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Analysis/CFG.h1
-rw-r--r--clang/lib/Analysis/CFG.cpp5
-rw-r--r--clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp1
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp6
-rw-r--r--clang/test/Analysis/designated-initializer-values.c38
-rw-r--r--clang/test/Analysis/designated-initializer.c13
-rw-r--r--clang/test/Analysis/initializers-cfg-output.cpp15
-rw-r--r--clang/test/Analysis/temp-obj-dtors-cfg-output.cpp3
8 files changed, 64 insertions, 18 deletions
diff --git a/clang/include/clang/Analysis/CFG.h b/clang/include/clang/Analysis/CFG.h
index a8301a0e006..ea3d8b2921a 100644
--- a/clang/include/clang/Analysis/CFG.h
+++ b/clang/include/clang/Analysis/CFG.h
@@ -1251,6 +1251,7 @@ public:
bool AddRichCXXConstructors = false;
bool MarkElidedCXXConstructors = false;
bool AddVirtualBaseBranches = false;
+ bool OmitImplicitValueInitializers = false;
BuildOptions() = default;
diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp
index bc21d1c9076..e10bfd80593 100644
--- a/clang/lib/Analysis/CFG.cpp
+++ b/clang/lib/Analysis/CFG.cpp
@@ -2135,6 +2135,11 @@ CFGBlock *CFGBuilder::Visit(Stmt * S, AddStmtChoice asc,
default:
return VisitStmt(S, asc);
+ case Stmt::ImplicitValueInitExprClass:
+ if (BuildOpts.OmitImplicitValueInitializers)
+ return Block;
+ return VisitStmt(S, asc);
+
case Stmt::AddrLabelExprClass:
return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
diff --git a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
index 73e1a0d0000..94fc09e64aa 100644
--- a/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -43,6 +43,7 @@ AnalysisManager::AnalysisManager(ASTContext &ASTCtx,
CreateConstraintMgr(constraintmgr), CheckerMgr(checkerMgr),
options(Options) {
AnaCtxMgr.getCFGBuildOptions().setAllAlwaysAdd();
+ AnaCtxMgr.getCFGBuildOptions().OmitImplicitValueInitializers = true;
}
AnalysisManager::~AnalysisManager() {
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 2a23d1cae7b..f917a4c8637 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1321,6 +1321,11 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::WhileStmtClass:
case Expr::MSDependentExistsStmtClass:
llvm_unreachable("Stmt should not be in analyzer evaluation loop");
+ case Stmt::ImplicitValueInitExprClass:
+ // These nodes are shared in the CFG and would case caching out.
+ // Moreover, no additional evaluation required for them, the
+ // analyzer can reconstruct these values from the AST.
+ llvm_unreachable("Should be pruned from CFG");
case Stmt::ObjCSubscriptRefExprClass:
case Stmt::ObjCPropertyRefExprClass:
@@ -1391,7 +1396,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::IntegerLiteralClass:
case Stmt::FixedPointLiteralClass:
case Stmt::CharacterLiteralClass:
- case Stmt::ImplicitValueInitExprClass:
case Stmt::CXXScalarValueInitExprClass:
case Stmt::CXXBoolLiteralExprClass:
case Stmt::ObjCBoolLiteralExprClass:
diff --git a/clang/test/Analysis/designated-initializer-values.c b/clang/test/Analysis/designated-initializer-values.c
new file mode 100644
index 00000000000..1efc10aece6
--- /dev/null
+++ b/clang/test/Analysis/designated-initializer-values.c
@@ -0,0 +1,38 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -std=c99 -verify %s
+
+void clang_analyzer_eval(int);
+
+void array_init() {
+ int a[5] = {[4] = 29, [2] = 15, [0] = 4};
+ clang_analyzer_eval(a[0] == 4); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a[1] == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a[2] == 15); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a[3] == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(a[4] == 29); // expected-warning{{TRUE}}
+ int b[5] = {[0 ... 2] = 1, [4] = 5};
+ clang_analyzer_eval(b[0] == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b[1] == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b[2] == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b[3] == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(b[4] == 5); // expected-warning{{TRUE}}
+}
+
+struct point {
+ int x, y;
+};
+
+void struct_init() {
+ struct point p = {.y = 5, .x = 3};
+ clang_analyzer_eval(p.x == 3); // expected-warning{{TRUE}}
+ clang_analyzer_eval(p.y == 5); // expected-warning{{TRUE}}
+}
+
+void array_of_struct() {
+ struct point ptarray[3] = { [2].y = 1, [2].x = 2, [0].x = 3 };
+ clang_analyzer_eval(ptarray[0].x == 3); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ptarray[0].y == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ptarray[1].x == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ptarray[1].y == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ptarray[2].x == 2); // expected-warning{{TRUE}}
+ clang_analyzer_eval(ptarray[2].y == 1); // expected-warning{{TRUE}}
+}
diff --git a/clang/test/Analysis/designated-initializer.c b/clang/test/Analysis/designated-initializer.c
index 920b2f08d7e..adca0ab6c87 100644
--- a/clang/test/Analysis/designated-initializer.c
+++ b/clang/test/Analysis/designated-initializer.c
@@ -31,11 +31,10 @@ void test() {
// CHECK: 11: struct LUQ var = {getUQ(), .uq.q.a = 100};
// CHECK: 12: 1
// CHECK: 13: 2
-// CHECK: 14: /*implicit*/(int)0
-// CHECK: 15: {[B1.12], [B1.13]}
+// CHECK: 14: {[B1.12], [B1.13]}
+// CHECK: 17: /*no init*/
// CHECK: 18: /*no init*/
-// CHECK: 19: /*no init*/
-// CHECK: 20: 3
-// CHECK: 21: {[B1.18], [B1.19], [B1.20]}
-// CHECK: 22: {/*base*/[B1.17], /*updater*/[B1.21]}
-// CHECK: 24: struct Q s[] = {[0] = (struct Q){1, 2}, [0].c = 3};
+// CHECK: 19: 3
+// CHECK: 20: {[B1.17], [B1.18], [B1.19]}
+// CHECK: 21: {/*base*/[B1.16], /*updater*/[B1.20]}
+// CHECK: 23: struct Q s[] = {[0] = (struct Q){1, 2}, [0].c = 3};
diff --git a/clang/test/Analysis/initializers-cfg-output.cpp b/clang/test/Analysis/initializers-cfg-output.cpp
index f8338649265..14c1b1e99a4 100644
--- a/clang/test/Analysis/initializers-cfg-output.cpp
+++ b/clang/test/Analysis/initializers-cfg-output.cpp
@@ -126,14 +126,13 @@ public:
// WARNINGS-NEXT: 5: (CXXConstructExpr, class A)
// ANALYZER-NEXT: 5: (CXXConstructExpr, A() (Base initializer), class A)
// CHECK-NEXT: 6: A([B1.5]) (Base initializer)
-// CHECK-NEXT: 7: /*implicit*/(int)0
-// CHECK-NEXT: 8: i([B1.7]) (Member initializer)
-// CHECK-NEXT: 9: this
-// CHECK-NEXT: 10: [B1.9]->i
-// CHECK-NEXT: 11: r([B1.10]) (Member initializer)
-// WARNINGS-NEXT: 12: (CXXConstructExpr, class A)
-// ANALYZER-NEXT: 12: (CXXConstructExpr, [B1.13], class A)
-// CHECK-NEXT: 13: A a;
+// CHECK-NEXT: 7: i(/*implicit*/(int)0) (Member initializer)
+// CHECK-NEXT: 8: this
+// CHECK-NEXT: 9: [B1.8]->i
+// CHECK-NEXT: 10: r([B1.9]) (Member initializer)
+// WARNINGS-NEXT: 11: (CXXConstructExpr, class A)
+// ANALYZER-NEXT: 11: (CXXConstructExpr, [B1.12], class A)
+// CHECK-NEXT: 12: A a;
// CHECK-NEXT: Preds (2): B2 B3
// CHECK-NEXT: Succs (1): B0
// CHECK: [B2]
diff --git a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
index d08b01cd396..5b16915ae6f 100644
--- a/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
+++ b/clang/test/Analysis/temp-obj-dtors-cfg-output.cpp
@@ -1224,8 +1224,7 @@ const C &bar3(bool coin) {
// CHECK: 16: a([B1.15]) (Member initializer)
// CHECK: 17: ~B() (Temporary object destructor)
// CHECK: 18: ~A() (Temporary object destructor)
-// CHECK: 19: /*implicit*/(int)0
-// CHECK: 20: b([B1.19]) (Member initializer)
+// CHECK: 19: b(/*implicit*/(int)0) (Member initializer)
// CHECK: Preds (1): B2
// CHECK: Succs (1): B0
// CHECK: [B0 (EXIT)]
OpenPOWER on IntegriCloud