Szelethus updated this revision to Diff 177182.
Szelethus retitled this revision from "[analyzer][WIP] Reimplement dependencies 
between checkers" to "[analyzer] Reimplement dependencies between checkers".
Szelethus edited the summary of this revision.
Szelethus added reviewers: MTC, baloghadamsoftware.
Szelethus added a comment.
This revision is now accepted and ready to land.

- No longer splitting up `InnerPointerChecker`
- After spending a lot of more time with the checker files, and adding various 
asserts in followup patches, realize that dependencies in between checkers are 
far, //far// more common than anticipated. I find it really cool that this is 
clearly visible now from the tblgen file. Add the following new checkers:
  - `StackAddrEscapeBase`
  - `StackAddrEscapeBase`
  - `CStringModeling`
  - `DynamicMemoryModeling` (base of the `MallocChecker` family)
  - `IteratorModeling` (base of the `IteratorChecker` family)
  - `ValistBase`
  - `SecuritySyntaxChecker` (base of `bcmp`, `bcopy`, etc...)
  - `NSOrCFErrorDerefChecker` (base of `NSErrorChecker` and  `CFErrorChecker`)
  - `IvarInvalidationModeling` (base of `IvarInvalidation` checker family)
- Make sure checkers are only enabled if all of their dependencies can be 
enabled
- Put strong emphasis on preserving the order of insertions when collecting 
enabled checkers
- It is no longer possible to enable `CallAndMessageUnInitRefArg` without 
`CallAndMessageChecker`. Disabling core checkers isn't supported anyways.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D54438/new/

https://reviews.llvm.org/D54438

Files:
  include/clang/StaticAnalyzer/Checkers/CheckerBase.td
  include/clang/StaticAnalyzer/Checkers/Checkers.td
  include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
  lib/StaticAnalyzer/Checkers/CStringChecker.cpp
  lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
  lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
  lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
  lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
  lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
  lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
  lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
  lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
  lib/StaticAnalyzer/Checkers/ValistChecker.cpp
  lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
  test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
  test/Analysis/NewDelete-checker-test.cpp
  utils/TableGen/ClangSACheckersEmitter.cpp

Index: utils/TableGen/ClangSACheckersEmitter.cpp
===================================================================
--- utils/TableGen/ClangSACheckersEmitter.cpp
+++ utils/TableGen/ClangSACheckersEmitter.cpp
@@ -57,6 +57,13 @@
   return std::string();
 }
 
+static void printChecker(llvm::raw_ostream &OS, const Record &R) {
+  OS << '\"';
+  OS.write_escaped(getCheckerFullName(&R)) << "\", ";
+  OS << R.getName() << ", \"";
+  OS.write_escaped(getStringValue(R, "HelpText")) << '\"';
+}
+
 namespace clang {
 void EmitClangSACheckers(RecordKeeper &Records, raw_ostream &OS) {
   std::vector<Record*> checkers = Records.getAllDerivedDefinitions("Checker");
@@ -64,7 +71,12 @@
 
   using SortedRecords = llvm::StringMap<const Record *>;
 
-  OS << "\n#ifdef GET_PACKAGES\n";
+  // Emit packages.
+  //
+  // PACKAGE(PACKAGENAME)
+  //   - PACKAGENAME: The name of the package.
+  OS << "\n"
+        "#ifdef GET_PACKAGES\n";
   {
     SortedRecords sortedPackages;
     for (unsigned i = 0, e = packages.size(); i != e; ++i)
@@ -79,19 +91,51 @@
       OS << ")\n";
     }
   }
-  OS << "#endif // GET_PACKAGES\n\n";
-  
-  OS << "\n#ifdef GET_CHECKERS\n";
-  for (unsigned i = 0, e = checkers.size(); i != e; ++i) {
-    const Record &R = *checkers[i];
+  OS << "#endif // GET_PACKAGES\n"
+        "\n";
 
-    OS << "CHECKER(" << "\"";
-    OS.write_escaped(getCheckerFullName(&R)) << "\", ";
-    OS << R.getName() << ", ";
-    OS << "\"";
-    OS.write_escaped(getStringValue(R, "HelpText")) << '\"';
+  // Emit checkers.
+  //
+  // CHECKER(FULLNAME, CLASS, HELPTEXT)
+  //   - FULLNAME: The full name of the checker, including packages, e.g.:
+  //               alpha.cplusplus.UninitializedObject
+  //   - CLASS: The name of the checker, with "Checker" appended, e.g.:
+  //            UninitializedObjectChecker
+  //   - HELPTEXT: The description of the checker.
+  OS << "\n"
+        "#ifdef GET_CHECKERS\n"
+        "\n";
+  for (const Record *checker : checkers) {
+    OS << "CHECKER(";
+    printChecker(OS, *checker);
     OS << ")\n";
   }
-  OS << "#endif // GET_CHECKERS\n\n";
+  OS << "\n"
+        "#endif // GET_CHECKERS\n"
+        "\n";
+
+  // Emit dependencies.
+  //
+  // CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)
+  //   - FULLNAME: The full name of the checker that depends on another checker.
+  //   - DEPENDENCY: The full name of the checker FULLNAME depends on.
+  OS << "\n"
+        "#ifdef GET_CHECKER_DEPENDENCIES\n";
+  for (const Record *checker : checkers) {
+    if (checker->isValueUnset("Dependencies"))
+      continue;
+
+    for (const Record *Dependency :
+                            checker->getValueAsListOfDefs("Dependencies")) {
+      OS << "CHECKER_DEPENDENCY(";
+      OS << '\"';
+      OS.write_escaped(getCheckerFullName(checker)) << "\", ";
+      OS << '\"';
+      OS.write_escaped(getCheckerFullName(Dependency)) << '\"';
+      OS << ")\n";
+    }
+  }
+  OS << "\n"
+        "#endif // GET_CHECKER_DEPENDENCIES\n";
 }
 } // end namespace clang
