Merge remote-tracking branch 'origin/swift-4.1-branch' into stable
diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td
index 0a79af3..9eaf55f 100644
--- a/include/clang/StaticAnalyzer/Checkers/Checkers.td
+++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td
@@ -132,7 +132,7 @@
   HelpText<"Generate dynamic type information">,
   DescFile<"DynamicTypePropagation.cpp">;
 
-def NonnullStringConstantsChecker: Checker<"NonnilStringConstants">,
+def NonnullGlobalConstantsChecker: Checker<"NonnilStringConstants">,
   HelpText<"Assume that const string-like globals are non-null">,
   DescFile<"NonilStringConstantsChecker.cpp">;
 
diff --git a/lib/StaticAnalyzer/Checkers/CMakeLists.txt b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
index bf9d361..7ab9c61 100644
--- a/lib/StaticAnalyzer/Checkers/CMakeLists.txt
+++ b/lib/StaticAnalyzer/Checkers/CMakeLists.txt
@@ -57,7 +57,7 @@
   NSErrorChecker.cpp
   NoReturnFunctionChecker.cpp
   NonNullParamChecker.cpp
-  NonnullStringConstantsChecker.cpp
+  NonnullGlobalConstantsChecker.cpp
   NullabilityChecker.cpp
   NumberObjectConversionChecker.cpp
   ObjCAtSyncChecker.cpp
diff --git a/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp b/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
similarity index 74%
rename from lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp
rename to lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
index 516544b..0b4ecb4 100644
--- a/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp
+++ b/lib/StaticAnalyzer/Checkers/NonnullGlobalConstantsChecker.cpp
@@ -1,4 +1,4 @@
-//==- NonnullStringConstantsChecker.cpp ---------------------------*- C++ -*--//
+//==- NonnullGlobalConstantsChecker.cpp ---------------------------*- C++ -*--//
 //
 //                     The LLVM Compiler Infrastructure
 //
@@ -7,15 +7,17 @@
 //
 //===----------------------------------------------------------------------===//
 //
-//  This checker adds an assumption that constant string-like globals are
+//  This checker adds an assumption that constant globals of certain types* are
 //  non-null, as otherwise they generally do not convey any useful information.
-//  The assumption is useful, as many framework use such global const strings,
+//  The assumption is useful, as many framework use e. g. global const strings,
 //  and the analyzer might not be able to infer the global value if the
 //  definition is in a separate translation unit.
-//  The following types (and their typedef aliases) are considered string-like:
+//  The following types (and their typedef aliases) are considered to be
+//  non-null:
 //   - `char* const`
 //   - `const CFStringRef` from CoreFoundation
 //   - `NSString* const` from Foundation
+//   - `CFBooleanRef` from Foundation
 //
 //===----------------------------------------------------------------------===//
 
