From ad8d9be58ec32f09df665d328853f66373b0543a Mon Sep 17 00:00:00 2001 From: Kristof Umann Date: Fri, 13 Jul 2018 12:21:38 +0000 Subject: [PATCH] [analyzer][UninitializedObjectChecker] Support for MemberPointerTypes Differential Revision: https://reviews.llvm.org/D48325 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@336994 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Checkers/UninitializedObjectChecker.cpp | 40 +++++-------------- .../cxx-uninitialized-object-ptr-ref.cpp | 12 ++---- 2 files changed, 15 insertions(+), 37 deletions(-) diff --git a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp index 016be6fed8..a44ae9cd8d 100644 --- a/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -131,12 +131,10 @@ private: // - a non-union record // - a pointer/reference // - an array - // - of a member pointer type - // - of a primitive type, which we'll define as either a BuiltinType or - // EnumeralType. + // - of a primitive type, which we'll define later in a helper function. // * the parent of each node is the object that contains it - // * every leaf is an array, a primitive object, a member pointer, a nullptr - // or an undefined pointer. + // * every leaf is an array, a primitive object, a nullptr or an undefined + // pointer. // // Example: // @@ -163,8 +161,8 @@ private: // // From this we'll construct a vector of fieldchains, where each fieldchain // represents an uninitialized field. An uninitialized field may be a - // primitive object, a member pointer, a pointer, a pointee or a union without - // a single initialized field. + // primitive object, a pointer, a pointee or a union without a single + // initialized field. // In the above example, for the default constructor call we'll end up with // these fieldchains: // @@ -189,10 +187,6 @@ private: bool isPointerOrReferenceUninit(const FieldRegion *FR, FieldChainInfo LocalChain); - /// This method checks a region of MemberPointerType, and returns true if the - /// the pointer is uninitialized. - bool isMemberPointerUninit(const FieldRegion *FR, FieldChainInfo LocalChain); - /// This method returns true if the value of a primitive object is /// uninitialized. bool isPrimitiveUninit(const SVal &V); @@ -225,10 +219,13 @@ static bool isCalledByConstructor(const CheckerContext &Context); /// known, and thus FD can not be analyzed. static bool isVoidPointer(const FieldDecl *FD); -/// Returns true if T is a primitive type. We'll call a type primitive if it's -/// either a BuiltinType or an EnumeralType. +/// Returns true if T is a primitive type. We defined this type so that for +/// objects that we'd only like analyze as much as checking whether their +/// value is undefined or not, such as ints and doubles, can be analyzed with +/// ease. This also helps ensuring that every special field type is handled +/// correctly. static bool isPrimitiveType(const QualType &T) { - return T->isBuiltinType() || T->isEnumeralType(); + return T->isBuiltinType() || T->isEnumeralType() || T->isMemberPointerType(); } /// Constructs a note message for a given FieldChainInfo object. @@ -392,13 +389,6 @@ bool FindUninitializedFields::isNonUnionUninit(const TypedValueRegion *R, continue; } - if (T->isMemberPointerType()) { - if (isMemberPointerUninit(FR, LocalChain)) - ContainsUninitField = true; - continue; - } - - // If this is a pointer or reference type. if (T->isPointerType() || T->isReferenceType()) { if (isPointerOrReferenceUninit(FR, LocalChain)) ContainsUninitField = true; @@ -542,14 +532,6 @@ bool FindUninitializedFields::isPointerOrReferenceUninit( return false; } -bool FindUninitializedFields::isMemberPointerUninit(const FieldRegion *FR, - FieldChainInfo LocalChain) { - assert(FR->getDecl()->getType()->isMemberPointerType() && - "This function only checks regions that hold MemberPointerTypes!"); - // TODO: Implement support for MemberPointerTypes. - return false; -} - bool FindUninitializedFields::isPrimitiveUninit(const SVal &V) { if (V.isUndef()) return true; diff --git a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp index e6c0b91a62..db025420d7 100644 --- a/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp +++ b/test/Analysis/cxx-uninitialized-object-ptr-ref.cpp @@ -416,14 +416,12 @@ struct UsefulFunctions { #ifdef PEDANTIC struct PointerToMemberFunctionTest1 { - // TODO: we'd expect the note {{uninitialized field 'this->f'}} - void (UsefulFunctions::*f)(void); // no-note + void (UsefulFunctions::*f)(void); // expected-note{{uninitialized field 'this->f'}} PointerToMemberFunctionTest1() {} }; void fPointerToMemberFunctionTest1() { - // TODO: we'd expect the warning {{1 uninitialized field}} - PointerToMemberFunctionTest1(); // no-warning + PointerToMemberFunctionTest1(); // expected-warning{{1 uninitialized field}} } struct PointerToMemberFunctionTest2 { @@ -460,14 +458,12 @@ void fMultiPointerToMemberFunctionTest2() { } struct PointerToMemberDataTest1 { - // TODO: we'd expect the note {{uninitialized field 'this->f'}} - int UsefulFunctions::*d; // no-note + int UsefulFunctions::*d; // expected-note{{uninitialized field 'this->d'}} PointerToMemberDataTest1() {} }; void fPointerToMemberDataTest1() { - // TODO: we'd expect the warning {{1 uninitialized field}} - PointerToMemberDataTest1(); // no-warning + PointerToMemberDataTest1(); // expected-warning{{1 uninitialized field}} } struct PointerToMemberDataTest2 { -- 2.40.0