Index: test/Analysis/NewDelete-checker-test.cpp
===================================================================
--- test/Analysis/NewDelete-checker-test.cpp
+++ test/Analysis/NewDelete-checker-test.cpp
@@ -1,11 +1,42 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -DTEST_INLINABLE_ALLOCATORS -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDeleteLeaks -DLEAKS -std=c++11 -fblocks -analyzer-config c++-allocator-inlining=true -DTEST_INLINABLE_ALLOCATORS -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDelete
+//
+// RUN: %clang_analyze_cc1 -DLEAKS -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDeleteLeaks
+//
+// RUN: %clang_analyze_cc1 -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDelete \
+// RUN:   -analyzer-config c++-allocator-inlining=true
+//
+// RUN: %clang_analyze_cc1 -DLEAKS -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDeleteLeaks \
+// RUN:   -analyzer-config c++-allocator-inlining=true
+//
+// RUN: %clang_analyze_cc1 -DTEST_INLINABLE_ALLOCATORS \
+// RUN:   -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDelete
+//
+// RUN: %clang_analyze_cc1 -DLEAKS -DTEST_INLINABLE_ALLOCATORS \
+// RUN:   -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDeleteLeaks
+//
+// RUN: %clang_analyze_cc1 -DTEST_INLINABLE_ALLOCATORS \
+// RUN:   -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDelete \
+// RUN:   -analyzer-config c++-allocator-inlining=true
+//
+// RUN: %clang_analyze_cc1 -DLEAKS -DTEST_INLINABLE_ALLOCATORS \
+// RUN:   -std=c++11 -fblocks -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDeleteLeaks \
+// RUN:   -analyzer-config c++-allocator-inlining=true
 
 #include "Inputs/system-header-simulator-cxx.h"
 
Index: test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
===================================================================
--- test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
+++ test/Analysis/NewDelete+MismatchedDeallocator_intersections.cpp
@@ -1,5 +1,14 @@
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,unix.MismatchedDeallocator -std=c++11 -verify %s
-// RUN: %clang_analyze_cc1 -analyzer-checker=core,cplusplus.NewDelete,cplusplus.NewDeleteLeaks,unix.MismatchedDeallocator -DLEAKS -std=c++11 -verify %s
+// RUN: %clang_analyze_cc1 -std=c++11 -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDelete \
+// RUN:   -analyzer-checker=unix.MismatchedDeallocator
+//
+// RUN: %clang_analyze_cc1 -std=c++11 -verify %s \
+// RUN:   -analyzer-checker=core \
+// RUN:   -analyzer-checker=cplusplus.NewDelete \
+// RUN:   -analyzer-checker=cplusplus.NewDeleteLeaks \
+// RUN:   -analyzer-checker=unix.MismatchedDeallocator
+
 // expected-no-diagnostics
 
 typedef __typeof(sizeof(int)) size_t;
Index: lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
===================================================================
--- lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
+++ lib/StaticAnalyzer/Frontend/CheckerRegistry.cpp
@@ -38,14 +38,21 @@
   return strcmp(versionString, CLANG_ANALYZER_API_VERSION_STRING) == 0;
 }
 
+static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
+                          const CheckerRegistry::CheckerInfo &b) {
+  return a.FullName < b.FullName;
+}
+
 CheckerRegistry::CheckerRegistry(ArrayRef<std::string> plugins,
                                  DiagnosticsEngine &diags,
                                  const LangOptions &LangOpts)
   : Diags(diags), LangOpts(LangOpts) {
 
 #define GET_CHECKERS
+
 #define CHECKER(FULLNAME, CLASS, HELPTEXT)                                     \
   addChecker(register##CLASS, shouldRegister##CLASS, FULLNAME, HELPTEXT);
+
 #include "clang/StaticAnalyzer/Checkers/Checkers.inc"
 #undef CHECKER
 #undef GET_CHECKERS
@@ -79,15 +86,21 @@
     if (registerPluginCheckers)
       registerPluginCheckers(*this);
   }
-}
 
-static constexpr char PackageSeparator = '.';
+  llvm::sort(Checkers, checkerNameLT);
 
-static bool checkerNameLT(const CheckerRegistry::CheckerInfo &a,
-                          const CheckerRegistry::CheckerInfo &b) {
-  return a.FullName < b.FullName;
+#define GET_CHECKER_DEPENDENCIES
+
+#define CHECKER_DEPENDENCY(FULLNAME, DEPENDENCY)                               \
+  addDependency(FULLNAME, DEPENDENCY);
+
+#include "clang/StaticAnalyzer/Checkers/Checkers.inc"
+#undef CHECKER_DEPENDENCY
+#undef GET_CHECKER_DEPENDENCIES
 }
 
+static constexpr char PackageSeparator = '.';
+
 static bool isInPackage(const CheckerRegistry::CheckerInfo &checker,
                         StringRef packageName) {
   // Does the checker's full name have the package as a prefix?
@@ -105,9 +118,48 @@
   return false;
 }
 