@@ -31,12 +33,13 @@
 
 namespace {
 
-class NonnullStringConstantsChecker : public Checker<check::Location> {
+class NonnullGlobalConstantsChecker : public Checker<check::Location> {
   mutable IdentifierInfo *NSStringII = nullptr;
   mutable IdentifierInfo *CFStringRefII = nullptr;
+  mutable IdentifierInfo *CFBooleanRefII = nullptr;
 
 public:
-  NonnullStringConstantsChecker() {}
+  NonnullGlobalConstantsChecker() {}
 
   void checkLocation(SVal l, bool isLoad, const Stmt *S,
                      CheckerContext &C) const;
@@ -46,22 +49,23 @@
 
   bool isGlobalConstString(SVal V) const;
 
-  bool isStringlike(QualType Ty) const;
+  bool isNonnullType(QualType Ty) const;
 };
 
 } // namespace
 
 /// Lazily initialize cache for required identifier informations.
-void NonnullStringConstantsChecker::initIdentifierInfo(ASTContext &Ctx) const {
+void NonnullGlobalConstantsChecker::initIdentifierInfo(ASTContext &Ctx) const {
   if (NSStringII)
     return;
 
   NSStringII = &Ctx.Idents.get("NSString");
   CFStringRefII = &Ctx.Idents.get("CFStringRef");
+  CFBooleanRefII = &Ctx.Idents.get("CFBooleanRef");
 }
 
 /// Add an assumption that const string-like globals are non-null.
-void NonnullStringConstantsChecker::checkLocation(SVal location, bool isLoad,
+void NonnullGlobalConstantsChecker::checkLocation(SVal location, bool isLoad,
                                                  const Stmt *S,
                                                  CheckerContext &C) const {
   initIdentifierInfo(C.getASTContext());
@@ -85,7 +89,7 @@
 
 /// \param V loaded lvalue.
 /// \return whether {@code val} is a string-like const global.
-bool NonnullStringConstantsChecker::isGlobalConstString(SVal V) const {
+bool NonnullGlobalConstantsChecker::isGlobalConstString(SVal V) const {
   Optional<loc::MemRegionVal> RegionVal = V.getAs<loc::MemRegionVal>();
   if (!RegionVal)
     return false;
@@ -99,7 +103,7 @@
 
   QualType Ty = Decl->getType();
   bool HasConst = Ty.isConstQualified();
-  if (isStringlike(Ty) && HasConst)
+  if (isNonnullType(Ty) && HasConst)
     return true;
 
   // Look through the typedefs.
@@ -109,14 +113,14 @@
     // It is sufficient for any intermediate typedef
     // to be classified const.
     HasConst = HasConst || Ty.isConstQualified();
-    if (isStringlike(Ty) && HasConst)
+    if (isNonnullType(Ty) && HasConst)
       return true;
   }
   return false;
 }
 
-/// \return whether {@code type} is a string-like type.
-bool NonnullStringConstantsChecker::isStringlike(QualType Ty) const {
+/// \return whether {@code type} is extremely unlikely to be null
+bool NonnullGlobalConstantsChecker::isNonnullType(QualType Ty) const {
 
   if (Ty->isPointerType() && Ty->getPointeeType()->isCharType())
     return true;
@@ -125,11 +129,12 @@
     return T->getInterfaceDecl() &&
       T->getInterfaceDecl()->getIdentifier() == NSStringII;
   } else if (auto *T = dyn_cast<TypedefType>(Ty)) {
-    return T->getDecl()->getIdentifier() == CFStringRefII;
+    IdentifierInfo* II = T->getDecl()->getIdentifier();
+    return II == CFStringRefII || II == CFBooleanRefII;
   }
   return false;
 }
 
-void ento::registerNonnullStringConstantsChecker(CheckerManager &Mgr) {
-  Mgr.registerChecker<NonnullStringConstantsChecker>();
+void ento::registerNonnullGlobalConstantsChecker(CheckerManager &Mgr) {
+  Mgr.registerChecker<NonnullGlobalConstantsChecker>();
 }
diff --git a/test/Analysis/nonnull-string-constants.mm b/test/Analysis/nonnull-global-constants.mm
similarity index 86%
rename from test/Analysis/nonnull-string-constants.mm
rename to test/Analysis/nonnull-global-constants.mm
index 8b56f2c..7900b9d 100644
--- a/test/Analysis/nonnull-string-constants.mm
+++ b/test/Analysis/nonnull-global-constants.mm
@@ -1,12 +1,13 @@
 // RUN: %clang_analyze_cc1 -analyzer-checker=core,debug.ExprInspection -verify %s
 
 // Nullability of const string-like globals, testing
-// NonnullStringConstantsChecker.
+// NonnullGlobalConstantsChecker.
 
 void clang_analyzer_eval(bool);
 
 @class NSString;
 typedef const struct __CFString *CFStringRef;
+typedef const struct __CFBoolean * CFBooleanRef;
 
 // Global NSString* is non-null.
 extern NSString *const StringConstGlobal;
@@ -88,3 +89,15 @@
 void testNestedTypedefsForNSString() {
   clang_analyzer_eval(nglobalStr2); // expected-warning{{TRUE}}
 }
+
+// And for CFBooleanRefs.
+extern const CFBooleanRef kBool;
+void testNonnullBool() {
+  clang_analyzer_eval(kBool); // expected-warning{{TRUE}}
+}
+
+// And again, only for const one.
+extern CFBooleanRef kBoolMutable;
+void testNonnullNonconstBool() {
+  clang_analyzer_eval(kBoolMutable); // expected-warning{{UNKNOWN}}
+}