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}}
+}