+/// Collects dependencies in \p ret, returns false on failure.
+static bool collectDependenciesImpl(
+                              const CheckerRegistry::ConstCheckerInfoList &deps,
+                              const LangOptions &LO,
+                              CheckerRegistry::CheckerInfoSet &ret);
+
+/// Collects dependenies in \p enabledCheckers. Return None on failure.
+LLVM_NODISCARD
+static llvm::Optional<CheckerRegistry::CheckerInfoSet> collectDependencies(
+     const CheckerRegistry::CheckerInfo &checker, const LangOptions &LO) {
+
+  CheckerRegistry::CheckerInfoSet ret;
+  // Add dependencies to the enabled checkers only if all of them can be
+  // enabled.
+  if (!collectDependenciesImpl(checker.Dependencies, LO, ret))
+    return None;
+
+  return ret;
+}
+
+static bool collectDependenciesImpl(
+                              const CheckerRegistry::ConstCheckerInfoList &deps,
+                              const LangOptions &LO,
+                              CheckerRegistry::CheckerInfoSet &ret) {
+
+  for (const CheckerRegistry::CheckerInfo *dependency : deps) {
+
+    if (!dependency->ShouldRegister(LO))
+      return false;
+
+    // Collect dependencies recursively.
+    if (!collectDependenciesImpl(dependency->Dependencies, LO, ret))
+      return false;
+
+    ret.insert(dependency);
+  }
+
+  return true;
+}
+
 CheckerRegistry::CheckerInfoSet CheckerRegistry::getEnabledCheckers(
                                             const AnalyzerOptions &Opts) const {
-
   assert(std::is_sorted(Checkers.begin(), Checkers.end(), checkerNameLT) &&
          "In order to efficiently gather checkers, this function expects them "
          "to be already sorted!");
@@ -117,7 +169,10 @@
 
   for (const std::pair<std::string, bool> &opt : Opts.CheckersControlList) {
     // Use a binary search to find the possible start of the package.
-    CheckerRegistry::CheckerInfo packageInfo(nullptr, nullptr, opt.first, "");
+    CheckerInfo packageInfo(nullptr, nullptr, opt.first, "");
+
+    assert(std::is_sorted(Checkers.cbegin(), Checkers.cend(), checkerNameLT));
+
     auto firstRelatedChecker =
       std::lower_bound(Checkers.cbegin(), end, packageInfo, checkerNameLT);
 
@@ -139,13 +194,31 @@
 
     // Step through all the checkers in the package.
     for (auto lastRelatedChecker = firstRelatedChecker+size;
-         firstRelatedChecker != lastRelatedChecker; ++firstRelatedChecker)
+         firstRelatedChecker != lastRelatedChecker; ++firstRelatedChecker) {
       if (opt.second) {
-        if (firstRelatedChecker->ShouldRegister(LangOpts))
-          enabledCheckers.insert(&*firstRelatedChecker);
+        if (!firstRelatedChecker->ShouldRegister(LangOpts))
+          continue;
+
+        // Recursively enable it's dependencies.
+        llvm::Optional<CheckerInfoSet> deps =
+            collectDependencies(*firstRelatedChecker, LangOpts);
+
+        if (!deps) {
+          // If we failed to enable any of the dependencies, don't enable this
+          // checker.
+          continue;
+        }
+
+        // Enable the checker.
+        enabledCheckers.insert(&*firstRelatedChecker);
+
+        // Note that set_union also preserves the order of insertion.
+        enabledCheckers.set_union(*deps);
       } else {
+        // Disable the checker.
         enabledCheckers.remove(&*firstRelatedChecker);
       }
+    }
   }
 
   return enabledCheckers;
@@ -167,9 +240,6 @@
 
 void CheckerRegistry::initializeManager(CheckerManager &checkerMgr,
                                         const AnalyzerOptions &Opts) const {
-  // Sort checkers for efficient collection.
-  llvm::sort(Checkers, checkerNameLT);
-
   // Collect checkers enabled by the options.
   CheckerInfoSet enabledCheckers = getEnabledCheckers(Opts);
 
@@ -206,8 +276,6 @@
   // FIXME: Alphabetical sort puts 'experimental' in the middle.
   // Would it be better to name it '~experimental' or something else
   // that's ASCIIbetically last?
-  llvm::sort(Checkers, checkerNameLT);
-
   // FIXME: Print available packages.
 
   out << "CHECKERS:\n";
@@ -241,9 +309,6 @@
 
 void CheckerRegistry::printList(raw_ostream &out,
                                 const AnalyzerOptions &opts) const {
-  // Sort checkers for efficient collection.
-  llvm::sort(Checkers, checkerNameLT);
-
   // Collect checkers enabled by the options.
   CheckerInfoSet enabledCheckers = getEnabledCheckers(opts);
 
Index: lib/StaticAnalyzer/Checkers/ValistChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/ValistChecker.cpp
+++ lib/StaticAnalyzer/Checkers/ValistChecker.cpp
@@ -400,6 +400,14 @@
   return std::make_shared<PathDiagnosticEventPiece>(Pos, Msg, true);
 }
 
+void ento::registerValistBase(CheckerManager &mgr) {
+  mgr.registerChecker<ValistChecker>();
+}
+
+bool ento::shouldRegisterValistBase(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name)                                                 \
   void ento::register##name##Checker(CheckerManager &mgr) {                    \
     ValistChecker *checker = mgr.registerChecker<ValistChecker>();             \
Index: lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -360,6 +360,14 @@
   }
 }
 
+void ento::registerStackAddrEscapeBase(CheckerManager &mgr) {
+  mgr.registerChecker<StackAddrEscapeChecker>();
+}
+
+bool ento::shouldRegisterStackAddrEscapeBase(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name) \
   void ento::register##name(CheckerManager &Mgr) { \
     StackAddrEscapeChecker *Chk = \
Index: lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -1182,6 +1182,14 @@
   }
 }
 
+void ento::registerNullabilityBase(CheckerManager &mgr) {
+  mgr.registerChecker<NullabilityChecker>();
+}
+
+bool ento::shouldRegisterNullabilityBase(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name, trackingRequired)                               \
   void ento::register##name##Checker(CheckerManager &mgr) {                    \
     NullabilityChecker *checker = mgr.registerChecker<NullabilityChecker>();   \
Index: lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
+++ lib/StaticAnalyzer/Checkers/NSErrorChecker.cpp
@@ -308,6 +308,14 @@
   return TT->getDecl()->getIdentifier() == II;
 }
 
+void ento::registerNSOrCFErrorDerefChecker(CheckerManager &mgr) {
+  mgr.registerChecker<NSOrCFErrorDerefChecker>();
+}
+
+bool ento::shouldRegisterNSOrCFErrorDerefChecker(const LangOptions &LO) {
+  return true;
+}
+
 void ento::registerNSErrorChecker(CheckerManager &mgr) {
   mgr.registerChecker<NSErrorMethodChecker>();
   NSOrCFErrorDerefChecker *checker =
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -3087,33 +3087,9 @@
 } // end namespace ento
 } // end namespace clang
 
