]> granicus.if.org Git - clang/commitdiff
[analyzer][UninitializedObjectChecker] New flag to turn off dereferencing
authorKristof Umann <dkszelethus@gmail.com>
Tue, 7 Aug 2018 12:55:26 +0000 (12:55 +0000)
committerKristof Umann <dkszelethus@gmail.com>
Tue, 7 Aug 2018 12:55:26 +0000 (12:55 +0000)
Even for a checker being in alpha, some reports about pointees held so little
value to the user that it's safer to disable pointer/reference chasing for now.
It can be enabled with a new flag, in which case checker should function as it
has always been. This can be set with `CheckPointeeInitialization`.

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

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339135 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp
test/Analysis/cxx-uninitialized-object-inheritance.cpp
test/Analysis/cxx-uninitialized-object-no-dereference.cpp [new file with mode: 0644]
test/Analysis/cxx-uninitialized-object-notes-as-warnings.cpp
test/Analysis/cxx-uninitialized-object-ptr-ref.cpp
test/Analysis/cxx-uninitialized-object.cpp

index 398228a9d8871736c93c023660fe8d6bcd5c4c61..2383ecff2295bfe76073df0ee79d51638dca3a3c 100644 (file)
 // This file defines a checker that reports uninitialized fields in objects
 // created after a constructor call.
 //
-// This checker has two options:
+// This checker has several options:
 //   - "Pedantic" (boolean). If its not set or is set to false, the checker
 //     won't emit warnings for objects that don't have at least one initialized
 //     field. This may be set with
 //
-//  `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`.
+//     `-analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true`.
 //
 //   - "NotesAsWarnings" (boolean). If set to true, the checker will emit a
 //     warning for each uninitalized field, as opposed to emitting one warning
 //     per constructor call, and listing the uninitialized fields that belongs
 //     to it in notes. Defaults to false.
 //
-//  `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`.
+//     `-analyzer-config \
+//         alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`.
+//
+//   - "CheckPointeeInitialization" (boolean). If set to false, the checker will
+//     not analyze the pointee of pointer/reference fields, and will only check
+//     whether the object itself is initialized. Defaults to false.
+//
+//     `-analyzer-config \
+//         alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true`.
+//
+//     TODO: With some clever heuristics, some pointers should be dereferenced
+//     by default. For example, if the pointee is constructed within the
+//     constructor call, it's reasonable to say that no external object
+//     references it, and we wouldn't generate multiple report on the same
+//     pointee.
 //
 //===----------------------------------------------------------------------===//
 
@@ -44,6 +58,7 @@ public:
   // These fields will be initialized when registering the checker.
   bool IsPedantic;
   bool ShouldConvertNotesToWarnings;
+  bool CheckPointeeInitialization;
 
   UninitializedObjectChecker()
       : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {}
@@ -109,13 +124,16 @@ class FindUninitializedFields {
   const TypedValueRegion *const ObjectR;
 
   const bool IsPedantic;
+  const bool CheckPointeeInitialization;
+
   bool IsAnyFieldInitialized = false;
 
   UninitFieldSet UninitFields;
 
 public:
   FindUninitializedFields(ProgramStateRef State,
-                          const TypedValueRegion *const R, bool IsPedantic);
+                          const TypedValueRegion *const R, bool IsPedantic,
+                          bool CheckPointeeInitialization);
   const UninitFieldSet &getUninitFields();
 
 private:
