From f051379fbc3fef3b884088082721a15bc8ee1ead Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Fri, 14 Sep 2018 10:18:26 +0000 Subject: [PATCH] [analyzer][UninitializedObjectChecker] Support for nonloc::LocAsInteger Differential Revision: https://reviews.llvm.org/D49437 llvm-svn: 342221 --- .../UninitializedObjectChecker.cpp | 6 ++--- .../UninitializedObject/UninitializedPointee.cpp | 31 ++++++++++++++-------- .../Analysis/cxx-uninitialized-object-ptr-ref.cpp | 18 +++++++++++++ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp index b632229..711b43f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedObjectChecker.cpp @@ -274,15 +274,15 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, continue; } - if (isDereferencableType(T)) { + SVal V = State->getSVal(FieldVal); + + if (isDereferencableType(T) || V.getAs()) { if (isDereferencableUninit(FR, LocalChain)) ContainsUninitField = true; continue; } if (isPrimitiveType(T)) { - SVal V = State->getSVal(FieldVal); - if (isPrimitiveUninit(V)) { if (addFieldToUninits(LocalChain.add(RegularField(FR)))) ContainsUninitField = true; diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp index fa7cf18..f60fc0d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -57,9 +57,9 @@ public: } }; -/// Represents a void* field that needs to be casted back to its dynamic type -/// for a correct note message. -class NeedsCastLocField final : public FieldNode { +/// Represents a nonloc::LocAsInteger or void* field, that point to objects, but +/// needs to be casted back to its dynamic type for a correct note message. +class NeedsCastLocField : public FieldNode { QualType CastBackType; public: @@ -71,7 +71,13 @@ public: } virtual void printPrefix(llvm::raw_ostream &Out) const override { - Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; + // If this object is a nonloc::LocAsInteger. + if (getDecl()->getType()->isIntegerType()) + Out << "reinterpret_cast"; + // If this pointer's dynamic type is different then it's static type. + else + Out << "static_cast"; + Out << '<' << CastBackType.getAsString() << ">("; } virtual void printNode(llvm::raw_ostream &Out) const override { @@ -106,11 +112,12 @@ static llvm::Optional dereference(ProgramStateRef State, bool FindUninitializedFields::isDereferencableUninit( const FieldRegion *FR, FieldChainInfo LocalChain) { - assert(isDereferencableType(FR->getDecl()->getType()) && - "This method only checks dereferencable objects!"); - SVal V = State->getSVal(FR); + assert((isDereferencableType(FR->getDecl()->getType()) || + V.getAs()) && + "This method only checks dereferencable objects!"); + if (V.isUnknown() || V.getAs()) { IsAnyFieldInitialized = true; return false; @@ -196,13 +203,15 @@ static llvm::Optional dereference(ProgramStateRef State, llvm::SmallSet VisitedRegions; - // If the static type of the field is a void pointer, we need to cast it back - // to the dynamic type before dereferencing. - bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()); - SVal V = State->getSVal(FR); assert(V.getAsRegion() && "V must have an underlying region!"); + // If the static type of the field is a void pointer, or it is a + // nonloc::LocAsInteger, we need to cast it back to the dynamic type before + // dereferencing. + bool NeedsCastBack = isVoidPointer(FR->getDecl()->getType()) || + V.getAs(); + // The region we'd like to acquire. const auto *R = V.getAsRegion()->getAs(); if (!R) diff --git a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp index 4ee113c..7669ac5 100644 --- a/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ b/clang/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -22,6 +22,24 @@ void fConcreteIntLocTest() { } //===----------------------------------------------------------------------===// +// nonloc::LocAsInteger tests. +//===----------------------------------------------------------------------===// + +using intptr_t = long; + +struct LocAsIntegerTest { + intptr_t ptr; // expected-note{{uninitialized pointee 'reinterpret_cast(this->ptr)'}} + int dontGetFilteredByNonPedanticMode = 0; + + LocAsIntegerTest(void *ptr) : ptr(reinterpret_cast(ptr)) {} // expected-warning{{1 uninitialized field}} +}; + +void fLocAsIntegerTest() { + char c; + LocAsIntegerTest t(&c); +} + +//===----------------------------------------------------------------------===// // Null pointer tests. //===----------------------------------------------------------------------===// -- 2.7.4