-void ento::registerNewDeleteLeaksChecker(CheckerManager &mgr) {
-  registerCStringCheckerBasic(mgr);
-  MallocChecker *checker = mgr.registerChecker<MallocChecker>();
-  checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption(
-      "Optimistic", false, checker);
-  checker->ChecksEnabled[MallocChecker::CK_NewDeleteLeaksChecker] = true;
-  checker->CheckNames[MallocChecker::CK_NewDeleteLeaksChecker] =
-      mgr.getCurrentCheckName();
-  // We currently treat NewDeleteLeaks checker as a subchecker of NewDelete
-  // checker.
-  if (!checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker]) {
-    checker->ChecksEnabled[MallocChecker::CK_NewDeleteChecker] = true;
-    // FIXME: This does not set the correct name, but without this workaround
-    //        no name will be set at all.
-    checker->CheckNames[MallocChecker::CK_NewDeleteChecker] =
-        mgr.getCurrentCheckName();
-  }
-}
-
-bool ento::shouldRegisterNewDeleteLeaksChecker(const LangOptions &LO) {
-  return true;
-}
-
 // Intended to be used in InnerPointerChecker to register the part of
 // MallocChecker connected to it.
 void ento::registerInnerPointerCheckerAux(CheckerManager &mgr) {
-    registerCStringCheckerBasic(mgr);
     MallocChecker *checker = mgr.registerChecker<MallocChecker>();
     checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption(
         "Optimistic", false, checker);
@@ -3122,9 +3098,16 @@
         mgr.getCurrentCheckName();
 }
 
+void ento::registerDynamicMemoryModeling(CheckerManager &mgr) {
+  mgr.registerChecker<MallocChecker>();
+}
+
+bool ento::shouldRegisterDynamicMemoryModeling(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name)                                                 \
   void ento::register##name(CheckerManager &mgr) {                             \
-    registerCStringCheckerBasic(mgr);                                          \
     MallocChecker *checker = mgr.registerChecker<MallocChecker>();             \
     checker->IsOptimistic = mgr.getAnalyzerOptions().getCheckerBooleanOption(  \
         "Optimistic", false, checker);                                         \
@@ -3138,4 +3121,5 @@
 
 REGISTER_CHECKER(MallocChecker)
 REGISTER_CHECKER(NewDeleteChecker)
+REGISTER_CHECKER(NewDeleteLeaksChecker)
 REGISTER_CHECKER(MismatchedDeallocatorChecker)
Index: lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
+++ lib/StaticAnalyzer/Checkers/IvarInvalidationChecker.cpp
@@ -736,6 +736,14 @@
 };
 } // end anonymous namespace
 
+void ento::registerIvarInvalidationModeling(CheckerManager &mgr) {
+  mgr.registerChecker<IvarInvalidationChecker>();
+}
+
+bool ento::shouldRegisterIvarInvalidationModeling(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name)                                                 \
   void ento::register##name(CheckerManager &mgr) {                             \
     IvarInvalidationChecker *checker =                                         \
Index: lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
+++ lib/StaticAnalyzer/Checkers/IteratorChecker.cpp
@@ -2349,6 +2349,14 @@
 
 } // namespace
 
+void ento::registerIteratorModeling(CheckerManager &mgr) {
+  mgr.registerChecker<IteratorChecker>();
+}
+
+bool ento::shouldRegisterIteratorModeling(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name)                                                 \
   void ento::register##name(CheckerManager &Mgr) {                             \
     auto *checker = Mgr.registerChecker<IteratorChecker>();                    \
Index: lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
===================================================================
--- lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
+++ lib/StaticAnalyzer/Checkers/InterCheckerAPI.h
@@ -17,9 +17,6 @@
 
 namespace ento {
 
-/// Register the checker which evaluates CString API calls.
-void registerCStringCheckerBasic(CheckerManager &Mgr);
-
 /// Register the part of MallocChecker connected to InnerPointerChecker.
 void registerInnerPointerCheckerAux(CheckerManager &Mgr);
 
Index: lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
+++ lib/StaticAnalyzer/Checkers/CheckSecuritySyntaxOnly.cpp
@@ -905,6 +905,14 @@
 };
 }
 
+void ento::registerSecuritySyntaxChecker(CheckerManager &mgr) {
+  mgr.registerChecker<SecuritySyntaxChecker>();
+}
+
+bool ento::shouldRegisterSecuritySyntaxChecker(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name)                                                 \
   void ento::register##name(CheckerManager &mgr) {                             \
     SecuritySyntaxChecker *checker =                                           \
Index: lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp
@@ -29,14 +29,6 @@
 
 namespace {
 
-struct ChecksFilter {
-  DefaultBool Check_CallAndMessageUnInitRefArg;
-  DefaultBool Check_CallAndMessageChecker;
-
-  CheckName CheckName_CallAndMessageUnInitRefArg;
-  CheckName CheckName_CallAndMessageChecker;
-};
-
 class CallAndMessageChecker
   : public Checker< check::PreStmt<CallExpr>,
                     check::PreStmt<CXXDeleteExpr>,
@@ -57,7 +49,8 @@
   mutable std::unique_ptr<BugType> BT_call_few_args;
 
 public:
-  ChecksFilter Filter;
+  DefaultBool Check_CallAndMessageUnInitRefArg;
+  CheckName CheckName_CallAndMessageUnInitRefArg;
 
   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
   void checkPreStmt(const CXXDeleteExpr *DE, CheckerContext &C) const;
@@ -152,7 +145,7 @@
     CheckerContext &C, const SVal &V, SourceRange ArgRange, const Expr *ArgEx,
     std::unique_ptr<BugType> &BT, const ParmVarDecl *ParamDecl, const char *BD,
     int ArgumentNumber) const {
-  if (!Filter.Check_CallAndMessageUnInitRefArg)
+  if (!Check_CallAndMessageUnInitRefArg)
     return false;
 
   // No parameter declaration available, i.e. variadic function argument.
@@ -608,17 +601,21 @@
   C.addTransition(state);
 }
 
-#define REGISTER_CHECKER(name)                                                 \
-  void ento::register##name(CheckerManager &mgr) {                             \
-    CallAndMessageChecker *Checker =                                           \
-        mgr.registerChecker<CallAndMessageChecker>();                          \
-    Checker->Filter.Check_##name = true;                                       \
-    Checker->Filter.CheckName_##name = mgr.getCurrentCheckName();              \
-  }                                                                            \
-                                                                               \
-  bool ento::shouldRegister##name(const LangOptions &LO) {                     \
-    return true;                                                               \
-  }
+void ento::registerCallAndMessageChecker(CheckerManager &mgr) {
+  mgr.registerChecker<CallAndMessageChecker>();
+}
+
+bool ento::shouldRegisterCallAndMessageChecker(const LangOptions &LO) {
+  return true;
+}
 