@@ -262,8 +280,8 @@ void UninitializedObjectChecker::checkEndFunction(
   if (!Object)
     return;
 
-  FindUninitializedFields F(Context.getState(), Object->getRegion(),
-                            IsPedantic);
+  FindUninitializedFields F(Context.getState(), Object->getRegion(), IsPedantic,
+                            CheckPointeeInitialization);
 
   const UninitFieldSet &UninitFields = F.getUninitFields();
 
@@ -327,8 +345,10 @@ void UninitializedObjectChecker::checkEndFunction(
 //===----------------------------------------------------------------------===//
 
 FindUninitializedFields::FindUninitializedFields(
-    ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic)
-    : State(State), ObjectR(R), IsPedantic(IsPedantic) {}
+    ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic,
+    bool CheckPointeeInitialization)
+    : State(State), ObjectR(R), IsPedantic(IsPedantic),
+      CheckPointeeInitialization(CheckPointeeInitialization) {}
 
 const UninitFieldSet &FindUninitializedFields::getUninitFields() {
   isNonUnionUninit(ObjectR, FieldChainInfo());
@@ -468,6 +488,11 @@ bool FindUninitializedFields::isPointerOrReferenceUninit(
     return addFieldToUninits({LocalChain, FR});
   }
 
+  if (!CheckPointeeInitialization) {
+    IsAnyFieldInitialized = true;
+    return false;
+  }
+
   const FieldDecl *FD = FR->getDecl();
 
   // TODO: The dynamic type of a void pointer may be retrieved with
@@ -685,4 +710,6 @@ void ento::registerUninitializedObjectChecker(CheckerManager &Mgr) {
       "Pedantic", /*DefaultVal*/ false, Chk);
   Chk->ShouldConvertNotesToWarnings = Mgr.getAnalyzerOptions().getBooleanOption(
       "NotesAsWarnings", /*DefaultVal*/ false, Chk);
+  Chk->CheckPointeeInitialization = Mgr.getAnalyzerOptions().getBooleanOption(
+      "CheckPointeeInitialization", /*DefaultVal*/ false, Chk);
 }
index 3b048b759e13b5fcfedbfff10b23e2e01d0e3f26..9f6d2a0e71de5a92a1c2b2313fc052ac1cf83cfb 100644 (file)
@@ -1,4 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
+// RUN: -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN: -std=c++11 -verify  %s
 
 //===----------------------------------------------------------------------===//
 // Non-polymorphic inheritance tests
diff --git a/test/Analysis/cxx-uninitialized-object-no-dereference.cpp b/test/Analysis/cxx-uninitialized-object-no-dereference.cpp
new file mode 100644 (file)
index 0000000..0309c28
--- /dev/null
@@ -0,0 +1,27 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN:   -std=c++11 -DPEDANTIC -verify %s
+
+class UninitPointerTest {
+  int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}}
+  int dontGetFilteredByNonPedanticMode = 0;
+
+public:
+  UninitPointerTest() {} // expected-warning{{1 uninitialized field}}
+};
+
+void fUninitPointerTest() {
+  UninitPointerTest();
+}
+
+class UninitPointeeTest {
+  int *ptr; // no-note
+  int dontGetFilteredByNonPedanticMode = 0;
+
+public:
+  UninitPointeeTest(int *ptr) : ptr(ptr) {} // no-warning
+};
+
+void fUninitPointeeTest() {
+  int a;
+  UninitPointeeTest t(&a);
+}
index a49507a1aa5d37b28f013e859dcf526d2907892b..2a5fcbc923902118a4f5dcea9c703f1354afffd7 100644 (file)
@@ -1,4 +1,7 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN:   -std=c++11 -verify %s
 
 class NotesAsWarningsTest {
   int a;
index 1507098c5e75718f5262b9338d34a606b8b9a32a..bfffc800bc46372f39613d9977fa2f970f9e6485 100644 (file)
@@ -1,6 +1,11 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
-
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN:   -std=c++11 -verify  %s
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN:   -std=c++11 -verify  %s
 
 //===----------------------------------------------------------------------===//
 // Concrete location tests.
index 39d4a7f80183139be1243ca5e500d4e82cd7aa91..0c5c1c246c4d1fa6b5122e341ad4b412bb4e8cbf 100644 (file)
@@ -1,6 +1,11 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -std=c++11 -DPEDANTIC -verify %s
-
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:Pedantic=true -DPEDANTIC \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN:   -std=c++11 -verify  %s
+
+// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject \
+// RUN:   -analyzer-config alpha.cplusplus.UninitializedObject:CheckPointeeInitialization=true \
+// RUN:   -std=c++11 -verify  %s
 
 //===----------------------------------------------------------------------===//
 // Default constructor test.