[analyzer] Move zero-size allocation checks to optin.portability.

This is a new checker package. It contains checkers that highlight
well-documented implementation-defined behavior. Such checkers are only useful
to developers that intend to write portable code. Code that is only compiled for
a single platform should be allowed to rely on this platform's specific
documented behavior.

rdar://problem/30545046

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

llvm-svn: 306396
diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
index 26bf597..7f9a00f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -45,6 +45,8 @@
   mutable Optional<uint64_t> Val_O_CREAT;
 
 public:
+  DefaultBool CheckMisuse, CheckPortability;
+
   void checkPreStmt(const CallExpr *CE, CheckerContext &C) const;
 
   void CheckOpen(CheckerContext &C, const CallExpr *CE) const;
@@ -437,29 +439,42 @@
   if (FName.empty())
     return;
 
-  SubChecker SC =
-    llvm::StringSwitch<SubChecker>(FName)
-      .Case("open", &UnixAPIChecker::CheckOpen)
-      .Case("openat", &UnixAPIChecker::CheckOpenAt)
-      .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
-      .Case("calloc", &UnixAPIChecker::CheckCallocZero)
-      .Case("malloc", &UnixAPIChecker::CheckMallocZero)
-      .Case("realloc", &UnixAPIChecker::CheckReallocZero)
-      .Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
-      .Cases("alloca", "__builtin_alloca", &UnixAPIChecker::CheckAllocaZero)
-      .Case("__builtin_alloca_with_align",
-            &UnixAPIChecker::CheckAllocaWithAlignZero)
-      .Case("valloc", &UnixAPIChecker::CheckVallocZero)
-      .Default(nullptr);
-
-  if (SC)
-    (this->*SC)(C, CE);
+  if (CheckMisuse) {
+    if (SubChecker SC =
+            llvm::StringSwitch<SubChecker>(FName)
+                .Case("open", &UnixAPIChecker::CheckOpen)
+                .Case("openat", &UnixAPIChecker::CheckOpenAt)
+                .Case("pthread_once", &UnixAPIChecker::CheckPthreadOnce)
+                .Default(nullptr)) {
+      (this->*SC)(C, CE);
+    }
+  }
+  if (CheckPortability) {
+    if (SubChecker SC =
+            llvm::StringSwitch<SubChecker>(FName)
+                .Case("calloc", &UnixAPIChecker::CheckCallocZero)
+                .Case("malloc", &UnixAPIChecker::CheckMallocZero)
+                .Case("realloc", &UnixAPIChecker::CheckReallocZero)
+                .Case("reallocf", &UnixAPIChecker::CheckReallocfZero)
+                .Cases("alloca", "__builtin_alloca",
+                       &UnixAPIChecker::CheckAllocaZero)
+                .Case("__builtin_alloca_with_align",
+                      &UnixAPIChecker::CheckAllocaWithAlignZero)
+                .Case("valloc", &UnixAPIChecker::CheckVallocZero)
+                .Default(nullptr)) {
+      (this->*SC)(C, CE);
+    }
+  }
 }
 
 //===----------------------------------------------------------------------===//
 // Registration.
 //===----------------------------------------------------------------------===//
 
-void ento::registerUnixAPIChecker(CheckerManager &mgr) {
-  mgr.registerChecker<UnixAPIChecker>();
-}
+#define REGISTER_CHECKER(Name)                                                 \
+  void ento::registerUnixAPI##Name##Checker(CheckerManager &mgr) {             \
+    mgr.registerChecker<UnixAPIChecker>()->Check##Name = true;                 \
+  }
+
+REGISTER_CHECKER(Misuse)
+REGISTER_CHECKER(Portability)