diff options
author | Kristof Umann <dkszelethus@gmail.com> | 2018-08-14 08:20:51 +0000 |
---|---|---|
committer | Kristof Umann <dkszelethus@gmail.com> | 2018-08-14 08:20:51 +0000 |
commit | 5a42441d8192827bcf12fea1dd04f7c0f599b114 (patch) | |
tree | 190c5cd0fb07d8edc9073e88c699b041f165fa4b /clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp | |
parent | 5d94b25ffedbdc036ba467ece1695627b1210a8d (diff) | |
download | bcm5719-llvm-5a42441d8192827bcf12fea1dd04f7c0f599b114.tar.gz bcm5719-llvm-5a42441d8192827bcf12fea1dd04f7c0f599b114.zip |
[analyzer][UninitializedObjectChecker] Void pointers are casted back to their dynamic type in note message
Differential Revision: https://reviews.llvm.org/D49228
llvm-svn: 339653
Diffstat (limited to 'clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp index 6c83b2e146d..c855f97de2c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UninitializedObject/UninitializedPointee.cpp @@ -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::isPointerOrReferenceUninit( 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::isPointerOrReferenceUninit( 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::isPointerOrReferenceUninit( "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; |