diff options
author | Kristof Umann <dkszelethus@gmail.com> | 2018-08-13 18:17:05 +0000 |
---|---|---|
committer | Kristof Umann <dkszelethus@gmail.com> | 2018-08-13 18:17:05 +0000 |
commit | 56963aec8b8b1d0defe486dc576a9721866c609d (patch) | |
tree | b902b5dc112112502b3b8fcf8440ef08a2c59d28 /clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp | |
parent | 4bcf369d9b7cc2b8452ce42203a82e752c2de795 (diff) | |
download | bcm5719-llvm-56963aec8b8b1d0defe486dc576a9721866c609d.tar.gz bcm5719-llvm-56963aec8b8b1d0defe486dc576a9721866c609d.zip |
[analyzer][UninitializedObjectChecker] Refactoring p2.: Moving pointer chasing to a separate file
In this patch, the following classes and functions have been moved to a header file:
FieldChainInfo
FindUninitializedFields
isPrimitiveType
This also meant that they moved from anonymous namespace to clang::ento.
Code related to pointer chasing now relies in its own file.
There's absolutely no functional change in this patch -- its literally just copy pasting.
Differential Revision: https://reviews.llvm.org/D50504
llvm-svn: 339595
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp | 171 |
1 files changed, 171 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp new file mode 100644 index 00000000000..3c3c256ad9f --- /dev/null +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -0,0 +1,171 @@ +//===----- UninitializedPointer.cpp ------------------------------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines functions and methods for handling pointers and references +// to reduce the size and complexity of UninitializedObjectChecker.cpp. +// +// To read about command line options and a description what this checker does, +// refer to UninitializedObjectChecker.cpp. +// +// To read about how the checker works, refer to the comments in +// UninitializedObject.h. +// +//===----------------------------------------------------------------------===// + +#include "UninitializedObject.h" +#include "ClangSACheckers.h" +#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h" +#include "clang/StaticAnalyzer/Core/Checker.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h" + +using namespace clang; +using namespace clang::ento; + +// Utility function declarations. + +/// Returns whether T can be (transitively) dereferenced to a void pointer type +/// (void*, void**, ...). The type of the region behind a void pointer isn't +/// known, and thus FD can not be analyzed. +static bool isVoidPointer(QualType T); + +//===----------------------------------------------------------------------===// +// Methods for FindUninitializedFields. +//===----------------------------------------------------------------------===// + +// Note that pointers/references don't contain fields themselves, so in this +// function we won't add anything to LocalChain. +bool FindUninitializedFields::isPointerOrReferenceUninit( + const FieldRegion *FR, FieldChainInfo LocalChain) { + + assert((FR->getDecl()->getType()->isPointerType() || + FR->getDecl()->getType()->isReferenceType() || + FR->getDecl()->getType()->isBlockPointerType()) && + "This method only checks pointer/reference objects!"); + + SVal V = State->getSVal(FR); + + if (V.isUnknown() || V.getAs<loc::ConcreteInt>()) { + IsAnyFieldInitialized = true; + return false; + } + + if (V.isUndef()) { + return addFieldToUninits({LocalChain, FR}); + } + + if (!CheckPointeeInitialization) { + IsAnyFieldInitialized = true; + return false; + } + + assert(V.getAs<loc::MemRegionVal>() && + "At this point V must be loc::MemRegionVal!"); + auto L = V.castAs<loc::MemRegionVal>(); + + // We can't reason about symbolic regions, assume its initialized. + // Note that this also avoids a potential infinite recursion, because + // constructors for list-like classes are checked without being called, and + // the Static Analyzer will construct a symbolic region for Node *next; or + // similar code snippets. + if (L.getRegion()->getSymbolicBase()) { + IsAnyFieldInitialized = true; + return false; + } + + DynamicTypeInfo DynTInfo = getDynamicTypeInfo(State, L.getRegion()); + if (!DynTInfo.isValid()) { + IsAnyFieldInitialized = true; + return false; + } + + QualType DynT = DynTInfo.getType(); + + if (isVoidPointer(DynT)) { + IsAnyFieldInitialized = true; + return false; + } + + // At this point the pointer itself is initialized and points to a valid + // location, we'll now check the pointee. + SVal DerefdV = State->getSVal(V.castAs<Loc>(), DynT); + + // If DerefdV is still a pointer value, we'll dereference it again (e.g.: + // int** -> int*). + while (auto Tmp = DerefdV.getAs<loc::MemRegionVal>()) { + if (Tmp->getRegion()->getSymbolicBase()) { + IsAnyFieldInitialized = true; + return false; + } + + DynTInfo = getDynamicTypeInfo(State, Tmp->getRegion()); + if (!DynTInfo.isValid()) { + IsAnyFieldInitialized = true; + return false; + } + + DynT = DynTInfo.getType(); + if (isVoidPointer(DynT)) { + IsAnyFieldInitialized = true; + return false; + } + + DerefdV = State->getSVal(*Tmp, DynT); + } + + // If FR is a pointer pointing to a non-primitive type. + if (Optional<nonloc::LazyCompoundVal> RecordV = + DerefdV.getAs<nonloc::LazyCompoundVal>()) { + + const TypedValueRegion *R = RecordV->getRegion(); + + if (DynT->getPointeeType()->isStructureOrClassType()) + return isNonUnionUninit(R, {LocalChain, FR}); + + if (DynT->getPointeeType()->isUnionType()) { + if (isUnionUninit(R)) { + return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true}); + } else { + IsAnyFieldInitialized = true; + return false; + } + } + + if (DynT->getPointeeType()->isArrayType()) { + IsAnyFieldInitialized = true; + return false; + } + + llvm_unreachable("All cases are handled!"); + } + + assert((isPrimitiveType(DynT->getPointeeType()) || DynT->isPointerType() || + DynT->isReferenceType()) && + "At this point FR must either have a primitive dynamic type, or it " + "must be a null, undefined, unknown or concrete pointer!"); + + if (isPrimitiveUninit(DerefdV)) + return addFieldToUninits({LocalChain, FR, /*IsDereferenced*/ true}); + + IsAnyFieldInitialized = true; + return false; +} + +//===----------------------------------------------------------------------===// +// Utility functions. +//===----------------------------------------------------------------------===// + +static bool isVoidPointer(QualType T) { + while (!T.isNull()) { + if (T->isVoidPointerType()) + return true; + T = T->getPointeeType(); + } + return false; +} |