Index: lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp =================================================================== --- lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp +++ lib/StaticAnalyzer/Checkers/UninitializedObjectChecker.cpp @@ -10,7 +10,7 @@ // This file defines a checker that reports uninitialized fields in objects // created after a constructor call. // -// This checker has two options: +// This checker has several options: // - "Pedantic" (boolean). If its not set or is set to false, the checker // won't emit warnings for objects that don't have at least one initialized // field. This may be set with @@ -24,6 +24,12 @@ // // `-analyzer-config alpha.cplusplus.UninitializedObject:NotesAsWarnings=true`. // +// - "NoDereference" (boolean). If set to true, the checker will not analyze +// the pointee of pointer/reference fields, and will only check whether the +// object itself is initialized. Defaults to false. +// +// `-analyzer-config alpha.cplusplus.UninitializedObject:NoDereference=true`. +// //===----------------------------------------------------------------------===// #include "ClangSACheckers.h" @@ -44,6 +50,7 @@ // These fields will be initialized when registering the checker. bool IsPedantic; bool ShouldConvertNotesToWarnings; + bool ShouldDereference; UninitializedObjectChecker() : BT_uninitField(new BuiltinBug(this, "Uninitialized fields")) {} @@ -109,13 +116,16 @@ const TypedValueRegion *const ObjectR; const bool IsPedantic; + const bool ShouldDereference; + bool IsAnyFieldInitialized = false; UninitFieldSet UninitFields; public: FindUninitializedFields(ProgramStateRef State, - const TypedValueRegion *const R, bool IsPedantic); + const TypedValueRegion *const R, bool IsPedantic, + bool ShouldDereference); const UninitFieldSet &getUninitFields(); private: @@ -261,8 +271,8 @@ if (!Object) return; - FindUninitializedFields F(Context.getState(), Object->getRegion(), - IsPedantic); + FindUninitializedFields F(Context.getState(), Object->getRegion(), IsPedantic, + ShouldDereference); const UninitFieldSet &UninitFields = F.getUninitFields(); @@ -326,8 +336,10 @@ //===----------------------------------------------------------------------===// FindUninitializedFields::FindUninitializedFields( - ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic) - : State(State), ObjectR(R), IsPedantic(IsPedantic) {} + ProgramStateRef State, const TypedValueRegion *const R, bool IsPedantic, + bool ShouldDereference) + : State(State), ObjectR(R), IsPedantic(IsPedantic), + ShouldDereference(ShouldDereference) {} const UninitFieldSet &FindUninitializedFields::getUninitFields() { isNonUnionUninit(ObjectR, FieldChainInfo()); @@ -474,6 +486,11 @@ return addFieldToUninits({LocalChain, FR}); } + if (!ShouldDereference) { + IsAnyFieldInitialized = true; + return false; + } + const FieldDecl *FD = FR->getDecl(); // TODO: The dynamic type of a void pointer may be retrieved with @@ -700,4 +717,6 @@ "Pedantic", /*DefaultVal*/ false, Chk); Chk->ShouldConvertNotesToWarnings = Mgr.getAnalyzerOptions().getBooleanOption( "NotesAsWarnings", /*DefaultVal*/ false, Chk); + Chk->ShouldDereference = !Mgr.getAnalyzerOptions().getBooleanOption( + "NoDereference", /*DefaultVal*/ false, Chk); } Index: test/Analysis/cxx-uninitialized-no-dereference.cpp =================================================================== --- /dev/null +++ test/Analysis/cxx-uninitialized-no-dereference.cpp @@ -0,0 +1,26 @@ +// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.cplusplus.UninitializedObject -analyzer-config alpha.cplusplus.UninitializedObject:NoDereference=true -std=c++11 -DPEDANTIC -verify %s + +class UninitPointerTest { + int *ptr; // expected-note{{uninitialized pointer 'this->ptr'}} + int dontGetFilteredByNonPedanticMode = 0; + +public: + UninitPointerTest() {} // expected-warning{{1 uninitialized field}} +}; + +void fUninitPointerTest() { + UninitPointerTest(); +} + +class UninitPointeeTest { + int *ptr; // no-note + int dontGetFilteredByNonPedanticMode = 0; + +public: + UninitPointeeTest(int *ptr) : ptr(ptr) {} // no-warning +}; + +void fUninitPointeeTest() { + int a; + UninitPointeeTest t(&a); +}