-REGISTER_CHECKER(CallAndMessageUnInitRefArg)
-REGISTER_CHECKER(CallAndMessageChecker)
+void ento::registerCallAndMessageUnInitRefArg(CheckerManager &mgr) {
+  CallAndMessageChecker *Checker =
+      mgr.registerChecker<CallAndMessageChecker>();
+  Checker->Check_CallAndMessageUnInitRefArg = true;
+  Checker->CheckName_CallAndMessageUnInitRefArg = mgr.getCurrentCheckName();
+}
+
+bool ento::shouldRegisterCallAndMessageUnInitRefArg(const LangOptions &LO) {
+  return true;
+}
Index: lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -2404,6 +2404,14 @@
   C.addTransition(state);
 }
 
+void ento::registerCStringModeling(CheckerManager &Mgr) {
+  Mgr.registerChecker<CStringChecker>();
+}
+
+bool ento::shouldRegisterCStringModeling(const LangOptions &LO) {
+  return true;
+}
+
 #define REGISTER_CHECKER(name)                                                 \
   void ento::register##name(CheckerManager &mgr) {                             \
     CStringChecker *checker = mgr.registerChecker<CStringChecker>();           \
@@ -2419,7 +2427,3 @@
   REGISTER_CHECKER(CStringOutOfBounds)
   REGISTER_CHECKER(CStringBufferOverlap)
 REGISTER_CHECKER(CStringNotNullTerm)
-
-  void ento::registerCStringCheckerBasic(CheckerManager &Mgr) {
-    Mgr.registerChecker<CStringChecker>();
-  }
Index: include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
===================================================================
--- include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
+++ include/clang/StaticAnalyzer/Frontend/CheckerRegistry.h
@@ -90,20 +90,24 @@
   using InitializationFunction = void (*)(CheckerManager &);
   using ShouldRegisterFunction = bool (*)(const LangOptions &);
 
+  struct CheckerInfo;
+
+  using CheckerInfoList = std::vector<CheckerInfo>;
+  using ConstCheckerInfoList = llvm::SmallVector<const CheckerInfo *, 0>;
+  using CheckerInfoSet = llvm::SetVector<const CheckerInfo *>;
+
   struct CheckerInfo {
     InitializationFunction Initialize;
     ShouldRegisterFunction ShouldRegister;
     StringRef FullName;
     StringRef Desc;
+    llvm::SmallVector<const CheckerInfo *, 0> Dependencies;
 
     CheckerInfo(InitializationFunction rfn, ShouldRegisterFunction sfn,
                 StringRef name, StringRef desc)
         : Initialize(rfn), ShouldRegister(sfn), FullName(name), Desc(desc) {}
   };
 
-  using CheckerInfoList = std::vector<CheckerInfo>;
-  using CheckerInfoSet = llvm::SetVector<const CheckerRegistry::CheckerInfo *>;
-
 private:
   template <typename T>
   static void initializeManager(CheckerManager &mgr) {
@@ -132,6 +136,28 @@
                &CheckerRegistry::returnTrue<T>, fullName, desc);
   }
 
+  /// Makes the checker with the full name \p fullName depends on the checker
+  /// called \p dependency.
+  void addDependency(StringRef fullName, StringRef dependency) {
+    auto CheckerThatNeedsDeps =
+       [&fullName](const CheckerInfo &Chk) { return Chk.FullName == fullName; };
+    auto Dependency =
+      [&dependency](const CheckerInfo &Chk) {
+        return Chk.FullName == dependency;
+      };
+
+    auto CheckerIt = llvm::find_if(Checkers, CheckerThatNeedsDeps);
+    assert(CheckerIt != Checkers.end() &&
+           "Failed to find the checker while attempting to set up it's "
+           "dependencies!");
+
+    auto DependencyIt = llvm::find_if(Checkers, Dependency);
+    assert(DependencyIt != Checkers.end() &&
+           "Failed to find the dependency of a checker!");
+
+    CheckerIt->Dependencies.push_back(&*DependencyIt);
+  }
+
   /// Initializes a CheckerManager by calling the initialization functions for
   /// all checkers specified by the given CheckerOptInfo list. The order of this
   /// list is significant; later options can be used to reverse earlier ones.
@@ -148,10 +174,13 @@
   void printList(raw_ostream &out, const AnalyzerOptions &opts) const;
 
 private:
+  /// Collect all enabled checkers. The returned container preserves the order
+  /// of insertion, as dependencies have to be enabled before the checkers that
+  /// depend on them.
   CheckerInfoSet getEnabledCheckers(const AnalyzerOptions &Opts) const;
 
-  mutable CheckerInfoList Checkers;
-  mutable llvm::StringMap<size_t> Packages;
+  CheckerInfoList Checkers;
+  llvm::StringMap<size_t> Packages;
 
   DiagnosticsEngine &Diags;
   const LangOptions &LangOpts;
Index: include/clang/StaticAnalyzer/Checkers/Checkers.td
===================================================================
--- include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -122,8 +122,12 @@
 def UndefResultChecker : Checker<"UndefinedBinaryOperatorResult">,
   HelpText<"Check for undefined results of binary operators">;
 
+def StackAddrEscapeBase : Checker<"StackAddrEscapeBase">,
+  HelpText<"Generate information about stack address escapes.">;
+
 def StackAddrEscapeChecker : Checker<"StackAddressEscape">,
-  HelpText<"Check that addresses to stack memory do not escape the function">;
+  HelpText<"Check that addresses to stack memory do not escape the function">,
+  Dependencies<[StackAddrEscapeBase]>;
 
 def DynamicTypePropagation : Checker<"DynamicTypePropagation">,
   HelpText<"Generate dynamic type information">;
@@ -168,7 +172,8 @@
 def CallAndMessageUnInitRefArg : Checker<"CallAndMessageUnInitRefArg">,
   HelpText<"Check for logical errors for function calls and Objective-C "
            "message expressions (e.g., uninitialized arguments, null function "
-           "pointers, and pointer to undefined variables)">;
+           "pointers, and pointer to undefined variables)">,
+  Dependencies<[CallAndMessageChecker]>;
 
 def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
   HelpText<"Check for division by variable that is later compared against 0. "
@@ -179,33 +184,50 @@
            "are unrelated.">;
 
 def StackAddrAsyncEscapeChecker : Checker<"StackAddressAsyncEscape">,
-  HelpText<"Check that addresses to stack memory do not escape the function">;
+  HelpText<"Check that addresses to stack memory do not escape the function">,
+  Dependencies<[StackAddrEscapeBase]>;
 
 } // end "alpha.core"
 
+//===----------------------------------------------------------------------===//
+// Nullability checkers.
+//===----------------------------------------------------------------------===//
+
 let ParentPackage = Nullability in {
 
+def NullabilityBase : Checker<"NullabilityBase">,
+  HelpText<"Stores information during the analysis about nullability.">;
+
 def NullPassedToNonnullChecker : Checker<"NullPassedToNonnull">,
   HelpText<"Warns when a null pointer is passed to a pointer which has a "
-           "_Nonnull type.">;
+           "_Nonnull type.">,
+  Dependencies<[NullabilityBase]>;
 
 def NullReturnedFromNonnullChecker : Checker<"NullReturnedFromNonnull">,
   HelpText<"Warns when a null pointer is returned from a function that has "
-           "_Nonnull return type.">;
+           "_Nonnull return type.">,
+  Dependencies<[NullabilityBase]>;
 
 def NullableDereferencedChecker : Checker<"NullableDereferenced">,
-  HelpText<"Warns when a nullable pointer is dereferenced.">;
+  HelpText<"Warns when a nullable pointer is dereferenced.">,
+  Dependencies<[NullabilityBase]>;
 
 def NullablePassedToNonnullChecker : Checker<"NullablePassedToNonnull">,
   HelpText<"Warns when a nullable pointer is passed to a pointer which has a "
-           "_Nonnull type.">;
+           "_Nonnull type.">,
+  Dependencies<[NullabilityBase]>;
 
 def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">,
   HelpText<"Warns when a nullable pointer is returned from a function that has "
-           "_Nonnull return type.">;
+           "_Nonnull return type.">,
+  Dependencies<[NullabilityBase]>;
 
 } // end "nullability"
 
+//===----------------------------------------------------------------------===//
+// APIModeling.
+//===----------------------------------------------------------------------===//
+
 let ParentPackage = APIModeling in {
 
 def StdCLibraryFunctionsChecker : Checker<"StdCLibraryFunctions">,
@@ -255,22 +277,111 @@
 
 } // end "core.uninitialized"
 
