Author: szelethus Date: Tue Aug 14 01:20:51 2018 New Revision: 339653 URL: http://llvm.org/viewvc/llvm-project?rev=339653&view=rev Log: [analyzer][UninitializedObjectChecker] Void pointers are casted back to their dynamic type in note message
Differential Revision: https://reviews.llvm.org/D49228 Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp?rev=339653&r1=339652&r2=339653&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp Tue Aug 14 01:20:51 2018 @@ -60,6 +60,32 @@ 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 { + QualType CastBackType; + +public: + NeedsCastLocField(const FieldRegion *FR, const QualType &T) + : FieldNode(FR), CastBackType(T) {} + + virtual void printNoteMsg(llvm::raw_ostream &Out) const override { + Out << "uninitialized pointee "; + } + + virtual void printPrefix(llvm::raw_ostream &Out) const override { + Out << "static_cast" << '<' << CastBackType.getAsString() << ">("; + } + + virtual void printNode(llvm::raw_ostream &Out) const override { + Out << getVariableName(getDecl()) << ')'; + } + + virtual void printSeparator(llvm::raw_ostream &Out) const override { + Out << "->"; + } +}; + } // end of anonymous namespace // Utility function declarations. @@ -122,6 +148,10 @@ bool FindUninitializedFields::isPointerO QualType DynT = DynTInfo.getType(); + // 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()); + if (isVoidPointer(DynT)) { IsAnyFieldInitialized = true; return false; @@ -160,11 +190,16 @@ bool FindUninitializedFields::isPointerO const TypedValueRegion *R = RecordV->getRegion(); - if (DynT->getPointeeType()->isStructureOrClassType()) + if (DynT->getPointeeType()->isStructureOrClassType()) { + if (NeedsCastBack) + return isNonUnionUninit(R, LocalChain.add(NeedsCastLocField(FR, DynT))); return isNonUnionUninit(R, LocalChain.add(LocField(FR))); + } if (DynT->getPointeeType()->isUnionType()) { if (isUnionUninit(R)) { + if (NeedsCastBack) + return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); return addFieldToUninits(LocalChain.add(LocField(FR))); } else { IsAnyFieldInitialized = true; @@ -185,8 +220,11 @@ bool FindUninitializedFields::isPointerO "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)) + if (isPrimitiveUninit(DerefdV)) { + if (NeedsCastBack) + return addFieldToUninits(LocalChain.add(NeedsCastLocField(FR, DynT))); return addFieldToUninits(LocalChain.add(LocField(FR))); + } IsAnyFieldInitialized = true; return false; Modified: cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp?rev=339653&r1=339652&r2=339653&view=diff ============================================================================== --- cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp (original) +++ cfe/trunk/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp Tue Aug 14 01:20:51 2018 @@ -292,7 +292,7 @@ void fCyclicVoidPointerTest() { } struct IntDynTypedVoidPointerTest1 { - void *vptr; // expected-note{{uninitialized pointee 'this->vptr'}} + void *vptr; // expected-note{{uninitialized pointee 'static_cast<int *>(this->vptr)'}} int dontGetFilteredByNonPedanticMode = 0; IntDynTypedVoidPointerTest1(void *vptr) : vptr(vptr) {} // expected-warning{{1 uninitialized field}} @@ -305,8 +305,8 @@ void fIntDynTypedVoidPointerTest1() { struct RecordDynTypedVoidPointerTest { struct RecordType { - int x; // expected-note{{uninitialized field 'this->vptr->x'}} - int y; // expected-note{{uninitialized field 'this->vptr->y'}} + int x; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}} + int y; // expected-note{{uninitialized field 'static_cast<struct RecordDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}} }; void *vptr; @@ -322,9 +322,9 @@ void fRecordDynTypedVoidPointerTest() { struct NestedNonVoidDynTypedVoidPointerTest { struct RecordType { - int x; // expected-note{{uninitialized field 'this->vptr->x'}} - int y; // expected-note{{uninitialized field 'this->vptr->y'}} - void *vptr; // expected-note{{uninitialized pointee 'this->vptr->vptr'}} + int x; // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->x'}} + int y; // expected-note{{uninitialized field 'static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->y'}} + void *vptr; // expected-note{{uninitialized pointee 'static_cast<char *>(static_cast<struct NestedNonVoidDynTypedVoidPointerTest::RecordType *>(this->vptr)->vptr)'}} }; void *vptr; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits