NoQ created this revision.
NoQ added reviewers: dcoughlin, xazax.hun, a_sidorin, rnkovacs, 
mikhail.ramalho, Szelethus, baloghadamsoftware, Charusso.
Herald added subscribers: cfe-commits, jdoerfert, dkrupp, donat.nagy, 
a.sidorin, szepet.
Herald added a project: clang.
NoQ added a parent revision: D59573: [analyzer] C++17: PR41142: Ignore 
transparent InitListExprs when finding construction contexts..

When evaluating a transparent `InitListExpr`, eg. `{{{{{{X}}}}}}}` (when it's 
equivalent to a plain `X`), don't try to think of it as of a compound value of 
type `X` that contains an `X` - just think of it as of `X` itself.

I hope this should take care of the remaining problems that i identified in 
D59573 <https://reviews.llvm.org/D59573>, for which this patch is a follow-up.

On second thought, there shouldn't be any correctness problems because of 
multiple inheritance. If there's just one object in the initializer list, it's 
always at offset 0. So i don't think there are going to be any other changes in 
the actual behavior - just less crashes.

There's a chance that i missed other cases when a non-aggregate would be 
accidentally represented as a compound value, but i'm not immediately aware of 
such cases.

Add the original test from https://bugs.llvm.org/show_bug.cgi?id=41142 (the 
top-level recursive call would now evaluate into `Unknown` rather than 
`compoundVal{Unknown}` - which is still worse than the correct `Undefined` 
value, but it's at least not crashing). Btw, once we make sure it's 
`Undefined`, we should probably also add a path note indicating that the 
function returns a garbage value because there's no return statement in it on 
the current execution path.


Repository:
  rC Clang

https://reviews.llvm.org/D59622

Files:
  clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
  clang/test/Analysis/initializer.cpp


Index: clang/test/Analysis/initializer.cpp
===================================================================
--- clang/test/Analysis/initializer.cpp
+++ clang/test/Analysis/initializer.cpp
@@ -1,7 +1,17 @@
-// RUN: %clang_analyze_cc1 
-analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection
 -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 
-analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection
 -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -verify %s
-// RUN: %clang_analyze_cc1 
-analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection
 -analyzer-config c++-inlining=constructors -std=c++11 
-DTEST_INLINABLE_ALLOCATORS -verify %s
-// RUN: %clang_analyze_cc1 
-analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection
 -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 
-DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++11
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++17
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++11\
+// RUN:   -DTEST_INLINABLE_ALLOCATORS
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++17\
+// RUN:   -DTEST_INLINABLE_ALLOCATORS
 
 void clang_analyzer_eval(bool);
 
@@ -232,7 +242,7 @@
 
   D d = {}; // no-crash
 
-#ifdef CPLUSPLUS17
+#if __cplusplus >= 201703L
   C cd = {{}}; // no-crash
   const C &cdl = {{}}; // no-crash
   C &&cdr = {{}}; // no-crash
@@ -260,4 +270,8 @@
 void foo2() {
   C c { coo() }; // no-crash
 }
+
+B foo_recursive() {
+  B b { foo_recursive() };
+}
 } // namespace CXX17_transparent_init_list_exprs
Index: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -702,7 +702,7 @@
   QualType T = getContext().getCanonicalType(IE->getType());
   unsigned NumInitElements = IE->getNumInits();
 
-  if (!IE->isGLValue() &&
+  if (!IE->isGLValue() && !IE->isTransparent() &&
       (T->isArrayType() || T->isRecordType() || T->isVectorType() ||
        T->isAnyComplexType())) {
     llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList();


Index: clang/test/Analysis/initializer.cpp
===================================================================
--- clang/test/Analysis/initializer.cpp
+++ clang/test/Analysis/initializer.cpp
@@ -1,7 +1,17 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++11 -DTEST_INLINABLE_ALLOCATORS -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks,debug.ExprInspection -analyzer-config c++-inlining=constructors -std=c++17 -DCPLUSPLUS17 -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++11
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++17
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++11\
+// RUN:   -DTEST_INLINABLE_ALLOCATORS
+// RUN: %clang_analyze_cc1 -w -verify %s\
+// RUN:   -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\
+// RUN:   -analyzer-checker=debug.ExprInspection -std=c++17\
+// RUN:   -DTEST_INLINABLE_ALLOCATORS
 
 void clang_analyzer_eval(bool);
 
@@ -232,7 +242,7 @@
 
   D d = {}; // no-crash
 
-#ifdef CPLUSPLUS17
+#if __cplusplus >= 201703L
   C cd = {{}}; // no-crash
   const C &cdl = {{}}; // no-crash
   C &&cdr = {{}}; // no-crash
@@ -260,4 +270,8 @@
 void foo2() {
   C c { coo() }; // no-crash
 }
+
+B foo_recursive() {
+  B b { foo_recursive() };
+}
 } // namespace CXX17_transparent_init_list_exprs
Index: clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp
@@ -702,7 +702,7 @@
   QualType T = getContext().getCanonicalType(IE->getType());
   unsigned NumInitElements = IE->getNumInits();
 
-  if (!IE->isGLValue() &&
+  if (!IE->isGLValue() && !IE->isTransparent() &&
       (T->isArrayType() || T->isRecordType() || T->isVectorType() ||
        T->isAnyComplexType())) {
     llvm::ImmutableList<SVal> vals = getBasicVals().getEmptySValList();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to