+//===----------------------------------------------------------------------===//
+// Unix API checkers.
+//===----------------------------------------------------------------------===//
+
+let ParentPackage = UnixAlpha in {
+
+def ChrootChecker : Checker<"Chroot">,
+  HelpText<"Check improper use of chroot">;
+
+def PthreadLockChecker : Checker<"PthreadLock">,
+  HelpText<"Simple lock -> unlock checker">;
+
+def StreamChecker : Checker<"Stream">,
+  HelpText<"Check stream handling functions">;
+
+def SimpleStreamChecker : Checker<"SimpleStream">,
+  HelpText<"Check for misuses of stream APIs">;
+
+def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
+  HelpText<"Check for calls to blocking functions inside a critical section">;
+
+} // end "alpha.unix"
+
+let ParentPackage = CString in {
+
+def CStringModeling : Checker<"CStringModeling">,
+  HelpText<"The base of several CString related checkers. On it's own it emits "
+           "no reports, but adds valuable information to the analysis when "
+           "enabled.">;
+
+def CStringNullArg : Checker<"NullArg">,
+  HelpText<"Check for null pointers being passed as arguments to C string "
+           "functions">,
+  Dependencies<[CStringModeling]>;
+
+def CStringSyntaxChecker : Checker<"BadSizeArg">,
+  HelpText<"Check the size argument passed into C string functions for common "
+           "erroneous patterns">,
+  Dependencies<[CStringModeling]>;
+
+} // end "unix.cstring"
+
+let ParentPackage = CStringAlpha in {
+
+def CStringOutOfBounds : Checker<"OutOfBounds">,
+  HelpText<"Check for out-of-bounds access in string functions">,
+  Dependencies<[CStringModeling]>;
+
+def CStringBufferOverlap : Checker<"BufferOverlap">,
+  HelpText<"Checks for overlap in two buffer arguments">,
+  Dependencies<[CStringModeling]>;
+
+def CStringNotNullTerm : Checker<"NotNullTerminated">,
+  HelpText<"Check for arguments which are not null-terminating strings">,
+  Dependencies<[CStringModeling]>;
+
+} // end "alpha.unix.cstring"
+
+let ParentPackage = Unix in {
+
+def UnixAPIMisuseChecker : Checker<"API">,
+  HelpText<"Check calls to various UNIX/Posix functions">;
+
+def DynamicMemoryModeling: Checker<"DynamicMemoryModeling">,
+  HelpText<"The base of several malloc() related checkers. On it's own it "
+           "emits no reports, but adds valuable information to the analysis "
+           "when enabled.">,
+  Dependencies<[CStringModeling]>;
+
+def MallocChecker: Checker<"Malloc">,
+  HelpText<"Check for memory leaks, double free, and use-after-free problems. "
+           "Traces memory managed by malloc()/free().">,
+  Dependencies<[DynamicMemoryModeling]>;
+
+def MallocSizeofChecker : Checker<"MallocSizeof">,
+  HelpText<"Check for dubious malloc arguments involving sizeof">;
+
+def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">,
+  HelpText<"Check for mismatched deallocators.">,
+  Dependencies<[DynamicMemoryModeling]>;
+
+def VforkChecker : Checker<"Vfork">,
+  HelpText<"Check for proper usage of vfork">;
+
+} // end "unix"
+
 //===----------------------------------------------------------------------===//
 // C++ checkers.
 //===----------------------------------------------------------------------===//
 
 let ParentPackage = Cplusplus in {
 
-def InnerPointerChecker : Checker<"InnerPointer">,
-  HelpText<"Check for inner pointers of C++ containers used after "
-           "re/deallocation">;
-
 def NewDeleteChecker : Checker<"NewDelete">,
   HelpText<"Check for double-free and use-after-free problems. Traces memory "
-           "managed by new/delete.">;
+           "managed by new/delete.">,
+  Dependencies<[DynamicMemoryModeling]>;
+
+def InnerPointerChecker : Checker<"InnerPointer">,
+  HelpText<"Check for inner pointers of C++ containers used after "
+           "re/deallocation">,
+  Dependencies<[DynamicMemoryModeling]>;
 
 def NewDeleteLeaksChecker : Checker<"NewDeleteLeaks">,
-  HelpText<"Check for memory leaks. Traces memory managed by new/delete.">;
+  HelpText<"Check for memory leaks. Traces memory managed by new/delete.">,
+  Dependencies<[NewDeleteChecker]>;
 
 def CXXSelfAssignmentChecker : Checker<"SelfAssignment">,
   HelpText<"Checks C++ copy and move assignment operators for self assignment">;
@@ -293,15 +404,21 @@
 def EnumCastOutOfRangeChecker : Checker<"EnumCastOutOfRange">,
   HelpText<"Check integer to enumeration casts for out of range values">;
 
+def IteratorModeling : Checker<"IteratorModeling">,
+  HelpText<"Models iterators of C++ containers">;
+
 def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
-  HelpText<"Check for use of invalidated iterators">;
+  HelpText<"Check for use of invalidated iterators">,
+  Dependencies<[IteratorModeling]>;
 
 def IteratorRangeChecker : Checker<"IteratorRange">,
-  HelpText<"Check for iterators used outside their valid ranges">;
+  HelpText<"Check for iterators used outside their valid ranges">,
+  Dependencies<[IteratorModeling]>;
 
 def MismatchedIteratorChecker : Checker<"MismatchedIterator">,
   HelpText<"Check for use of iterators of different containers where iterators "
-           "of the same container are expected">;
+           "of the same container are expected">,
+  Dependencies<[IteratorModeling]>;
 
 def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">,
      HelpText<"Method calls on a moved-from object and copying a moved-from "
@@ -319,14 +436,20 @@
 
 let ParentPackage = Valist in {
 
+def ValistBase : Checker<"ValistBase">,
+  HelpText<"Gathers information about va_lists.">;
+
 def UninitializedChecker : Checker<"Uninitialized">,
-  HelpText<"Check for usages of uninitialized (or already released) va_lists.">;
+  HelpText<"Check for usages of uninitialized (or already released) va_lists.">,
+  Dependencies<[ValistBase]>;
 
 def UnterminatedChecker : Checker<"Unterminated">,
-  HelpText<"Check for va_lists which are not released by a va_end call.">;
+  HelpText<"Check for va_lists which are not released by a va_end call.">,
+  Dependencies<[ValistBase]>;
 
 def CopyToSelfChecker : Checker<"CopyToSelf">,
-  HelpText<"Check for va_lists which are copied onto itself.">;
+  HelpText<"Check for va_lists which are copied onto itself.">,
+  Dependencies<[ValistBase]>;
 
 } // end : "valist"
 
@@ -366,30 +489,54 @@
 
 let ParentPackage = InsecureAPI in {
 
+def SecuritySyntaxChecker : Checker<"SecuritySyntaxChecker">,
+  HelpText<"Base of various security function related checkers">;
+
 def bcmp : Checker<"bcmp">,
-  HelpText<"Warn on uses of the 'bcmp' function">;
+  HelpText<"Warn on uses of the 'bcmp' function">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def bcopy : Checker<"bcopy">,
-  HelpText<"Warn on uses of the 'bcopy' function">;
+  HelpText<"Warn on uses of the 'bcopy' function">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def bzero : Checker<"bzero">,
-  HelpText<"Warn on uses of the 'bzero' function">;
+  HelpText<"Warn on uses of the 'bzero' function">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def gets : Checker<"gets">,
-  HelpText<"Warn on uses of the 'gets' function">;
+  HelpText<"Warn on uses of the 'gets' function">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def getpw : Checker<"getpw">,
-  HelpText<"Warn on uses of the 'getpw' function">;
+  HelpText<"Warn on uses of the 'getpw' function">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def mktemp : Checker<"mktemp">,
-  HelpText<"Warn on uses of the 'mktemp' function">;
+  HelpText<"Warn on uses of the 'mktemp' function">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def mkstemp : Checker<"mkstemp">,
   HelpText<"Warn when 'mkstemp' is passed fewer than 6 X's in the format "
-           "string">;
+           "string">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def rand : Checker<"rand">,
-  HelpText<"Warn on uses of the 'rand', 'random', and related functions">;
+  HelpText<"Warn on uses of the 'rand', 'random', and related functions">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def strcpy : Checker<"strcpy">,
-  HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">;
+  HelpText<"Warn on uses of the 'strcpy' and 'strcat' functions">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def vfork : Checker<"vfork">,
-  HelpText<"Warn on uses of the 'vfork' function">;
+  HelpText<"Warn on uses of the 'vfork' function">,
+  Dependencies<[SecuritySyntaxChecker]>;
+
 def UncheckedReturn : Checker<"UncheckedReturn">,
   HelpText<"Warn on uses of functions whose return values must be always "
-           "checked">;
+           "checked">,
+  Dependencies<[SecuritySyntaxChecker]>;
 
 } // end "security.insecureAPI"
 
@@ -434,74 +581,6 @@
 
 } // end "alpha.security.taint"
 
