diff options
| author | George Karpenkov <ekarpenkov@apple.com> | 2017-10-13 00:51:41 +0000 |
|---|---|---|
| committer | George Karpenkov <ekarpenkov@apple.com> | 2017-10-13 00:51:41 +0000 |
| commit | 9a542f7553f198251869ef377a748e92e545c8f0 (patch) | |
| tree | c021fd54869ec8a16d04f5b6eacfbdcefdc17241 /clang/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp | |
| parent | 4516caef8e8760a011c501deca6cc3aaf21c75f0 (diff) | |
| download | bcm5719-llvm-9a542f7553f198251869ef377a748e92e545c8f0.tar.gz bcm5719-llvm-9a542f7553f198251869ef377a748e92e545c8f0.zip | |
[Analyzer] Assume that CFBooleanRef const globals are non-null
Differential Revision: https://reviews.llvm.org/D38867
llvm-svn: 315655
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp')
| -rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp | 135 |
1 files changed, 0 insertions, 135 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp deleted file mode 100644 index 516544b0f5c..00000000000 --- a/clang/lib/StaticAnalyzer/Checkers/NonnullStringConstantsChecker.cpp +++ /dev/null @@ -1,135 +0,0 @@ -//==- NonnullStringConstantsChecker.cpp ---------------------------*- C++ -*--// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This checker adds an assumption that constant string-like globals 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, -// 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: -// - `char* const` -// - `const CFStringRef` from CoreFoundation -// - `NSString* const` from Foundation -// -//===----------------------------------------------------------------------===// - -#include "ClangSACheckers.h" -#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" -#include "clang/StaticAnalyzer/Core/Checker.h" -#include "clang/StaticAnalyzer/Core/CheckerManager.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" - -using namespace clang; -using namespace ento; - -namespace { - -class NonnullStringConstantsChecker : public Checker<check::Location> { - mutable IdentifierInfo *NSStringII = nullptr; - mutable IdentifierInfo *CFStringRefII = nullptr; - -public: - NonnullStringConstantsChecker() {} - - void checkLocation(SVal l, bool isLoad, const Stmt *S, - CheckerContext &C) const; - -private: - void initIdentifierInfo(ASTContext &Ctx) const; - - bool isGlobalConstString(SVal V) const; - - bool isStringlike(QualType Ty) const; -}; - -} // namespace - -/// Lazily initialize cache for required identifier informations. -void NonnullStringConstantsChecker::initIdentifierInfo(ASTContext &Ctx) const { - if (NSStringII) - return; - - NSStringII = &Ctx.Idents.get("NSString"); - CFStringRefII = &Ctx.Idents.get("CFStringRef"); -} - -/// Add an assumption that const string-like globals are non-null. -void NonnullStringConstantsChecker::checkLocation(SVal location, bool isLoad, - const Stmt *S, - CheckerContext &C) const { - initIdentifierInfo(C.getASTContext()); - if (!isLoad || !location.isValid()) - return; - - ProgramStateRef State = C.getState(); - SVal V = State->getSVal(location.castAs<Loc>()); - - if (isGlobalConstString(location)) { - Optional<DefinedOrUnknownSVal> Constr = V.getAs<DefinedOrUnknownSVal>(); - - if (Constr) { - - // Assume that the variable is non-null. - ProgramStateRef OutputState = State->assume(*Constr, true); - C.addTransition(OutputState); - } - } -} - -/// \param V loaded lvalue. -/// \return whether {@code val} is a string-like const global. -bool NonnullStringConstantsChecker::isGlobalConstString(SVal V) const { - Optional<loc::MemRegionVal> RegionVal = V.getAs<loc::MemRegionVal>(); - if (!RegionVal) - return false; - auto *Region = dyn_cast<VarRegion>(RegionVal->getAsRegion()); - if (!Region) - return false; - const VarDecl *Decl = Region->getDecl(); - - if (!Decl->hasGlobalStorage()) - return false; - - QualType Ty = Decl->getType(); - bool HasConst = Ty.isConstQualified(); - if (isStringlike(Ty) && HasConst) - return true; - - // Look through the typedefs. - while (auto *T = dyn_cast<TypedefType>(Ty)) { - Ty = T->getDecl()->getUnderlyingType(); - - // It is sufficient for any intermediate typedef - // to be classified const. - HasConst = HasConst || Ty.isConstQualified(); - if (isStringlike(Ty) && HasConst) - return true; - } - return false; -} - -/// \return whether {@code type} is a string-like type. -bool NonnullStringConstantsChecker::isStringlike(QualType Ty) const { - - if (Ty->isPointerType() && Ty->getPointeeType()->isCharType()) - return true; - - if (auto *T = dyn_cast<ObjCObjectPointerType>(Ty)) { - return T->getInterfaceDecl() && - T->getInterfaceDecl()->getIdentifier() == NSStringII; - } else if (auto *T = dyn_cast<TypedefType>(Ty)) { - return T->getDecl()->getIdentifier() == CFStringRefII; - } - return false; -} - -void ento::registerNonnullStringConstantsChecker(CheckerManager &Mgr) { - Mgr.registerChecker<NonnullStringConstantsChecker>(); -} |