-//===----------------------------------------------------------------------===//
-// Unix API checkers.
-//===----------------------------------------------------------------------===//
-
-let ParentPackage = Unix in {
-
-def UnixAPIMisuseChecker : Checker<"API">,
-  HelpText<"Check calls to various UNIX/Posix functions">;
-
-def MallocChecker: Checker<"Malloc">,
-  HelpText<"Check for memory leaks, double free, and use-after-free problems. "
-           "Traces memory managed by malloc()/free().">;
-
-def MallocSizeofChecker : Checker<"MallocSizeof">,
-  HelpText<"Check for dubious malloc arguments involving sizeof">;
-
-def MismatchedDeallocatorChecker : Checker<"MismatchedDeallocator">,
-  HelpText<"Check for mismatched deallocators.">;
-
-def VforkChecker : Checker<"Vfork">,
-  HelpText<"Check for proper usage of vfork">;
-
-} // end "unix"
-
-let ParentPackage = UnixAlpha in {
-
-def ChrootChecker : Checker<"Chroot">,
-  HelpText<"Check improper use of chroot">;
-
-def PthreadLockChecker : Checker<"PthreadLock">,
-  HelpText<"Simple lock -> unlock checker">;
-
-def StreamChecker : Checker<"Stream">,
-  HelpText<"Check stream handling functions">;
-
-def SimpleStreamChecker : Checker<"SimpleStream">,
-  HelpText<"Check for misuses of stream APIs">;
-
-def BlockInCriticalSectionChecker : Checker<"BlockInCriticalSection">,
-  HelpText<"Check for calls to blocking functions inside a critical section">;
-
-} // end "alpha.unix"
-
-let ParentPackage = CString in {
-
-def CStringNullArg : Checker<"NullArg">,
-  HelpText<"Check for null pointers being passed as arguments to C string "
-           "functions">;
-
-def CStringSyntaxChecker : Checker<"BadSizeArg">,
-  HelpText<"Check the size argument passed into C string functions for common "
-           "erroneous patterns">;
-
-} // end "unix.cstring"
-
-let ParentPackage = CStringAlpha in {
-
-def CStringOutOfBounds : Checker<"OutOfBounds">,
-  HelpText<"Check for out-of-bounds access in string functions">;
-
-def CStringBufferOverlap : Checker<"BufferOverlap">,
-  HelpText<"Checks for overlap in two buffer arguments">;
-
-def CStringNotNullTerm : Checker<"NotNullTerminated">,
-  HelpText<"Check for arguments which are not null-terminating strings">;
-
-} // end "alpha.unix.cstring"
-
 //===----------------------------------------------------------------------===//
 // Mac OS X, Cocoa, and Core Foundation checkers.
 //===----------------------------------------------------------------------===//
@@ -521,6 +600,9 @@
 def ObjCPropertyChecker : Checker<"ObjCProperty">,
   HelpText<"Check for proper uses of Objective-C properties">;
 
+def NSOrCFErrorDerefChecker : Checker<"NSOrCFErrorDerefChecker">,
+  HelpText<"Implementation checker for NSErrorChecker and CFErrorChecker">;
+
 } // end "osx"
 
 let ParentPackage = Cocoa in {
@@ -569,13 +651,15 @@
            "super">;
 
 def NSErrorChecker : Checker<"NSError">,
-  HelpText<"Check usage of NSError** parameters">;
+  HelpText<"Check usage of NSError** parameters">,
+  Dependencies<[NSOrCFErrorDerefChecker]>;
 
 def RetainCountChecker : Checker<"RetainCount">,
   HelpText<"Check for leaks and improper reference count management">;
 
 def ObjCGenericsChecker : Checker<"ObjCGenerics">,
-  HelpText<"Check for type errors when using Objective-C generics">;
+  HelpText<"Check for type errors when using Objective-C generics">,
+  Dependencies<[DynamicTypePropagation]>;
 
 def ObjCDeallocChecker : Checker<"Dealloc">,
   HelpText<"Warn about Objective-C classes that lack a correct implementation "
@@ -599,13 +683,20 @@
 
 let ParentPackage = CocoaAlpha in {
 
+def IvarInvalidationModeling : Checker<"IvarInvalidationModeling">,
+  HelpText<"Gathers information for annotation driven invalidation checking "
+           "for classes that contains a method annotated with "
+           "'objc_instance_variable_invalidator'">;
+
 def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">,
   HelpText<"Check that the invalidatable instance variables are invalidated in "
-           "the methods annotated with objc_instance_variable_invalidator">;
+           "the methods annotated with objc_instance_variable_invalidator">,
+  Dependencies<[IvarInvalidationModeling]>;
 
 def MissingInvalidationMethod : Checker<"MissingInvalidationMethod">,
   HelpText<"Check that the invalidation methods are present in classes that "
-           "contain invalidatable instance variables">;
+           "contain invalidatable instance variables">,
+  Dependencies<[IvarInvalidationModeling]>;
 
 def DirectIvarAssignment : Checker<"DirectIvarAssignment">,
   HelpText<"Check for direct assignments to instance variables">;
@@ -613,7 +704,8 @@
 def DirectIvarAssignmentForAnnotatedFunctions :
   Checker<"DirectIvarAssignmentForAnnotatedFunctions">,
   HelpText<"Check for direct assignments to instance variables in the methods "
-           "annotated with objc_no_direct_instance_variable_assignment">;
+           "annotated with objc_no_direct_instance_variable_assignment">,
+  Dependencies<[DirectIvarAssignment]>;
 
 } // end "alpha.osx.cocoa"
 
@@ -626,7 +718,8 @@
   HelpText<"Check for null arguments to CFRetain/CFRelease/CFMakeCollectable">;
 
 def CFErrorChecker : Checker<"CFError">,
-  HelpText<"Check usage of CFErrorRef* parameters">;
+  HelpText<"Check usage of CFErrorRef* parameters">,
+  Dependencies<[NSOrCFErrorDerefChecker]>;
 
 } // end "osx.coreFoundation"
 
Index: include/clang/StaticAnalyzer/Checkers/CheckerBase.td
===================================================================
--- include/clang/StaticAnalyzer/Checkers/CheckerBase.td
+++ include/clang/StaticAnalyzer/Checkers/CheckerBase.td
@@ -37,8 +37,23 @@
 /// Note that a checker has a name (e.g.: 'NullDereference'), and a fullname,
 /// that is autogenerated with the help of the ParentPackage field, that also
 /// includes package names (e.g.: 'core.NullDereference').
+/// Example:
+///   def DereferenceChecker : Checker<"NullDereference">,
+///     HelpText<"Check for dereferences of null pointers">;
 class Checker<string name = ""> {
-  string      CheckerName = name;
-  string      HelpText;
-  Package ParentPackage;
+  string        CheckerName = name;
+  string        HelpText;
+  Package       ParentPackage;
+  list<Checker> Dependencies;
+}
+
+/// Describes dependencies in between checkers. For example, InnerPointerChecker
+/// relies on information MallocBase gathers.
+/// Example:
+///   def InnerPointerChecker : Checker<"InnerPointer">,
+///     HelpText<"Check for inner pointers of C++ containers used after "
+///              "re/deallocation">,
+///     Dependencies<[MallocBase]>;
+class Dependencies<list<Checker> Deps = []> {
+  list<Checker> Dependencies = Deps;
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to